多重定義の罠(自動キャストに注意)

関数の多重定義ってのは、非常に便利な機能で、同じ名前でも引数の数や型が違うと別の関数として判別してくれる、っていう技です。

オブジェクト指向言語は、大抵これを利用しています。

# オブジェクト指向的には必須って訳ではないんだろうけど、引数の数が異なる度に
# 関数名を考えないと駄目ってのもアレなわけで。

# あと、C++/C# に限って言えば、コンストラクタの多重定義ができないと言語的に
# 成り立たないってのがあります。

class A
{
private:
 int _x ;
public:
 // 引数のないコンストラクタ
 A() { _x = 0; }
 // 引数のあるコンストラクタ
 A( int x ) { _x = x; }
};

ここで多重定義ができないと、A(x) ってのができません。
仕方がないので、A::CreateX( int x ) なんて云うスタティッククラスを使うような
ファクトリーパターンを使うようになる訳です。Java の場合は、Factory パターンが
主流ですが、C++のほうはコンストラクタの多重定義が多いですね。

# objective-c の場合は、このあたり中途半端(っぽく見える)なので、
# Aクラスに initWithX というメソッドを作ります。

さて、この多重定義を突き詰めていくと、出来るだけ短い名前で表現したいという欲望に駆られます。勿論一方で、elementById という名前も主流でもあるわけですが。

ひとまず、ざっと次のコードをご覧ください。

using System;

public class RGB {
 private double _r;
 private double _g;
 private double _b;
 
 public RGB() {
  _r = _g = _b = 0.0;
 }
 public RGB( double r, double g, double b ) {
  _r = r;
  _g = g;
  _b = b;
 }
 public RGB( byte r, byte g, byte b ) {
  _r = ((double)r)/255.0;
  _g = ((double)g)/255.0;
  _b = ((double)b)/255.0;
 }
 public override string ToString() {
  return string.Format("r:{0} g:{1} b:{2}", _r, _g, _b );
 }
}

public class Test {
 
 public static void Main( string[] args ) {
  Console.WriteLine("RGB check");
  
  RGB col = new RGB();
  Console.WriteLine("RGB {0}", col );
  // 実数で指定
  col = new RGB(1.0, 1.0, 0.0);
  Console.WriteLine("RGB {0}", col );
  // WindowsのRGB値(0-255)で指定
  col = new RGB(0,255,255);
  Console.WriteLine("RGB {0}", col );
  // 実数で指定したつもり
  col = new RGB(1, 1, 0);  // byte型とみなされてしまう。
  Console.WriteLine("RGB {0}", col );
  col = new RGB(1.0, 1, 0); // ひとつでもdouble型にしておけばok
  Console.WriteLine("RGB {0}", col );
 }
}

RGB値を扱う関数なのですが、Mac の場合、RGB値は1.0から0.0の実数を取るんだよね~、ってことが分かって、まあ画像解析がてら double 型に組んでいたいのです。
(実際は、float 型なのですが、キャストが面倒なのと説明の関係で double 型にしてあります)

ご存じの通り、Windows の RGB 値は 0 から 255 の整数値を取ります。ですが、これはディスプレイに表示するときには便利なのですが、色相を変えたりするときは、結局実数で扱うので、そのまま扱うと不便です。

なので、内部的には double 型で扱う。けれども、RGB 値を整数値(byte型)でも渡せるよ、というクラスを作ってみたわけです。

RGB( double r, double g, double b )
RGB( byte r, byte g, byte b )

この2つのコンストラクタ(関数でもいいけど)は多重定義を使っていて、一方は double 型、もう一方は byte 型で初期化できるものです。

多重定義ができないと、

RGBByDouble( double r, double g, double b )
RGBByByte( byte r, byte g, byte b )

な感じになるんですが、まあ、RGB コンストラクタのほうがスマートでしょう?

ですが、ここに落とし穴があるんですねぇ。
先のプログラムを実行すると、こんな感じになります。

RGB check
RGB r:0 g:0 b:0
RGB r:1 g:1 b:0
RGB r:0 g:1 b:1
RGB r:0.00392156862745098 g:0.00392156862745098 b:0 ★
RGB r:1 g:1 b:0

★の部分が、意図しなかった動きです。

// 実数で指定したつもり
col = new RGB(1, 1, 0);  // byte型とみなされてしまう。
Console.WriteLine("RGB {0}", col );

実は、上記のように即値で指定する場合、「1」や「0」は整数とみなされるために、byte 型で初期化するコンストラクタが呼び出されます。勿論、C言語を習ったときのように、

「実数を指定するときは、明示的に 1.0 としないと駄目」

ってことを忘れずにいればいいんですが。

そんな訳で

col = new RGB(1.0, 1, 0); // ひとつでもdouble型にしておけばok
Console.WriteLine("RGB {0}", col );

こんな風に、即値の場合は明示的に指定するのが吉です。
自動キャストは、データ型の小さいところから判断されるので、

byte -> int -> long -> float -> double

の順番にキャストされています。先の例では byte 型なので、見当が付きそうですが、

int型とlong型の混在なんかやると、もう駄目ですね。意図通りに動きません。
なので、そういう風な場合は、「やめましょう」ってのが筋です。
そうそう、C言語ならば typedef、C# ならば型を継承するってのもひとつの方法です。
標準で定義されている typedef unsigned long size_t ; のように、しておけば型が厳密に判断されて、先の自動キャストの範囲外になり、混乱が少なくなります。

