犀角(Diceros Horn) 2006 01

とくながの「書き散らかし」です

ここは研究・調査・開発などの記録がメインのページです。 日常の雑事、読書記録は はてなダイアリー の方に書いています。よろしければそちらもどうぞ。

Wed, 11 Jan 2006

結び目

結び目を円周から3次元空間への写像とみなし、 それを三角関数で展開したときの係数を与えて結び目を描く。 有名な結び目については、あらかじめ与えている。

まずはメニューから有名どころの結び目を選んでみてください。 それから係数を変化させてお楽しみください。 他の結び目の係数を御存じの方はぜひお知らせください。

履歴

2003/6/15
いつ作ったかよく覚えていないのだけれど、2003年になってからなのは 確か。Swing でスライダーを作って係数を変更するようにしている。 法線ベクトルを GeometryInfo を使わずに自力で計算するようにしたが、 しわになっていしまうこともある。他に依存しないような法線ベクトル の作り方を考え中。

posted at 22:32 | category: /Program/Knot | 固定リンク(結び目 )

ローレンツアトラクタ

3次元の常微分方程式の中で視覚化することに意義があるものとして 取り上げた。たぶん一番最初に作ったまともな Java3D の プログラムだったような・・・・・。

方程式

  x' = -10x + 10y
  y' = 28x -y -xz
  z' = xy - 8/3z
を初期値 (x,y,z) = (0,5,0) の下で数値計算する。

posted at 21:31 | category: /Program/Physics | 固定リンク(ローレンツアトラクタ )

剛体の運動シミュレータ

力学の教科書の内容は質点系の力学と剛体の力学の二つに大きく分けられている。 質点系の力学を Java3D で行うことための処方箋はほぼ分かってきて、 むしろネタ切れの感があったので、剛体の力学に挑戦することにした。

使い方

内部角運動量、慣性テンソル、軌道を表示する場合の局所座標の点、外部重力ベクトル を与えて、シミュレーションをする。剛体の運動方程式に従って数値計算を行う。 剛体は独楽のような形をしているが、便宜上であって、独楽の慣性モーメントを 持つわけではない。次のような特徴的な初期値を与えることができる。
Unstable
主慣性モーメント(つまり慣性作用素が対角行列のときの対角成分)が全て 異なるときに、中間の大きさの主慣性軸は安定ではない。そこで、 その方向の角運動量を大きくとって、それ以外の角運動量をわずかな値にして シミュレーションをすると興味深い運動が見られる。
Lagrange
いわゆるラグランジュのコマ。回転の軸に対して、主慣性モーメントが対称。
Kowalevski
いわゆるコワレスカヤのコマ。回転軸は剛体の主軸と一致するが、 主慣性モーメントは回転軸と、それに垂直な一成分が等しく、 残りの一成分はそれらの2倍。
剛体の運動を空間上の回転を表すリー群上の運動だと思い、 角運動量はそのリー環(本当はその双対空間とすべきだけど、計量によって 同一視しておく)に値を持つと考える。 慣性テンソルをリー環上の対称作用素と考えて、 リー環の変数 M についての微分方程式
 dM
 --  = [M,Ω]
 dt

  M  = A(Ω)
を解いて、角運動量 M を求める。 その角運動量にしたがって りー群上の運動を求め、それに従って剛体の座標系を回転させている。 ちなみにこれは外力のない場合、つまりは 無重力空間内での剛体の運動となっている。 剛体がある重力場の中にいるときには、次の方程式になる。
 dM
 --  = [M,Ω]  + [G,L]
 dt

  M  = A(Ω)
ここで、G は剛体の座標系による 重力ベクトル場で、L は固定点を原点とした時の重心の位置ベクトルである。

はじめ Arnold の「古典力学における数学的方法」を見たが、剛体の運動は のっていても、Hamilton 力学ではない。そこで、Abraham and Marsden の Foundations of Mechanics とか、Marsden and Ratiu の Introduction to Mechanics and Symmetry などを参考にした。この方程式の導出自体は Hamilton 力学でなくてもできる。

数値計算は局所座標に書き下さずに行列のまま vecmath パッケージを用いて計算した。ルンゲクッタ法は 行列環上の演算に翻訳して用いている。翻訳があっているかについて 理論的にチェックしていないので、ひょっとしたら積の非可換性から ルンゲクッタ法で保証される以上の誤差が出てきてしまうかもしれない。

履歴

