vieweditattachhistorytopchangessearchhelp

Genie その1(基本)

Genie はベースはひと筆手書き文字認識エンジンですが、メッセージ式の評価のトリガーにも使えるので文字入力だけでなくモーフやウインドウを画面に呼び出したり、もっと複雑なことをさせることも可能です。Palm の Graffiti のおばけ、もしくは、ひと筆書きジェスチャ認識エンジン+アルファといったところでしょうか。いくつかのサンプル辞書が提供されていますが、結局自分好みに学習させ直す必要があるので最初から自分で作ったとしても手間としてはそれほど変わりません。--sumim - 2003-01-06, 15:55:56

Genie はまず、デスクトップメニューの Help... から eneble genie を選択して起動しておきます。まだ辞書がない状態なので、何も変わった様子はないと思います。続けて同じメニューすぐ下の genie gesture dictionaries を選択して辞書管理用モーフを開きます。--sumim - 2003-01-06, 16:06:11

External Image

辞書はまだないので、Empty と書かれているはずです。New ボタンを押すと新しい辞書を作ることができます。この画面でジェスチャー登録以外のいくつかの設定をしておきます。ひとつは辞書名の登録で Name の右側の入力欄をクリックしてアクティブにし、適当な名前を入力して return キーもしくは cmd-s を押して accept します。ここでは JinroTest とでもしておきましょうか。もうひとつは、これは本質的で、どんな種類のモーフの上でジェスチャー認識機能を可能にするかを指定するための Exported Name です。ここでは、ジェスチャーによる文字入力の様子をテストするため、Text と入力して accept します。最後に下にある Accept ボタンをクリックして設定を終わります。--sumim - 2003-01-06, 16:12:04

External Image

External Image

続けてジェスチャーの登録に移ります。2段目の Browse タブをクリックして切り換えます。やはりジェスチャーもなにも登録されていないので Empty とでるはずです。下段の New ボタンをクリックするとどんな文字を入力するためのジェスチャーを登録するかを訪ねる FilInTheBlank が表示されます。ここでは a を入力するためのジェスチャーを登録するので a とタイプして accept します。a 入力用のジェスチャーフォルダができるので、ピンクの枠内で a を入力するためのジェスチャーを描いた後、Add ボタンを押して登録します。--sumim - 2003-01-06, 16:16:53

External Image

これで辞書とジェスチャーの登録が終わるので、あとは Workspace などの適当な場所で登録したのと似せたジェスチャーを描くと、a が入力されるはずです。--sumim - 2003-01-06, 16:18:59

External Image

>メッセージ式の評価のトリガーにも使える
そうでしたか.当初,Genieは一筆書き文字認識エンジンだと考えていましたので,Sqewtonでスクラブ出来ているのが理解出来ませんでした.なるほど,評価のトリガーになれるのであれば,事実上何でもありなのかも.--人狼 - 2003-01-06, 17:13:00

早速aを登録してWorkspaceで試してみました.大丈夫みたいです.--人狼 - 2003-01-06, 17:16:59

>New ボタンを押すと新しい辞書
と言う事は,辞書は何種類も用意して使い分ける事が出来るのでしょうか?--人狼 - 2003-01-06, 17:17:51

先回りだったら,ごめんなさい.グラフィティのように,Shift状態にする,と言う事も出来るのでしょうか?--人狼 - 2003-01-06, 17:36:37

