正弦波の合成とベルハルストの曲線

戻る

::::::::::::::
CommonView.java
::::::::::::::
import java.awt.*;
import java.util.*;

/**
* $Id: composite.html,v 1.1 2009/06/22 16:12:07 kishi Exp kishi $
* @author KISHI Yasuhiro
* 2次元座標をリスト化したものを線分で繋いで描画する汎用クラス 
*/

public class CommonView implements Paintable {

    private java.util.List list;
    private Color color;

    public void setModel( java.util.List list, Color color ) {
        this.list = list;
        this.color = color;
    }

    public void paint( Graphics g ) {
        for ( int i = 1;i < list.size();i++ ) {

            g.setColor( color );
            double[] from = ( double[] ) list.get( i - 1 );
            double[] to = ( double[] ) list.get( i );
            g.drawLine( ( int ) from[ 0 ], ( int ) from[ 1 ], ( int ) to[ 0 ], ( int ) to[ 1 ] );

        }
    }
}
::::::::::::::
CompositeWaveModel.java
::::::::::::::
import java.util.*;

/**
$Id: composite.html,v 1.1 2009/06/22 16:12:07 kishi Exp kishi $
*/

public class CompositeWaveModel {

    private double verticalPosition;

    /** WaveModelを格納するリスト */
    private List waveList;

    /** 複数個のWaveModelから得られた座標を合成した結果を格納する配列 */
    private double[][] compositePoint;

    /** 計算結果を格納するリスト */
    private List pointList;

    private int count;

    public CompositeWaveModel( double verticalPosition , int count ) {
        this.verticalPosition = verticalPosition;
        this.count = count;

        waveList = new LinkedList();
        pointList = new LinkedList();

        compositePoint = new double[ count ][];
        for ( int i = 0;i < count;i++ ) {
            compositePoint[ i ] = new double[ 2 ];
        }
    }

    public List getList() {
        return pointList;
    }

    public void addWaveModel( WaveModel waveModel ) {
        waveList.add( waveModel );
    }

    /** 合成した座標の最新の値を求める */
    public void recalculate() {

        // 合計値を初期化
        for ( int i = 0;i < count;i++ ) {
            compositePoint[ i ][ 0 ] = 0.0;
            compositePoint[ i ][ 1 ] = 0.0;
        }

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

            WaveModel model = ( WaveModel ) iterator.next();

            // 波モデルが持つ現在の座標をリストで取得
            List points = model.getList();

            for ( int i = 0;i < count;i++ ) {
                double[] point = ( double[] ) points.get( i );

                // System.out.printf( "X=%8.3f", point[ 0 ] );
                // System.out.printf( "Y=%8.3f", point[ 1 ] );
                // System.out.println();

                // X座標
                compositePoint[ i ][ 0 ] = point[ 0 ];
                // Y座標には垂直位置の基準点も加算する
                compositePoint[ i ][ 1 ] += ( point[ 1 ] + verticalPosition );
            }

        }

        // リストを全クリア
        pointList.clear();
        for ( int i = 0;i < count;i++ ) {
            double[] point = new double[ 2 ];
            point[ 0 ] = compositePoint[ i ][ 0 ];
            point[ 1 ] = compositePoint[ i ][ 1 ];

            /*
                        System.out.printf( "X=%8.3f", point[ 0 ] );
                        System.out.printf( "Y=%8.3f", point[ 1 ] );
                        System.out.println();
            */

            pointList.add( point );
        }

    }

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

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

import java.io.*;

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

public class DrawingPanel extends JPanel implements Runnable {

    private WaveModel waveModel1, waveModel2;
    private CompositeWaveModel cwm;
    private LogisticCurveModel lcModel;
    private CommonView view1, view2, view3, view4;