2002/3/9
取りあえず重力場対応にして、重心の位置と重力場を入力可能にする。 パラメータの指定方法はあまりよい方法ではないかもしれない。
2002/3/6
軌跡を描画するための軸の方向を変更可能にする。 軌跡を書くためのクラス Tail を Shape3D から BranchGroup に変更。 さらにデータ処理方法も参照モードに変更。たぶんコピーモード よりも速い。さらに頂点の色も指定するようにして、色が減衰してい くようにした。オマケとして Rainbow モードで作成。
2002/3/4
軸の軌跡を描画する。
2002/3/3
数値計算をルンゲクッタ法に変える。発散はおさまる。
2002/2/26
オイラー法で数値計算する。すぐ発散してしまう。
2002/2/23
開発開始。

posted at 21:19 | category: /Program/Physics | 固定リンク(剛体の運動シミュレータ )

4x4ルービックキューブ

ルービックキューブのシミュレーションプログラムの4x4バージョンです。 Java3D で作っています。

画面下のボタンを押すか、色名のキーを押すと、 デフォルトの状態でその色が中心にある面をその面の上から見て 時計回りに90度回転します。 4x4なので、中心の色もそのうち変わってしまうので注意。

posted at 00:39 | category: /Program | 固定リンク(4x4ルービックキューブ )

三体問題のシミュレータ

三体問題は、ハミルトン系の例として教科書によく現れ、また初等的に解けない例としても よく紹介される。そこで Java3D でハミルトン系を扱う場合の例として取り上げることにしました。 数値計算はシンプレクティック法を Java で実装したものを使っています。

開発履歴:はじめ2000年の秋頃に作ったのですが、そのときの履歴をなくしてしまいました。
2003/8/2
うまく動かなくなっていたのを直す。アプレットにおけるパラメータ表示のための スレッドの処理などを変更。
2000/秋頃
開発開始。数値計算に使うためにシンプレクティック法をパッケージ化する。

posted at 00:25 | category: /Program/Physics | 固定リンク(三体問題のシミュレータ )

Tue, 10 Jan 2006

ただいま整理中

古いコンテンツなどを整理しています。すべてを blosxom のコンテンツとして統合しようと思っています。そのため日付が変わっていたり、古いコンテンツが新しい日付で登録されていたり、と見にくくなってしまっていますが、ご容赦くださいませ。

posted at 23:56 | category: /About | 固定リンク(ただいま整理中 )

Mon, 09 Jan 2006

ルービックキューブ

以前作ったルービックキューブのシミュレーションプログラムを Java Web Start で起動できるようにしてみました。ただし、セキュリティ証明書は 証明書発行期間から取得したわけではない、いわゆるオレオレ証明書。 しかも6ヶ月で期限切れになる。対策はそのうち考えます。

画面下のボタンを押すか、色名のキーを押すと、 その色が中心にある面をその面の上から見て 時計回りに90度回転します。

posted at 23:23 | category: /Program | 固定リンク(ルービックキューブ )

Canvas の内容を jpeg ファイルに保存するには

Canvas の内容をそのまま保存することはできない。 BufferedImage に書き込んで、Canvas には drawImage() で書き込むことにしておく。 その状態で、image を BufferedImage のインスタンスとして、

    FileOutputStream output = new FileOutputStream("test.jpg");
    JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(output);
    jpeg.encode(image);
    output.flush();
    output.close();
とすればよい。ただし、IOException を throw するので例外処理が必要。

サンプルソース 参照。

posted at 19:38 | category: /Java/tips | 固定リンク(Canvas の内容を jpeg ファイルに保存するには )

ダブルバッファリング

Canvas に図形を描画するときに、直接 Graphics に書き込むのではなく、 バッファーとして Image オブジェクトを作成し、その Graphics に書き込んでから drawImage メソッドで Canvas の Graphics に書き込む。

具体的には、Canvas のフィールド変数として、

    Image image;            // イメージの保存
    Graphics g0;            // image に描画するための Graohics
を追加し、paint() メソッドは
    public void paint(Graphics g){
        // image が初期化されていたいときは初期化する
        if(image == null){
            image = createImage(getSize().width,
                                getSize().height);
            // Graphics の取得
            g0 = image.getGraphics();
        }
        // image を表示する
        g.drawImage(image,0,0,this);   
    }
とし、実際の描画は
        g0.fillRect(20,20,50,50);
        getGraphics().drawImage(image,0,0,this);