カテゴリー: 開発 | 多重定義の罠(自動キャストに注意) はコメントを受け付けていません

意外と画面が狭いぞ!ネットブック

ネットブックで業務アプリを動かそう、なぞと構想しているのですが、それってユーザーに使いやすい画面になるのでしょうか? ってなわけで「ドックフード」してみました。

ネットブックの画面サイズは、大抵は 1024×600 だそうです。
ブラウザで表示、タスクバーなんかが表示されると、結構画面が狭くなります。

「ネットブック」には何が出来て、何が出来ないのか?

まぁ、ネットブックの基本はメール送受信とブラウザ閲覧なわけなので、そんなに大きな
画面は必要ないのですが、意外と縦が狭い!意外とどころじゃなくて、狭すぎる!

<016>
20100219_161

画面キャプチャの、上のIE部分が実際に表示できるところです。
次なるスクリプトを書いて、タスクバー分(50ドットぐらい)減らしています。
# XPのタスクバーは30ドットです。

on error resume next
set fso = CreateObject("Scripting.FileSystemObject")
txt = ""
for each br in CreateObject("Shell.Application").Windows
  pname = ""
  pname = fso.GetFileName( br.FullName )
   if br.LocationURL <> &quot;about:blank&quot; then
    br.top = 0
    br.left = 0
    br.width = 1024
    br.Height = 600 - 50
  end if
next

このブログを表示させると、タイトルしか表示されませんね。。。
XPにIE8を乗せて、

・メニューバー
・お気に入り等のショートカット
・タブ
・ステータスバー

を全て表示させるとこんな感じです。
更に、google ツールバーやら yahoo ツールバーやらが入るとえらいことになりそうです。
業務系の場合は、タスクバーを消すように設定して全画面表示で使う、という技、あるいは、ツールを使って画面の解像度を高くする、という荒業もできますが、一般の場合はそうもいきません。特に、ブラウザで表示する場合は、相手にどんな状態で使ってくれと要求することはできませんから、この画面でなんとか操作性を上げる努力をしないと駄目なわけです。

ただし、業務系に限って言えば、解像度が低いことが問題にはならない。ネットブック用にフォントを小さくしたり、画像を小さくすればいい訳で、小さな画面の視認性を上げるための限界を知っておくのと、画面が横長になることに配慮すればいいだけです。

カテゴリー: 設計, 雑談 | 意外と画面が狭いぞ!ネットブック はコメントを受け付けていません

Expression Blend 3 のサンプルプロジェクト

訳あって Silverlight の機能を網羅的に調べているので、そのお裾分け。
「Expression Blend 3 にはデモプロジェクトが付いているので、見てね~」と言っていたのは、MSの大西さんだったか?なのですが、ネットを見ても情報がないので晒しておきます。

# Blend 3 の試用版を入れれば見れると思うのだけど、「インストール」という高い敷居があるからね。

Blend 3 のサンプルプロジェクトは、7つあります。

<001>
20100219_01

・ShowboardSketch
・PCGameingSketch

の2つは、Blend 3 から導入されたスケッチフローという機能のサンプルです。
スケッチフローは、簡単にいえば、Web サイトの構想を紙に書く変わりに、電子的に書く、というものです。紙で書いたものをスキャナで取り込んだり、鉛筆で書いたようなスタイルのボタンやリストボックスが用意されています。

Expression Blend 3+SketchFlowを使ってみた
http://www.atmarkit.co.jp/fwcr/design/tool/expressionblend3/03.html

なところを参照してください。

■Zune3D

携帯電話のデザインを変えられるサイトのデモです。
flash を使って商品で色を変えたり、柄を変えたりするパターンですね。

<002>
20100219_02

<003>
20100219_03

■Wall3D

写真を閲覧できるサイトのサンプルです。
ajax を使って、3Dやポラロイド風に写真を並べられますが、それと同じパターンです。

<004>
20100219_04

<005>
20100219_05

■SnowboardSketch

商品サイトのスケッチフローです。
手書き風のフォントと手書き風のボタンを配置して、「制作途中」を演出します。
かつて、mac のインターフェースに、そういうアイデアがあったのですが、それと似たようなものです。

<006>
20100219_06

<007>
20100219_07

日本語の場合は、みかちゃんフォントなどを使うと、フォントも含めて手書き風をアレンジできますよ。

みかちゃんフォント
http://www001.upp.so-net.ne.jp/mikachan/

SketchFlow は専用のビューアやブラウザで表示できます。

■PCGameingSketch

WEBサイトではなくて、ゲーム作成途中のバージョン別によるスケッチです。
画面切り替えがあるアプリケーションは、ボタンをクリックして次の画面へ、なんてことができるので紙芝居が楽にできますね。

<008>
20100219_08

<009>
20100219_09

Visio や、VB 6.0、Excel で作ったりしますね。
画面遷移ができるので、私は VB6 をよく使っていました。

■PCGaming

WEBサイトのサンプルです。先ほどの、スケッチを利用して作った、という想定です。

<010>
20100219_10

<011>
20100219_11

■ColorSwatchSL

flash や ajax でも作れる、カラーチャートのサンプルです。

<012>
20100219_12

<013>
20100219_13

■BeeHive

