Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Boost.Unitsを使ってみる

タグ: C++ Boost

boost 1.36.0で追加されたBoost.Unitsライブラリは、「ラジアン」や「度」などの角度の単位も扱う。
これを使えば、日々M_PI/180を掛ける作業に見切りを付けられるかもしれない。

#include <boost/units/systems/si.hpp>
#include <boost/units/systems/angle/degrees.hpp>
#include <boost/units/systems/angle/revolutions.hpp>
#include <boost/units/cmath.hpp>
#include <boost/units/io.hpp>

using namespace std;
using namespace boost::units;

template <typename Quantity>
void foo(const Quantity& angle)
{
	cout << "[" << name_string(typename Quantity::unit_type()) << "]" << endl;
	cout << angle << endl;
	cout << sin(angle) << endl;
	cout << acos(cos(angle)) << endl;
	cout << angle / si::second << endl;
	cout << quantity<si::angular_velocity>(angle / si::second) << endl;
	cout << "cat air " << Quantity(3 * revolution::revolutions) << endl;
}

int main()
{
	quantity<degree::plane_angle> deg(45 * degree::degrees);
	foo(deg);
	
	quantity<si::plane_angle> rad(deg);
	foo(rad);
}
[degree]
45 deg
0.707107 dimensionless
45 deg
45 deg s^-1
0.785398 s^-1 rad
cat air 1080 deg
[radian]
0.785398 rad
0.707107 dimensionless
0.785398 rad
0.785398 s^-1 rad
0.785398 s^-1 rad
cat air 18.8496 rad

Boost.Unitsには、長さの単位としてヤード等もあらかじめ定義されている。
meterdegree に比べて、やや使うのが手間ではあるが。

#include <iostream>
#include <boost/units/systems/si.hpp>
#include <boost/units/base_units/us/mile.hpp>
#include <boost/units/make_scaled_unit.hpp>
#include <boost/units/scaled_base_unit.hpp>

using namespace std;
using namespace boost::units;

typedef us::mile_base_unit::unit_type us_mile;
typedef us::yard_base_unit::unit_type us_yard;

template <typename LengthQuantity>
void foo(const LengthQuantity& length)
{
	quantity<us_yard> yard(length);
	quantity<us_mile> mile(yard);
	
	cout << "[" << name_string(typename LengthQuantity::unit_type()) << "]" << endl;
	cout << mile << " = " << yard << " = " << length << endl;
	cout << mile * yard * length << endl;
	cout << length * length * length << endl;
}

int main()
{
	typedef make_scaled_unit<si::length, scale<10, static_rational<3> > >::type kilometer;
	typedef scaled_base_unit<si::meter_base_unit, scale<10, static_rational<3> > >::type kilometer_tag;
	
	quantity<si::length> meter(1 * us_mile());
	foo(meter);
	
	quantity<kilometer> kilometer1(meter);
	foo(kilometer1);
	
	quantity<kilometer_tag::unit_type> kilometer2(meter);
	foo(kilometer2);
}
[meter]
1 mi = 1760 yd = 1609.34 m
2.83245e+06 yd mi m
4.16818e+09 m^3
[kilometer]
1 mi = 1760 yd = 1.60934 km
2832.45 k(yd mi m)
4.16818 G(m^3)
[kilometer]
1 mi = 1760 yd = 1.60934 km
2832.45 yd mi km
4.16818 km^3

Boost 1.37.0 symmetric_adaptorのコンパイルエラー

タグ: C++ Boost
#include <boost/numeric/ublas/symmetric.hpp>

int main () {
    using namespace boost::numeric::ublas;
    matrix<double> m (3, 3);
    symmetric_adaptor<matrix<double>, lower> sal (m);
    sal *= 1.0; // error
}

このコードはBoost 1.36.0では問題なく動作するが、Boost 1.37.0ではコンパイルエラーとなる。変更点を見るに、これは#2275の修正が symmetric_adaptor に及んでいないためであると思われる。 symmetric_matrix と同様の変更を symmetric_adaptor に施せば、それが正しいかどうかはともかく、とりあえずコンパイルは通る。

GTM Unit Test

タグ: Objective-C iPhone

Google Toolbox for Mac(GTM)には、Developer Tools標準のユニットテストフレームワーク「SenTestingKit」を利用したユニットテストコードが含まれている。
SenTestingKitがiPhone SDKに対応していないのに対し、このユニットテストコードは独自にSenTestingKitの実装を補うことで、iPhone向けビルドでも使えるようになっている。
ただ、その挙動はSenTestingKit本来のものとは少々異なるようだ(バージョン1.5.1)。

例えば次のテストケース。

- (void)test
{
	STAssertEquals(1, 2, NULL);

	const int actual = 3;
	STAssertEquals(1, actual, @"1 のはずなのに %d になっている", actual);
	
	STAssertEquals(1L, 1UL, @"(´・∀・` )");
}

これをSenTestingKitでテストすると「全ての STAssertEquals がエラーを出力する」

それに対し、GTMを使ったiPhone向けビルドでは「最初の STAssertEquals がエラーを出した時点でテストケースは中断される」

これは、SenTestingKitの SenTestCase::failWithException: が渡された例外のreasonを出力するに留めるのに対し、GTMのものは例外をraiseするからである(SenTestingKitのものも、事前に raiseAfterFailure を呼んでいれば例外をraiseする)。
なのでこのメソッドをオーバーライドすれば、SenTestingKitでテストケースを中断させるようにも……

GTMでテストケースを継続させるようにもできる。

11月11日のココロ日記(BlogPet)

むいさんは三度の飯よりズームイン・アウトが好きだと思うんです。ココロの思い過ごしですか?

*このエントリは、ブログペットのココロが書いてます♪

テンプレート関数では高速列挙できない

タグ: Objective-C C++

テンプレート定義に高速列挙(Fast Enumeration)構文が含まれていると、そのテンプレートが具現されるか否かに関わらずコンパイルエラーとなる(Xcode 3.1.1)。

template <typename OutputIterator>
inline OutputIterator copy(NSArray* array, OutputIterator result)
{
	for(id elem in array) // internal compile error: Bus error
	{
		*result = elem;
		++result;
	}
	return result;
}
template <typename T>
class Foo
{
public:
	void foo()
	{
		for(id elem in [NSArray array]); // internal compile error: Bus error
	}
};

UIScrollViewによる拡大縮小

タグ: iPhone Objective-C

UIScrollView によって拡大縮小されたビューのスケールは、拡大縮小されたビュー自身に記録される。

- (void)applicationDidFinishLaunching:(UIApplication*)application
{
    UIScrollView* scrollView = [[UIScrollView alloc] initWithFrame:window.bounds];
    scrollView.delegate = self;

    // Earth.jpg は /Library/Desktop Pictures/Nature から拝借
    UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Earth.jpg"]];
    scrollView.contentSize = imageView.bounds.size;
    scrollView.minimumZoomScale = 0.25;
    scrollView.maximumZoomScale = 4.0;
    [scrollView addSubview:imageView];
    [imageView release];

    [window addSubview:scrollView];
    [window makeKeyAndVisible];

    [scrollView release];
}

- (UIView*)viewForZoomingInScrollView:(UIScrollView*)scrollView
{
    UIView* view = [scrollView.subviews objectAtIndex:0];
    id gestureInfo = [view valueForKey:@"gestureInfo"];
    NSLog(
        @"will: %f %@ %@ %@",
        view.transform.a,
        [gestureInfo valueForKey:@"zoomScale"],
        [gestureInfo valueForKey:@"minScale"],
        [gestureInfo valueForKey:@"maxScale"]
    );
    return view;
}

- (void)scrollViewDidEndZooming:(UIScrollView*)scrollView withView:(UIView*)view atScale:(float)scale
{
    id gestureInfo = [view valueForKey:@"gestureInfo"];
    NSLog(
        @"did: %f %f %@ %@ %@",
        scale,
        view.transform.a,
        [gestureInfo valueForKey:@"zoomScale"],
        [gestureInfo valueForKey:@"minScale"],
        [gestureInfo valueForKey:@"maxScale"]
    );
}

以上のコードで作られたスクロールビューを、適当にピンチイン・アウトしてログを出力してみる。

will: 1.000000 1 0.35 1.6
did: 0.757831 0.757831 0.7578313 0.25 4
will: 0.757831 0.7578313 0.25 4
did: 1.281839 1.281839 1.281839 0.25 4
will: 1.281839 1.281839 0.25 4
did: 0.250000 0.250000 0.25 0.25 4

viewForZoomingInScrollView: が呼ばれる前に UIView::transform をいじっても、初回呼び出し時はスケール1から、それ以降は(おそらく) zoomScale の値から拡大縮小が始まる。
このスケール値を直接操作するAPIは公開されていない。
そのため、 viewForZoomingInScrollView: の戻り値となるビューのスケール操作は、全て UIScrollView に任せるのが基本となる。
しかし、 UIScrollView には「ダブルタップによるズームイン・アウト」は実装されていない。
Photos等に見られるそのような操作を実現するには、何かしら小細工が必要になる。

iPhoneの文字座標

タグ: iPhone Quartz

NSView等、Macの座標系は左下基点。
それに対し、UIView等、iPhoneの座標系は左上基点。
drawAtPoint 等、iPhone用の文字列描画関数はその違いを吸収するが、 CGContextShowGlyphsAtPoint のような素のCore Graphics向け文字列描画関数は、自分でtext matrixを上下逆に設定しなければならない。

const CGGlyph glyphs[] = { 674, 1, 127, 1058, 646, 675  };

CGFontRef font = CGFontCreateWithFontName((CFStringRef)@"HiraKakuProN-W6");
CGContextSetFont(context, font);
CGContextSetFontSize(context, 48);
CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 1.0f);
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextShowGlyphsAtPoint(context, 50, 50, glyphs, sizeof(glyphs) / sizeof(*glyphs));
CGFontRelease(font);

↑のコードでNSViewに描くと

UIViewに描くと

フィッシングメールが来たよ

Welcome,

Thank you for choosing MobileMe. Unfortunately there has been a
problem processing your billing information for the month of November, 2008.

Did you recently change your bank, phone number or credit card?
To avoid suspension of your account please login to update your information.

この文章の後に「Log in」という絵とリンクが貼り付けられたメールが私のメールエイリアスに届いた。
リンク先は appleupdate.uk.com 。
本アカウントならともかく、エイリアスではなぁ。

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。