>辞書は何種類も用意して使い分ける事が出来るのでしょうか?
できます。が、別の辞書に同じ Exported Name を持たせることはできないようです。Exported Name には原則としてそのジェスチャを認識させたいモーフのクラス名を入力します。なので1モーフ1辞書で、モーフごとの辞書の切り換え…となります。ただ、Exported Name はクラス名の一部をしてそれに代えることができ、同じ文字列を含む複数のクラス(たとえば例のように Text とすると、
Smalltalk allClasses select: [ :c | ('*Morph' match: c name) and: [(c name findString: 'Text') > 0]]
なクラス群)に属するモ[フを対象にできるので、この機能を使って複数のモーフに対して同じ辞書を用いることは可能です。
--sumim
- 2003-01-06, 17:39:28

>同じ文字列を含む複数のクラスに属するモーフを対象
すみません。これは大嘘でした。原則としてモーフのフルネーム、一部のテキスト系のモーフに関しては、Text という特殊な Exported Name を持った辞書への反応が可能なようにハードコードされている…ってだけでした(^_^;)。--sumim
- 2003-01-06, 18:45:59

あと、Exported Name で指定したクラス以外に、そのサブクラスのモーフに関しても辞書は適用されるようです。MenuMorph とすると、MVCMenuMorph でも動きます。--sumim - 2003-01-06, 18:53:08

>1モーフ1辞書で、モーフごとの辞書の切り換え
なるほど.了解しました.sumimさんの手書き辞書と,人狼の手書き辞書が共存できるわけではなくて,モーフ毎に辞書を用意するという事なのですね.--人狼 - 2003-01-07, 13:11:40

>原則としてモーフのフルネーム
了解いたしました.わざわざ調べて頂き,有り難うございます.--人狼 - 2003-01-07, 13:12:28

>サブクラスのモーフに関しても辞書は適用されるよう
Genieから入力を受け取るところ,とか辞書を参照するところ,のような部分はクラスで実装してるんだから継承されている,って事になるのでしょうかね.サブモーフに独自の辞書を割り当てると,どうなるのかな?ちょっと後で試してみようかな.--人狼 - 2003-01-07, 13:15:24

モーフならなんでもいいか…というとそうではなく、たとえば Exported Name を Morph にしてもジェスチャーを受け付けないウィジェットもあるようです。きっと Genie を受け付けるかそうでないかという違いがあるのでしょうね。--sumim - 2003-01-07, 14:19:33

>グラフィティのように,Shift状態にする
新しいジェスチャーを登録するときに現われる FillInTheBlank の黄ボタンメニューには通常のアルファベットの他に、キーボードの特殊ボタンやある種のマウス操作などを登録するためのコマンド( # で始まる、っちゅうかシンボルのリテラル)の記入補助を行なうメニュー項目が用意されています。この Modifier-keys の #capsLock を選んで適当なジェスチャーを割り当てると、caps lock をシミュレート( shift 状態に)できます。残念ながら Genie では Graffiti のように上方向へのスクラッチ2回、というようなジェスチャーは割り当てられないので、私は Graffiti の shift に相当するジェスチャーにしています。なお、Text-editting の #changeCase とすると最後に入力した文字フ大カ字小文字を切り換えられます。ちょっと先走りますが、Graffiti のような caps lock 操作や、Newton のような選択文字列の大文字小文字、キャピタルワードの切り換えについてもできないわけではなく、後で説明するスクリプトの組み方しだいでできるようになります。--sumim
- 2003-01-07, 14:31:28

既存のジェスチャーについて、その役割りを変更するには、そのジェスチャーの名称部分をクリックし FillInTheBlank を呼び出して行ないます。--sumim - 2003-01-07, 14:33:02

>Genieを受け付けるかそうでないかという違い
ジェスチャーを受け付けないウィジェットもあるのでしたら,そう言う事になりますね.安直に「Genie」でcmd-Eしても,それっぽいのはありませんでした.--人狼 - 2003-01-07, 15:13:16

>キーボードの特殊ボタンやある種のマウス操作などを登録するためのコマンド
見てみました>黄ボタンメニュー.色々と(本当に驚いてます)出来るのですね.
>caps lockをシミュレート(shift状態に)
迷ったのですが,caps lockではなくて,shiftにしたいと思います.「次の一文字だけshiftね」って言う方がGraffitiっぽいので.あまりGraffitiでcaps lock使わないもんで(汗)
>後で説明するスクリプトの組み方しだい
スクリプトで,可能性はどんどん広がりそうですね.その反面,しっかり勉強しないと.--人狼 - 2003-01-07, 15:26:05

>既存のジェスチャーについて、その役割りを変更
してみました>変更.これは問題ありませんでした.--人狼 - 2003-01-07, 15:27:56

ではコマンドの例をひとつ挙げてみましょう。Mouse & Halo の #blueClick は青ボタンクリック、つまりモーフの選択をシミュレートするコマンドです。ホットスポットを青ボタンクリックしたのと同じ効果を得ることができます。ホットスポットは通常、ジェスチャーの開始点ですが、これはジェスチャー登録時に現われる M ボタンから、Hotspot サブメニューよりいくつかの中から選択して切り換えられます。例えば周囲から中心に向かう渦巻き状のジェスチャーに対し、最後の点をホットスポットとして登録すると、マウスボタンを放した時にポインタが置かれた場所を青ボタンクリックしたことにできます。このコマンドを割り振ったジェスチャーを PasteUpMorph に対して Exported した辞書に登録しておくと、ジェスチャーでモーフの青クリックができるようになります。これはよく利用する青ボタンにいちいち cmd キーを押し下げなければならないワンボタンマウスの場合はもちろん、Sqewton では特にペン操作のとォにュ力なサポートをしてくれます。ペン操作ではウインドウの大きさの調節もままならないので、モーフとしていったん選択して黄ハローボタンをドラッグするととても快適に扱えます。--sumim - 2003-01-07, 16:23:14

External Image

>ちょっと後で試してみようかな
はまりました(汗)例えばTextのサブクラスを作ったとしても,どうやってそれを使えばよいか判りません(大汗)TextJinrouなるサブクラスを作って,TextJinrou newとやっても,インスタンスは出来てるかも知れませんが,一体どこにテキストフィールドが(大汗)--人狼 - 2003-01-07, 16:26:30

Text ってのがちょっとまずかったですね。ここで Text というのは単なるテキスト関連のモーフをいっしょくたに扱うための Exported Name 用のシンボルとして使われていて、これと同名のフォントやサイズなどの情報を持つことができる文字列のクラスとは無関係です。したがって、Text のサブクラスを作っても、これはモーフではないのでインスタンスを直接見ることも、ましてジェスチャーをためすことも難しいと思います。もし、試されるのでしたら TextMorph というのがありますので、これのサブクラス JinroTextMorph などを作ってみてはいかがでしょうか。これなら、クラスペインのシフト黄ボタンメニューにある sample instance で grab することができます。もちろん、
JinroTextMorph new newContents: 'test string'; openInHand
とでも。--sumim
- 2003-01-07, 16:45:12

>コマンドの例をひとつ挙げて
なるほど,これは便利ですね.おっしゃっておられるように,一々cmdキーを押下するのが大変でしたので,これはありがたいです.
ところで…ジェスチャーの登録の方法で疑問が出てきました.さきほど「a」を登録した時は,Newをクリックして,出てきたFillInTheBlankに「a」と入力してaccept,ピンクの枠内でジェスチャーを描いてAddでしたよね.これで確かに登録出来ました.そして次にFillInTheBlankで「b」として,ピンクの枠内で「b」を描いてマウスのボタンを離すと左に「b」が,右に「a」の時のジェスチャーが表示されます.何がよろしくないのでしょう?--人狼 - 2003-01-07, 17:19:37

>ここでTextというのは単なるテキスト関連のモーフをいっしょくたに扱うためのExported Name用のシンボル
あれ?Exported Nameにはクラス名を記述するのではありませんでしたっけ?ソょっと混乱してるかも,私(汗)
おっしゃってらっしゃる通り,Textはモーフではないですね.これは失礼しました.TextMorphで後ほど試してみます.--人狼 - 2003-01-07, 17:23:21

>右に「a」の時のジェスチャ[ェ表示
これは単に、登録されたジェスチャーにこんなんもありますよ…という意味だと思っています。あまりに似たものを登録した場合、混同される可能性があることを示唆しているものかと。--sumim
- 2003-01-07, 17:26:26

>あれ?Exported Nameにはクラス名を記述するのではありませんでしたっけ?
原則としてクラス名を書きます。ただ、Text とするとテキスト関係のモーフ(StringMorph、TextMorph、PluggableTextMorph など)で利用できるようになります。なので、テキスト入力編集用の辞書は Text として Export しておくのがよいようです。--sumim
- 2003-01-07, 17:28:26

>登録されたジェスチャーにこんなんもありますよ
了解です.ちょっと紛らわしいですね(汗)ちなみに,sumimさんが#blueClickやaを登録されている時は,二つ手描きのジェスチャーがありますが,これは二回Addしたと言う事で良いのでしょうか?(サンプルが多い方が認識率があがる,とかそう言う理由でしょうか?)--人狼 - 2003-01-07, 22:34:36

>Text とするとテキスト関係のモーフ(StringMorph、TextMorph、PluggableTextMorph など)で利用できるようになります
失敬しました.これが,上述頂いたハードコードの部分でしたね.すっかり失念していました.申し訳ありません.
ところで,sumimさんと辞書の登録状態をあわせておきたいのですが,CapsLockとアルファベット26文字まででよいですか?--人狼 - 2003-01-07, 22:36:14

>TextMorphで後ほど試してみます
やってみましたが…予想通り,期待した結果になりませんでした.(わけわからんすね)
期待した結果:モーフに辞書を割り当てて,そのサブモーフには別な辞書を割り当てると,サブモーフは新しい辞書で理解する.
予想:Text関係はハードコートされているので,サブモーフであろうとTextの辞書を参照するので,何も変わらない.
で,予想通りの結果でした.ちゃんちゃん--人狼 - 2003-01-07, 22:42:40

>これは二回Addした
そうです。たいてい何度か気分を変えて登録するようにしています。--sumim
- 2003-01-08, 00:20:53

>CapsLockとアルファベット26文字まで
辞書はそのうちアップしておきますので、そちらをベースに作り直していただいてもいいですし、この機会に作り込んでいただいてもかまいません。とりあえず、モーフ描画用iPasteUpMorph 用)辞書とテキスト用辞書を分けておけば問題はないかと思います。--sumim
- 2003-01-08, 00:23:35

>サブモーフであろうとTextの辞書を参照する
いや。そういうテストなら、Exported Name は Text とせずに、TextMorph としておけばいいのではないでしょうか? それでサブモーフ(例えば JinroTextMorph )用には別の JinroTextMorph という Exported Name を付けた別の辞書を用意する…としてみてください。--sumim
- 2003-01-08, 00:26:20

それとも Text という Exported Name の辞書をオーバーライドしたい…ということでしょうか?--sumim - 2003-01-08, 00:28:34

まあいずれにせよ、ここで TextMorph を使うのもうまくなかったみたいです。ごめんなさい。TextMorph >> #defaultGestureDictionaryOrName による Morph >> #defaultGestureDictionaryOrName のオーバーライドを許しているかぎり、謎の動きをすると思います。試しにこれを外すと TextMorph とその自作サブクラスに関しては期待通りの動きをしてくれるようになります。ただ、TextMorphForEditView が TextMorph のサブクラスであるにもかかわらず、TextMorph という Exported Name の辞書を認識しません。どうやら PluggableTextMorph に embed されるとこういう傾向を示すようです。--sumim - 2003-01-08, 01:02:01

>どうやら PluggableTextMorph に embed されるとこういう傾向を示す
ちょっとずつ謎が解けてきました。TextMorph >> #gestureHandler というのがあって、ここでテキストモーフが PluggableTextMorph のサブモーフの場合の例外処理をしています。これも外すと完璧に期待どおりの(まあ、当たり前ですが Morph >> #defaultGestureDictionaryOrName に記述されているとおりの、つまり Exported Name にクラス名かスーパークラス名が一致すればその辞書を適用するという)動きをしてくれるようになりました。もちろんこの場合、Text という Exported Name を付けた辞書は、Text のインスタンスがモーフでないという先の理由からいかなる状況においても参照されることはなくなり、意味を持たなくなります。--sumim
- 2003-01-08, 01:17:07

>何度か気分を変えて登録する
了解しました.(Safariによる初カキコでし)--人狼 - 2003-01-08, 11:02:19

>この機会に作り込んでいただいても
Genieのアクションに自分が慣れる為にも作り込んだ方が良いのかもしれませんDと閧?えずアルファベットは登録したのですが,数字をどう書くか悩んでいます(笑)
>モーフ描画用(PasteUpMorph 用)辞書とテキスト用辞書を分けて
了解です.#blueClick等はPasteUpMorph用で,と使い分ければ良いのですね.--人狼 - 2003-01-08, 11:05:05

>ちょっとずつ謎が解けてきました
済みません,私がだらだらと寝ている間に色々と調べて頂きまして.私のちょっとした好奇心からお手数をおかけしました.時間に余裕のある時に,ご呈示頂いた箇所を試してみたいと思います.--人狼 - 2003-01-08, 11:11:56

>Safariによる初カキコ
ちっ、先を越されたか(笑)。--sumim
- 2003-01-08, 12:16:18

>私がだらだらと寝ている間に色々と調べて頂き
ど〜せキーノートのついでがありましたし(笑)。もっとも肝心の新発表の前に退屈して寝てしまいましたが<バカ--sumim
- 2003-01-08, 12:17:34

>数字をどう曹ュか
そうですね。Graffiti の数字枠ならぬ、数字モードというのもひとつの手かもしれませんね。一筆書きの限界をどう克服するか…が課題になりそうです。--sumim
- 2003-01-08, 12:21:52

>先を越されたか(笑)
すみません(笑)結構使い勝手が良いです>Safari.一部のサイトを表示出来なかったり,日本語の表示に乱れがあったりもしますが,Chimeraよりは安定していますね.しかし,なぜAmazon.co.jpとセキュアな通信が出来ないのかなぁ.--人狼 - 2003-01-08, 12:46:26

>キーノートのついでがありました
ご覧になっていたですか.昨夜は眠気に勝てずに諦めてしまいました.
>肝心の新発表の前に退屈して寝てしまいました
それもまた,何とも(笑)--人狼 - 2003-01-08, 12:47:42

>一筆書きの限界をどう克服するか…が課題
う〜ん,数字モードと言う物を作る方法も判らな「のですが(汗)確かに一筆書きで,どう数字を表現するかは難しい問題ですね.--人狼 - 2003-01-08, 12:49:21

>数字モードと言う物を作る方法も判らない
まあ、これは簡単にはまいりませんので忘れてください。では、これに絡めてコードをジェスチャーに登録してみましょうか。コードはコマンド同様に # を使って明示的にします。#ジェスチャー名#コード という具合です。コードが短いメッセージ式ならジェスチャー名を省きそれ自身をジェスチャー名として表示させることもできます。
#beep#Smalltalk beep
##Smalltalk beep
とか。--sumim
- 2003-01-08, 15:55:42

たとえば、
#openWorkspace#Workspace openLabel: 'Genie'
というコマンドを書くと、そのジェスチャーで Genie というタイトルのワークスペースを開くことができます。--sumim
- 2003-01-08, 15:58:28

2番目の # 以下を do-it しているだけのようなので、一時変数宣言もできるようです。また、ここで
##inspect self
##self inspect
とすると分かるように、self でジェスチャー(CRGesture)を参照できます。ジェスチャーは coodinate に CRRecognizerCoordinates というホットスポットなどに関する情報を有するオブジェクトを束縛しているので、さらにこれに start、end などのメッセージを送信することで、ジェスチャーの特徴点やジェスチャーの bounds ??セるアとができます。--sumim
- 2003-01-08, 16:04:35

>コードが短いメッセージ式ならジェスチャー名を省きそれ自身をジェスチャー名
ご呈示頂いた例を見ると,beepと言うメッセージ自身をジェスチャー名としているのですよね?メッセージ式が2つの単語以上で構成されている場合は,どうなるんでしょう?基本的には明示的にジェスチャー名を指定するのが良いのかもしれませんね.--人狼 - 2003-01-08, 17:11:49

>一時変数宣言もできるよう
えっと(汗)これは,どうやって確かめれば良いのでしょう?Workspaceでは宣言しなくても一時変数が使えてしまいますよね,確か.--人狼 - 2003-01-08, 17:23:59

>##inspect self
とすると,MessageNotUnderstoodと怒られてしまいます(泣)--人狼 - 2003-01-08, 17:26:33

寝ぼけていました。##self inspect です。しかしこれはうがってみればトラップともいえるわけで、ノーティファイアで驚かれたまま打つ手なしというのではちょっと寂しいものがあります(笑)。お互い正月ぼけがまだぬけきれていないようで(^_^;)。--sumim - 2003-01-08, 17:32:40

>メッセージ式が2つの単語以上で構成されている場合
ながったらしいジェスチャー名になるのではないかと(^_^;)。ただ、ジェスチャー名を他から参照するなどすることはないと思うので実害はないと思われます。--sumim
- 2003-01-08, 17:35:02

>Workspaceでは宣言しなくても一時変数が使えてしまいます
Workspace で宣言しない場合はワークスペース変数になります。一時変数の場合は | | でくくって do-it したい文字列の先頭で宣言します。--sumim
- 2003-01-08, 17:36:24

>beepと言うメッセージ自身をジェスチャー名としている
いえ。beep だけでなく、Smalltalk beep というメッセージ式自体がジェスチャー名として表示されます。--sumim
- 2003-01-08, 17:37:36

>ノーティファイアで驚かれたまま打つ手なしというのではちょっと寂しい
いや,まったくもって面目ありません.いかんですな.烽、少オ目を覚まウないと.すみません.--人狼 - 2003-01-08, 17:55:17

>ながったらしいジェスチャー名になるのではないか
試してみました.長ったらしくなりました.--人狼 - 2003-01-08, 18:00:41

>Workspace で宣言しない場合はワークスペース変数になります
そうでした,ますますもってリハビリの必要性を感じております.つまり,ジェスチャーに割り当てるコードの中で使う一時変数を宣言出来ると言う事ですよね.理解力が足りてないですね.--人狼 - 2003-01-08, 18:02:15

コードのジェスチャー名は、キーボードイベントやコマンドの場合と違って、ジオングの足みたいなもんです(笑)。--sumim - 2003-01-09, 00:43:18

>ジオングの足みたいなもん
あんなものただの飾りですよ. 偉い人にはそれがわからんのです .……偉い人って…誰?(そう言う問題ではないだろ!>自分)--人狼 - 2003-01-09, 07:39:24

さて.「今まで色々といぢったので,Sqewtonプロジェクトに向けてイメージファイル凾?炎?サしてヘH」との助言を頂きましたので,オリジナルに戻しました.そこに,sumimさんに作って頂いたパッチを二つとも適用しまして,その後で辞書をチマチマ作りました.昨日のRectangleMorphの例を参考にEllipseも作ってみました.Starはverticesをどうして良いか判らずに現在奮闘中です.(これが判れば,Polygonを使った三角形も作れそう)と,言うわけで途中報告でした.--人狼 - 2003-01-09, 09:45:31

よかったら、ご自作の Ellipse 作成用コードを <code></code> タグで括って書き込んでいただけますか?--sumim - 2003-01-09, 10:24:12

>ご自作のEllipse作成用コード
えっと,恥ずかしながら(汗)まるっきり,昨日のコードのぱくりです.
#EllipseMorph#
EllipseMorph new
	topLeft: self coordinates topLeft;
	extent: self coordinates extent;
	color: Color paleGreen;
	borderWidth: 5;
openInWorld

となりました.--人狼 - 2003-01-09, 10:40:52

よろしいんじゃないでしょうかね。>パクリ EllipseMorph について詳しくやっていない現段階で、これ以外にどう書けっちゅうんじゃってところもありますし(笑)。これを機会に EllipseMorph や BorderedMorph の仲間達のソースを見て、仲良くなっておくのもよいかもmれません。--sumim - 2003-01-09, 10:50:54

>verticesをどうして良いか判らずに現在奮闘中
実は StarMorph はな〜んもしていません(^_^;)。でも良い機会ですので PolygonMorph のもっとも単純な形の LineMorph を描くジェスチャーを例に、PolygonMorph や StarMorph にせまってみましょう。

話は逸れますが、最近クラス名をしてそのインスタンスを指し示す傾向が強まってしまっていますが混乱はないですね?

LineMoprh は LineMorph class >> #from:to:color:width: でインスタンスを作ることができます。したがって、
#LineMorph#
| coordinates |
coordinates _ self coordinates.
(LineMorph from: coordinates start to: coordinates end color: Color black width: 5) openInWorld
でいけます。この場合 openInWorld をカスケード(前のメッセージ式の括弧を省いて ; openInWorld と続ける)にはできないことに注意してください。あと、むりやり一時変数も使ってみました。--sumim
- 2003-01-09, 11:08:37

>よろしいんじゃないでしょうかね
ほっ.良かった良かった.今は気を取り直してStarMorph >> #initialize:を眺めています.pt _ 10@10が,なぜこの値の代入なのか,そして,そもそもptは何と言うオブジェクトなのか調査中です.そすれば,下の計算も判るかなぁ…と.それが理解出来ればstarMorphのジェスチャーは作れそうです.
>EllipseMorphやBorderedMorphの仲間達のソースを見て
こっちにヒントがあるかも知れませんね.眺めてみますです.--人狼 - 2003-01-09, 11:10:02

10@10 を選択して inspect-it でおわかりいただけるように pt に束縛されるのはそのものずばり Point(のもちろんインスタンス)です。x と y、2つのインスタンス変数を持っています。って、そういう話ではなくて?--sumim - 2003-01-09, 11:15:31

この pt は星の“手”の長さとそのひとつの向きを決めています。--sumim - 2003-01-09, 11:30:06
>実は StarMorphはな〜んもしていません
え?そ〜なんですか?う〜ん,アプローチを間違えているかなぁ.--人狼 - 2003-01-09, 11:32:35

>最近クラス名をしてそのインスタンスを指し示す傾向が強まってしまっていますが
今のところ混乱はしていませんが,イ塔XタンXと明示Iにしらしめる記法があるのでしたら,そちらの方がよろしいかと思います.そろそろ書き方も標準…と言うか慣例に則った書き方にすべきでしょうかね?--人狼 - 2003-01-09, 11:34:49

>アプローチを間違えているかなぁ.
いや。公開したり、お見せしたものは…ということです。ここではもうちょっとちゃんとやりましょう。その前に、LineMorph を是非。--sumim - 2003-01-09, 11:35:15

>例に則った書き方にすべき
ではまあ、Object >> #printOn: に従って、a/an でも付けて様子をみましょうか(^_^;)--sumim
- 2003-01-09, 11:38:06

>LineMoprhはLineMorph class >> #from:to:color:width:で
この書き方は判りやすいですね.これで行ってよいですか?
さてさて,一時変数は「こう使います」的サンプルですよね.
>この場合openInWorldをカスケードにはできない
えぇっと,これはLineMorph class >> #from:to:color:width:(クラスメソッド)でインスタンスを作成しているので,クラスにopenInWorldは送れない.出来上がったCンスタンスに送らなくてヘならない,と言うことでしょうか?--人狼 - 2003-01-09, 11:42:45

>そういう話ではなくて?
いえ,そういう話しでした.後ろに続く計算式を理解したいなぁ…と思ったので,pt rrと言うメッセージが知りたかったのです.極座標でした.だめぽ.
>LineMorphを是非
気を取り直して話しをLineMorphに戻します(汗)ジェスチャーの登録はしました.LineMorpht class >> #new:を使わないのは,これでは出現位置がハードコードされているからですね.--人狼 - 2003-01-09, 11:49:08

>出来上がったインスタンスに送らなくてはならない
そうです。EllipseMorph の例では、EllipseMorph new で作った an EllpseMoprh に対してカスケードしているのですね。--sumim
- 2003-01-09, 12:17:34

>これでは出現位置がハードコードされているから
いや、そんなことはないですよ。たまたま(^_^;) from:to:color:width: が見つかったから使っただけです(笑)。もちろん、RectangleMoprh フときのようにしても構わないと思います。--sumim
- 2003-01-09, 12:21:04

LineMoprh class >> #new でおもしろいのは、我々が a LineMoprh だと思っているモーフは実は a PolygonMorph で、a LineMoprh はふつう世の中には存在しないということです。--sumim - 2003-01-09, 12:26:47

new を使うなら、
#LineMorph#
| coordinates |
coordinates _ self coordinates.
LineMorph new
	vertices: {coordinates start. coordinates end}
	color: Color paleGreen
	borderWidth: 5
	borderColor: Color black; openInWorld
こんなかんじになるでしょうか。--sumim
- 2003-01-09, 12:53:45

まあ、これだとメッセージ式の文面はすでに a PolygonMorph がレシーバであることを念頭に置いたものになってしまっているので判読性は落ちるでしょうね。--sumim - 2003-01-09, 12:57:33

すなおに、
#LineMorph#
| coordinates |
coordinates _ self coordinates.
PolygonMorph new
	vertices: {coordinates start. coordinates end}
	color: Color paleGreen
	borderWidth: 5
	borderColor: Color black; openInWorld
でもいいかも。--sumim
- 2003-01-09, 13:05:22

>EllipseMorphの例では、EllipseMorph newで作ったan EllpseMoprhに対して
了解です.EllipseMorph newで作ったan EllipseMorphにtopLeft, extent, color, borderWidth, openInWorldをカスケードで送っていたと言う事ですよね.--人狼 - 2003-01-09, 13:14:07

>そんなことはないです
ありゃりゃ(汗)--人狼 - 2003-01-09, 13:15:13

>実はa PolygonMorphで、a LineMoprhはふつう世の中には存在しない
そうですね.LineMorph class >> #newを見るとself from:to:color:widthとありますので,from:to:color:widthを見るとなんとレシーバーはPolygonMorphだったと言う事で驚きです.でもよくみると,そもそもスーパークラスがPolygonMorphでした.RectangleMorphやEllipseMorphやPolygonMorphのスーパークラスはBorderedMorphですものね.そして,ここまで来てようやくstarMorphの親もPolygonMorphと気付きました.--人狼 - 2003-01-09, 13:21:53

newを使ったコードですが,最初にご呈示頂いたコードは確かにa PolygonMorphがレシーバーでありネがら,私ノはそ黷ェすぐには読み取れ無いかもしれないので可読性と言うお話ですと,ちょっと私にはまだ辛いかもしれません.かと言って,二つ目のコードでa PolygonMorphに対して直接送っているのも「LineMorph classは実はPolygonMorph classだよ」と言う事を,何の説明もなく行ってしまっていますので,やらない方が良さそうな気がします.LineMorph classが実はPolygonMorph classでしたと言うのは,LineMorph class >>#from:to:color:widthの中で行われている事ですので,そこに任せる事としてジェスチャのコードはfrom:to:color:widthを送るのが自然な気がします.もっともこの論では「LineMorph class >>#from:to:color:widthでもPolygonMorphがいきなり出てくるじゃないか」との意見には耐えられませんが,LineMorph classの中だけで完結している出来事なので大目に見てもらうということで.--人狼 - 2003-01-09, 13:29:13

StarMorph は、公開しス辞書やお見せしているデモでは RectangleMoprh などと同じことしかしていません。
#StartMorph#
StarMorph new
	topLeft: self coordinates topLeft;
	extent: self coordinates extent;
	color: Color paleGreen;
	borderWidth: 5;
		openInWorld
デモするとき最終的に描かれる a StarMorph をイメージしてジェスチャーすると、まるでそう描かれたように見えるというからくりです。それではお粗末なので、せめて coordinates start と coordinates の領域の中心((coordinates topLeft + coordinates bottomRight) // 2)の成す角度に星の5本の“手”のうソいずれかの向きが一致するように細工してみるのを課題にしてみましょうか。--sumim
- 2003-01-09, 14:07:57

しかしなんで CRRecognizerCoordinates は Rectangle のサブクラスにしなかったんでしょうねぇ…(^_^;)。そうだったなら中心点は coordinates center で一発なんですが。--sumim - 2003-01-09, 14:12:07

>デモするとき最終的に描かれるa StarMorphをイメージしてジェスチャーする
ぐはっ.やられました.てっきり,角度とか付けてるもんだと思ってました.と思ったらそれが課題になってしまったのですね.
課題にある>coordinates startとcoordinatesの領域の中心の成す角度 のところがよく判りませんでした.点と点の成す角度,と言うのがイメージできませんでした.--人狼 - 2003-01-09, 14:42:03

>(coordinates topLeft + coordinates bottomRight) // 2
ところで,ここで除算演算子のスラッシュが2回あるのはなぜなんでしょう?Workspaceで演算してみると,スラッシュ一つでも二つでも結果は同じみたいなんですが.--人狼 - 2003-01-09, 14:59:52

>なんで CRRecognizerCoordinates は Rectangleのサブクラスにしなかったんでしょうねぇ
む〜,なんででしょうねぇ.どうせ四角い領域だかあRectangleのサブクラスの方が使い勝手は良さそうなんですけどね.ただRectangleを継承すると,いらんもんがいっぱい付いてきちゃいますからね.それを嫌ったのかも知れませんね.しかし,いやしくも「coordinates」と名乗るのであれば,centerくらいは欲しいもんです.--人狼 - 2003-01-09, 15:03:08

>除算演算子のスラッシュが2回
SmallInteger >> #// と SmallInteger >> #/ ですね。前者は商で後者は引数によって分数の生成か除算になります。詳しくはソースを見てみてください。--sumim
- 2003-01-09, 15:07:13

>点と点の成す角度
2点を通る直線の傾きという意味です。成すっちゅうのは確かにおかしいですね(^_^;)。--sumim
- 2003-01-09, 15:08:07

>前者は商で後者は引数によって分数の生成か除算
了解しました.ソースを見てきます.う〜ん,PointなのにSmallIntegerと言うのが直感的にいや〜んな感じです.--l狼 - 2003-01-09, 15:17:17

2点を通る直線の傾き
了解しました.ちょっと悩んでみます.さっきお手上げしたStarMorph >> #initialize: 中の計算をまじめに考えないとだめかぁ.--人狼 - 2003-01-09, 15:20:59

>PointなのにSmallIntegerと言うのが直感的にいや〜ん
ああ、すみません。たんなる // についてではなく a Point 同士の演算における // の位置づけ分からなかったのですね。これは対応する要素( x もしくは y )それぞれについて // を行ない、新たな a Point を生成します。文字通り Point >> #// の引数が a Point の場合をご覧ください。--sumim
- 2003-01-09, 15:35:57

>対応する要素(xもしくはy)それぞれについて//を行ない、新たなa Pointを生成
了解しました.Point >>#//をちゃんと見てきます.どうして,ここに考えが及ばないのかなぁ.済みません.あ,今日は所用がありまして早退しますので,ここまでとなります.明日は午前中だけです.午後からは学校に行ってきます.と,言う事でStarMorphの件は宿題にさせてください.--人狼 - 2003-01-09, 15:55:06

>どうして,ここに考えが及ばないのかなぁ.
演算子 = 組み込み = ソース“クローズド”が当たり前だし、それゆえ通常はドキュメントを参照 で Squeak はドキュメントがないからお手上げ…というパターンでしょうか?(笑) Swiki などで「他人の公開したホームページを書き換える…という発想」に多くの人がなかなか馴染まないのと似た部分(公式に提供された機能のソースを見たり、ましてや書き換えたりする…なんて!)があるのかも知れませんね。--sumim
- 2003-01-09, 18:20:09

>演算子 = 組み込み = ソース“クローズド”が当たり前
いや,まさにおっしゃる通りでしょうね.お恥ずかしい.ソースを潜る,と言う行為が自然と行えないでいます.もう少し慣れたら…と思うのですが.
さて,今日はいつものPBG4は持ってきていないので,ここのWinにSqueakを仕込みたいと思います.StarMorphはその後になります.う〜ん,連休にかかっちゃいそう.--人狼 - 2003-01-10, 08:56:10

>もう少し慣れたら…と思うのですが.
見かけないメッセージセレクタに出会ったら implementors(ブラウザ内なら同名ボタンのメニューから、それ以外の場所ではキーワードメッセージの場合は引数とスペースを取り去る必要がありますがとノかくセレクタだけを選択して cmd-m )、見かけないオブジェクトに出会ったら inspect 後に self を browse-it …を“なぜなし”で心がけるようにするとよいと思います。あとこの習慣を意味あるものにするためにも、メッセージ式の全体とその要素(どこまでが一文で、レシーバとメッセージはそれぞれどの部分で、引数はどれでメッセージセレクタは何か)をコードを見たときにざっと判断できるように目を慣らしておく必要もあるでしょう。特に引数が2つ以上のキーワードメッセージの場合、その一部を implementors しても答えが得られないので、どこまでがメッセージなのかを知ることは大切です。ちょっと事情は違いますが、上の // の場合も「 / を2回」ではなくて、// でひとつのセレクタで / とは別物(換言すれば #/ と #// は別のシンボル)である…と意識できることも大切かもしれません。// に疑問を持っても、/ だけ選択して cmd-m してしまうのは(ブラウザの implementors ボタンなら // と出るので大丈夫ですが)キーワードメッセージの一部をひとつのメッセージと勘違いする(その返値を引数にするために挿入されたメッセージ式で隔てられたメッセージセレクタの後半部分を見落とす)のに似てなくもありません。ではまた連休明けに。--sumim
- 2003-01-10, 14:56:40

おはようございます.この連休は大学の試験でいっぱいいっぱいでした.試験が終わったら気が緩んだのか,風邪を引いてしまました.ゲホゲホ.今週末にも試験があるのに(泣)--人狼 - 2003-01-14, 09:01:56

>“なぜなし”で心がけるようにするとよい
そうですよね.おっしゃる通りです.知らないセレクタはimplements-it,知らないオブジェクトはbrowse-itを“なぜなし”で…と言うのは至極当たり前の事でした.すみません.
>上の//の場合も「/を2回」ではなくて、//でひとつのセレクタで/とは別物
そうでした.演算子もセレクタなのですから,書式を思い出せば「//」でひとつのセレクタだと判りそうなのものです.しっかりしろ>自分.--人狼 - 2003-01-14, 09:08:14

さて,問題のStarMorphの手の件ですが,実は未だに解決出来ていません.アプローチとしては二種類あると思っていて,一つは先にStarMorphを生成して,それから角度を変えると言う方法.もう一つはStarMorph生成時に,予め角度を指定する方法.当然後者の方がスマートなので,後者で実装したいと思っています.しかし,手の方向をどのように指定すれば良いかで困っています.手の頂点をverticesに与えていけばヌ「のナしょうが,そもそも,どう頂点を配したら課題の通りに手の方向を定められるのかと言う,Squeakと言うよりも数学のところで悩んでいます.(算数かも(苦笑))もう少し時間がかかりそうです.トホホ.--人狼 - 2003-01-14, 09:17:41

>風邪を引いてしまいました.
どうぞAお大事に。焦らずまた〜りゆきましょう。--sumim
- 2003-01-14, 10:18:21

>どうぞ、お大事に
ありがとうございます.あまり無理をしない程度にします.
>焦らずまた〜りゆきましょう
はい,あまり焦らずに.でも,StarMorphの件は考え続けています.熱で頭がぼ〜っとしてますけど(汗)上にも書きましたが数学or算数のところで悩んでいるのが情けないです(苦笑)StarMorph>>#initializeの式を読み解くところから始めてみます.--人狼 - 2003-01-14, 10:28:29

>後者の方がスマート
そうですね。ただ、StarMoprh は角度を受け付けるプロトコルを持っていないので、結局、両者似たようなことになると思います。無理に後者を実装しようとするとそれは a StarMorph ではなく、a PolygonMorph になってしまうので注意が必要です。 いずれにせよ、やはり StarMoprh >> #initialize を読み解く必要がありそうです。まず、ハードコードした角度にいずれかの手を伸ばす a StarMorph を描くコードをワークスペースなどで書くのにチャレンジしてみてください。例えば「do-it すると左上方向45度に手を伸ばす a StarMoprh か a StarMorph 型の a PolygonMorph を画面の 0@0 extent: 100@100 の領域に描く」コードを書いてみてください。--sumim
- 2003-01-14, 10:29:22

a StarMorph 型の a PolygonMorph なら StarMorph >> #initialize を真似すれば容易いと思います。a StarMorph を作るなら 前者のアプローチなら、vertices、もしくはその要素をいじるメッセージをスーパークラス(具体的には PolygonMorph )から探す必要があります。--sumim - 2003-01-14, 10:35:29

数学的には見た目ほどたいしたことはやっていません。正十角形を描いて、そのときに交互に中心からの距離を変えているだけです。例えば十角形は、
(PolygonMorph 
	vertices: ((0 to: 9) collect: [ :idx | 
		(Point 
			r: 50 
			degrees: (idx * (360 // 10))) + (0@0 extent: 100@100) center]) 
	color: Color paleGreen 
	borderWidth: 5 
	borderColor: Color black) openInWorld
こんなかんじでこれを星形にするには r:degrees: のひとつ目の引数(このコードでは 50 で固定)を idx の偶奇に合わせて長短、互い違いにすればよいだけなのですが、参考になりますでしょうか。--sumim
- 2003-01-14, 10:52:31

>それは a StarMorph ではなく、a PolygonMorph になってしまう
>a StarMorph 型の a PolygonMorph なら
…と思ったのですが、このコードでレシーバを StarMorph に変えるだけなので、そんな心配はなさそうですね。論よりコードとはことのことで<違う!。撤回します。--sumim
- 2003-01-14, 10:56:17

>やはり StarMoprh >> #initialize を読み解く必要がありそう
やはり,そうなのですね.極座標と言う物を知らないので,そこのお勉強もしなくては.読み解きが出来たら,次にワークスペースにコードを書く段階に移ります.--人狼 - 2003-01-14, 15:26:22

>数学的には見た目ほどたいしたことはやっていません
んが.そうなんですか?う〜ん…与えて頂いた十角形のコードのverticesのところを順に考えてみたいと思います.
(0 to: 9)はnumber >> #toで,0から9までのan Intervalを生成.
collect:はInterval >> #collectで,[]ブロック内を順次an Intervalに設定.
[]内ですが,idxにa PointをPoint >> #r:degreesで次々に束縛していってるっぽいのですが,こ黷ェ10回行われるのはInterval >>#collectにコーディングされているsizeによるのでしょうか?また,このcenterはMorph >> #centerだと読んだのですが,その内容のbouds >> #centerがよく判りませんでした.
で,Point >> #r:degreesですが,ここが極座標っぽいので,とりあえず極座標って何?を勉強して出直してきます.--人狼 - 2003-01-14, 15:49:39

>レシーバを StarMorph に変えるだけなので、そんな心配はなさそう
このコードでレシーバーをStarMorphにしても,描かれるモーフは同じ形をしていますよね.名前はStar1ですけど.なぜなんだろう.結局StarMorphと言うのは,verticesの指定無しでインスタンスを生成すると星形になるようにPolygonMorphを機能拡張したってことなのでしょうか…StarMorphのコードを仔細に眺めればもっと違うはあるのかも知れませんが.--人狼 - 2003-01-14, 15:54:30

>座標って何?
x、y ではなく、原点を通る決められた直線(この場合 x 軸)となす角度(degrees)と原点からの距離(r)で座標を表す方法です。ちなみに Squeak の座標は左上が 0@0 で右にゆくと x が、下にゆくと y が正に大きくなります。--sumim
- 2003-01-14, 17:16:15

>このcenterは
かえってわかりづらくしてしまいましたね。ごめんなさい。(0@0 extent: 100@100) center は単に指定された区画の中心の座標(50@50)を算出しているにすぎません。ですから、
(PolygonMorph 
        vertices: ((0 to: 9) collect: [ :idx | 
                (Point 
                        r: 50 
                        degrees: (idx * (360 // 10))) + (50@50)]) 
        color: Color paleGreen 
        borderWidth: 5 
        borderColor: Color black) openInWorld
と同じです。--sumim
- 2003-01-14, 17:19:37

(0 to: 9) collect: [ :idx | idx ] を inspect-it してみてください。--sumim - 2003-01-14, 17:24:01

では、まあ、ステップバイステップでまいりましょうか。まず、PolygonMorph は、vertices:color:borderWidth:borderColor: というメッセージを受けて、a PolygonMoprh を生み出します。2番目の引数は囲まれた領域を塗る色、3番目の引数は線の幅、4番目は線の色でこれはだいじょうぶですね。問題は1つめの引数です。ここには、a Point の配列を渡します。たとえば、
(PolygonMorph 
	vertices: {0@0. 50@25. 25@50} 
	color: Color paleGreen 
	borderWidth: 5 
	borderColor: Color black) openInWorld
とす驍ニ原点(0@0)と、50@25、25@50 をそれぞれ通る三角形が描かれます。ここまではよろしいでしょうか?--sumim
- 2003-01-14, 17:35:43

そこで、ここで星形を描くポイントとしては、ひとつめの引数として渡す a Point のリストをうまく星形になるような a Point 群とできるかどうかということになります。--sumim - 2003-01-14, 17:37:49

a Point の作り方にはいくつかの方法があります。ひとつは、すでに何度か出ている、数値に @数値 というメッセージを送る方法です。もうひとつは、クラス Point にメッセージを送る方法で、Point class をブラウズすると3つの方法が用意されていることがわかります。fromUser は画面上でクリックした座標のインスタンスを生成するメッセージ、x:y: はインスタンス変数、x、y にそれぞれ直接数値を指定して代入する方法でA数l @数値 というメッセージ式と事実上同じ。r:degrees: は、原点からの距離および、めざす座標と原点を通る直線が x 軸となす角度から、x、y を算出して a Point を作る方法です。--sumim - 2003-01-14, 17:42:20

極座標系で a Point を作る方法は 正 n 角形 の頂点の座標を求めるときに便利で、たとえば、原点を中心に持ち、各頂点から原点までの距離が 50 の正三角形の各頂点の座標の配列は、
{Point r: 50 degrees: 0.
Point r: 50 degrees: 120.
Point r: 50 degrees: 240}
と書けます。つまり第1引数(原点からの距離)は変えずに、第2引数だけを 120(つまり、360 // 3 )ずつ変化させるだけで正三角形の頂点が求まるわけです。--sumim
- 2003-01-14, 17:52:28

なので、第2引数だけ計算で出せるようにしてやれば、これらの a Point たちは自動生成が可能になります。他方で、(0 to: 2) collect: [ :idx | idx ] というメッセージ式で、collect: はレシーバの各要素(ここでは 0、1、2 )を引数にした value: を、自らの引数であるブロック(ここでは [ :idx | idx ])に送信して得られたオブジェクトを要素とする配列( { [ :idx | idx ] value: 0. [ :idx | idx ] value: 1. [ :idx | idx ] value: 2 } )を作る役割りを果たします。したがって、(0 to: 2) collect: [ :idx | Point r: 50 degrees: idx * 120 ] とすることで、先の3つの Point をレシーバにするメッセージ式を含んだ配列のリテラル式と同じことを表現できます。--sumim - 2003-01-14, 18:00:29

>x、yではなく、原点を通る決められた直線となす角度(degrees)と原点からの距離(r)で座標を表す
了解しました.有り難うございます.雰囲気的には「2時の方向,距離800〜」みたいな感じですね(大ざっぱすぎ.)--人狼 - 2003-01-15, 10:05:01

>(0@0 extent: 100@100) centerは単に指定された区画の中心の座標(50@50)を算出
算出される値は了解しました.済みません,Morph >>#centerではありませんでしたね.この(0@0 extent: 100@100)はa Rectangleを生成しますので,Rectangle >>#centerで戻り値がa Pointになっていました.--人狼 - 2003-01-15, 10:16:33

>inspect-itしてみてください
an Arrayが生成されまして,1〜10の要素に,それぞれ0〜9のa SmallIntegerが束縛されていました.--人狼 - 2003-01-15, 10:54:01

>ステップバイステップで
すみません,お手数をおかけします.
>ここまではよろしいでしょうか
はい,指定した点を通る多角形を描くのはOKです.--人狼 - 2003-01-15, 10:55:37

>星形を描くポイントとしては
verticesを構成するa Point群を結んで図形が描かれるわけですから,そうなりますよね.--人狼 - 2003-01-15, 10:58:06

>数値に @数値 というメッセージを送る方法
Number >>#@ですね.レシーバーがx座標,引数がy座標になりますね.
>fromUserは画面上でクリックした座標
Point fromUserをprint-itすると,十字カーソルに変わりました.画面をクリックするとa Pointが返されました.
>x:y: はインスタンス変数、x、yにそれぞれ直接数値を指定して代入
まず,a Pointをnewで生成してPoint >> #setX:setY:をしていますね.数値@数値と言うメッセージ式も内部でPoint class >> #x:yを呼んでいる事から事実上同じと言うのも了解です.
>r:degrees: は、原点からの距離および、めざす座標と原点を通る直線がx軸となす角度
これが,私が悩んでいた極座標だったのですね.--人狼 - 2003-01-15, 11:28:48

>極座標系でa Pointを作る方法は 正n角形 の頂点の座標を求めるときに便利
ご呈示頂いた,正三角形の例を見て判りました.これは原点を中心として,原点からの距離50の3点をx軸上,x軸と120度をなす直線上,x軸と240度をなす直線上にそれぞれ取ると言う事ですよね.これをPolygonMorph >> #vertices:color:borderWidth:borderColor:に渡すと確かにそのような正三角形が描画されました.--人狼 - 2003-01-15, 11:34:08

ここまでご理解いただけたところで、いま一度 StarMorph >> #initialize をみてみてください。すこしは前と印象が違いますでしょうか。--sumim - 2003-01-15, 12:17:23

>すこしは前と印象が違いますでしょうか
borderWidth,borderColorは良いとして.
pt _ 10@10として,ext _ pt rとしていますので,extは原点から10@10までの距離です.つーことは,ptに束縛する値を変えればStarMorphの大きさが変わる?おぉっ!変わった.
oldR _ extとする事で初期値の距離を記憶します.(後で長い線と短い線を分けるため)
points _ 5で,星の手の数を決めます.つーことで六芒星に挑戦.よしよし.
(0 to: 359 by: (360//points//2))collect: [hogehoge]で360度を,手の数の2倍(星型の点の数は手の数の2倍)分の配列にしたてます.
hogehogeはa Point群で.各a PointのrはoldRですが,束縛した後に,oldRとextを比較し,等しければoldRにext*5//12を束縛し,違えばextを束縛します.これによって手の長さを交互に変えています.ext*5//12の計算の意味までは判りませんでした.
degreesの方はangleのvalue(360度を手の数の2倍=点の数で割っていった値.StarMorphの場合は0, 36, 72,……,288,324)にpt(=10@10)のdegreesを加えています.ここでpt degreesを加えている理由が判りませんでした.加えないと生成されるStarMorphの角度が変わりますから,ここはポイントなのかなぁ.
最後に計算により生成された各a Pointに45@45を加えていますが,この理由も判りませんでした.
今のところはこんな感じです.--人狼 - 2003-01-15, 13:22:17

>ここでpt degreesを加えている理由が判りません
ああ。これは私もわかりませんでした(^_^;)。pt なんかを大仰に用意しているところをみると(これは事実上半径を決めればいいので a Point である必要はない)なにかをやろうとして忘れた…てなところでしょうか。いや、なにか深遠なものがあるのかも(笑)。いずれにせよ、今のところは手のひとつの角度を微調整している計算という理解でかまわないと思います。--sumim
- 2003-01-15, 13:56:52

>各a Pointに45@45を加えていますが,この理由も判りません
これは a Point 群を 45@45 だけ右下に平行移動しているのですね。結果、出来上がる星の中心が 45@45 だけ右下にずれます。なくても良いように思いますが、StarMoprh new openInWorld したときに中心が 0@0 に来てしまうと見栄えが悪いので、適当に 45@45 くらいずらした…のではないかと思っています。ただ、我々がこれから書こうとしているコードの場合、この“中心ずらし”は結構重要です。何もしないと、指定した領域(たとえば 0@0 extent: 100@100 )の右上を中心に星が描かれてしまいます。そこで、先に呈示した正十角形の例では 50@50 を足しているわけです。--sumim
- 2003-01-15, 14:07:19

>今のところは手のひとつの角度を微調整
何も深遠なものが無い事を期待して(笑)でも,ここで角度を微調整しているらしいとのことですが,元々の課題では原点とジェスチャーの矩形の中心を通る直線の傾きに手のうちのいずれかの角度を合わせると言う事でしたので,この微妙なずれは関係しないのかが不安です.とは言え,まだそこまで到達しておりませんので,心配するのはまだ早いかも知れませんね.--人狼 - 2003-01-15, 14:25:34

>a Point 群を 45@45 だけ右下に平行移動
なるほど.全ての点を45@45だけ平行移動ですか.確かにそう言う意味ですね.45@45と言う座標そのものにとらわれていました.確かにこれは平行移動ですよね.この中心をずらす,と言うのは大切ですね.--人狼 - 2003-01-15, 14:29:17

>ext5//12の計算の意味
これは星のかたちを五芒星に近づけるために、ちょっとややこしい幾何学の問題を解く必要がありますが(いやなにも幾何学的に解くことはないのですが…(^_^;))、その結果出てくる 0.382 … という値に近い分数として 5/12 を、それをかけた結果に近い整数を出すのに // としているのではないかと推察しています(それなら、なぜ 5/13 にしなかったか…という疑問は残りますが(^_^;))。--sumim
- 2003-01-15, 15:00:08

さて,まだ課題通りのStarMorphを描くところまで到達していないわけですが,sumimさんより
>「do-itすると左上方向45度に手を伸ばすa StarMorphを画面の0@0 extent: 100@100の領域に描く」
とのご助言の方から挑戦しています.まだ完成していませんが,現在のコードはこんな感じです.
| pt ext oldR points |
pt _ 10@10.
ext _ pt r.
oldR _ ext.
points _ 5.
(StarMorph
        vertices: ((0 to: 359 by: (360//points//2)) collect: [:angle |
		(Point r: (oldR _ oldR = ext ifTrue: [ext*5//12] ifFalse:
		[ext]) degrees: angle - 135+ pt degrees)
		+ (50@50)])
        color: Color paleGreen 
        borderWidth: 1
        borderColor: Color black) openInWorld 

Point class >> #r:degrees:のdegreesより135を減じていますが,これにより左上45度から360度を数えるようにオフセットするためです.また,平行移動量を50@50として,a StarMorphの中心を0@0 extent: 100@100の中心にしています.が,肝心の大きさは0@0 extent: 100@100に出来なくて悩んでいます.ptに与える座標で大きさが変わるのでしょうが,単に100@100としたらやたら巨大になりました.もう少し悩んできます.--人狼 - 2003-01-15, 15:02:26

pt のあたりは無理に真似する必要はないと思います。私は、こんなふうにしてみました。
| r angle bounds |
r _ 50.
angle _ 45.
bounds _ 0@0 extent: 100@100.
(StarMorph
        vertices: ((0 to: 9) collect: [ :idx |
		(Point 
			r: (idx even ifTrue: [r * 5 // 12] ifFalse: [r])
			degrees: idx * 360 // 10 + angle) + bounds center])
        color: Color paleGreen 
        borderWidth: 5
        borderColor: Color black) openInWorld
これなら半径を r に与えるだけで望む手の長さの星を描くことができます。--sumim
- 2003-01-15, 15:19:20

ただこれだと、angle の 45度っていったいなに?ってことになるので、システムの極座標系(右向き水平が零度で時計回りに角度を増す)に合わせて、左斜め 45 度は 225度( 180 + 45 )もしくは -135度( -180 + 45 )としていずれの数字を angle に与えてもよいように、
| r angle bounds |
r _ 50.
angle _ 225. "-135"
bounds _ 0@0 extent: 100@100.
(StarMorph
        vertices: ((0 to: 9) collect: [ :idx |
		(Point 
			r: (idx even ifTrue: [r * 5 // 12] ifFalse: [r])
			degrees: idx * 360 // 10 + angle + 180) + bounds center])
        color: Color paleGreen 
        borderWidth: 5
        borderColor: Color black) openInWorld
としてみました。--sumim
- 2003-01-15, 15:39:48

さらに、r も bounds に収まる最大の円の半径から求めて、
| r angle bounds |
angle _ 225. "-135"
bounds _ 0@0 extent: 100@100.
r _ (bounds width min: bounds height) // 2.
(StarMorph
        vertices: ((0 to: 9) collect: [ :idx |
		(Point 
			r: (idx even ifTrue: [r * 5 // 12] ifFalse: [r])
			degrees: idx * 360 // 10 + angle + 180) + bounds center])
        color: Color paleGreen 
        borderWidth: 5
        borderColor: Color black) openInWorld
とするのがよろしいかなと。--sumim
- 2003-01-15, 15:42:38

>こんなふうにしてみました
えぇ〜っと.rは,原点からの距離そのものずばりなんですね.boundsと言うa Rectangleを用意して,そのcenterを平行移動のオフセットとしているんですね.これはジェスチャーの矩形にする時に,ほぼそのまま応用可能ですね.いや,さすが.ところで,angleに45度を足していますね.角度のプラスとマイナスと0度の方向を私が誤解していたようです.--人狼 - 2003-01-15, 15:42:43

>ところで,angleに45度を足していますね
上に補足をしておきましたので、そちらをぜひ。左上 45度というのは、Squeak の極座標では、-135度、もしくは 225 度になります。angle にこの値を与えたときに予想外の事態が起こらないように修正しました。--sumim
- 2003-01-15, 15:49:28

これで cordinates topLeft extent: corner: coordinates bottomRight を bounds に、coordinates start と bounds center とを通る直線が x 軸と成す角度を angle に指定してやることで、ほぼ目的は達成できると思います。--sumim - 2003-01-15, 15:56:00

“ほぼ”と申し上げたのは、bounds が縦長もしくは横長のときに、ユーザーを騙しきれないかなぁ…と(^_^;)。そのときのための細工もちょっと仕込んでおきましょう。--sumim - 2003-01-15, 15:59:02

>システムの極座標系に合わせて
えっと,ここで180度を加えているのは-135度だった場合に正の値にする為でしょうか?0度〜359度の範囲に正規化する必要はないみたいですね.
ところで,例えば-135度を与えた時には180-135で45がangleに足される事となり,つまるところangleに加えているのは45度だ,と言う事になるかと思うのです.ここがシステムの座標系(225度or-135度)とは異なる理由を今ひとつ理解できていません.--人狼 - 2003-01-15, 16:53:00

>180度を加えているのは
気付かれてしまいましたか…<ぉぃ! 実は0度のところに手がないからです(^_^;)。( idx が 0 のとき、idx even は true なので、半径は短くなるため)  180度 でなくとも、n * 72 + 36( n は整数)ならなんでもかまいません。じゃあ手(長い半径)から描くようにすればいいじゃん…と思うのですがじつはこれはこれで shift-クリックで選択したときにちと問題がありまして(^_^;)。--sumim
- 2003-01-15, 17:12:06

>さらに、rもboundsに収まる最大の円の半径から求めて
このrの計算ですが,boundsの幅か高さのどちらか小さい方の半分が最大の円の半径と言う事ですよね.--人狼 - 2003-01-15, 17:15:02

>幅か高さのどちらか小さい方の半分が最大の円の半径
そうです。--sumim
- 2003-01-15, 17:20:10

で、先ほどのユーザーの目を欺くための仕掛けと、Genie コードとの互換性をとりつつワークスペース上での do-it で任意の bounds でテストできるようにもするための処理を書き足したのが
| ratio v r angle bounds |
coordinates _ Rectangle fromUser. "remove this line for Genie code" 
bounds _ coordinates topLeft corner: coordinates bottomRight.
r _ (bounds width min: bounds height) // 2.
ratio _ bounds height / bounds width.
v _ coordinates topLeft - bounds center.
angle _ ((v x) @ (v y / ratio)) degrees.
(StarMorph
        vertices: ((0 to: 9) collect: [ :idx |
		(Point 
			r: (idx even ifTrue: [r * 5 // 12] ifFalse: [r])
			degrees: idx * 360 // 10 + angle + 180) + bounds center])
        color: Color paleGreen 
        borderWidth: 5
        borderColor: Color black) extent: bounds extent; openInWorld
です。ちょっとややこしくなってしまいましたが、頑張って読んでみてください。--sumim
- 2003-01-15, 17:19:23

coordinates topLeft は、Genie のコードとして使うときは、coordinates start に置き換えます。念のため。--sumim - 2003-01-15, 17:29:30

>実は0度のところに手がないから
なるほど.0度のところはidx evenがtrueなので半径が短くなる…と.なぜshiftクリックした時に問題になるかは,また別な問題なのですね.(とりあえず今は深く考えずに,頭の片隅に置いておきます)--人狼 - 2003-01-15, 17:32:33

>頑張って読んでみてください
御意.頑張ってみます.ちょっと時間がかかるかも知れませんが.
ところで,fromUserでRectangleの範囲を取得していますが,左上から右下に矩形を作成した場合は問題無いのですが,右上から左下の場合は必ず縦長に,左下から右上の場合は必ず横長に,右下から左上の場合は必ず小さな星になってしまいます.ふ,深みにはまりそう--人狼 - 2003-01-15, 17:40:16

ああ、それは fromUser(Rectangle class >> #fromUser:、もしくは Rectangle class >> #corner: )の設計ミスです。かならず「左上から右下に」矩形を描いてください。気になるようでしたら…もう、おわかりですね(^_^;)。ちなみに私はぜんぜん気にならないのでそのままにしています<こら!--sumim - 2003-01-15, 17:47:06

>気になるようでしたら…もう、おわかりですね
えぇっと(汗)とりあえずは気にしないでおきます.本題はそちらでは無いので(大汗)そのうち余裕が出てきたら改めて考えてみます.(と,先送りばかりで済みません.)--人狼 - 2003-01-15, 17:52:18

でもまあ気になるので、直して(ただしクイックレイジーダーティフィックス(^_^;))みました<ぉぃ!
fromUser: gridPoint
	"Answer a Rectangle that is determined by having the user 
	designate the top left and bottom right corners. 
	The cursor reamins linked with the sensor, but
	the outline is kept gridded."
	| originRect newRect |
	originRect _ Cursor origin showWhile: 
		[((Sensor cursorPoint grid: gridPoint) extent: 0@0) newRectFrom:
			[:f | (Sensor cursorPoint grid: gridPoint) extent: 0@0]].
	newRect _ Cursor corner showWhile:
		[originRect newRectFrom:
			[:f | f origin corner: (Sensor cursorPoint grid: gridPoint)]].
	^ (newRect left min: newRect right) @ (newRect top min: newRect bottom)
		corner: (newRect left max: newRect right) @ (newRect top max: newRect bottom)
さらに本格的にやろうとしたら、Rectangle >> #newRectFrom: とかもいじらんと(指定中に正しく矩形が描かれないのを修正せんと)いかんのでしょうが。今のところはこのへんで勘弁してください。--sumim
- 2003-01-15, 18:07:56

>ちょっとややこしくなってしまいましたが
遅くなりました.ちょっと寝不足気味のぼけた頭で考えております.なんかいきなりとん挫してますけど(汗)
| ratio v r angle bounds |
coordinates _ Rectangle fromUser. 

のところですが,このcoordinatesは一時変数の宣言をしていませんが,よいのでしょうか?ちなみに,このcoordinatesはa Rectangleでよろしいのでしょうか?次の行の
bounds _ coordinates topLeft corner: coordinates bottomRight. 

のboundsもa Rectangleで,座標はcoordinatesと同じですよね?
rはboundsの幅か高さの内,小さい方の1/2(=半径)を束縛.ratioは高さ/幅で対角線(即ちジェスチャーの始点と矩形の中心を通る線)の傾きを束縛.
さて,ここで次のvの計算ですが,coordinatesの左上から中止の座標を減じていますが,ここが判りませんでした.ここが判れば次のangleの計算も判ると思います.以降は大丈夫です.--人狼 - 2003-01-16, 14:14:20

>でもまあ気になるので
かえってお手数をおかけしました.意識レベルが上がった時に,元のソースと見比べてみます.しかし,朦朧とした意識でもクイックレイジー…は大受けでした(笑)--人狼 - 2003-01-16, 14:15:54

>coordinatesは一時変数の宣言をしていません
これはわざとワークスペース変数を使っています。次の bounds と同じもの…とのご指摘ともからみますが、Genie のコードとして使うときに、coordinates への代入の行だけ省けば(あと、coodinates topLeft を coodinates start に変えれば)よいように書いています。--sumim
- 2003-01-16, 14:32:49

>ratioは高さ/幅で対角線(即ちジェスチャーの始点と矩形の中心を通る線)の傾き
いえ、違います。ここでは単に文字通り縦横比として束縛しています。これが今回の修正のミソです。--sumim
- 2003-01-16, 14:36:20

>vの計算ですが,coordinatesの左上から中止の座標を減じていますが,ここが判りません
この v(ベクトルの意味)が手の向きを調節するための「(即ちジェスチャーの始点と矩形の中心を通る線)の傾き」を算出するためのものです。今は a Rectangle が start を理解できないので topLeft に仮置きしていますが Genie のコードでは coordinates start に置き換えることで、正式に中心からジェスチャーの開始点へ向かうベクトル(実体は a Point )を v に束縛します。この後、degrees メッセージを送って angle 算出しているわけですが、このとき単に degrees を送らずに、いったん v の y の値に先ほどの ratio を使って細工をしている理由をご理解いただけるかどうかがポイントだと思いますがいかがでしょうか。--sumim
- 2003-01-16, 14:44:13

ratio が1付近のとき、つまり、縦横がほぼ同じ長さの正方形に近い bounds のとき、coordinates start(今は topLeft )と bounds 中心点の両者を通る直線と x 軸のなす角度はほぼそのまま angle に束縛されます。ratio が大きな数字のとき、つまり縦長の矩形の場合、v の y は実際の値より小さい値にして、つまり水平に近づけた状態になり、その角度が angle に束縛されます。逆に横長の矩形のときは、angle は実際の値よりも垂直に近い値に変換されます。--sumim - 2003-01-16, 14:58:55

>これはわざとワークスペース変数
なるほど,そう言う配慮があったのですね.--人狼 - 2003-01-16, 15:29:33

>縦横比として束縛しています
縦/横の比のままだったんですね.
>これが今回の修正のミソ
これは下で明らかにされている事なのですね.いやはや,読み取れていませんでした.--人狼 - 2003-01-16, 15:32:25

>中心からジェスチャーの開始点へ向かうベクトル(実体はa Point)
例えば,a Rectangleが0@0 extent: 100@100だとすると,vは-50@-50となりますよね.これは「中心からv移動するとtopLeft(=ジェスチャーの開始点)に達する」と言う事でvectorなのですね.--人狼 - 2003-01-16, 15:36:52

>先ほどのratioを使って細工をしている理由
ratioを使ってどう細工しているかの説明を有り難うございます.指定された矩形に応じてa StarMorphの扁平率を変えているのですね.--人狼 - 2003-01-16, 15:39:19

ではこのコードを Genie の #StarMorph# に置き換えてみましょう。すでに申し上げたとおり、1行目の coordinates への代入文は削除しておきます。また、5行目の topLeft は start に置き換えて
#StarMorph#
| ratio v r angle bounds |
bounds _ coordinates topLeft corner: coordinates bottomRight.
r _ (bounds width min: bounds height) // 2.
ratio _ bounds height / bounds width.
v _ coordinates start - bounds center.
angle _ ((v x) @ (v y / ratio)) degrees.
(StarMorph
        vertices: ((0 to: 9) collect: [ :idx |
		(Point 
			r: (idx even ifTrue: [r * 5 // 12] ifFalse: [r])
			degrees: idx * 360 // 10 + angle + 180) + bounds center])
        color: Color paleGreen 
        borderWidth: 5
        borderColor: Color black) extent: bounds extent; openInWorld
というように変えてGenie の StarMorph 用のジェスチャーの FillInTheBlank にペーストして accept してみてください。さて、期待通りに描かれますでしょうか。--sumim
- 2003-01-16, 15:44:29

>期待通りに描かれますでしょうか
す,すごいです.ちゃんと描画されます.素晴らしい.--人狼 - 2003-01-16, 16:21:58

こんな調子で なんちゃって手書き図形認識もある程度可能です。ストローク情報を利用すればかなり本格的に手書き図形の特徴を考慮した描画もかのうなのでしょうが、そこまでやると大変そうなので、今はこのあたり(coodinates 情報の活用)にとどめておくのがよろしいかと。--sumim - 2003-01-16, 16:36:57

>なんちゃって手書き図形認識もある程度可能
なんちゃって,とは言えここまで出来るのは凄いですね.一筆書きですよね〜.いやぁ,かなりおなかいっぱいです(苦笑)--人狼 - 2003-01-16, 17:52:34

このページを編集 (73461 bytes)


Congratulations! 以下の 1 ページから参照されています。

This page has been visited 4670 times.