Blend 3 で作ったブロック崩しです。
「Blend 3 のみで作れる」という謳い文句になっていますが、内部ではコードビハイドというC#のコードがぎっしり詰まっています。なので、これだと、素直に C# で作ったほうが楽そうですね。

ただし、ちょっとしたイベントや計算などを、プログラマが提供して、デザイナが使うってことができます。実は、ボタンのbluer機能なんかは、C# のライブラリとして提供されています。

<014>
20100219_14

<015>
20100219_15

ちなみに、BeeHive のブロックやバーは、画像ファイルです。。。どうせならば、xaml で作って欲しかった。

あと、Blend は、Adoble の Photoshop、Illuastratorのデータをインポートできます。このあたりは便利ですね。
ちなみに、ドロー系のIllustrator の代替としては、Expression Desine が用意されていますが、ペイント系のPhotoshop の 代替は

Graphic Designer
http://www.microsoft.com/products/expression/ja/graphic_designer/gd_features.mspx

みたいですね。Expression Studio 3 には、Desiner というドロー系のアプリが入っているのですが、Graphic Desinger とは別ものなのかな?
こんなわけで、Blend 3 に入っているサンプルプロジェクトの一覧にでも。

カテゴリー: 開発 | Expression Blend 3 のサンプルプロジェクト はコメントを受け付けていません

GNUstepでobjective-cを学ぶ(4)

objective-cを使うと、「id」という型がよく使われます。どうやら、smalltalkがそうらしいのですが、メソッド(あるいはメッセージ)を実行時にチェックしているために、このid型が使われます。
所謂、voidポインタのように使えるわけですが、objective-cのnilポインタ(NULLポインタのようなもの)に対してメソッド呼び出しをしても、「何も起こらない」という特徴があります。

ええとですね。C++やJavaとobjetive-cのメソッド呼び出し方が違うんですね。

C++の場合は、vtbl構造体に配置されている関数ポインタを直接呼び出します。
つまり。

obj->func( ... );

な形になるわけです。

ですが、objective-c の場合は、次のように「func」という関数名を探し出した後に、メソッド呼び出しをするんですね。

Func *func = obj->seekMethod( &quot;func&quot; );
if ( func != NULL ) {
 func( ... );
}

当然、実行時にはC++やJavaのほうが早いのですが(更にC言語の呼び出しのほうがアセンブラ的には早い。単純な call 命令だからね)、まぁ、色々便利な機能ではあるのです。

C#では「デリゲート」という機能がありますが、これは、主として windows gui のイベント駆動をうまく動かすための仕組みです。デリゲートがない場合は、java ではリスナー、C++ では関数ポインタなどが使われます。

いわゆる、インターフェースを定義して呼び出す、というリスナーパターンです。

// インターフェースを定義する
class Listener {
public:
 void func( void );
};
// 実装クラス
class Window : public Listener {
 void func( void ) {
  ...
 }
}

int main( void )
{
 Listener *win = new Window();
 // ここで func メソッドを呼ぶ
 win->func();
}

C++ の場合は、もっと直接的に、関数ポインタを使う方法もあります。

class Window {
 void func( void ) {
  g_func();
 }
}

// グローバルな関数
static void g_func( void ) {
 ...
}

int main( void )
{
 Window *win = new Window();
 // ここで func メソッドを呼ぶ
 win->func();
}

長い前置きでしたが、これからが本題。
オブジェクト指向の便利なところは、クラス(カテゴリ)に分けておいて、同じメソッド名を使えるというところです。文法でいえば、メソッドが「動詞」で、オブジェクトが「主格」あるいは「目的格」ですね(このあたり、昔から議論がありますが、省きます)。

なので、A クラスと B クラスという2つのクラスに、同じ print というメソッドを使うと、

A a;
B b;

a.print();
b.print();

のような形で、同じメソッド名を使えます。この print メソッドは、基底クラスから継承するようにして、

class Base {
public:
 void print( void );
}
class A : public Base {
public:
 void print( void ) {
  ...
 }
};
class B : public Base {
public:
 void print( void ) {
  ...
 }
};

のように定義しておいて、実行時に切り替えることが可能なのです。

Base *a = new A();
Base *b = new B();

a->print();
b->print();

これは、それぞれの print メソッドが呼び出されます。これはリスナーパターンの基本ですね。

さて、このインターフェースの機能ですが、メソッド名に制約を付ける、という恩恵があるのですが、逆に言えば「基底クラス/インターフェースにあらかじめ、メソッドを用意しないといけない」という制限があります。
当たり前と言えば、当たり前なのですが、インターフェースにを作成するときに「未来の機能を予測しないといけない」というジレンマが発生します。このために、基底クラスが膨大になってしまったり、やたらに仮想関数の多いクラスが作成されてしまいます。
# 残念ながら、デリゲートも同じ制限があります。

残念ながら、我々は予知力がありません(笑)ので、これから作成されるサブクラスの機能を完全に予測することはできません。つまり、同時期に作ればよいのですが、数年後に拡張される機能を、基底クラスに盛り込むことは不可能なのです。

そこで、objective-c の(一見すると)不思議なメソッド呼び出しが功を奏します。

@interface A
- (void)print ;
@end
@implementation A
- (void)print {
 ...
}
@end

@interface B
- (void)print ;
@end
@implementation B
- (void)print {
 ...
}
@end