    public DrawingPanel() {

        int pCount = 160;
        int pitch = 5;

        // 波#1
        waveModel1 = new WaveModel( 0.0, 50.0 );
        waveModel1.setParticleCount( pCount, pitch );
        waveModel1.setIntialAngle( 20.0 );
        waveModel1.setAnglularSpeed( 45.0 );
        waveModel1.setMaxHeight( 50.0 );
        waveModel1.setPhasePitch( 15.0 );
        waveModel1.init();

        view1 = new CommonView();
        view1.setModel( waveModel1.getList(), Color.green );

        // 波#2
        waveModel2 = new WaveModel( 0.0, 75.0 );
        waveModel2.setParticleCount( pCount, pitch );
        waveModel2.setIntialAngle( 20.0 );
        waveModel2.setAnglularSpeed( 60.0 );
        waveModel2.setMaxHeight( 75.0 );
        waveModel2.setPhasePitch( 25.0 );
        waveModel2.init();

        view2 = new CommonView();
        view2.setModel( waveModel2.getList(), Color.white );

        // 合成波
        cwm = new CompositeWaveModel( 100.0, pCount );
        cwm.addWaveModel( waveModel1 );
        cwm.addWaveModel( waveModel2 );

        view3 = new CommonView();
        view3.setModel( cwm.getList(), Color.red );

        // ベルハルストの曲線
        lcModel = new LogisticCurveModel( 160, 5, 300 );
        lcModel.setBirthRate( 1.0 );

        view4 = new CommonView();
        view4.setModel( lcModel.getList(), Color.yellow );

        /***************************************************************************************/
        /** ThreadクラスはRunnableインタフェースで実装されているクラスをrunさせることができる **/
        /***************************************************************************************/
        Thread thread = new Thread( this );
        thread.start();
    }

    public void run() {
        while ( true ) {

            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 );

        // 波#1
        waveModel1.move( );
        view1.paint( g );

        // 波#2
        waveModel2.move( );
        view2.paint( g );

        // 合成波
        //System.out.println( cwm.getList().size());
        cwm.recalculate( );
        view3.paint( g );

        // ベルハルストの曲線
        g.setColor( Color.yellow );
        StringBuilder message = new StringBuilder( "■ベルハルストの曲線 -- " );
        try {
            String currentBirthRate = sprintf( "%8.2f", lcModel.getBirthRate() );

            message.append( currentBirthRate );


        } catch ( Exception e ) {
            e.printStackTrace();
        }
        g.drawString( message.toString(), 10, 280 );

        lcModel.generate();
        view4.paint( g );

        lcModel.augmentBirthRate( 0.01 );
        if ( lcModel.getBirthRate() > 5.0 ) {
            lcModel.setBirthRate( 1.0 );
        }


    }

    static String sprintf( String format, Object obj ) throws Exception {

        String value = null;
        try {

            // C言語のsprinfもどき
            ByteArrayOutputStream baos = new ByteArrayOutputStream();

            PrintWriter pw = new PrintWriter( baos );
            pw.printf( format, obj );
            pw.flush();
            pw.close();

            value = baos.toString( "UTF8" );

            baos.close();


        } catch ( Exception e ) {
            throw e;
        } finally {

            return value;
        }

    }
}

::::::::::::::
LogisticCurveModel.java
::::::::::::::
import java.util.*;
/**
$Id: composite.html,v 1.1 2009/06/22 16:12:07 kishi Exp kishi $
*/

public class LogisticCurveModel {

    private double birthRate;
    private List list;
    private int pCount;
    private int pitch;
    private double verticalPosition;

    public LogisticCurveModel( int pCount, int pitch, double verticalPosition ) {
        this.pCount = pCount;
        this.pitch = pitch;
        this.verticalPosition = verticalPosition;

        list = new LinkedList();
    }

    public List getList() {
        return list;
    }

    public void setBirthRate( double birthRate ) {
        this.birthRate = birthRate;
    }
    public double getBirthRate() {
        return birthRate;
    }

    public void augmentBirthRate( double value ) {
        birthRate += value;
    }

    public void generate() {
        double height = 0.01;

        list.clear();

        for ( int i = 0;i < pCount;i++ ) {
            height = birthRate * height * ( 1 - height );

            if ( Math.abs( height * 100.0 ) >= 600.0 ) {
                // System.out.println("*** overflowed ***");
                break;
            }

            double[] point = new double[ 2 ];
            point[ 0 ] = i * pitch;
            point[ 1 ] = verticalPosition + height * 100.0;
            list.add( point );

        }

    }

