ホモサピエンス

戻る

::::::::::::::
Animal.java
::::::::::::::
/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
*/
public interface Animal {
    public void move();
}
::::::::::::::
Ape.java
::::::::::::::
import javax.swing.*;

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

/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class Ape implements Animal {
    /** 頭の中心座標 */
    private Point head;
    /** 頭の半径 */
    private double headSize = 10.0;
    /** 首根っこ */
    private Point scrag;
    /** 首の長さ */
    private double lengthOfNeck = 10.0;
    /** 尻 */
    private Point hip;

    public Ape( double x, double y ) {
        head = new Point( x, y );
        scrag = new Point( head.getX(), head.getY() + lengthOfNeck );
        hip = new Point( scrag.getX() + 2.5, scrag.getY() + 20.0 );
    }

    public void move() {}

    public void paint( Graphics g ) {

        g.setColor( Color.green );

        // 頭を描画
        g.fillOval( ( int ) ( head.getX() - 0.5 * headSize ), ( int ) ( head.getY() - 0.5 * headSize ), ( int ) headSize, ( int ) headSize );
        // 首を描く
        g.drawLine( ( int ) head.getX(), ( int ) head.getY(), ( int ) scrag.getX(), ( int ) scrag.getY() );
        // 背骨を描く
        g.drawLine( ( int ) scrag.getX(), ( int ) scrag.getY(), ( int ) hip.getX(), ( int ) hip.getY() );

    }
}
::::::::::::::
Branch.java
::::::::::::::
import java.util.*;
import javax.swing.*;

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

/**
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuhiro
* 描画はBranchManagerに任せる
*/

public class Branch implements Runnable {
    /** 寿命 */
    private int lifeDuration = 200;
    /** 現在の年齢 */
    private int currentAge = 0;
    /** 1年で伸びる長さ */
    private double pitch;
    /** 角度 */
    private double angle;
    private Point from;
    private Point to;
    private BranchManager manager;
    private Map map;
    /** 描画色 */
    private Color color = Color.red;

    public Branch( BranchManager manager, double angle, Point from, double pitch ) {
        this.manager = manager;
        this.angle = angle;

        this.from = from;
        this.to = new Point( from.getX(), from.getY() );

        this.pitch = pitch;

        // BranchManagerにこのインスタンスを登録
        manager.addBranch( this );

        // 子供の枝を生成するタイミングを設定する
        MilestoneProvider milestoneProvider = new MilestoneProvider( lifeDuration );
        map = milestoneProvider.getMilestones();

        // 自身のスレッド開始
        ( new Thread( this ) ).start();
    }

    /** 描画色を決める */
    public void setColor( Color color ) {
        this.color = color;
    }

    public void run() {

        while ( isGrowable() ) {
            // 増分を求める
            double deltaX = pitch * Math.cos( HomoSapiensUtil.degreeToRadian( angle ) );
            double deltaY = pitch * Math.sin( HomoSapiensUtil.degreeToRadian( angle ) );

            // 増分を与える
            to.add( deltaX, deltaY );

            // System.out.printf( "%8.3f - %8.3f\n", to.getX(), to.getY() );

            currentAge++;

            // 子供の枝を生成する
            beget();

            try {
                Thread.sleep( 100 );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }

    }

    private void beget() {
        if ( !manager.isAcceptable() ) {
            //-----------------------------------------------------
            // 枝の数の上限を超えたら、新たな枝を生成しない
            //-----------------------------------------------------
            return ;
        }

        //-------------------------------------------------------------
        // 子供の枝を生成させる年齢に達したかどうかをチェックする
        //-------------------------------------------------------------
        Integer key = new Integer( currentAge );
        if ( map.containsKey( key ) ) {
            Double value = ( Double ) map.get( key );
            System.out.printf( "%3d %6.2f\n", key.intValue(), value.doubleValue() );

            // 新たな枝の開始位置
            Point newFrom = new Point( to.getX(), to.getY() );
            Branch newBranch = new Branch( manager, angle + value, newFrom, pitch * 0.8 );
            newBranch.setColor( color );
        }
    }

    /** 成長可能かどうか */
    private boolean isGrowable() {
        return currentAge < lifeDuration;
    }

    public void paint( Graphics g ) {

        g.setColor( color );
        g.drawLine( ( int ) from.getX(), ( int ) from.getY(), ( int ) to.getX(), ( int ) to.getY() );

    }

    static public void main( String[] args ) {
        BranchManager manager = new BranchManager( 500 );

        Point from = new Point( 0.0, 0.0 );
        Branch branch = new Branch( manager, 90.0, from, 1.0 );
    }
}
::::::::::::::
BranchManager.java
::::::::::::::
import java.util.*;
import javax.swing.*;

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

/**
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuhiro
* 複数のブランチを管理するクラス
*/

public class BranchManager {
    /** 許容最大数 */
    private int permissibleCount;
    private java.util.List list = new LinkedList();