のように基底クラスを「共有しない」で定義しておいて、id 型で受けます。

id a = [A new];
id b = [B new];

[a print];
[b print];

こういう風にすると、まるで「あらかじめメソッド定義している」ように見えるんですね。
まぁ、コンパイル時にチェックが入らないので、インターフェースを使った型の厳密性は損なわれるのですが、あたかもRubyのようにメソッドが追加できるのが面白いです。

と言う訳で、基底クラスを使わないリスナーパターンということで。サンプルを晒しておきます。

#import <stdio.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>

@interface A : NSObject
- (void)print ;
- (void)printX:(int)x ;
@end

@interface B : NSObject
- (void)print ;
- (void)printX:(int)x y:(int)y ;
@end

@implementation A
- (void)print {
 printf(&quot;in class A\n&quot;);
}

- (void)printX:(int)x {
 printf(&quot;in print A: %d\n&quot;, x );
}
@end

@implementation B
- (void)print {
 printf(&quot;in class B\n&quot;);
}
- (void)printX:(int)x y:(int)y {
 printf(&quot;in print B: %d %d\n&quot;, x, y );
}
@end

id CreateObject( int type )
{
 id obj ;
 switch ( type ) {
 case 0:
  obj = [A new];
  break;
 case 1:
  obj = [B new];
  break;
 default:
  obj = nil;
 }
 return obj;
}

int main( void )
{
 printf(&quot;hello4.m\n&quot; );
 
 A *a = [A new];
 [a print];
 [a printX:10];
 [a release];

 id x = [A new];
 [x print];
 [x printX:10];
 [x release];
 // 同じidを使える
 x = [B new];
 [x print];
 [x printX:10 y:20];
 [x release];
 
 // こんなこともできる
 x = CreateObject(0);
 [x print];
 [x release];
 x = CreateObject(1);
 [x print];
// [x printX:10]; // 間違えてもコンパイルエラーにならない。
 [x printX:10 y:20];
 [x release];
 
 // nilに対しては何も反応しない
 x = CreateObject(10); // nil を返す場合
 [x print];
 [x release];
 
 return 1;
}
/**
実行結果

hello4.m
in class A
in print A: 10
in class A
in print A: 10
in class B
in print B: 10 20
in class A
in class B
in print B: 10 20
**/
カテゴリー: 開発 | GNUstepでobjective-cを学ぶ(4) はコメントを受け付けていません

Silverlight Sample Browser

Home – Silverlight SDK Sample Browser
http://samples.msdn.microsoft.com/Silverlight/SampleBrowser/#/?sref=HomePage
Silverlight
http://msdn.microsoft.com/ja-jp/library/cc838158(VS.95).aspx
Silverlight SDK
http://blogs.msdn.com/silverlight_sdk/
ダウンロードの詳細 : Silverlight 3 ドキュメント
http://www.microsoft.com/downloads/details.aspx?FamilyID=0a9773a7-c854-41fa-b73d-535abfb73baf&displaylang=ja
Silverlight ダウンロード
http://msdn.microsoft.com/ja-jp/silverlight/bb187452.aspx

備忘録的に、Silverlightのドキュメントを記録しておきます。
Silverlight 4 がベータ版が出てきているので、
http://msdn.microsoft.com/ja-jp/silverlight/bb187452.aspx

近々変わるとは思うのですが、まぁ一応。

~~

microsoft社の戦略はさておき、私としては、flashに代替するものになるか?がポイントですね。.NET Framework でプログラミングできるのも魅力的なのですが、巷の flash アニメーションやメニュー操作、異なったところでは Curl に匹敵するものができないと、「機能が実現できない」という本末転倒なことになります。

silverlight の場合、ブラウザ上で動作するにせよ、最初はインストールが必要です。ただし、flash を動かす場合にも最初のインストールが必要なので、あまり障壁になりません。

flash からの代替ポイントは次なものです。

・手軽に動的なチャート/グラフが書けるか?
・手軽に flash アニメーションが作成できるか(トップ画面のCMみたいなの)
・プログラマがデザイナの力を借りられるか?

なところです。基本、flash のプログラミングは actionscript を使うところもあるのですが、デザイナが一人で作るものが多いのです。なので、silverlight のような、プログラマ主導のものを、デザイナが受け付けるか?デザイナと共同作業ができるか? がプロジェクト単位では重要になります。

となれば、flash で作れるような、アニメーション効果やチャートが、手軽にできるのか。手軽じゃなくてもいいけど、デザインセンスが発揮できるもの、デザインの作業を妨げないようにできるか、がポイントになりますね。

チャートに関しては、silverlight SDK ブログを見ると
http://blogs.msdn.com/silverlight_sdk/archive/2009/12/07/getting-started-with-the-charting-controls.aspx

円グラフ等が加わっています。デモを見る限り、それなりに揃っているようですが、flash の代替とするならば、google analytics のマイレポートのように、マウスでポイントしたところにメッセージを出す機能を「標準で」欲しいところです。
# まあ、そのあたりは売り物に期待するっていのもアリなんですが。

flash アニメーションについては、Expression Blend を使うのでしょうが、ここの情報が不足し過ぎています。flash アニメーションの書籍は多いのですが、Blend で作るアニメーションの書籍は皆無です。基本は Blend のストリーボードを使えばいいのですが、その説明すら、公式のドキュメント以外には良いものが見当たりません。これでは、flash アニメーションの代替にはなりません。