のように g0 に書き込んでから drawImage で Canvas に書き込めばよい。

posted at 19:36 | category: /Java/tips | 固定リンク(ダブルバッファリング )

アプレットとアプリケーションの兼用プログラム

アプレットを作るときに、わざわざhtmlファイルを書いてブラウザで 動作を確認するのは面倒である。(appletviewer をつけばちょっと楽だが) そんなときはアプレットとして作ったプログラムをアプリケーションとして実行 させよう。

次のアプレットはボタンを押せばメッセージが出ると言う定番のアプレットだが、 これをアプリケーションとして動くようにするために、main メソッドを付け足 している。そこでは、Frame を生成し、Applet を張り付けているだけである。

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class HelloAppletcation extends Applet{
  Button bt;
  TextField tf;
  
  public static void main(String args[]){
    Frame fr = new Frame("Hello Applet");
    fr.addWindowListener(new WindowAdapter(){
      public void windowClosing(WindowEvent e){
	System.exit(0);
      }
    });
    Applet app = new HelloAppletcation();
    app.init();
    fr.add(app);
    fr.setSize(400,100);
    fr.setVisible(true);
    app.start();
  }

  public void init(){
    bt = new Button("PUSH");
    tf = new TextField(30);
    add(bt);
    add(tf);
    bt.addActionListener(new HelloButton());
  }

  class HelloButton implements ActionListener{
    public void actionPerformed(ActionEvent e){
      tf.setText("Hello, Java World!!");
    }
  }
}

動的に Applet として実行しているか Application として実行しているかを 判定したい場合は、Applet クラスの getCodeBase() メソッドを呼ぶとよい。 Application の場合は例外が発生する。

posted at 19:35 | category: /Java/tips | 固定リンク(アプレットとアプリケーションの兼用プログラム )

クラスの動的読み込み

実行時にクラスを呼ぶ例を挙げよう。 まず A(String str,double x) と言うコンストラクタを持つようなクラス A を考えよう。このクラス A を動的に呼んでインスタンス化するには次のようにする。 ここで、ClassLoader クラスは抽象クラスなので、それを継承したクラスを ClassLoadTest とする。

  ClassLoader loader = new ClassLoadTest();
  Class c = loader.loadClass("A");
  Constructor con = c.getDeclaredConstructor(
                    new Class[]{String.class,double.class});
  A a = (A)con.newInstance(new Object[]{"circle",new Double(3.14)});
例外処理に付いては省略した。

posted at 19:33 | category: /Java/tips | 固定リンク(クラスの動的読み込み )

内部クラスから外のクラスを呼ぶ

外のクラス名.this でアクセスできる。

class InnerOuter{
    String str = "Outer";
    A a;
    InnerOuter(){
        a = new A();
    }

    class A{
        String str = "Inner";
        
        void outerMessage(){
            System.out.println(InnerOuter.this.str);
        }

        void innerMessage(){
            System.out.println(this.str);
        }
    }

    public static void main(String args[]){
        InnerOuter inn = new InnerOuter();
        inn.a.outerMessage();
        inn.a.innerMessage();
    }
}
これをコンパイルして実行すると、
$ java InnerOuter
Outer
Inner
のように出力される。

posted at 19:29 | category: /Java/tips | 固定リンク(内部クラスから外のクラスを呼ぶ )

あるオブジェクトがあるクラスのオブジェクトかどうかを判定する

この手の実行時型判定は instanceof または Class クラスの isInstance() メソッドまたは Class クラスの isAssignableFrom() メソッドを使う。 次の3つは全て同じ意味で、オブジェクト a がクラス A またはそのサブクラスの インスタンスのときに true を返す。

  • a instanceof A
  • A.class.isInstance(a)
  • A.class.isAssignableFrom(a.getClass())
また、次のように書くと、オブジェクト a がクラス A またはその スーパークラスのインスタンスかどうかを判定できる。
  • a.getClass().isAssignableFrom(A.class)
詳しくは Class クラスのAPI仕様書を参考のこと。

posted at 19:28 | category: /Java/tips | 固定リンク(あるオブジェクトがあるクラスのオブジェクトかどうかを判定する )

RMIの例

RMI の例として、クライアント側の名前を登録、解除、および 現在登録されている名前全てを得る RMI サーバを作成。 チャットなどに応用できるだろう。

$ javac MyRemote.java
$ javac MyServer.java
$ javac MyClient.java
$ rmi MyServer

とした後に、

$ java MyServer

