#author("2019-06-05T11:34:31+09:00","default:qua","qua")
#navi(Processing/3.ライブラリの利用)
* 4-2 Fisicaの図形の描き方 [#yd58001a]
#author("2019-06-05T12:09:35+09:00","default:qua","qua")

次のスケッチを実行してみよう。
 import fisica.*;
 
 FWorld world;
 FCircle ball1, ball2;
 
 void setup(){
   size(600,300);
   Fisica.init(this);
   world = new FWorld();
   world.setEdges();
   world.setEdgesFriction( 0 );
   ball1=new FCircle(40);
   ball1.setDamping( 0 );
   ball1.setDensity( 2 );
   ball1.setFriction( 0.1 );
   ball1.setRestitution( 1 );
   ball1.setPosition( 50, 274.5 );
   ball1.setGrabbable( false );
   ball1.setFill( 128, 255, 128 );
   world.add( ball1 );
 
   ball2=new FCircle(40);
   ball2.setDamping( 0 );
   ball2.setDensity( 4 );
   ball2.setFriction( 0.1 );
   ball2.setRestitution( 1 );
   ball2.setPosition( 200, 274.5 );
   ball2.setGrabbable( false );
   ball2.setFill( 255, 128, 128 );
   world.bottom.setFill(128);
   world.top.setFill(128);
   world.left.setFill(192);
   world.right.setFill(192);
   world.bottom.setStroke(128);
   world.top.setStroke(128);
   world.left.setStroke(192);
   world.right.setStroke(192);
   world.add( ball2 );
 }
 
 void mouseClicked(){
   if( dist( mouseX, mouseY, ball1.getX(), ball1.getY()) < ball1.getSize() ){
     ball1.addImpulse( ball1.getMass()*200, 0, mouseX-ball1.getX(), mouseY-ball1.getY() );
   }
 }
 
 void draw(){
   background(0);
   world.step();
   world.draw();
 }
これを実行すると、左側の球をマウスでクリックすると、クリックした点に力積が加えられる。
#ref(http://www.ist.aichi-pu.ac.jp/lab/qua/~qua/pbl/processing/img/4-2-1.png,450x245)
これだけでは、どこをクリックしてもあまり様子が変わらない。そこで、球のどこかに目印をつけて回転する様子を眺めてみよう。それには、自前のクラスMyBallを作成して、描き方だけを変えてみればよい。まず、クラスを定義する。
 class MyBall extends FCircle{
   MyBall( float r ){
     super( r );
   }
   public void draw(PGraphics applet) {
     preDraw(applet);
     if (m_image != null ) {
       drawImage(applet);
     } else {
       applet.ellipse(0, 0, getSize(), getSize());
       applet.fill( 0 );
       applet.ellipse( getSize()/3, 0, 3, 3 );
     }
     postDraw(applet);
   }
 }
1行目の
 class MyBall extends FCircle
では、FCircleクラスを拡張して、MyBallクラスを定義することを宣言している。次の
 MyBall( float r ){ super( r ); }
はnew MyBall( r )でインスタンスを作成するときに、拡張元であるFCircle( r )と同じ
コンストラクタを利用することを書いている。
 public void draw(PGraphics applet)
が球を描画する部分である。もともとのFCircleのdraw()は次の通りである。
 public void draw(PGraphics applet) {
   preDraw(applet);
   if (m_image != null ) {
     drawImage(applet);
   } else {
     applet.ellipse(0, 0, getSize(), getSize());
   }
   postDraw(applet);
 }
ここに 
   applet.fill( 0 );
   applet.ellipse( getSize()/3, 0, 3, 3 );
として、getSize()で得られる直径の1/3のところに半径3の黒い点を追加して描く。
あとは、FCircleをMyBallに置き換えればよい。その結果を下記に示す。

 import fisica.*;
 
 FWorld world;
 MyBall ball1, ball2;
 
 class MyBall extends FCircle{
   MyBall( float r ){
     super( r );
   }
   public void draw(PGraphics applet) {
     preDraw(applet);
 
     if (m_image != null ) {
       drawImage(applet);
     } else {
       applet.ellipse(0, 0, getSize(), getSize());
       applet.fill( 0 );
       applet.ellipse( getSize()/3, 0, 3, 3 );
     }
 
     postDraw(applet);
   }
 }
 
 
 void setup(){
   size(600,300);
   Fisica.init(this);
   world = new FWorld();
   world.setEdges();
   world.setEdgesFriction( 0 );
   ball1=new MyBall(40);
   ball1.setDamping( 0 );
   ball1.setDensity( 2 );
   ball1.setFriction( 0.1 );
   ball1.setRestitution( 1 );
   ball1.setPosition( 50, 274.5 );
   ball1.setGrabbable( false );
   ball1.setFill( 128, 255, 128 );
   world.add( ball1 );
 
   ball2=new MyBall(40);
   ball2.setDamping( 0 );
   ball2.setDensity( 4 );
   ball2.setFriction( 0.1 );
   ball2.setRestitution( 1 );
   ball2.setPosition( 200, 274.5 );
   ball2.setGrabbable( false );
   ball2.setFill( 255, 128, 128 );
   world.bottom.setFill(128);
   world.top.setFill(128);
   world.left.setFill(192);
   world.right.setFill(192);
   world.bottom.setStroke(128);
   world.top.setStroke(128);
   world.left.setStroke(192);
   world.right.setStroke(192);
   world.add( ball2 );
 }
 
 void mouseClicked(){
   if( dist( mouseX, mouseY, ball1.getX(), ball1.getY()) < ball1.getSize() ){
     ball1.addImpulse( ball1.getMass()*200, 0, mouseX-ball1.getX(), mouseY-ball1.getY() );
   }
 }
 
 
 void draw(){
   background(0);
   world.step();
   world.draw();
 }
#ref(http://www.ist.aichi-pu.ac.jp/lab/qua/~qua/pbl/processing/img/4-2-2.png,450x245)

調子に乗って、3次元的に描いてみる。上のプログラムとの違いは、
- MyBallクラスのdraw()で、ellipseではなく、sphereで立体的に描いていること
- size(600,300,P3D)で3次元描画にしていること
- setup内で壁(world.top, world.bottom, world.left, world.right)を描かないように設定し、その代わりに、drawEdges()関数を用いて立体的に描いていること
- 計算が面倒なので、マウスのクリックの処理を手抜きしていること

 import fisica.*;
 
 FWorld world;
 MyBall ball1, ball2;
 FBox bottom;
 
 class MyBall extends FCircle{
   MyBall( float r ){
     super( r );
   }
   public void draw(PGraphics applet) {
     preDraw(applet);
     if (m_image != null ) {
       drawImage(applet);
     } else {
       applet.sphere( getSize()/2 );
     }
     postDraw(applet);
   }
 }
 
 void setup(){
   size(600,300,P3D);
   Fisica.init(this);
   world = new FWorld();
   world.setEdges();
   world.setEdgesFriction( 0 );
   ball1=new MyBall(60);
   ball1.setDamping( 0 );
   ball1.setDensity( 2 );
   ball1.setFriction( 0.1 );
   ball1.setRestitution( 1 );
   ball1.setPosition( 50, 264.5 );
   ball1.setGrabbable( false );
   ball1.setFill( 128, 255, 128 );
   ball1.setNoStroke();
   world.add( ball1 );
 
   ball2=new MyBall(60);
   ball2.setDamping( 0 );
   ball2.setDensity( 4 );
   ball2.setFriction( 0.1 );
   ball2.setRestitution( 1 );
   ball2.setPosition( 200, 264.5 );
   ball2.setGrabbable( false );
   ball2.setFill( 255, 128, 128 );
   ball2.setNoStroke();
   world.add( ball2 );
   world.bottom.setNoFill();
   world.top.setNoFill();
   world.left.setNoFill();
   world.right.setNoFill();
   world.bottom.setNoStroke();
   world.top.setNoStroke();
   world.left.setNoStroke();
   world.right.setNoStroke();
   println( world.bottom.getY() );
 }
 
 void drawEdges(){
   pushMatrix();
   translate( world.bottom.getX(), world.bottom.getY(), 0 );
   rotateX(radians(90));
   fill( 128 );
   rect( -500, -500, 1000, 1000 );
   popMatrix();
   pushMatrix();
   translate( world.left.getX(), world.left.getY(), 0 );
   rotateY(radians(90));
   fill( 192 );
   rect( -500, -500, 1000, 1000 );
   popMatrix();
   pushMatrix();
   translate( world.right.getX(), world.right.getY(), 0 );
   rotateY(radians(90));
   fill( 192 );
   rect( -500, -500, 1000, 1000 );
   popMatrix();
 }  
 
 void mouseClicked(){
     ball1.addImpulse( ball1.getMass()*200, 0 );
 }
 
 
 void draw(){
   background(0);
   lights();
   drawEdges();
   translate( 0, 0, -100 );
   world.step();
   world.draw();
 }
#ref(http://www.ist.aichi-pu.ac.jp/lab/qua/~qua/pbl/processing/img/4-2-3.png,450x245)


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS