import java.awt.*; public class B_SplineClosed{ double PARAM=0.05; int error=0; double ww,hh; int numberofpoint=0; int numberofpoint_buffer=0; Knot BHead; Knot BTail; Knot P[]; Knot Head; Knot Tail; double mydistance=1.0; double scalefactor=1.0; int scalestate = 0; double scale=100.0; double iscale=100.0; Dimension aread; int ptype; boolean split; public B_SplineClosed() { split=false; ptype=0; aread = new Dimension(800,400); this.listinitialize(); } public B_SplineClosed(int ww,int hh) { split=false; ptype=0; aread = new Dimension(ww,hh); this.listinitialize(); } public B_SplineClosed(int ww,int hh,int cptype) { split=false; ptype=3; numberofpoint=0; aread = new Dimension(ww,hh); Head = new Knot(); Tail = new Knot(); Init(Head,Tail); } public void changePARAM(double dp){ PARAM = dp; } public void initdimension(int ww,int hh) { aread = new Dimension(ww,hh); } public Knot getVirtualC(double dx,double dy){ double nx,ny; nx = ((dx - 5.0)/(scale)); ny = ((aread.height - (dy - 5.0))/(scale)); return new Knot(nx,ny); } public void SplitCP(){ split=true; numberofpoint_buffer = numberofpoint; numberofpoint = 2*numberofpoint_buffer; BHead = new Knot(); BTail = new Knot(); Init(BHead,BTail); Knot now = Head; while(Next(now) != Tail){ now = Next(now); Append(new Knot(now.x,now.y),BTail); } Head = new Knot(); Tail = new Knot(); Init(Head,Tail); now = BHead; while(Next(Next(now)) != BTail){ now = Next(now); Append(new Knot(now.x,now.y),Tail); Append(new Knot((Next(now).x + now.x)/2.0, (Next(now).y + now.y)/2.0),Tail); } now = Next(now); Append(new Knot(now.x,now.y),Tail); Append(new Knot((Next(BHead).x + now.x)/2.0, (Next(BHead).y + now.y)/2.0),Tail); int i=0; P = new Knot[numberofpoint]; now = Next(Head); P[0] = new Knot(now.x,now.y); while(Next(now)!=Tail){ now = Next(now); i++; P[i] = new Knot(now.x,now.y); } } public void CollapseCP(){ split=false; numberofpoint = numberofpoint_buffer; Head = new Knot(); Tail = new Knot(); Init(Head,Tail); Knot now = BHead; while(Next(now) != BTail){ now = Next(now); Append(new Knot(now.x,now.y),Tail); } int i=0; P = new Knot[numberofpoint]; now = Next(Head); P[0] = new Knot(now.x,now.y); while(Next(now)!=Tail){ now = Next(now); i++; P[i] = new Knot(now.x,now.y); } } public void listinitialize() { double nx,ny; System.gc(); Head = new Knot(); Tail = new Knot(); Init(Head,Tail); /* Make Ellipse */ nx = ((200 - 5)/(scale)); ny = ((aread.height - (200 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((200 - 5)/(scale)); ny = ((aread.height - (100 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((400 -5)/(scale)); ny = ((aread.height - (100 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((600 -5)/(scale)); ny = ((aread.height - (100 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((600 -5)/(scale)); ny = ((aread.height - (200 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((600 -5)/(scale)); ny = ((aread.height - (300 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((400 -5)/(scale)); ny = ((aread.height - (300 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; nx = ((200 -5)/(scale)); ny = ((aread.height - (300 - 5))/(scale)); Append(new Knot(nx,ny),Tail); numberofpoint++; int i=0; P = new Knot[numberofpoint]; Knot now = Next(Head); P[0] = new Knot(now.x,now.y); while(Next(now)!=Tail){ now = Next(now); i++; P[i] = new Knot(now.x,now.y); } } public void setInitControlPs(){ int i=0; P = new Knot[numberofpoint]; Knot now = Next(Head); P[0] = new Knot(now.x,now.y); while(Next(now)!=Tail){ now = Next(now); i++; P[i] = new Knot(now.x,now.y); } } public double getOrthotomicK(double t,Knot ps){ DoubleVector d1 = RoundOrthotomic(t,ps); DoubleVector d2 = Round2Orthotomic(t,ps); double curvature; double dd1x = (d1.x*d1.x); double dd1y = (d1.y*d1.y); double dx1y2 = (d1.x*d2.y); double dx2y1 = (d1.y*d2.x); if((dd1x==0.0)&&(dd1y==0.0)){ curvature = 1000.0; }else{ curvature = ((dx1y2 - dx2y1)/Math.pow(dd1x + dd1y,1.5)); } return curvature; } public DoubleVector getOrthotomicNormal(double t,Knot ps){ DoubleVector d1 = Normalize(RoundOrthotomic(t,ps)); if(d1.size!=0){ return new DoubleVector(-d1.y,d1.x); }else{ DoubleVector target = getOrthotomic(t,ps); DoubleVector targetB = getOrthotomic((t-PARAM),ps); DoubleVector dnormal2; if(targetB.size!=0){ dnormal2 = Normalize(new DoubleVector((-(target).y + (targetB.y)), -(-(target).x + (targetB.x)))); }else{ DoubleVector targetN = getOrthotomic((t+PARAM),ps); dnormal2 = Normalize(new DoubleVector(((target).y - (targetN.y)), -((target).x - (targetN.x)))); } return dnormal2; } } public DoubleVector RoundOrthotomic(double t,Knot ps){ DoubleVector now,nowd,nowdd; double dx,dy,d1,d2,d3,d4; now = getPoint(t); nowd = Round(t); nowdd = Round2(t); d1 = (nowd.x*nowd.x); d2 = (nowd.y*nowd.y); d3 = (ps.y - now.y); d4 = (ps.x - now.x); dx = ((2.0*(d3*d1 - 2.0*d4*nowd.x*nowd.y - d3*d2)* (-nowd.y*nowdd.x + nowd.x*nowdd.y))/Math.pow((d1 + d2),2)); dy = ((2.0*(d4*d1 + 2.0*d3*nowd.x*nowd.y - d4*d2)* (-nowd.y*nowdd.x + nowd.x*nowdd.y))/Math.pow((d1 + d2),2)); return new DoubleVector(dx,dy); } public DoubleVector Round2Orthotomic(double t,Knot ps){ DoubleVector now,nowd,nowdd,nowddd; double dx,dy,d1,d2,d3,d4,d5,d6,d7,d8; now = getPoint(t); nowd = Round(t); nowdd = Round2(t); nowddd = Round3(t); d1 = (nowd.x*nowd.x); d2 = (nowd.y*nowd.y); d3 = (ps.y - now.y); d4 = (ps.x - now.x); d5 = (d1 + d2); d6 = (nowd.x*nowdd.x + nowd.y*nowdd.y); d7 = (-d3*nowd.x + d4*nowd.y); d8 = (-d3*nowdd.x + d4*nowdd.y); dx = ((2.0*(-2.0*d5*(-2.0*d6*d7 + d5*d8)*nowdd.y - Math.pow(d5,2.0)*d7*nowddd.y - nowd.y*(-4.0*d5*d6*d8 + Math.pow(d5,2.0)*(nowd.y*nowdd.x - nowd.x*nowdd.y - d3*nowddd.x + d4*nowddd.y) + d7*(8.0*Math.pow(d6,2.0) - 2.0*d5*(Math.pow(nowdd.x,2.0) + Math.pow(nowdd.y,2.0) + nowd.x*nowddd.x + nowd.y*nowddd.y)))))/(Math.pow(d5,3.0))); dy = ((2.0*(2.0*d5*(-2.0*d6*d7 + d5*d8)*nowdd.x + Math.pow(d5,2.0)*d7*nowddd.x + nowd.x*(-4.0*d5*d6*d8 + Math.pow(d5,2.0)*(nowd.y*nowdd.x - nowd.x*nowdd.y - d3*nowddd.x + d4*nowddd.y) + d7*(8.0*Math.pow(d6,2.0) - 2.0*d5*(Math.pow(nowdd.x,2.0) + Math.pow(nowdd.y,2.0) + nowd.x*nowddd.x + nowd.y*nowddd.y)))))/(Math.pow(d5,3.0))); return new DoubleVector(dx,dy); } /* public DoubleVector RoundOrthotomic(double t,Knot ps){ DoubleVector now,back,next; double dx,dy,d1,d2; next = getOrthotomic((t+PARAM),ps); now = getOrthotomic(t,ps); back = getOrthotomic((t-PARAM),ps); d2 = Distance(now,next); d1 = Distance(now,back); dx = (((next.x - now.x)/d2) + ((now.x - back.x)/d1) - ((next.x - back.x)/(d1+d2))); dy = (((next.y - now.y)/d2) + ((now.y - back.y)/d1) - ((next.y - back.y)/(d1+d2))); return new DoubleVector(dx,dy); } public DoubleVector Round2Orthotomic(double t,Knot ps){ DoubleVector now,back,next; double dx,dy,d1,d2; next = getOrthotomic((t+PARAM),ps); now = getOrthotomic(t,ps); back = getOrthotomic((t-PARAM),ps); d2 = Distance(now,next); d1 = Distance(now,back); dx = (((2.0*next.x)/(d2*(d1+d2))) - ((2.0*now.x)/(d1*d2)) + ((2.0*back.x)/(d1*(d1+d2)))); dy = (((2.0*next.y)/(d2*(d1+d2))) - ((2.0*now.y)/(d1*d2)) + ((2.0*back.y)/(d1*(d1+d2)))); return new DoubleVector(dx,dy); } */ public DoubleVector getOrthotomic(double t,Knot ps){ double dx,dy,ddx,ddy,dddx,dddy; DoubleVector dp = getPoint(t); DoubleVector ndp = Round(t); dy = (dp.y - ps.y); dx = (dp.x - ps.x); DoubleVector dfg = new DoubleVector((dy*ndp.x),(dx*ndp.y)); ddx = dfg.x; ddy = dfg.y; DoubleVector ddgf = new DoubleVector((ndp.y*(ddx-ddy)),(ndp.x*(ddx-ddy)));; if((ndp.x==0.0)&&(ndp.y==0.0)){ System.out.println("Error !"); System.out.println("ndp.x*ndp.x + ndp.y*ndp.y = 0"); return new DoubleVector(0.0,0.0); } dddx = (-(2.0*ddgf.x)/(ndp.x*ndp.x + ndp.y*ndp.y)); dddy = ((2.0*ddgf.y)/(ndp.x*ndp.x + ndp.y*ndp.y)); return new DoubleVector((dddx+ps.x),(dddy+ps.y)); } public DoubleVector getPoint(double t){ double dx=0.0,dy=0.0; int j = 0; dx = N5(t +4.0)*P[(numberofpoint-4)].x + N5(t +3.0)*P[(numberofpoint-3)].x + N5(t +2.0)*P[(numberofpoint-2)].x + N5(t +1.0)*P[(numberofpoint-1)].x + N5(t)*P[0].x; dy = N5(t +4.0)*P[(numberofpoint-4)].y +N5(t +3.0)*P[(numberofpoint-3)].y +N5(t +2.0)*P[(numberofpoint-2)].y + N5(t +1.0)*P[(numberofpoint-1)].y + N5(t)*P[0].y; for(j=1;j<(numberofpoint-1);j++){ double function = N5(t - (double)(j)); dx += function*P[j].x; dy += function*P[j].y; } dx += N5(t - (double)(numberofpoint-1))*P[(numberofpoint-1)].x + N5(t - (double)(numberofpoint))*P[0].x + N5(t - (double)(numberofpoint+1))*P[1].x+ N5(t - (double)(numberofpoint+2))*P[2].x + N5(t - (double)(numberofpoint+3))*P[3].x; dy += N5(t - (double)(numberofpoint-1))*P[(numberofpoint-1)].y + N5(t - (double)(numberofpoint))*P[0].y + N5(t - (double)(numberofpoint+1))*P[1].y + N5(t - (double)(numberofpoint+2))*P[2].y + N5(t - (double)(numberofpoint+3))*P[3].y; DoubleVector dummy = new DoubleVector(dx,dy); return dummy; } public Knot CatchPoint(DoubleVector target){ Knot now = Head; DoubleVector dnowummy; while(Next(now)!=Tail){ now = Next(now); dnowummy = new DoubleVector(now.x,now.y); if(Distance(target,dnowummy) <= 0.15) return now; } return new Knot(0.0,0.0,0); } public DoubleVector getTangent(double t){ DoubleVector d1 = Normalize(Round(t)); if(d1.size!=0){ return new DoubleVector(d1.x,d1.y); }else{ DoubleVector target = getPoint(t); DoubleVector targetB = getPoint((t-PARAM)); DoubleVector dtangent2; if(targetB.size!=0){ dtangent2 = Normalize(new DoubleVector((-(target).x + (targetB.x)), (-(target).y + (targetB.y)))); }else{ DoubleVector targetN = getPoint((t+PARAM)); dtangent2 = Normalize(new DoubleVector(((target).x - (targetN.x)), ((target).y - (targetN.y)))); } return dtangent2; } } public DoubleVector getNormal(double t){ DoubleVector d1 = Normalize(Round(t)); if(d1.size!=0){ return new DoubleVector(-d1.y,d1.x); }else{ DoubleVector target = getPoint(t); DoubleVector targetB = getPoint((t-PARAM)); DoubleVector dnormal2; if(targetB.size!=0){ dnormal2 = Normalize(new DoubleVector((-(target).y + (targetB.y)), -(-(target).x + (targetB.x)))); }else{ DoubleVector targetN = getPoint((t+PARAM)); dnormal2 = Normalize(new DoubleVector(((target).y - (targetN.y)), -((target).x - (targetN.x)))); } return dnormal2; } } public double getS(double t){ DoubleVector d1 = getPoint(t); DoubleVector d2 = getPoint((t+PARAM)); return Distance(d1,d2); } public double getTotalS(){ double length=0.0; for(double t = 0.0;t<=((double)(numberofpoint-PARAM));t+=PARAM) length += getS(t); return length; } /* public double getRoundK(double t){ DoubleVector d1 = Round(t); DoubleVector d2 = Round2(t); DoubleVector d3 = Round3(t); double dumterm = (d1.x*d1.x + d1.y*d1.y); double kt = ((6.0*(d1.y*d2.x - d1.x*d2.y)*(d1.x*d2.x+d1.y*d2.y) + 2.0*dumterm*(-d1.y*d3.x + d1.x*d3.y))/ (2.0*Math.pow(dumterm,2.5))); if(dumterm == 0.0){ kt = 1000.0; } return kt; } */ public double getRoundK(double t){ double now,back,next; double dk,dy,d1,d2; next = getK((t+PARAM)); now = getK(t); back = getK((t-PARAM)); DoubleVector nn,no,nb; nn = getPoint((t+PARAM)); no = getPoint(t); nb = getPoint((t-PARAM)); d2 = Distance(no,nn); d1 = Distance(no,nb); dk = (((next - now)/d2) + ((now - back)/d1) - ((next - back)/(d1+d2))); return dk; } public double getK(double t){ DoubleVector d1 = Round(t); DoubleVector d2 = Round2(t); double curvature; double dd1x = (d1.x*d1.x); double dd1y = (d1.y*d1.y); double dx1y2 = (d1.x*d2.y); double dx2y1 = (d1.y*d2.x); if((dd1x==0.0)&&(dd1y==0.0)){ curvature = 1000.0; }else{ curvature = ((dx1y2 - dx2y1)/Math.pow(dd1x + dd1y,1.5)); } return curvature; } /* private */ public DoubleVector Round(double t){ double dx=0.0,dy=0.0; int j = 0; dx = N5D(t +4.0)*P[(numberofpoint-4)].x + N5D(t +3.0)*P[(numberofpoint-3)].x + N5D(t +2.0)*P[(numberofpoint-2)].x + N5D(t +1.0)*P[(numberofpoint-1)].x + N5D(t)*P[0].x; dy = N5D(t +4.0)*P[(numberofpoint-4)].y +N5D(t +3.0)*P[(numberofpoint-3)].y +N5D(t +2.0)*P[(numberofpoint-2)].y + N5D(t +1.0)*P[(numberofpoint-1)].y + N5D(t)*P[0].y; for(j=1;j<(numberofpoint-1);j++){ double function = N5D(t - (double)(j)); dx += function*P[j].x; dy += function*P[j].y; } dx += N5D(t - (double)(numberofpoint-1))*P[(numberofpoint-1)].x + N5D(t - (double)(numberofpoint))*P[0].x + N5D(t - (double)(numberofpoint+1))*P[1].x+ N5D(t - (double)(numberofpoint+2))*P[2].x+ N5D(t - (double)(numberofpoint+3))*P[3].x; dy += N5D(t - (double)(numberofpoint-1))*P[(numberofpoint-1)].y + N5D(t - (double)(numberofpoint))*P[0].y + N5D(t - (double)(numberofpoint+1))*P[1].y + N5D(t - (double)(numberofpoint+2))*P[2].y + N5D(t - (double)(numberofpoint+3))*P[3].y; DoubleVector dummy = new DoubleVector(dx,dy); return dummy; } private DoubleVector Normalize(DoubleVector v) { v.size = Math.sqrt((v.x)*(v.x)+(v.y)*(v.y)); if(v.size!=0){ v.x = (double)(v.x/v.size); v.y = (double)(v.y/v.size); v.size = 1.0; }else{ v.size = 0.0; } return v; } /* private */ public DoubleVector Round2(double t){ double dx=0.0,dy=0.0; int j = 0; dx = N5DD(t +4.0)*P[(numberofpoint-4)].x +N5DD(t +3.0)*P[(numberofpoint-3)].x +N5DD(t +2.0)*P[(numberofpoint-2)].x + N5DD(t +1.0)*P[(numberofpoint-1)].x + N5DD(t)*P[0].x; dy = N5DD(t +4.0)*P[(numberofpoint-4)].y +N5DD(t +3.0)*P[(numberofpoint-3)].y +N5DD(t +2.0)*P[(numberofpoint-2)].y + N5DD(t +1.0)*P[(numberofpoint-1)].y + N5DD(t)*P[0].y; for(j=1;j<(numberofpoint-1);j++){ double function = N5DD(t - (double)(j)); dx += function*P[j].x; dy += function*P[j].y; } dx += N5DD(t - (double)(numberofpoint-1))*P[(numberofpoint-1)].x + N5DD(t - (double)(numberofpoint))*P[0].x + N5DD(t - (double)(numberofpoint+1))*P[1].x+ N5DD(t - (double)(numberofpoint+2))*P[2].x+ N5DD(t - (double)(numberofpoint+3))*P[3].x; dy += N5DD(t - (double)(numberofpoint-1))*P[(numberofpoint-1)].y + N5DD(t - (double)(numberofpoint))*P[0].y + N5DD(t - (double)(numberofpoint+1))*P[1].y+ N5DD(t - (double)(numberofpoint+2))*P[2].y+ N5DD(t - (double)(numberofpoint+3))*P[3].y; DoubleVector dummy = new DoubleVector(dx,dy); return dummy; } private double N5(double t){ if((-3 < t)&&(t <= -2)){ double d = (3.0 + t); return ((d*d*d*d*d)/120.0); }else if((-2