と実行し、 同じホスト上で、

$ java MyClient

とすると、

server> John Lennon
-------------------------
server> John Lennon
server> Paul McCartney
server> George Harrison
server> Ringo Starr
-------------------------
server> Paul McCartney
server> Ringo Starr
-------------------------

のように表示されるはず。

posted at 19:03 | category: /Java/tips | 固定リンク(RMIの例 )

ThreadのOn/Off

Thread の制御には wait() と notify() が用意されているが、 多くのサンプルでは Thread を起動するたびにインスタンス化して、不要になったら null を代入することで実現している。それでできてしまうのだから問題ないと言う 考え方もあるだろうが、ここでは wait() notify() を使う方法を考えてみよう。

基本

  • wait() でスレッドを待機状態にする
  • notify() でスレッドを再開する
  • wait() と notify() は synchronized させる

同じスレッドの wait() と notify() を実行することと、実行するときに syncronized(スレッドのオブジェクト)で同期させる。 以下にアプレットでスレッドを使うときの例を挙げる。

/*
<applet code="AppletOnOff" width="100" height="100">
</applet>
 */
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class AppletOnOff extends Applet{
    TextField tf;
    long n = 0;
    SuspendableThread th;
    Button btn;

    public void init(){
	add(btn = new Button("START"));
	add(tf = new TextField(Long.toString(n),10));
	btn.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent evt){
		    if(btn.getLabel().equals("START")){
			th.restartThread();
			btn.setLabel("STOP");
		    }else{
			th.suspendThread();
			btn.setLabel("START");
		    }
		}
	    });
	th = new SuspendableThread();
	th.start();
    }

    class SuspendableThread extends Thread{
	boolean flag = false;

	public void suspendThread(){
	    flag = false;
	}
	
	public void restartThread(){
	    flag = true;
	    synchronized(this){
		notify();
	    }
	}
	
	public void run(){
	    while(true){
		try{
		    th.sleep(100);
		    if(!flag){
			synchronized(this){
			    wait();
			}
		    }
		}catch(InterruptedException e){
		}
		n++;
		tf.setText(Long.toString(n));
	    }
	}
    }
}

posted at 18:48 | category: /Java/tips | 固定リンク(ThreadのOn/Off )

Java3D リンク集

Java 3D(TM) API Home Page
Sun による本家ホームページ。API の仕様書も読める。
Java 3D for Linux: Status and Information
Linux 用の Java3D の開発元 Blackdown
Java Friendly Society
「Java3Dプログラミング・バイブル」についての情報など。
Atsushi's Homepage 〜 Java3DTips
Atsushi さんによる Tips。大変役に立つページです。
Java 3D API Collateral
SUN が出している公式のAPI解説書。これを熟読すれば、他の解説書は要らな いかもしれません。
The Java 3D Community
総合的なサイトとしてはまずここがお勧め。ただし英語。困ったときは まずここの FAQ にあたると解決することも。
Java 3D Programming
英語の本です。ebook Edition をダウンロードすることができます。 API の仕様について細かく解説している本。一通りプログラムの作り方が わかった後に、自分の実現したいことを調べるのに役にたつ。
Java 3D
ABA さんのペ−ジ。Java3D で作ったゲ−ムなどがある。
vecmath package
Kenji Hiranabe さんの unofficial Java3D vecmath package。 「vecmath を理解するための数学」は必読。
Archives of JAVA3D-INTEREST@JAVA.SUN.COM
java3d-interest メーリングリストの過去記事が読めます。

posted at 13:55 | category: /Java/Java3D | 固定リンク(Java3D リンク集 )

Fri, 06 Jan 2006

カルマン渦

カルマン渦のプログラム

posted at 04:11 | category: /Program/Physics | 固定リンク(カルマン渦 )

デローニー

Delaunay2D

posted at 04:10 | category: /Program | 固定リンク(デローニー )

ニューラルネット

隠れ層が1000個ある3層ニューラルネットで2次関数の近似

posted at 04:09 | category: /Program | 固定リンク(ニューラルネット )

EMアルゴリズム

EMアルゴリズム

EMアルゴリズムで混合正規分布の学習を行います。

posted at 04:09 | category: /Program | 固定リンク(EMアルゴリズム )

Java Web Start で Java3D

Java Web Startの例

Java Web Start を使って Java3D のアプリケーションを起動してみます。

posted at 04:08 | category: /Program | 固定リンク(Java Web Start で Java3D )