    static public void main( String[] args ) {
        if ( args.length != 1 ) {
            System.out.println( "Usage: java LogisticCurveModel [birthRate]" );
            System.exit( 1 );
        }

        LogisticCurveModel lcModel = new LogisticCurveModel( 160, 5, 0 );
        double birthRate = new Double( args[ 0 ] ).doubleValue();
        lcModel.setBirthRate( birthRate );
        lcModel.generate();

        List list = lcModel.getList();
        Iterator iterator = list.iterator();
        int i = 0;
        while ( iterator.hasNext() ) {
            double[] point = ( double[] ) iterator.next();
            System.out.printf( "%3d: %8.3f\n", i, point[ 1 ] );

            i++;
        }
    }

}
::::::::::::::
Paintable.java
::::::::::::::
import java.awt.*;

/**
$Id: composite.html,v 1.1 2009/06/22 16:12:07 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public interface Paintable {

    public void paint( Graphics g );
}
::::::::::::::
WaveGenerator.java
::::::::::::::
import javax.swing.*;

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

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

public class WaveGenerator extends JApplet {

    public void init() {

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

        DrawingPanel dp = new DrawingPanel();
        dp.setPreferredSize( new Dimension( 800 , 600 ) );

        contentPane.add( dp );

    }

}

::::::::::::::
WaveModel.java
::::::::::::::
import java.util.*;

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

public class WaveModel {

    private List list;
    private double angle;
    private int count;
    private int horizontalPitch;
    private double x, y, maxHeight, phasePitch, angularSpeed;

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

    /** 粒子の数と水平のピッチを決める
    @param count 粒子の数
    @param horizontalPitch 粒子同士の水平の間隔
    */
    public void setParticleCount( int count, int horizontalPitch ) {
        this.count = count;
        this.horizontalPitch = horizontalPitch;
    }

    public void setIntialAngle( double initialAngle ) {
        this.angle = initialAngle;
    }

    public void setMaxHeight( double maxHeight ) {
        this.maxHeight = maxHeight;
    }

    public void setPhasePitch( double phasePitch ) {
        this.phasePitch = phasePitch;
    }

    public void setAnglularSpeed( double angularSpeed ) {
        this.angularSpeed = angularSpeed;
    }

    /** 初期状態をセットする */
    public void init() {
        list = new ArrayList();

        for ( int i = 0;i < count;i++ ) {
            double point[] = new double[ 2 ];
            point[ 0 ] = x + i * horizontalPitch;
            point[ 1 ] = y + getVerticalDisplacement( i );

            list.add( point );
        }
    }

    /** 角速度分移動する */
    public void move( ) {
        angle += angularSpeed;
        for ( int i = 0;i < list.size();i++ ) {
            // 各々のY座標を変更する
            rotate( ( double[] ) list.get( i ), i );
        }
    }

    public List getList() {
        return this.list;
    }

    /** 垂直方向の変位を求める */
    private double getVerticalDisplacement ( int i ) {
        return maxHeight * Math.sin( ( angle + i * phasePitch ) * Math.PI / 180.0 );
    }

    private void rotate( double[] point, int i ) {
        point[ 1 ] = y + getVerticalDisplacement( i );
    }

    public void dump() {

        System.out.println( "angle=" + angle );
        for ( int i = 0;i < list.size();i++ ) {
            double[] point = ( double[] ) list.get( i );
            System.out.print( "(x=" + point[ 0 ] );
            System.out.print( " " );
            System.out.print( "y=" + point[ 1 ] + ")" );
            System.out.print( " " );
        }
        System.out.println();

    }

    static public void main( String[] args ) {
        WaveModel wm = new WaveModel( 0.0, 0.0 );

        wm.setParticleCount( 5, 10 );
        wm.setMaxHeight( 30.0 );
        wm.setIntialAngle( 20.0 );
        wm.setAnglularSpeed( 6 );
        wm.setPhasePitch( 15.0 );
        wm.init();

        wm.dump();
        for ( int i = 0;i < 3;i++ ) {
            wm.move( );
            wm.dump();
        }
    }
}


戻る inserted by FC2 system