そんな訳で、現段階では代替するのは無理、と思うのですが如何でしょう?

~~

「代替しない」という方法もあるんですけど、どうなんでしょうねぇ?
トップ画面のアニメーション/ナビゲーションは flash で作って、内部の業務的なものを silverlight で作るとか?

カテゴリー: 開発 | Silverlight Sample Browser はコメントを受け付けていません

Zaku認識(2)

前回のZaku認識(1)の続きです。
http://www.moonmile.net/blog/archives/576

物体/動体認識をするときに、白黒を使うことが多いのですが、残念ながら、これでは「シャアザク」と「ザク」の区別がつきません。何故、この2つを区別しなければいけないのか、、、は脇に置いて、区別できる方法で、認識をさせます。

RGB(赤/緑/青)の3値から、白黒画像を作る場合は、YCbCr(YIQ)画像に変換して、Y値だけ残します。

まず、次の画像を見てください。

<001>
20100208_001

真ん中にあるガンダムの左上にシャアがいますね。
これをグレー色調にすると、

<002>
20100208_002

こんな風に、シャアがザクに隠れてしまいます。
これでは、シャアザクだけを攻撃することはできませんね(笑)。

そんな訳で、YIQからHSV表示に変換して、H値(色相)だけ残します。

<003>
20100208_003

サーモグラフィのような画像になりますが、シャアザクの位置が、なんとなくわかります。

同様に次の3つを見比べると、ガンダムの右にシャアがいそうな感じ、ってくぐらいは分かります。

<004>
20100208_004

<005>
20100208_005

<006>
20100208_006

色が単純化されるのは、色相のみ残して、輝度、彩度を一定値にしているからです。
これを使うと、緑の量産ザクと、赤のシャアザクが区別できるんですね。
グレーの場合は、赤緑色盲と一緒で、輝度が同じなので区別がつきません。

RGB/YIQ/HSV表示の相互変換は、こちら

namespace zaku.monoeye
{
 // RGB表示系クラス
 // r: 赤
 // g: 緑
 // b: 青
 public class RGB
 {
  public double r;
  public double g;
  public double b;
  
  public RGB()
  {
   r = g = b = 0;
  }

        // 正規化されたRGB値(0.0-1.0)
  public RGB( double r, double g, double b )
  {
   this.r = r;
   this.g = g;
   this.b = b;
  }
        // ディスプレイのRGB値(0-255)
        public RGB(Color col)
        {
            this.r = ((double)col.R) / 255.0;
            this.g = ((double)col.G) / 255.0;
            this.b = ((double)col.B) / 255.0;
        }

        public Color ToColor()
        {
            int r, g, b;
            r = (int)(this.r * 255);
            g = (int)(this.g * 255);
            b = (int)(this.b * 255);
         if ( r < 0 ) r = 0;
         if ( g < 0 ) g = 0;
         if ( b < 0 ) b = 0;
            if (r > 255) r = 255;
            if (g > 255) g = 255;
            if (b > 255) b = 255;

            Color col = Color.FromArgb(255, r, g, b );
            return col;
        }

  
  public YIQ ToYIQ()
  {
   YIQ yiq = new YIQ(
    0.2990 * r + 0.5870 * g + 0.1140 * b,
    0.5959 * r - 0.2750 * g - 0.3210 * b,
    0.2065 * r - 0.4969 * g + 0.2904 * b );
   
   return yiq;
  }
 }
 
 // YIQ表示系クラス
 // y: 輝度
 // i: 青み成分
 // q: 赤み成分
 public class YIQ
 {
  public double y;
  public double i;
  public double q;
  
  public YIQ()
  {
   y = i = q = 0.0;
  }
  public YIQ( double y, double i, double q )
  {
   this.y = y;
   this.i = i;
   this.q = q;
  }
  
  public RGB ToRGB()
  {
   RGB rgb = new RGB(
    1.001 * y + 0.955 * i + 0.622 * q,
    0.999 * y - 0.272 * i - 0.648 * q,
    1.004 * y - 1.106 * i + 1.704 * q );
   return rgb;
  }
  public HSV ToHSV()
  {
   HSV hsv = new HSV();
            hsv.h = Math.Atan2(i, q);
            hsv.s = Math.Sqrt(i * i + q * q);
   hsv.v = y;
            return hsv;
  }
 }
 
 // HSV表示系クラス
 // h: 色相
 // s: 彩度
 // v: 輝度
 public class HSV
 {
  public double h;
  public double s;
  public double v;
  
  public HSV()
  {
   h = s = v = 0.0;
  }
  public HSV( double h, double s, double v )
  {
   this.h = h;
   this.s = s;
   this.v = v;
  }
  public YIQ ToYIQ()
  {
   YIQ yiq = new YIQ();
   yiq.y = v;
   yiq.i = s * Math.Sin( h );
            yiq.q = s * Math.Cos(h);
            return yiq;
  }
 }
}

次回は、背景から動体抽出ですね~。

カテゴリー: 雑談 | Zaku認識(2) はコメントを受け付けていません

GNUstepでobjective-cを学ぶ(3)

ひとつ、objective-cのメソッド記述について、癖があるので書き直しておきます。

先日書いた、class のところ、C++ で言えば、

class A
{
public:
void print( int x );
void print( char *s );
};

なところを、書き換えるとすれば、

