📄 curve.java
字号:
//vertical line from left-top to right-top
rightTopX =x1;
rightTopY =y2;
}else if ((float)divisor==0){
//horizontal line from left-top to right-top
rightTopX =x2;
rightTopY =y1;
}else{
double k2 =divisor/dividend;
double k3 =-1/k2;
rightTopX =(y2-k3 * x2 - y1 + k2 * x1)/(k2-k3);
rightTopY =k2 * (rightTopX-x1) + y1;
}
}
double leftBottomX=x1 - (rightTopX - x2);
double leftBottomY=y1 - (rightTopY - y2);
JFPoint mid1 =startPoint.midPoint(rightTopX,rightTopY);
JFPoint mid2 =endPoint.midPoint(leftBottomX,leftBottomY);
setValue(x1,y1,mid1.getX(),mid1.getY(),mid2.getX(),mid2.getY(),x2,y2);
}
/**
* Set value of a curve. We will keep two control points poistion relative to two end points.
*
* @param startPoint Coordinates of start point.
* @param endPoint Coordinates of end point.
*
*/
public void setValueByKeepingShape(JFPoint startPoint, JFPoint endPoint){
//step 1, store the shape
//distance from old start point to old end point.
double dist =m_startPoint.distance(m_endPoint);
//angle between the line that from start point to control point1 and horizontal line
double angle1 =Angle.getAngle(m_startPoint,m_controlPoint1,false);
//scale of that the distance from start point to control point1 compares to dist above.
double scale1 =m_startPoint.distance(m_controlPoint1)/dist;
//direction of that the vector from start point to the control point1 compares to the vector from start point to end point.
boolean direction1 = JFVector.underClockwiseSide(m_startPoint,m_controlPoint1,m_startPoint,m_endPoint);
//angle between the line that from start point to control point2 and horizontal line
double angle2 =Angle.getAngle(m_startPoint,m_controlPoint2,false);
//scale that the distance from start point to control point2 compares to dist above.
double scale2 =m_startPoint.distance(m_controlPoint2)/dist;
//direction of that the vector from start point to the control point2 compares to the vector from start point to end point.
boolean direction2 = JFVector.underClockwiseSide(m_startPoint,m_controlPoint2,m_startPoint,m_endPoint);
//the angle between the line from start point to end point and horzontal line.
double angleBase =Angle.getAngle(m_startPoint,m_endPoint,false);
//step 2, set new value to two endpoints.
m_startPoint.setValue(startPoint);
m_endPoint.setValue(endPoint);
//step 3, restore the shape
dist =m_startPoint.distance(m_endPoint);
if ((float)dist==0)
return;
double dist1 =dist * scale1;
double dist2 =dist * scale2;
//the angle between the line from start point to end point and horzontal line.
double angleBase1 =Angle.getAngle(m_startPoint,m_endPoint,false);
//angle increment
angleBase1 -=angleBase;
//new angle for controlpoints
angle1 =Angle.getValidAngle(angle1+angleBase1);
angle2 =Angle.getValidAngle(angle2+angleBase1);
//new slope for line from start point to controlpoints
double slope1 =0;
int angle_degree=(int)(angle1/Angle.PI*180);
if (angle_degree==90 || angle_degree==270)
slope1 =GeomConst.LARGE_VALUE;
else
slope1 =Math.tan(angle1);
double slope2 =0;
angle_degree=(int)(angle2/Angle.PI*180);
if (angle_degree==90 || angle_degree==270)
slope2 =GeomConst.LARGE_VALUE;
else
slope2 =Math.tan(angle2);
JFPoint control1=m_startPoint.nearPoint(slope1,dist1,m_endPoint,direction1);
JFPoint control2=m_startPoint.nearPoint(slope2,dist2,m_endPoint,direction2);
if (control1!=null && control2!=null){
m_controlPoint1.setValue(control1);
m_controlPoint2.setValue(control2);
}
}
//***************** constructors *************************
/**
* Constructor for Curve.
*/
public Curve(){
}
/**
* Constructor for Curve.
*
* @param curve A Curve object.
*/
public Curve(Curve curve){
setValue(curve);
}
/**
* Constructor for Curve.
*
* @param startPoint Coordinates of start point.
* @param controlPoint1 Coordinates of control point1.
* @param controlPoint2 Coordinates of control point2.
* @param endPoint Coordinates of end point.
*
*/
public Curve(JFPoint startPoint, JFPoint controlPoint1, JFPoint controlPoint2, JFPoint endPoint){
setValue(startPoint,controlPoint1,controlPoint2,endPoint);
}
/**
* Constructor for Curve.
*
* @param x1; y1 Coordinates of start point.
* @param x2; y2 Coordinates of control point1.
* @param x3; y3 Coordinates of control point2.
* @param x4; y4 Coordinates of end point.
*
*/
public Curve(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4){
setValue(x1,y1,x2,y2,x3,y3,x4,y4);
}
//***************** other methods *************************
/**
* Get the bounds of this curve.
*
* @return The bounds rectangle.
*
*/
public Rect getBounds(){
double x1 =getX1();
double y1 =getY1();
double x2 =getX2();
double y2 =getY2();
double x3 =getX3();
double y3 =getY3();
double x4 =getX4();
double y4 =getY4();
double minX =Math.min(Math.min(x1,x2),Math.min(x3,x4));
double minY =Math.min(Math.min(y1,y2),Math.min(y3,y4));
double maxX =Math.max(Math.max(x1,x2),Math.max(x3,x4));
double maxY =Math.max(Math.max(y1,y2),Math.max(y3,y4));
return new Rect(minX,minY,maxX-minX,maxY-minY);
}
/**
* Get the center of this curve.
*
* @return The center.
*
*/
public JFPoint getCenter(){
double x1 =getX1();
double y1 =getY1();
double x2 =getX2();
double y2 =getY2();
double x3 =getX3();
double y3 =getY3();
double x4 =getX4();
double y4 =getY4();
double minX =Math.min(Math.min(x1,x2),Math.min(x3,x4));
double minY =Math.min(Math.min(y1,y2),Math.min(y3,y4));
double maxX =Math.max(Math.max(x1,x2),Math.max(x3,x4));
double maxY =Math.max(Math.max(y1,y2),Math.max(y3,y4));
return new JFPoint((minX+maxX)/2,(minY+maxY)/2);
}
/**
* Test if a point is on the outline of this curve.
*
* @param pnt A point to be measured.
*
* @return True if the point is on the outline of this curve, false otherwise.
*
*/
public boolean contains(JFPoint pnt){
return contains(pnt.getX(),pnt.getY());
}
/**
* Test if a point is on the outline of this curve.
*
* @param x; y A point to be measured.
*
* @return True if the point is on the outline of this curve, false otherwise.
*
*/
public boolean contains(double x, double y){
return contains(x,y,0);
}
/**
* Test if a point is on the outline of this curve.
*
* @param pnt A point to be measured.
*
* @param pickOffset An analog offset for 'pick' this curve.
*
* @return True if the point is on the outline of this curve, false otherwise.
*
*/
public boolean contains(JFPoint pnt,double pickOffset){
return contains(pnt.getX(),pnt.getY(),pickOffset);
}
/**
* Test if a point is on the outline of this curve.
*
* @param x; y A point to be measured.
*
* @param pickOffset An analog offset for 'pick' this curve.
*
* @return True if the point is on the outline of this curve, false otherwise.
*
*/
public boolean contains(double x, double y, double pickOffset){
if (m_startPoint.distance(x,y)<=pickOffset ||
// m_controlPoint1.distance(x,y)<=pickOffset ||
// m_controlPoint2.distance(x,y)<=pickOffset ||
m_endPoint.distance(x,y)<=pickOffset)
return true;
JFPoint pnt =intersectsAt(x,y,pickOffset);
return pnt!=null;
}
/**
* Test if current curve intersects the point at a position.
*
* @param x; y A point to be measured.
* @param pickOffset An analog offset for 'pick' this curve.
* @return A result curvePoint that represents an intersected point.
*
*/
public JFCurvePoint intersectsAt(double x, double y, double pickOffset){
double x1 =getX1();
double y1 =getY1();
double x2 =getX2();
double y2 =getY2();
double x3 =getX3();
double y3 =getY3();
double x4 =getX4();
double y4 =getY4();
return intersectsAt(x,y,x1,y1,x2,y2,x3,y3,x4,y4,pickOffset);
}
/**
* Test if current curve intersects the point at a position.
*
* @param x; y A point to be measured.
* @param x1,y1 A start point of a bezier curve.
* @param x2,y2 A first control point of a bezier curve.
* @param x3,y3 A second control point of a bezier curve.
* @param x4,y4 An end point of a bezier curve.
*
* @param pickOffset An analog offset for 'pick' this curve.
*
* @return A result curvePoint that represents an intersected point.
*
*/
public static JFCurvePoint intersectsAt(double x, double y,
double x1,double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4,
double pickOffset){
JFCurvePoint resultPoint =new JFCurvePoint();
JFPoint pnt =new JFPoint();
pnt.setValue(x1,y1);
if (pnt.distance(x,y)<=pickOffset){
resultPoint.setValue(x1,y1);
resultPoint.setTimeInterval(0);
return resultPoint;
}
pnt.setValue(x4,y4);
if (pnt.distance(x,y)<=pickOffset){
resultPoint.setValue(x4,y4);
resultPoint.setTimeInterval(1);
return resultPoint;
}
double startX, startY, endX, endY;
LineSeg line =new LineSeg();
//start to test point on the whole outline of curve.
startX =x1;
startY =y1;
double t; //the time interval
double k = .025; //time step value for drawing curve
for(t=k;t<=1+k;t+=k){
//use Bernstein polynomials
endX=(x1+t*(-x1*3+t*(3*x1-x1*t)))+
t*(3*x2+t*(-6*x2+ x2*3*t))+t*t*(x3*3-x3*3*t)+
x4*t*t*t;
endY=(y1+t*(-y1*3+t*(3*y1-y1*t)))+
t*(3*y2+t*(-6*y2+ y2*3*t))+t*t*(y3*3-y3*3*t)+
y4*t*t*t;
line.setPoint1(startX,startY);
line.setPoint2(endX,endY);
if (line.contains(x,y,GeomConst.PICK_OFFSET)){
resultPoint.setValue(endX,endY);
resultPoint.setTimeInterval(t);
return resultPoint;
}
startX =endX;
startY =endY;
}
return null;
}
/**
* Get a point by time interval.
*
* @param interval A time interval on this curve.
* @return The point on the curve.
*
*/
public JFPoint getPoint(double interval){
double x1 =getX1();
double y1 =getY1();
double x2 =getX2();
double y2 =getY2();
double x3 =getX3();
double y3 =getY3();
double x4 =getX4();
double y4 =getY4();
return getPoint(x1,y1,x2,y2,x3,y3,x4,y4,interval);
}
/**
* Get a point by time interval.
*
* @param x1,y1 A start point of a bezier curve.
* @param x2,y2 A first control point of a bezier curve.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -