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;&nbsp;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,&nbsp;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,&nbsp;Y1 the start point of line.
     *	
     * @param X2,&nbsp;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,&nbsp;Y1 the start point of line.
     * @param X2,&nbsp;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 + -
显示快捷键?