arc.java

来自「用Java开发的、实现类似Visio功能的应用程序源码」· Java 代码 · 共 1,554 行 · 第 1/3 页

JAVA
1,554
字号
    *   Get the bounds of this arc.
    *
    *   @return The bounds rectangle.
    *
    */ 	
   public Rect getBounds(){
   	JFPoint center	=getCenter();
   	double radius	=center.distance(m_startPoint);
   	return new Rect(center.getX()-radius,center.getY()-radius,2*radius,2*radius);
   }
 
   /**
    *   Get start angle of this arc.
    *   A start angle of an arc is constructed 
    *   by the horizontal line(from left to right) and the line from center to start point.
    *
    *   @return The start angle.
    *
    */ 	
   public double getStartAngle(){
   	JFPoint center	=getCenter();
   	return Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
   }

   /**
    *   Get end angle of this arc.
    *   A end angle of an arc is constructed 
    *   by the horizontal line(from left to right) and the line from center to end point.
    *
    *   @return The ending angle.
    *
    */ 	
   public double getEndAngle(){
   	return Angle.getValidAngle(getStartAngle()+getAngle());
   }


   /**
    *   Set value of current Arc.
    *
    *   @param val  A new Arc object.
    *
    */ 	
   public void setValue(Arc arc){
	setValueByControl(arc.getStartPoint(),arc.getEndPoint(),arc.getControlPoint(),arc.getArcType());
   }


   /**
    *   Set value of current Arc.
    *   Attention: The distance from startPoint to center must equal to the distance from endPoint to center.
    *   Otherwise we will make a correction for the difference.
    *
    *   @param center The center point of this arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param angle The angle of this arc.
    *
    */ 	
   public void setValue(JFPoint center,JFPoint startPoint,double angle){
   	setValue(center,startPoint,angle,m_arcType);
   }

   /**
    *   Set value of current Arc.
    *   Attention: The distance from startPoint to center must equal to the distance from endPoint to center.
    *   Otherwise we will make a correction for the difference.
    *
    *   @param center The center point of this arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param angle The angle of this arc.
    *
    *   @param arcType type of current arc.
    *
    */ 	
   public void setValue(JFPoint center,JFPoint startPoint,double angle, int arcType){
  	
	m_startPoint.setValue(startPoint);
	
	//set angle, then adjust the end point and control point.
	if (!setAngle(angle,m_startPoint,center)){
		//if failed to set the angle, may be the angle is too small, so we consider an 1 degree angle.
		setAngle(1/180*Angle.PI,m_startPoint,center);
	}
   	m_arcType 	=arcType;
   }


   /**
    *   Set value of current Arc.
    *
    *   @param center The center point of this arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param endPoint The end point of this arc.
    *
    *   @param clockwiseControl If control point is under clockwise side of the vector from start point to end point. False default.
    *
    *   @param arcType type of current arc.
    *
    */ 	
   public void setValue(JFPoint center,JFPoint startPoint,JFPoint endPoint, boolean clockwiseControl,int arcType){

	m_startPoint.setValue(startPoint);
	m_endPoint.setValue(endPoint);
	
	double radius		=center.distance(m_startPoint);
	
	//slope of the line from start point to end point.
	double	slope	=m_startPoint.getSlope(m_endPoint);
	//slope of the erect perpendicular bisector of the line from startpoint to end point
	if (slope==GeomConst.LARGE_VALUE)
		slope	=0;
	else if (slope==0)
		slope	=GeomConst.LARGE_VALUE;
	else 
		slope	=-1/slope;

	m_controlPoint		=center.nearPoint(slope,radius,m_startPoint,!clockwiseControl);
	
	m_arcType		=arcType;
   }


   /**
    *   Get a default control point decided by start point and end point of an arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param endPoint The end point of this arc.
    *
    *   @return The default control point.
    *
    */ 	
   private static JFPoint getDefaultControlPoint(JFPoint startPoint, JFPoint endPoint){
   	if (startPoint==null || endPoint==null)
   		return null;

   	//length of the line from center of arc to centerPoint.
   	double  chordHeight     =startPoint.distance(endPoint)/3;
   	
   	return JFPoint.getMiddleUprightPoint(startPoint,endPoint,chordHeight,false);
   }
   	
   /**
    *   Set value of current Arc.
    *   We decide an arc by a startpoint and an endpoint. This method is always used while
    *   drawing an arc when two end points are decided.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param endPoint The end point of this arc.
    *
    *   @param arcType type of current arc.
    *
    */ 	
   public void setValueByDraw(JFPoint startPoint, JFPoint endPoint,int arcType){
   	JFPoint controlPoint	=getDefaultControlPoint(startPoint, endPoint);
   	if (controlPoint==null)
   		return;

	setValueByControl(startPoint,endPoint,controlPoint,arcType);
   }


   /**
    *   Set value of current Arc.
    *   We decide an arc by a startpoint ,an endpoint and a control point. This method is always used while
    *   adjusting an arc when two end points and a control point are decided.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param endPoint The end point of this arc.
    *
    *   @param controlPoint The control point of this arc.
    *
    *   @param arcType type of current arc.
    *
    */ 	
   public void setValueByControl(JFPoint startPoint, JFPoint endPoint,JFPoint controlPoint,int arcType){
   	if (startPoint==null || endPoint==null || controlPoint==null)
   		return;
   	
   	//test if a control point is actuall a control point that is on the middle upright line of 
   	//the line from start Point to end point.
   	if ((float)controlPoint.distance(startPoint)!=(float)controlPoint.distance(endPoint)){
   		
   		//default control point of arc.
   		JFPoint defaultControlPoint	=getDefaultControlPoint(startPoint,endPoint);
   		//center point between startpoint and endpoint.
   		JFPoint centerPoint		=startPoint.midPoint(endPoint);
   		//line from center point to default control point.
   		LineSeg  line = new LineSeg(centerPoint,defaultControlPoint);
   		//projective upright foot on line above by 'control point'.
   		controlPoint 	=line.uprightFoot(controlPoint.getX(), controlPoint.getY());
   		if (controlPoint==null)
   			return;
   	}
   	
   	m_startPoint.setValue(startPoint);
   	m_endPoint.setValue(endPoint);
   	m_controlPoint.setValue(controlPoint);
   	m_arcType	=arcType;
   }

   
   /**
    *   Move control point of  current Arc to a new position.
    *
    *   @param controlPoint A new position of control point.
    *
    */ 	
   public void moveControlPointTo(JFPoint controlPoint){
   	setControlPoint(controlPoint,true);
   }

   /**
    *   Move center point of  current Arc to a new position.
    *
    *   @param centerPoint A new position of center point.
    *
    */ 	
   public void moveCenterPointTo(JFPoint centerPoint){

   	//if control point is under clockwise side of vector from startpoint to endpoint.
	boolean clockwise	=JFVector.underClockwiseSide(m_startPoint,m_controlPoint,m_startPoint,m_endPoint);


	JFPoint midPoint	=m_startPoint.midPoint(m_endPoint);
	JFPoint defaultControl	=getDefaultControlPoint(m_startPoint,m_endPoint);
	LineSeg	line	=new LineSeg(midPoint,defaultControl);
	
   	//projective upright foot on line above by 'center point'.
   	JFPoint newCenter 	=line.uprightFoot(centerPoint.getX(),centerPoint.getY());
   	if (newCenter==null || newCenter.distance(midPoint)<GeomConst.MIN_LINELENGTH)
   		return;


	setValue(newCenter,m_startPoint,m_endPoint,clockwise,m_arcType);
   }


   /**
    *   Move start point of  current Arc to a new position.
    *
    *   @param newStartPoint A new position of start point.
    *
    */ 	
   public void moveStartPointTo(JFPoint newStartPoint){
   	setStartPoint(newStartPoint,true);
   }


   /**
    *   Move end point of  current Arc to a new position.
    *
    *   @param newEndPoint A new position of end point.
    *
    */ 	
   public void moveEndPointTo(JFPoint newEndPoint){
   	setEndPoint(newEndPoint,true);
   }


   /**
    *   Constructor for Arc.
    */ 	
   public Arc(){
   }

   /**
    *   Constructor for Arc.
    *   
    *   @param arc A Arc object.
    */ 	
   public Arc(Arc arc){
   	setValue(arc);
   }

   /**
    *   Constructor for Arc.
    *
    *   @param center The center point of this arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param angle the angle of this arc.
    *
    */ 	
   public Arc(JFPoint center,JFPoint startPoint,double angle){
   	setValue(center,startPoint,angle);
   }


   /**
    *   Constructor for Arc.
    *
    *   @param center The center point of this arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param angle the angle of this arc.
    *
    *   @param arcType  type of this arc.
    *
    */ 	
   public Arc(JFPoint center,JFPoint startPoint,double angle, int arcType){
   	setValue(center,startPoint,angle,arcType);
   }

   /**
    *   Constructor for Arc.
    *
    *   @param center The center point of this arc.
    *
    *   @param startPoint The start point of this arc.
    *
    *   @param endPoint the end point of this arc.
    *
    *   @param clockwiseControl If control point is under clockwise side of the vector from start point to end point. False default.
    *
    *   @param arcType  type of this arc.
    *
    */ 	
   public Arc(JFPoint center,JFPoint startPoint,JFPoint endPoint, boolean clockwiseControl,int arcType){
   	setValue(center,startPoint,endPoint,clockwiseControl,arcType);
   }

   /**
    *   Test if a point is within this arc.
    *
    *   @param pnt A point to be measured.
    *
    *   @return True if the point is within the arc, false otherwise.
    *
    */ 	
   public boolean contains(JFPoint pnt){
   	return contains(pnt.getX(),pnt.getY());
   }


   /**
    *   Test if the line that from center to this point is in the PIE angle of this arc.
    *
    *   @param x,&nbsp;y A point to be measured.
    *
    *   @return True if the line from center to this point is within the arc, false otherwise.
    *
    */ 	
   private boolean ifInPie(double x, double y){
	
	JFPoint center		=getCenter();
	double angle		=getAngle();

   	double startAngle	=Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
   	double endAngle		=Angle.getValidAngle(Angle.getAngle(center,m_endPoint));
	double thisAngle	=Angle.getValidAngle(Angle.getAngle(center.getX(),center.getY(),x,y));
	
	if (angle==0){
		return (thisAngle==startAngle);

	}else if (startAngle<endAngle){
		if (angle>=0){
			return (thisAngle>=startAngle && thisAngle<=endAngle);
		}else{
			return (thisAngle<startAngle || thisAngle>endAngle);
		}
	}else{
		if (angle>=0){
			return (thisAngle>startAngle || thisAngle<endAngle);
		}else{
			return (thisAngle>=endAngle && thisAngle<=startAngle);
		}
	}
   }


   /**
    *   Test if a point is within this arc.
    *
    *   @param x,&nbsp;y A point to be measured.
    *
    *   @return True if the point is within the arc, false otherwise.
    *
    */ 	
   public boolean contains(double x, double y){

	JFPoint center		=getCenter();
   	double radius		=getRadius();
   	double angle		=getAngle();

	//test if this angle is in pie
	boolean inPie	=ifInPie(x,y);

	double dist	=center.distance(x,y);

	//if this point is inside the circle that its center is at center and with a radius m_radius
	if ((Math.abs(dist-radius)<=GeomConst.PICK_OFFSET) && inPie)
		return true;
	else if (dist>radius)
		return false;
	
	if (m_arcType==OPEN) 
		return false;

	//test if the line from start point to end point and the line from center to target point 
	//are intersected.
	
	//line from start point to end point.
	LineSeg line1	=new LineSeg(getStartPoint(),getEndPoint());

	
	//if intersect with line from center to target point.
	boolean intersected	=line1.intersects(center.getX(),center.getY(),x,y);
	
	if (intersected){	
		return Math.abs(angle)<Angle.PI && inPie;
	}else{

		if (Math.abs(angle)>=Angle.PI)
			if (m_arcType!=PIE)
				return true;
			else	
				return inPie;
		else{

			if (!inPie)
				return false;
			else{
				return m_arcType==PIE;
			}
		}
	}
 
   }

   /**
    *   Test if current arc intersects the point at a position.
    *
    *   @param x;&nbsp;y A point to be measured.
    *   @param pickOffset An analog offset for 'pick' this arc.
    *   @return A result arcPoint that represents an intersected point.
    *
    */ 	
   public JFArcPoint intersectsAt(double x, double y, double pickOffset){

	JFArcPoint resultPoint	=new JFArcPoint();
	JFPoint center		=getCenter();
	JFPoint startPoint	=getStartPoint();
	JFPoint endPoint	=getEndPoint();
   	double radius		=getRadius();
   	double radius1		=center.distance(x,y);
   	double angle		=getAngle();

	//test if this angle is in pie
	boolean inPie	=ifInPie(x,y);
  	
	//if this point is on the curve.
	if (Math.abs(radius1-radius)<=pickOffset && inPie){
   		double startAngle	=Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
   		double endAngle		=Angle.getValidAngle(Angle.getAngle(center,m_endPoint));
		double thisAngle	=Angle.getValidAngle(Angle.getAngle(center.getX(),center.getY(),x,y));
		double minus		=thisAngle-startAngle;
		double scale		=0;


		if ((float)angle==0){
			scale	=0;

		}else if (startAngle<endAngle){
			if (angle>0){
				//this angle must between start angle and end angle.
				scale	=minus/angle;
			}else{
				if (thisAngle<startAngle){//this angle must less than endangle.
					scale	=minus/angle;
				}else{//this angle must greater than endAngle
					scale	=(Angle.PI*2-Math.abs(minus))/angle;
				}
			}
		}else{
			if (angle>0){
				if (thisAngle>startAngle){//this angle must greater than endangle.
					scale	=minus/angle;
				}else{//this angle must less than start angle.
					scale	=(Angle.PI*2-Math.abs(minus))/angle;
				}
			}else{
				//this angle must greater than end angle or less than start angle.
				scale	=minus/angle;
			}
		}
		
		
		//get the result point's position
		resultPoint.setValue(getPoint(thisAngle));
   		resultPoint.setScale(Math.abs(scale));
		resultPoint.setType(JFArcPoint.POINTTYPE_CURVE);
		return resultPoint;
	}	
	
	//if radius is out side the circle, return false.
	if (radius1>radius)	
		return null;


	LineSeg line	=new LineSeg();
	JFPoint pnt	=new JFPoint();
	double dist;

	
	boolean intersectLine	=false;
	int portType=0;
	//point is on the chord.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?