ともさんのHP >プロブラミング >自作JavaLibrary >JAVAでBスプライン曲線
JAVAでBスプラインを計算するクラス
Javaを使ってBスプラインを計算。線を画面に表示させるClassを作ってみました。
現在作っている描画アプリのための部品として作りました。
ソースのほうですが、いつものようにネットを回って諸先輩方のソースコードを大いに参考にさせていただきました。
ありがとうございます。
今回は特にこちら
を参考にさせいただいております。
Bスプライン描画の概要
pointというクラスとlineというクラスをあらかじめ作っておきます。
pointには点の情報を入れ、lineには線情報が入ります。
Bスプラインを引くための制御点をpoint配列で入れると、Bスプラインの線情報がLine配列で得られます。
下の絵が計算結果。制御点の最初と最後も都合により線の端に入っています。
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スプライン曲線
ツイート