    public BranchManager( int permissibleCount ) {
        this.permissibleCount = permissibleCount;
        ;
    }

    public void addBranch( Branch branch ) {
        list.add( branch );
    }

    public int getSize() {
        return list.size();
    }

    public synchronized boolean isAcceptable() {
        return permissibleCount > list.size();
    }

    public synchronized void paintAll( Graphics g ) {
        Iterator iterator = list.iterator();
        while ( iterator.hasNext() ) {
            Branch branch = ( Branch ) iterator.next();
            branch.paint( g );
        }
    }
}
::::::::::::::
Centipede.java
::::::::::::::
import java.util.*;
import javax.swing.*;

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

/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class Centipede implements Animal {
    private int count;
    private int angle = 0;
    private java.util.List pointList = new LinkedList();
    /** 節点間の距離 */
    private double segmentLength = 128.0;

    public Centipede( double sx, double sy, int count ) {
        this.count = count;

        double[] point = new double[ 2 ];
        point[ 0 ] = sx;
        point[ 1 ] = sy;
        pointList.add( point );

        for ( int i = 1;i < count;i++ ) {
            double[] nextPoint = new double[ 2 ];

            sy += segmentLength;
            nextPoint[ 0 ] = sx;
            nextPoint[ 1 ] = sy;

            pointList.add( nextPoint );
        }

        System.out.println( pointList.size() );

    }

    public void move() {

        angle++;
        if ( angle == 360 ) {
            angle = 0;
        }

        // 先頭の点を移動させる
        double[] point	= ( double[] ) pointList.get( 0 );
        point[ 0 ] = 400 + 321 * Math.cos( Math.PI * angle / 60.0 );
        point[ 1 ] = 200 + 250 * Math.sin( Math.PI * angle / 240.0 );

        // 追従する点の座標を求める
        double[] attractor = point;
        for ( int i = 1;i < count;i++ ) {
            double[] follower = ( double[] ) pointList.get( i );

            //===================================================
            // アトラクタが動いた後の距離を求める
            //===================================================
            double newDistance = HomoSapiensUtil.getDistance( attractor, follower );

            //System.out.printf("-- %8.2f\n", newDistance);

            //===================================================
            // フォロワの次の位置を取得し、更新する
            //===================================================
            double xDiff = attractor[ 0 ] - follower[ 0 ];
            double yDiff = attractor[ 1 ] - follower[ 1 ];

            follower[ 0 ] += xDiff * ( segmentLength / newDistance );
            follower[ 1 ] += yDiff * ( segmentLength / newDistance );

            attractor = follower;
        }
    }

    public void paint( Graphics g ) {

        g.setColor( Color.white );
        for ( int i = 1;i < count;i++ ) {
            double[] from = ( double[] ) pointList.get( i - 1 );
            double[] to = ( double[] ) pointList.get( i );

            g.drawLine( ( int ) from[ 0 ], ( int ) from[ 1 ], ( int ) to[ 0 ], ( int ) to[ 1 ] );
        }
    }

    public void dumpAll() {
        Iterator iterator = pointList.iterator();
        while ( iterator.hasNext() ) {
            double[] point = ( double[] ) iterator.next();
            System.out.printf( "(%8.2f - %8.2f) ", point[ 0 ], point[ 1 ] );
        }
        System.out.println();
    }

    // 単体試験用
    public static void main( String[] args ) {

        Centipede centipede = new Centipede( 10.0, 0.0, 4 );
        centipede.dumpAll();

        for ( int i = 0;i < 50;i++ ) {
            centipede.move();
            centipede.dumpAll();
        }

    }
}
::::::::::::::
DrawingPanel.java
::::::::::::::
import javax.swing.*;

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

/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class DrawingPanel extends JPanel implements Runnable {
    private Ape ape;
    private Centipede centipede;
    private Plant plant;
    private PlantPainter plantPainter;
    private BranchManager branchManager;
    private BranchManager branchManager2;
    private BranchManager branchManager3;
    private Branch branch;
    private Branch branch2;
    private Branch branch3;
    private final double[] CENTER_POINT = {400.0, 300.0};
    private double rotationAngle = 0.0;

    public DrawingPanel() {

        System.out.println( isDoubleBuffered() );
        setDoubleBuffered( true );
        System.out.println( isDoubleBuffered() );

        //--------------------------------
        // お猿さん
        //--------------------------------
        ape = new Ape( 30, 50 );

        //--------------------------------
        // ムカデ
        //--------------------------------
        centipede = new Centipede( 400.0, 300.0, 500 );

        //--------------------------------
        // 植物
        //--------------------------------
        Point start = new Point( 200.0, 5.0 );
        plant = new Plant( start, 90.0, 3, 5, 60.0 );

        //--------------------------------
        // 枝
        //--------------------------------
        branchManager = new BranchManager( 1000 );
        branch = new Branch( branchManager, -90.0, new Point( 400, 600 ), 1.0 );
        branch.setColor( Color.blue );

        branchManager2 = new BranchManager( 2000 );
        branch2 = new Branch( branchManager2, -90.0, new Point( 200, 600 ), 0.5 );
        branch2.setColor( Color.red );

        branchManager3 = new BranchManager( 500 );
        branch3 = new Branch( branchManager, -90.0, new Point( 600, 600 ), 0.75 );
        branch3.setColor( Color.yellow );

        // スレッド開始
        Thread thread = new Thread( this );
        thread.start();
    }

    public void run() {
        while ( true ) {

            // System.out.println( ( new java.util.Date() ).toString() );

            SwingUtilities.invokeLater(
                new Runnable() {
                    public void run() {
                        repaint();
                    }
                }
            );

            try {
                Thread.sleep( 100 );
            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }

    public void paintComponent( Graphics g ) {

        int width = getWidth();
        int height = getHeight();

        //--------------------------------------------------
        // 画面クリア
        //--------------------------------------------------
        g.setColor( Color.black );
        //--------------------------------------------------
        // このコンポーネントのサイズを取得する
        //--------------------------------------------------
        g.fillRect( 0 , 0 , width , height );

        // お猿さん
        ape.move( );
        ape.paint( g );

        // ムカデ(ムカデに見えない)
        centipede.move( );
        centipede.paint( g );

        // 植物を描画してくれるクラスに線分のリストを引き渡す
        rotationAngle += 5.0;
        java.util.List rotatedSegmentList = SegmentRotator.getList( plant.getSegmentList(), CENTER_POINT, rotationAngle );
        plantPainter = new PlantPainter( rotatedSegmentList );
        plantPainter.paint( g );

        // 枝
        branchManager.paintAll( g );
        branchManager2.paintAll( g );
        branchManager3.paintAll( g );
    }

}
::::::::::::::
HomoSapiens.java
::::::::::::::
import javax.swing.*;

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

/**
* <pre>
* 人の動きをシミュレーションするApplet
* </pre>
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuhiro
*/

public class HomoSapiens extends JApplet {

    public void init() {

        Container contentPane = getContentPane();
        contentPane.setLayout( new FlowLayout() );

        DrawingPanel dp = new DrawingPanel();
        dp.setPreferredSize( new Dimension( getWidth() , getHeight() ) );

        contentPane.add( dp );

    }

}


::::::::::::::
HomoSapiensUtil.java
::::::::::::::
/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
*/

public class HomoSapiensUtil {

    /** 2点間の距離を求める */
    static public double getDistance( double[] from , double[] to ) {
        return Math.sqrt(
                   ( from[ 0 ] - to[ 0 ] ) * ( from[ 0 ] - to[ 0 ] )
                   + ( from[ 1 ] - to[ 1 ] ) * ( from[ 1 ] - to[ 1 ] )
               );
    }

    /** 2点間の距離を求める */
    static public double getDistance( Point from , Point to ) {
        return Math.sqrt(
                   ( from.getX() - to.getX() ) * ( from.getX() - to.getX() )
                   + ( from.getY() - to.getY() ) * ( from.getY() - to.getY() )
               );
    }

    /** 線分の傾きを角度で返す
    * @param from 開始点
    * @param to 終了点
    * @return 角度
    */
    static double getAngle( double[] from , double[] to ) {
        double xDiff = to[ 0 ] - from[ 0 ];
        double yDiff = to[ 1 ] - from[ 1 ];

        // 傾きを得る
        double gradient = yDiff / xDiff;

        // DEGREE(度)で返す
        return Math.atan( gradient ) * 180.0 / Math.PI;
    }

    /** 角度をラジアンに変換して返す */
    static double degreeToRadian( double angle ) {

        return angle * Math.PI / 180.0;
    }

    /** 指定した点を中心にある角度だけ回転させる */
    static double[] rotate( double[] originalPoint, double[] centerPoint, double rotationAngle ) {
        double[] newPoint = new double[ 2 ];

        double radius = getDistance( centerPoint, originalPoint );
        // System.out.println( "radius=" + radius );

        double currentAngle = getAngle( centerPoint, originalPoint );
        // System.out.println( "currentAngle=" + currentAngle );

        double nextAngle = currentAngle + rotationAngle;
        // System.out.println( "nextAngle=" + nextAngle );

        newPoint[ 0 ] = centerPoint[ 0 ] + radius * Math.cos( nextAngle / 180.0 * Math.PI );
        newPoint[ 1 ] = centerPoint[ 1 ] + radius * Math.sin( nextAngle / 180.0 * Math.PI );

        return newPoint;
    }
}
::::::::::::::
MilestoneProvider.java
::::::::::::::
import java.util.*;

/**
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuhiro
*/

public class MilestoneProvider {
    private Map milestones;

    public MilestoneProvider( int lifeDuration ) {
        /** 人生のうちに3回岐路がある? */

        milestones = new TreeMap();

        int first = lifeDuration / 2;
        milestones.put( new Integer( first ), new Double( getFluctuation() ) );

        int second = lifeDuration * 3 / 4;
        milestones.put( new Integer( second ), new Double( getFluctuation() ) );

        int third = lifeDuration * 7 / 8 ;
        milestones.put( new Integer( third ), new Double( getFluctuation() ) );
    }

    /** 揺らぎを取得する */
    private double getFluctuation() {
        Random random = new Random();

        // -45.0から+45.0の範囲内に収まるようにする
        return random.nextDouble() * 90.0 - 45.0;
    }

    public Map getMilestones() {
        // メソッドの戻り値の型は極力インタフェースあるは抽象クラスを使う!
        return milestones;
    }

    // 単体試験
    static public void main( String[] args ) {
        if ( args.length != 1 ) {
            System.out.println( "Usage: java MilestoneProvider [lifeDuration]" );
            System.exit( 1 );
        }

        MilestoneProvider mp = new MilestoneProvider( new Integer( args[ 0 ] ).intValue() );

        Map map = mp.getMilestones();
        Iterator iterator = map.keySet().iterator();
        while ( iterator.hasNext() ) {
            Integer key = ( Integer ) iterator.next();
            Double value = ( Double ) map.get( key );

            System.out.printf( "%3d %6.2f\n", key.intValue(), value.doubleValue() );
        }
    }
}

::::::::::::::
Plant.java
::::::::::::::
import java.util.*;

/**
* <pre>
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuiro
* 植物を表現するクラス(MODEL)
* </pre>
*/
public class Plant {
    private int childrenCount;
    private int depth;
    private double segmentLength;

    /** 最初に与える点 */
    private Point startPoint;
    /** 生成した線分をリストに格納したもの */
    private List segmentList = new LinkedList();

    public Plant( Point startPoint, double firstAngle, int childrenCount, int depth, double segmentLength ) {
        this.startPoint = startPoint;
        this.childrenCount = childrenCount;
        this.depth = depth;
        this.segmentLength = segmentLength;

        // 初期の角度を与える
        generate( startPoint, firstAngle, 0 );
    }

    private void generate( Point startPoint, double angle, int layer ) {

        if ( layer < depth ) {

            // 子ノードに与える角度を求める
            double[] nextAngles = getNextAngles( angle, layer );

            // 子ノードを生成する
            for ( int i = 0;i < childrenCount;i++ ) {

                double x = startPoint.getX() + segmentLength * Math.cos( nextAngles[ i ] * Math.PI / 180.0 );
                double y = startPoint.getY() + segmentLength * Math.sin( nextAngles[ i ] * Math.PI / 180.0 );
                Point nextStartPoint = new Point( x, y );

                // 線分を生成
                Segment segment = new Segment( startPoint, nextStartPoint );
                // segment.dump();

                // 線分をリストに追加
                segmentList.add( segment );

                // 再帰処理
                generate( nextStartPoint, nextAngles[ i ], layer + 1 );
            }
        }
    }

    private double[] getNextAngles( double angle, int layer ) {
        double[] nextAngles = new double[ childrenCount ];
        double range = 30.0;
        double diff = range / ( childrenCount - 1 );
        double firstAngle = angle - range / 2.0;

        /*
               indent( layer );
               System.out.printf( "もともとの角度=%6.3f\n" , angle );
        */

        for ( int i = 0;i < childrenCount;i++ ) {
            nextAngles[ i ] = firstAngle + i * diff;
            /*
                      indent( layer );
                      System.out.printf( "--得られた角度=%6.3f\n" , nextAngles[ i ] );
            */
        }
        return nextAngles;
    }

    public List getSegmentList() {
        return segmentList;
    }

    /** インデントする */
    private void indent( int layer ) {
        for ( int i = 0;i < layer;i++ ) {
            System.out.print( "  " );
        }
    }

    // 単体試験
    static public void main( String[] args ) {

        if ( args.length != 2 ) {
            System.out.println( "Usage: java Plant [childrenCount] [nodeDepth]" );
            System.exit( 1 );
        }

        Point start = new Point( 0.0, 0.0 );
        double firstAngle = 0.0;

        // インスタンス化およびツリーの生成
        Plant plant = new Plant( start, firstAngle, new Integer( args[ 0 ] ).intValue(), new Integer( args[ 1 ] ).intValue(), 10.0 );

    }
}
::::::::::::::
PlantPainter.java
::::::::::::::
import java.util.*;
import javax.swing.*;

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

/**
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuhiro
* 植物を描画するクラス
*/

public class PlantPainter {

    private java.util.List segmentList;

    public PlantPainter( java.util.List segmentList ) {
        this.segmentList = segmentList;

    }
    public void paint( Graphics g ) {

        g.setColor( new Color( 0xcc, 0xcc, 0xff ) );
        Iterator iterator = segmentList.iterator();
        while ( iterator.hasNext() ) {
            Segment segment = ( Segment ) iterator.next();

            Point from = segment.getFrom();
            Point to = segment.getTo();

            g.drawLine( ( int ) from.getX(), ( int ) from.getY(), ( int ) to.getX(), ( int ) to.getY() );
        }
    }
}
::::::::::::::
Point.java
::::::::::::::
/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
*/
public class Point {
    private double x, y;

    public Point( double x, double y ) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return x;
    }
    public double getY() {
        return y;
    }

    public void set
        ( double x, double y ) {
        this.x = x;
        this.y = y;
    }

    /** x,yの座標値を配列で返す */
    public double[] get
        () {
        double[] value = new double[ 2 ];

        value[ 0 ] = x;
        value[ 1 ] = y;
        return value;
    }

    public void add
        ( double deltaX, double deltaY ) {
        x += deltaX;
        y += deltaY;
    }
}
::::::::::::::
Segment.java
::::::::::::::
/**
* <pre>
* $Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
* @author KISHI Yasuiro
* 線分を表現するクラス
* </pre>
*/
public class Segment {
    private Point from, to;

    public Segment( Point from , Point to ) {
        this.from = from;
        this.to = to;
    }

    public Point getFrom() {
        return from;
    }
    public Point getTo() {
        return to;
    }

    public void dump() {
        System.out.printf( "( %6.3f, %6.3f ) - ( %6.3f, %6.3f )\n",
                           from.getX(), from.getY(),
                           to.getX(), to.getY() );
    }
}
::::::::::::::
SegmentRotator.java
::::::::::::::
import java.util.*;

/**
$Id: homo.html,v 1.1 2009/06/22 16:12:12 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class SegmentRotator {

    static public List getList( List segmentList, double[] centerPoint, double angle ) {
        List list = new LinkedList();

        Iterator iterator = segmentList.iterator();
        while ( iterator.hasNext() ) {

            Segment segment = ( Segment ) iterator.next();
            Point from = segment.getFrom();
            Point to = segment.getTo();

            double[] newFrom = HomoSapiensUtil.rotate( from.get(), centerPoint, angle );
            double[] newTo = HomoSapiensUtil.rotate( to.get(), centerPoint, angle );

            Segment newSegment = new Segment(
                                     new Point( newFrom[ 0 ], newFrom[ 1 ] )
                                     , new Point( newTo[ 0 ], newTo[ 1 ] ) );

            list.add( newSegment );

        }

        return list;
    }

}

戻る inserted by FC2 system