@interface A : NSObject
- (void)printInt:(int)x;
- (void)printString:(char*)s;
@end

こんな風に、printInt、printStringのようにメソッド名を変えないといけないのですが、メソッド名の工夫にはルールがあります。

 

– (戻り値)キーワード:(型)引数 キーワード:(型)引数

のようにメソッドが構成されますが、最初のキーワードはcocoaのライブラリを見ると命名ルールがあります。

RGB値を制御する、次のC++のクラスを考えます。

class RGB
{
float _r, _g, _b;
public:
void setColor( float r, float g, float b );
int getRed();
int getGreen();
int getBlue();
};

これを直す場合は、

 

@interface RGB : NSObject
{
float _r, _g, _b;
}
- (void)setColorRed:(float)r green:(float)g blue:(float)b ;
- (float)getRed ;
- (float)getGreen ;
- (float)getBlue ;
@end

のように、「setColorRed」というメソッド名を付けます、、、というか、「setColorRed:green:blue」というメソッド名を付けます、という言い方が正しいです。
と言うのも、区切り方としては、「setColor red:green:blue」のように、メソッド名と最初の引数のラベルを離して考えるのが良いようです。

 

NSMutableString
http://www.gnustep.org/resources/documentation/Developer/Base/Reference/

のドキュメントを見ると、そんな感じで多重定義をしています。

~~~
覚書 mac mini 購入の準備。

Windows マシンから Mac を操作する
http://tokyo.secret.jp/macs/vnc_mac.html

考えてみたら、VNC 接続でもいいんだ。若干もたつくだろうけど、基本は xcode しか使わないし。あと、プログラミングだけならば、telnetで繋ぐ(笑)という荒業もあるし。

ただし、ここで書かれている方法だと、mac の画面上でパスワードを入れないと駄目なので、mac にもディスプレイが必要、という難点がある。

やりたいことは、ディスプレイ無しの windows server に繋げるようにリモート接続したいので、

1.mac mini の電源ON
2.windows マシンからリモート接続して作業
3.windows マシンからリモートで mac の電源OFF

が、できないと困る。
まあ、FreeBSD ベースだから、

1.mac mini の電源ON
2.windows から telnet ログインして vnc サーバ立ち上げ
3.windows マシンから vnc 接続して作業
4.windows マシンから mac mini の電源OFF

でも、できるんでしょう。多分。

カテゴリー: 開発, Objective-C | GNUstepでobjective-cを学ぶ(3) はコメントを受け付けていません

GNUstepでobjective-cを学ぶ(2)

objective-cクラスメソッドの使い方で、多重定義のところが腑に落ちなかったのですが、一応氷解したので、記録として。

C++ の場合、次のようにメソッドの多重定義ができます。

class A
{
public:
void print( int x );
void print( char *s );
};

int型の引数を持つ場合と、char*型の引数を持つ場合の関数を「print」という同じ名前が使えるわけです。C言語の場合は「printInt」、「printString」なんて名前を変えないといけないので、この多重定義は名前を定義する際に非常に重要な機能なのです。

 

これを、「素直」にobjective-c の文法に直そうとすると、

@interface A : NSObject
- (void)print:(int)x ;
- (void)print:(char*)s ;
@end

と書きたいところですが、、、できません。名前が重複してる(duplicate declaration of method ‘-print:’)なるエラーが出ます。

 

実は、objective-cのメソッドの書き方は、

– メソッド名 :(型)仮引数 :(型)仮引数 ;

なのかと思い込んでいたのですが、実は違います。
最初の単語も含めて、キーワードと仮引数のペアなんですなぁ。

– キーワード:(型)仮引数 キーワード:(型)仮引数 ;

と考えるのが正しいのです。
で、objective-cの場合は、型の違いをチェック判別せずに、キーワードの違いで判別します。そんな訳で、

– print:(int)x :(int)y ;
– print:(int)x z:(int)z ;

の2つはキーワード無しと、キーワードあり「z」のメソッドとして違いが認識されます。
ですが、最初のキーワードと型のペア

– print:(int)x;
– print:(char*)s;

の2つは、同じ print というキーワードを使っているので「重複(duplicate)」ってな訳で、コンパイルエラーになるのです。

# objective-c のサンプルコードを見て、妙なメソッドの名前の付け方をしてる
# なあ、と思っていたら、そういう理由があったんですね…

#import <stdio.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>

@interface A : NSObject
- (void)print ;
//- (void)print :(void) ;  // できない
- (void)print:(int)x ;
//- (void)print:(char*)s ;  // 重複するためできない
- (void)print:(int)x  :(int)y ;
- (void)print:(int)x z:(int)z ; // キーワードで区別できる
@end

#if 0
// C++の場合

class A
{
public:
// void print();
void print( void );  // print()と同じ意味
void print( int x );
void print( char *s );
void print( int x, int y );
// void pritn( int x, int z ); // できない

};
#endif

@implementation A
- (void)print {
printf(&quot;in print\n&quot;);
}

- (void)print:(int)x {
printf(&quot;in print x\n&quot;);
}

- (void)print:(int)x :(int)y {
printf(&quot;in print x y\n&quot;);
}
/*
- (void)print:(char*)s {
printf(&quot;in print s\n&quot; );
}
*/
- (void)print:(int)x z:(int)z {
printf(&quot;in print x z\n&quot;);
}

@end

int main( void )
{
printf(&quot;hello3.m\n&quot; );

A *a = [A new];
[a print];
[a print :1];
[a print :1 :2 ];
[a print :1 z:2 ];
[a release];
return 1;
}
/** 実行結果

hello3.m
in print
in print x
in print x y
in print x z

**/

そんな訳で、ひとつの引数だけの場合は、実質、多重定義ができません。C言語のように「printInt」、「printString」としてメソッド名で区別をさせます。

 

# 実に「対称性」が悪い!と思うのは私だけではないハズ。
# ただ、objective-cの発祥時期を考えると、Cリンケージの考慮から、こういう形に
# なっているのだと思う。リンカーに対して厳密な名前を使うC++に対して(C言語自体
# のリンケージはかなり緩い)、objective-cはそのままC言語のリンクを使うように
# したので、こういう結果になったのでは?

カテゴリー: 開発, Objective-C | GNUstepでobjective-cを学ぶ(2) はコメントを受け付けていません

GNUstepでobjective-cを学ぶ(1)

昨日、cygwinでobjective-cを学ぼうとしましたが、無理でした(笑)。
最終的に、iPadのプログラミングをしたいので、NSStringクラスなりの、mac osxで動くobjective-cでないと駄目なので、、、GNUstepを使うこうとにします。

実は、GNUstepに入っているobjective-cだけを使うのであれば、何処の環境でもいいわけですが、何故かmingwしか対応していません。cygwinには未対応です、と明言されています。

WinwdowsでObjective-C パート2 (NS~クラスも利用可) : ページアウトされた記憶の残骸
http://take-blizzard.cocolog-nifty.com/blog/2009/01/winwdowsobjecti.html

なところから、Windows版のものをインストールします。

GNUstep Windows Installer
http://www.gnustep.org/experience/Windows.html

cygwinと同じで、「c:\GNUstep」のディレクトリ配下に全てファイルが作られるので安心です。

Windowsのコマンドプロンプトから使うのであれば、以下にパスを通しておきます。

C:\GNUstep\mingw\bin\
C:\GNUstep\GNUstep\System\Tools\

そして、ビルドする場合は、以下のようなバッチファイルを作るとok。

gcc -o %1 %1.m
-I c:/GNUstep/GNUstep/System/Library/Headers
-L c:/GNUstep/GNUstep/System/Library/Libraries
-lobjc
-lgnustep-base
-fconstant-string-class=NSConstantString
-enable-auto-import

mingwのコマンドラインを使う場合は、

export INCLUDE=/GNUstep/System/Library/Headers
export LIB=/GNUstep/System/Library/Libraries
export CFLAGS=’-fconstant-string-class=NSConstantString  -enable-auto-import’

と環境変数を設定しておいて、

gcc -o hello hello.m -lobjc -lgnustep-base -I $INCLUDE -L $LIB $CFLAGS

とすればok。

# 本来ならば、gccの環境変数を使えばいいんだろうけど、
# 何故か INCLUDE などを参照してくれない。
# ubuntu とかは大丈夫かな?

そんな訳で、準備ができたら、以下のソースがビルドできます。

#import <stdio.h>
#import <Foundation/Foundation.h>
#import <Foundation/NSObject.h>

@interface Point : NSObject
{
int _x, _y ;
}
- (void)set :(int)x :(int)y ;
- (void)print ;
@end

@implementation Point
- (void)set :(int)x :(int)y {
_x = x;
_y = y;
}

- (void)print {
printf(&quot;%d %d\n&quot;, _x, _y );
}
@end

int main( void )
{
id str = @&quot;hello objc++&quot;;
NSLog( str );

Point *pt = [Point new];
[pt set :10 :20 ];
[pt print];
[pt release];
return 1;
}

実行結果がこれ。

$ ./a
2010-02-04 14:47:38.815 a[6820] hello objc++
10 20

無事に、@付きのNSStringが使えます。
この手の基本的なクラス(Foundation/Base API)は、GNUstepのwikiで見ることができます。
# Xcodeなんかのヘルプでは別に参照があるんだろうけど。

GNUstepWiki
http://wiki.gnustep.org/index.php/Foundation

そんな訳で、windowsのコマンドラインでobjective-cがコンパイルできる環境が整った、と。

お次は、unit testですね。

OCUnit
http://www.sente.ch/software/ocunit/
http://homepage.mac.com/mindtools/OCUnitHowTo.html

なものを使うそうです。これは後日。

追記 2011/12/31

clang+llvm で objective-c 2.0 をコンパイルする | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/2252

gnustep だと @property が使えないので、objective-c のクラスの練習(あるいは、コーディング時)にちょっと困ります。なので、llvm もしておくのがベターです。

カテゴリー: 開発, Objective-C | 2件のコメント

cygwinでobjective-cを学ぶ(1)

iPadの開発を目指して、思い付き、objective-cを始めました。思い付きなものだから、途中でやめるかもしれないし、三日坊主かもしれないし、と。まぁ、C/C++/C#/Java以外の言語体系を学んでおくのも悪くないでしょう。

■cygiwnでobjective-cをインストール

そんな訳で、手元にはmacがありません(苦笑)ので、cygwinを使って、objective-cを勉強します。最終的には、Xcodeを使ってmac上で作らないと駄目なのですが、文法なところとかロジックのテストなところとか、そういうOSに関係ないところは、どの環境でもできるはずなので手元のwindows環境でやります。

