ともさんのHP >プロブラミング >自作JavaLibrary >JAVAでBスプライン曲線

JAVAでBスプラインを計算するクラス

Javaを使ってBスプラインを計算。線を画面に表示させるClassを作ってみました。
現在作っている描画アプリのための部品として作りました。

ソースのほうですが、いつものようにネットを回って諸先輩方のソースコードを大いに参考にさせていただきました。
ありがとうございます。
今回は特にこちら を参考にさせいただいております。

Bスプライン描画の概要

pointというクラスとlineというクラスをあらかじめ作っておきます。
pointには点の情報を入れ、lineには線情報が入ります。

広告

Bスプラインを引くための制御点をpoint配列で入れると、Bスプラインの線情報がLine配列で得られます。
下の絵が計算結果。制御点の最初と最後も都合により線の端に入っています。
JAVAでBスプライン

Bスプライン計算の仕方としくみ

どのように計算すると解が出てくるのか...私も理解せずに作っています。引けたラインがそれらしいので、OKとしています。

JavaBスプライン計算Class

ソースコードは以下の通り。

Java Class BSpline2

package tomojavalib.drawing;

import java.util.*;
import tomojavalib.drawing.*;

/*
 * Bスプライン曲線を計算するCLASS
 */

public class BSpline2 {
 // 制御点
 private Point p[];
 //制御点の数
 private int nPoints;
 // ノット値
 private double knot[];
 // Bスプライン曲線の次元数
 private int dimension = 3;
 //スプラインの構成線
 public Line line[];
 //スプラインの名前
 public String name ="";

  
public static void main(String[] args) 
{
 Point[] p = new Point[5];
 p[0]= new Point(100.,100.);
 p[1]= new Point(200.,150.);     
 p[2]= new Point(300.,300.);
 p[3]= new Point(400.,200.);  
 p[4]= new Point(500.,100.);
 BSpline2 bs = new BSpline2();
 bs.getBSpline( "name" , p );
 Line[] l = bs.line ;
 DrawFrame df = new DrawFrame( l, l.length );
 for(int I=0 ; I < l.length ; I++ )
 {
  System.out.println( "Line: " + l[I].stPoint.x +" "+ l[I].stPoint.y +" "+ l[I].endPoint.x +" "+ l[I].endPoint.y );  
 }       
}   
 
/*
 * 3点でBspline作成
 */
public void makeBspline3points(String n , Point p1, Point p2,Point p3 )
{
nPoints = 3;
dimension = 2;
name = n;
Point[] ptmp = {p1,p2,p3};
p = ptmp ;
knot = new double[ nPoints + dimension + 1 ];
for (int I = 0; I < nPoints+dimension; I++) { knot[I] = I - dimension; }
getLines();
}

/**
 * コンストラクタ
 */
public BSpline2() {} 
  
public void getBSpline( String n , Point[] point) 
{
 nPoints = point.length;
 if( nPoints ==3 ){ dimension = 2; } 
 p = point;
 knot = new double[ nPoints + dimension + 1 ];
 for (int I = 0; I < nPoints+dimension; I++) { knot[I] = I - dimension; }
 getLines();
 name = n;
}   
  
  
  /**
  * Bスプライン関数
  * @param n 関数の次元数
  * @param I 関数の添え字
  * @param t 関数の引数
  * @return 関数の値
  */
  private double bSplineFunction(int n, int I, double t) {
   if (n == 0) {
    if ((knot[I] <= t) && (t < knot[I+1])) {
     return 1.0;
    } else {
     return 0.0;
    }
   } else {
    return ((t - knot[I]) / (knot[I+n] - knot[I])) * bSplineFunction(n-1, I, t) +
       ((knot[I+n+1] - t) / (knot[I+n+1] - knot[I+1])) * bSplineFunction(n-1, I+1, t);
   }
  }

  /**
  * Bスプライン曲線の1点を計算
  * @param t 関数の引数
  */
  private Point getPoint( double t) {
   double tmpX = 0;
   double tmpY = 0;
   for (int I = 0; I < nPoints; I++) {
    tmpX = tmpX + p[I].getX() * bSplineFunction(dimension, I, t);
    tmpY = tmpY + p[I].getY() * bSplineFunction(dimension, I, t);
   }
   Point tmpP= new Point( tmpX , tmpY );
   return tmpP;
  }

  /**
  * Bスプラインを構成する点を得る
  */
  public Point[] getPoints() {
   Vector v = new Vector();
   for (double t = knot[dimension]; t < knot[nPoints]; t = t + 0.1) {
     v.addElement( getPoint(t) );
   }
   Point data[] = new Point[ v.size() + 2 ];
   data[0] = p[0];
   for(int I=1 ; I < ( v.size()+1 ) ; I++ )
   {
    data[I] = (Point)v.get(I-1);
   }
   data[ v.size()+1 ] = p[nPoints-1];
   return data;
  }   
  
