ellipse.java
来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 877 行 · 第 1/2 页
JAVA
877 行
*
* @param x X coordinate of this point.
*
* @param y Y coordinate of this point.
*
* @return True if the point is inside this rectangle, false otherwise.
*
*/
public boolean contains(double x, double y){
/**
* sum of the two length of that from this point to two foci
* of ellipse, must less or equan than 2a.
*/
double a = getSemimajor();
return getFociLen(x,y)<=2*a;
}
/**
* Test if current ellipse intersects the point at a position.
*
* @param x; y A point to be measured.
* @param pickOffset An analog offset for 'pick' this curve.
* @return An JFEllipsePoint intersected.
*
*/
public JFEllipsePoint intersectsAt(double x, double y, double pickOffset){
//const definition..
int n =BEZIER_SEGMENT_NUM;
int []qx =new int[n*3+1]; //n bezier curves
int []qy =new int[n*3+1];
//seperate this ellipse to bezier curve segments.
if (!getEllipseControlPoints(qx,qy))
return null;
double x1=0, y1=0, x2=0, y2=0, x3=0,y3=0, x4=0,y4=0;
int i =0;
JFCurvePoint curvePoint =new JFCurvePoint();
boolean found =false;
while (i<n*3){
x1 =qx[i]; y1 =qy[i];
x2 =qx[i+1]; y2 =qy[i+1];
x3 =qx[i+2]; y3 =qy[i+2];
x4 =qx[i+3]; y4 =qy[i+3];
curvePoint =Curve.intersectsAt(x,y,x1,y1,x2,y2,x3,y3,x4,y4,pickOffset);
if (curvePoint!=null){
found =true;
break;
}
i +=3;
}
if (!found)
return null;
//center of ellipse
JFPoint center =getCenter();
//3 * semimajor
double dist =getSemimajor()*3;
//near point outside the outer rectangle.
JFPoint newPoint =center.nearPoint(curvePoint,dist,true);
for (i=Rect.SIDETYPE_LEFT; i<=Rect.SIDETYPE_BOTTOM; i++){
LineSeg side =getSide(i);
JFPoint sidePoint =side.intersectsAt(center,newPoint);
if (sidePoint!=null){
JFEllipsePoint resultPoint =new JFEllipsePoint();
resultPoint.setValue(curvePoint);
resultPoint.getTargetPoint().setValue(sidePoint);
resultPoint.setTargetSideType(i);
return resultPoint;
}
}
return null;
}
/**
* Get a point on ellipse.
* @param targetPoint A point that is on the target side.
* @return The point on the ellipse.
*
*/
public JFPoint getPoint(JFPoint targetPoint){
//center of ellipse
JFPoint center =getCenter();
double semimajor =getSemimajor();
//extend the target point to satisfy the intersection demand.
targetPoint =center.nearPoint(targetPoint,semimajor*3,true);
return intersectsAt(center,targetPoint);
}
/**
* Tests if the specified point intersects the outline of this ellipse.
*
* @param x1, y1 the specified point.
*
* @param pickOffset An analog offset for 'pick' this line.
*
* @return <code>true</code> if the specified point intersects the outline of this ellipse.
* false otherwise.
*/
public boolean intersects(double x1, double y1, int pickOffset) {
/**
* sum of the two length of that from this point to two foci
* of ellipse, must less or equan than 2a.
*/
double a = getSemimajor();
//point picked the out line of this ellipse.
if (Math.abs(getFociLen(x1,y1) - 2*a) <=pickOffset)
return true;
return false;
/*
//point picked one of the four control point(the vertexes) of this ellipse.
return m_leftTop.contains(x1,y1,pickOffset) ||
m_rightTop.contains(x1,y1,pickOffset) ||
m_leftBottom.contains(x1,y1,pickOffset) ||
m_rightBottom.contains(x1,y1,pickOffset);
*/
}
/**
* Tests if the specified line segment intersects the outline of this ellipse.
*
* @return true if the line segment intersects the outline of this ellipse.
* false otherwise.
*/
public boolean intersects(LineSeg line) {
if (line==null)
return false;
return intersects(line.getX1(),line.getY1(),line.getX2(),line.getY2());
}
/**
* Tests if the specified line segment intersects the outline of this ellipse.
*
* @param X1, Y1 the start point of line.
*
* @param X2, Y2 the end point of line.
*
* @return <code>true</code> if the specified line segment intersects the ellipse of this curve.
* false otherwise.
*/
public boolean intersects(double X1, double Y1, double X2, double Y2) {
JFPoint pnt =intersectsAt(X1,Y1,X2,Y2);
return (pnt!=null);
}
/**
* Get an intersected point both on this ellipse and a new line.
*
* @param startPoint the first endpoint of the specified line segment
* @param endPoint the second endpoint of the specified line segment
* @return a intersected point, null if no interception.
*/
public JFPoint intersectsAt(JFPoint startPoint, JFPoint endPoint) {
return intersectsAt(startPoint.getX(),startPoint.getY(),endPoint.getX(),endPoint.getY());
}
/**
* Get an intersected point both on this ellipse and a new line.
*
* @param X1, Y1 the start point of line.
* @param X2, Y2 the end point of line.
* @return a intersected point, null if no interception.
*/
public JFPoint intersectsAt(double X1, double Y1, double X2, double Y2) {
//const definition..
int n =BEZIER_SEGMENT_NUM;
int []qx =new int[n*3+1]; //n bezier curves
int []qy =new int[n*3+1];
//seperate this ellipse to bezier curve segments.
if (!getEllipseControlPoints(qx,qy))
return null;
Curve curve =new Curve();
double x1=0, y1=0, x2=0, y2=0, x3=0,y3=0, x4=0,y4=0;
int i =0;
while (i<n*3){
x1 =qx[i]; y1 =qy[i];
x2 =qx[i+1]; y2 =qy[i+1];
x3 =qx[i+2]; y3 =qy[i+2];
x4 =qx[i+3]; y4 =qy[i+3];
curve.setValue(x1,y1,x2,y2,x3,y3,x4,y4);
JFPoint pnt=curve.intersectsAt(X1,Y1,X2,Y2);
if (pnt!=null)
return pnt;
i +=3;
}
return null;
}
/**
* Tests if the specified rectangle intersects the outline of this ellipse.
*
* @return true if the line segment intersects the outline of this ellipse.
* false otherwise.
*/
public boolean intersects(Rect rect) {
if (rect==null)
return false;
for (int i=Rect.SIDETYPE_LEFT; i<=Rect.SIDETYPE_BOTTOM; i++){
LineSeg side=rect.getSide(i);
if (intersects(side))
return true;
}
//test if current ellipse is inside the target rectangle.
return rect.contains(getCenter());
}
/**
* Draw an ellipse on specified graphic context.
*
* @param ellipse The ellipse to be drawn.
*
* @return A general path for drawing this ellipse.
*/
public static GeneralPath getEllipsePath(Ellipse ellipse){
JFPoint center =ellipse.getCenter();
if (center==null)
return null;
double x =center.getX();
double y =center.getY();
double a =ellipse.getSemimajor();
double b =ellipse.getSemiminor();
double angle =ellipse.getAngle();
if (ellipse.getType()==ELLIPSE_VERTICAL)
angle += Angle.PI/2;
return getEllipsePath(x,y,a,b,angle);
}
//seperate an ellipse into bezier segments.
private static final int BEZIER_SEGMENT_NUM =8;
/**
* Seperate an ellipse into control points list of a curved bezier.
*
* @param qx,qy Int arrays for storing x,y coordinates of a curved ellipse. These two arrays' size must be n*3+1.
* @return True if successfully get control points, false otherwise
*/
private boolean getEllipseControlPoints(int qx[], int qy[]){
JFPoint center =getCenter();
if (center==null)
return false;
double x =center.getX();
double y =center.getY();
double a =getSemimajor();
double b =getSemiminor();
double angle =getAngle();
if (getType()==ELLIPSE_VERTICAL)
angle += Angle.PI/2;
//seperate this ellipse to bezier curve segments.
return getEllipseControlPoints(x,y,a,b,angle,qx,qy);
}
/**
* Seperate an ellipse into control points list of a curved bezier.
*
* @param x,y Center coordinates of ellipse.
*
* @param a,b Semimajor and semiminor of ellipse.
*
* @param angle The angle that ellipse rotated.
* @param qx,qy Int arrays for storing x,y coordinates of a curved ellipse. These two arrays' size must be n*3+1.
* @return True if successfully get control points, false otherwise
*/
private static boolean getEllipseControlPoints(double x, double y ,double a ,double b, double angle, int qx[], int qy[]){
//const definition..
int n =BEZIER_SEGMENT_NUM;
double PI =Angle.PI;
double alpha =PI/n;
double beta =0.26521648984; // = 4*(1-cos(Alpha))/(3*sin(Alpha))
//pixel coordinates list for ellipse.
double []px =new double[n*3+1];
double []py =new double[n*3+1];
double sinA=0, cosA=0;
double temp=0;
int i=0,j=0,k=0;
for (i=0; i<=n-1; i++){
temp = i * (2*alpha);
cosA = Math.cos(temp);
sinA = Math.sin(temp);
k = i*3;
if (k==0)
j =n*3-1;
else
j =k-1;
px[k] =a * cosA;
py[k] =b * sinA;
sinA =beta * a * sinA;
cosA =beta * b * cosA;
px[j] =px[k] + sinA;
py[j] =py[k] - cosA;
px[k+1] =px[k] - sinA;
py[k+1] =py[k] + cosA;
}
px[n*3] =px[0];
py[n*3] =py[0];
cosA =Math.cos(angle);
sinA =Math.sin(angle);
// Rotate and translate
for (i=0; i<=n*3; i++){
qx[i] =(int)Math.round(px[i] * cosA - py[i] * sinA + x);
qy[i] =(int)Math.round(px[i] * sinA + py[i] * cosA + y);
}
return true;
}
/**
* Draw an ellipse on specified graphic context.
*
* @param x,y Center coordinates of ellipse.
*
* @param a,b Semimajor and semiminor of ellipse.
*
* @param angle The angle that ellipse rotated.
*
* @return A general path for drawing this ellipse.
*/
private static GeneralPath getEllipsePath(double x, double y ,double a ,double b, double angle){
//const definition..
int n =BEZIER_SEGMENT_NUM;
int []qx =new int[n*3+1]; //n bezier curves
int []qy =new int[n*3+1];
//seperate this ellipse to bezier curve segments.
getEllipseControlPoints(x,y,a,b,angle,qx,qy);
GeneralPath curve= new GeneralPath(GeneralPath.WIND_EVEN_ODD);
curve.moveTo(qx[0],qy[0]);
int i =1;
while (i<n*3){
curve.curveTo(qx[i],qy[i], qx[i+1],qy[i+1], qx[i+2],qy[i+2]);
i +=3;
}
curve.closePath();
return curve;
}
/**
* Draw a bezier curve on graphics context.
*
* @param x1,y1 Start end point of curve.
*
* @param x2,y2 One control point of curve.
*
* @param x3,y3 Another control point of curve.
*
* @param x4,y4 Another end point of curve.
*
* @param g The graphic context.
*
private static void drawCurve(double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4,
Graphics g){
double startX, startY, endX, endY;
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;
//draw curve
g.drawLine((int)startX,(int)startY,(int)endX,(int)endY);
startX =endX;
startY =endY;
}
}
*/
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?