Objective-CをWindowsで利用するために
http://take-blizzard.cocolog-nifty.com/blog/2009/01/objective-cwind.html

なところで、objective-cのインストールについて説明があります。
cygwinのDevelカテゴリの「gcc-objc」をインストールします。

コンパイルするときは、

gcc sample.m

ですね。クラスを使うときは、objc ライブラリを必要とするので、

gcc sample.m -l objc

とします。

ひとまず、

#import <stdio.h>
#import <objc/Object.h>

int main( void )
{
printf(&quot;Hello objective-c World.\n&quot;);
return 0;
}

がコンパイルできればOKです。

# printf関数を使っているところが弱いですが。
■文法のお勉強

文法に関しては、C++/C#/Javaのいずれかを理解していると学習が早いでしょう。
というか、いきなり objective-c を学ぶのは辛いかな、と。C言語を学んだあとに、引き続き objective-c に進むか、C++ から鞍替えするかがいいと思います。

Objective-C入門
http://wisdom.sakura.ne.jp/programming/objc/index.html
Objective-C Beginner’s Guide
http://www.otierney.net/objective-c.html
Objective-CをWindowsで利用するために: ページアウトされた記憶の残骸
http://take-blizzard.cocolog-nifty.com/blog/2009/01/objective-cwind.html

あたりを参照しながら、ゆっくりと進むのがいいでしょう。

オブジェクト指向言語なので、基本はC++やJavaなんかと同じです。
書き方が微妙なところがあるので、そのあたりが迷いますが、頭の中に対応表を持っておけば、直ぐに慣れるでしょう。
# メソッド呼び出しに [obj method] っていう括弧を使うのが、うーむって感じなのです。smalltalk がそうなのかな?

クラスに関しては、ざっと記述すると、こんな感じになりますね。

#import <stdio.h>
#import <objc/Object.h>

@interface Point : Object
{
// インスタンス変数
int _x, _y;
}
// クラスのメソッド
- (void)init ;
- (void)print;
- (void)setPoint:(int)x:(int)y;
- (int)add;
- (int)getX;
- (int)getY;
@end

@implementation Point
// コンストラクタ
- (void)init {
[super init]; // 親クラスのコンストラクタを呼び出し
}
// 引数のない関数
- (void)print {
printf(&quot;x:%d y:%d\n&quot;, _x, _y );
}
// 引数のある関数
- (void)setPoint:(int)x:(int)y {
_x = x;
_y = y;
}
// 戻り値を使う
- (int)add {
return _x + _y;
}
// プロパティ扱い
- (int)getX {
return _x;
}
- (int)getY {
return _y;
}
@end

int main() {
// インスタンスを生成
Point *pt = [Point new];
// メソッド呼び出し
[pt setPoint: 10: 20 ];
// メソッド呼び出し
[pt print];
// プロパティ呼び出し
printf(&quot;x:%d y:%d\n&quot;, [pt getX], [pt getY] );
// 戻り値を使う
int ret = [pt add];
printf(&quot;ret:%d\n&quot;, ret );
// 解放
[pt free];

return 0;
}

メソッドの定義と呼び出しが、C言語と違って妙な感じですが、まぁ、これも慣れですね。C言語の関数を使わなければ、[obj method: p1: p2]な形が羅列されるので、それほど違和感はないかもしれません。

■NSStringの問題

と、ここまで書いてですね、iPhone SDKでは「NSString」という文字列クラスが多く使われているのを思い出しました。調べてみると、cygwinのobjective-cには NSString がありません。

困った…
こういう場合は、GnuStep をダウンロードしてきて、やるか。
http://www.gnustep.org/

cygwin版のNSStringを作ってしまうか、ですね。

http://osdir.com/ml/lib.gnustep.user/2001-09/msg00030.html
にあるように、gnustep-objc-1.0.1.tar.gz をダウンロードして、cygwinのgccでビルドして使うってのもありですが、、、ちょっと大袈裟だなぁ。

# Windows環境で試す意義としては、学習用とビジネスロジック作成にあるので、
# 文字列クラス程度であれば、スタブで用意しておくのがいいでしょうねぇ。
# ユーザーインターフェースなんかは、結局 interface builder を使わないと
# 駄目だかろうから、mac osx 上でないとできないだろうし。

あぁ、それでもって、cygwinのobjcを使って、nsstringもどきを作ろうとしたのですが、どうもcygwinのobjcはコンパイルの動きが違うようです。多重定義ができない、というかメソッドの引数にラベルを使えない。このあたりは後日。

先の例で言えば、

– (void)setPoint:(int)x:(int)y;

は可能だけど

– (void)setPoint x:(int)x y:(int)y;

ができません。ややこしいこっちゃ。

★追記

ひとつ目の引数には名前がつけられないらしい。

– (void)setPoint :(int)x y:(int)y;

だと、通りますね。

追記 2012/01/03
という訳で、cygwin でも objective-c の学習はできるのですが、本来の目的が iphone/ipad プログラミングの場合は、GNUstep + clang + llvm という組み合わせになります。以下のページを参照してください。

Windowsで学ぶObjective-C | Moonmile Solutions Blog
http://www.moonmile.net/blog/article/windows-objective-c

 

 

カテゴリー: 開発 | 2件のコメント