  /**
  * Bスプラインを構成する線を得る
  */
  public Line[] getLines() {
    Point[] p = getPoints();
    Line[] l = new Line[ p.length-1 ];
    for(int I=0 ; I < l.length ; I++ )
   {
    l[I] = new Line();
    l[I].makeLineStpointEndpoint( "", p[I], p[I+1]);
   }
   line = l;
   return l;
  }  
     
}

Java Class Point

package tomojavalib.drawing;

public class Point {
public double x=0.;
public double y=0.;
public String name="";

public Point(double xx,double yy)
 {
 x=xx;
 y=yy;
 name ="";
 return;
 }

public void makePointXY( String nname, double xx,double yy)
{
 name = nname;
 x = xx;
 y = yy;
 return;
}

public double getX(){ return x;}

public double getY(){ return y;}


public void makeCrossPoint( String nname, Line L1 , Line L2 )
{
name = nname; 
if( L1.aflug==false ){  if( L2.aflug==false  )  {x = (L2.b-L1.b) / (L1.a - L2.a); y = L2.a * x + L2.b;  return ;}}
if( L1.aflug ){  if( L2.aflug )  {return ;}}
if( L1.aflug ){  if( L2.aflug==false )  { x = L1.stPoint.x; y = L2.a * x + L2.b;return ; }}
if( L1.aflug==false ){  if( L2.aflug )  { x = L2.stPoint.x; y = L1.a * x + L1.b;return ; }}
return ;
}

}

Java Class Line


package tomojavalib.drawing;

import tomojavalib.drawing.*;

public class Line {
Point stPoint = new Point(0.,0.);
Point endPoint = new Point(0.,0.);
double length = 0.;
double angle = 0.;
String name =null;
double a = 0. ; //y=ax+b
double b = 0.; //y=ax+b
boolean aflug = false;
 
public static void main(String[] args) 
{
}

/*
 *始点と終点を指定して線を作る 
 */
public void makeLineStpointEndpoint(String nname, Point stpoint, Point endpoint)
{
 stPoint = stpoint;
 endPoint = endpoint;
 length = Math.sqrt( ( stPoint.x -endPoint.x)*( stPoint.x -endPoint.x) + ( stPoint.y -endPoint.y)*( stPoint.y -endPoint.y) );
 angle = Math.atan( ( - stPoint.x + endPoint.x)/( - stPoint.y + endPoint.y) );
 name = nname;
 setAB();
 return;
}

広告

/*
 *始点と長さ、目標点を指定して線を作る 
 */
public void makeLineStpointTopointLength(String nname, Point stpoint, Point topoint,double length)
{
stPoint = stpoint;  
double L = Math.sqrt( ( stPoint.x -topoint.x)*( stPoint.x -topoint.x) + ( stPoint.y -topoint.y)*( stPoint.y -topoint.y) );
endPoint.x = stPoint.x - (stPoint.x -topoint.x) * length / L;
endPoint.y = stPoint.y - (stPoint.y -topoint.y) * length / L;
 length = Math.sqrt( ( stPoint.x -endPoint.x)*( stPoint.x -endPoint.x) + ( stPoint.y -endPoint.y)*( stPoint.y -endPoint.y) );
 angle = Math.atan( ( - stPoint.x + endPoint.x)/( - stPoint.y + endPoint.y) );
 name = nname;
 setAB();
 return;
}

private void setAB()
{
if( stPoint.x == endPoint.x){ aflug = true; ;return; }
a = ( stPoint.y - endPoint.y ) / ( stPoint.x - endPoint.x);
b = stPoint.y - ( a * stPoint.x );
aflug = false;
return;
}

/*
 *始点と直線、直線に対する角度、長さを指定して線を作る
 */
public void makeLineStpointLineAngleLength(String nname, Point stpoint, Line l , double ang ,double len)
{
 stPoint = stpoint;
 length = len;
 System.out.println( l.name +" _ ");
 angle = l.angle + (ang / 180.) * Math.PI ;
 endPoint.x = stPoint.x + length * Math.sin(angle);
 endPoint.y = stPoint.y + length * Math.cos(angle);
 name = nname;
 setAB();
 return;
}

}

最終更新日: 2012-12-18 19:53:20

ともさんのHP >プロブラミング >自作JavaLibrary >JAVAでBスプライン曲線

このエントリーをはてなブックマークに追加
広告
おすすめ記事
新着ページ

キャスケット型紙の設計方法と型紙ダウンロード  
重箱式巣箱の図面  
ブルーベリーの挿し木  
ホオノキ  
アリジゴクの飼いかた  
シンプルなパネルラインワンピースの型紙と作りかた  
ベジェ曲線の原理  
ハンチング型紙の作りかた  
和風コートの作り方  
3D-CADでカバンの型紙  
雑草を利用した家庭菜園用堆肥の作りかた  

私の他のサイト

ともさんの箱庭(ブログ)
家庭菜園
3D-CAD
洋裁CAD

いいねなど

 RSS 
PageSpeedInsights
html5チェック

Author: Tomoyuki Ito

このサイトの文章・写真の無断転載を禁じます