arc.java

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

JAVA
1,554
字号
	if (m_arcType==CHORD){
		//line from start point to end point.
		line.setValue(startPoint,endPoint);
		if (line.contains(x,y,pickOffset)){
			intersectLine	=true;
			portType	=JFArcPoint.POINTTYPE_CHORD;
		}

	}else if (m_arcType==PIE){
		
		//line from center to start point
		line.setValue(center,startPoint);
		if (line.contains(x,y,pickOffset)){
			intersectLine	=true;
			portType	=JFArcPoint.POINTTYPE_PIE_START;
		}else{
			//line from center to start point
			line.setValue(center,endPoint);
			if (line.contains(x,y,pickOffset)){
				intersectLine	=true;
				portType	=JFArcPoint.POINTTYPE_PIE_END;
			}
		}
	}


	if (intersectLine){
		JFPoint pnt1	=line.getPoint1();
		JFPoint pnt2	=line.getPoint2();
		
		if (pnt1.distance(x,y)<=pickOffset)
			pnt	=pnt1;
		else if (pnt2.distance(x,y)<=pickOffset)
			pnt	=pnt2;
		else
			pnt	=line.uprightFoot(x,y);
		
		dist	=pnt1.distance(pnt2);
		if (dist<1) dist=1;
		resultPoint.setValue(pnt);
		resultPoint.setScale(pnt.distance(pnt1)/dist);
		resultPoint.setType(portType);
		return resultPoint;
	}
	
	return null;
   }



   /**
    *   Get a point on the arc by an angle. We assume this point will always on the arc.
    *
    *   @param angle An angle from 0 to 2*PI, counter-clockwise angle is plus angle.
    *   @return The point on the arc.
    *
    */ 	
   public JFPoint getPoint(double angle){
	JFPoint center		=getCenter();
   	double radius		=getRadius();

   	angle	  	=Angle.getValidAngle(angle);
   	double x  	=radius * Math.cos(angle);
   	double y	=radius * Math.sin(angle);
   	
   	x	=center.getX()+x;
   	y	=center.getY()-y;
   	
   	return new JFPoint(x,y);
   }



   /**
    *   Get a point by point type and scale.
    *
    *   @param pointType Type of current port.
    *   @param scale Scale of this port compare to start point or start angle or center.
    *   @return The point on the arc.
    *
    */ 	
   public JFPoint getPoint(int pointType, double scale){
	JFPoint center		=getCenter();
	double dist=0;
   	
   	switch (pointType){
   		case JFArcPoint.POINTTYPE_CURVE:
   			double angle		=getAngle();
   			double startAngle	=Angle.getValidAngle(Angle.getAngle(center,m_startPoint));
			double thisAngle	=startAngle + scale * angle;
			return getPoint(thisAngle);

   		case JFArcPoint.POINTTYPE_CHORD:
			dist		=m_startPoint.distance(m_endPoint) * scale;
			return m_startPoint.nearPoint(m_endPoint,dist);			   		

   		case JFArcPoint.POINTTYPE_PIE_START:
   		case JFArcPoint.POINTTYPE_PIE_END:
			dist		=getRadius() * scale;
			if (pointType==JFArcPoint.POINTTYPE_PIE_START)
				return center.nearPoint(m_startPoint,dist);
			else
				return center.nearPoint(m_endPoint,dist);
   	}
   	
   	return null;
   }



    /**
     * Tests if the specified point intersects the curve of this arc.
     *
     * @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 curve of this arc.
     * false otherwise.
     */
    public boolean intersects(double x1, double y1, int pickOffset) {
	
	JFPoint center	=getCenter();
	    	
    	//the radius of this arc.
    	double radius	=getRadius();
    	
    	//the virtual radius from center to this point.
    	double radius1	=center.distance(x1,y1);
    	
    	//this new 'radius1' will between the maximum radius and minimum radius.
    	if (radius1>=radius - pickOffset && radius1<=radius + pickOffset && ifInPie(x1,y1)){
		return true;
	}
	else{
		JFPoint startPoint	=getStartPoint();
		if (startPoint.distance(x1,y1)<=pickOffset)
			return true;
			
		JFPoint endPoint	=getEndPoint();
		if (endPoint.distance(x1,y1)<=pickOffset)
			return true;
		
		JFPoint controlPoint	=getControlPoint();
		if (controlPoint.distance(x1,y1)<=pickOffset)
			return true;
		
		if (m_arcType==CHORD){
			LineSeg	line		=new LineSeg(startPoint,endPoint);
			return line.contains(x1,y1,pickOffset);

		}else if (m_arcType==PIE){
			JFPoint centerPoint	=getCenter();
			if (centerPoint.distance(x1,y1)<=pickOffset)
				return true;
			
			LineSeg	line		=new LineSeg(startPoint,centerPoint);
			if (line.contains(x1,y1,pickOffset))
				return true;
							
			line.setValue(endPoint,centerPoint);
			if (line.contains(x1,y1,pickOffset))
				return true;
		}
				
		return false;
	}
    }


    /**
     * Tests if the specified line intersects the curve of this arc.
     *
     * @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 point intersects the curve of this arc.
     * false otherwise.
     */
    private boolean arcIntersects(double x1, double y1, double x2, double y2) {
	
	JFPoint center	=getCenter();	
	double radius	=getRadius();    		
	//test if this line intersected with the whole ellipse
	List l	=Ellipse.pointsIntersected(x1,y1,x2,y2,center.getX(),center.getY(),radius);
	
	//test if the points intersected with ellipse are actually falling on the arc.	
	if (l!=null && l.size()>0){
		Iterator it	=l.iterator();
		while (it!=null && it.hasNext()){
			JFPoint	pnt	=(JFPoint)it.next();
			if (ifInPie(pnt.getX(),pnt.getY()))
				return true;
		}
	}
	
	return false;
    }


    /**
     * Tests if the specified line intersects this arc.
     *
     * @param line The specified line segment.
     *	
     * @return <code>true</code> if the specified line segment intersects the curve of this arc.
     * 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 intersects this arc.
     *
     * @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 curve of this arc.
     * false otherwise.
     */
    public boolean intersects(double x1, double y1, double x2, double y2) {
    	return intersects(x1,y1,x2,y2,false);
    }

    /**
     * Tests if the specified line intersects this arc.
     *
     * @param x1,&nbsp;y1 the start point of line.
     *	
     * @param x2,&nbsp;y2 the end point of line.
     *	
     * @param curveOnly Test if line intersects the curve of arc only.
     *	
     * @return <code>true</code> if the specified line segment intersects the curve of this arc.
     * false otherwise.
     */
    public boolean intersects(double x1, double y1, double x2, double y2, boolean curveOnly) {
    	
    	//test if arc intersects
    	if (arcIntersects(x1,y1,x2,y2)){
    		return true;
    	}
    	if (m_arcType==OPEN || curveOnly){
    		return false;
    	}
	
	JFPoint		startPoint	=getStartPoint();
	JFPoint 	endPoint	=getEndPoint();	
	JFPoint		center		=getCenter();
	
	LineSeg	line		=new LineSeg(x1,y1,x2,y2);
	//test if the chord line intersects while arc type is CHORD.
	if (m_arcType==CHORD){
		return line.intersects(startPoint,endPoint);
	}else if (m_arcType==PIE){
		return line.intersects(startPoint,center) || line.intersects(endPoint,center);	
	}else{
		return false;
	}
    }

    /**
     * Tests if the specified rectangle intersects the interior of this
     * <code>Arc</code>.
     * @param rect the specified {@link Rect} to test for intersection
     * with the interior of this <code>Arc</code>
     * @return <code>true</code> if the specified <code>Rect</code>
     * intersects the interior of this <code>Arc</code>;
     * <code>false</code> otherwise.
     */
    public boolean intersects(Rect rect) {
	
	LineSeg side	=null;
	//test if each side of rectangle intersects.
	for (int i = Rect.SIDETYPE_LEFT; i<=Rect.SIDETYPE_BOTTOM; i++){
		side	=rect.getSide(i);
		if (intersects(side))
			return true;
	}
	
	//test if current arc is inside the target rectangle.
	return  rect.contains(getStartPoint()) ||
	     	rect.contains(getEndPoint());
    }


   /**
    *   Scale current rectangle by specified points and scale percent.
    *   We only support a concurrent width-height scale here, suppose width as the length from
    *   basePoint to refPoint1, height as the length from basePoint to refPoint2, and 
    *   one scale percent acts on both width and height.
    *
    *   @param basePoint A base point that is unmovable.
    *   @param refPoint1 A 'width' reference point.
    *   @param refPoint2 A 'height' reference point.
    *   @param scale A reference scale percent.
    *
    */ 	
   public void scaleBy(JFPoint basePoint, JFPoint refPoint1, JFPoint refPoint2, double scale){

   	JFPoint center	=getCenter();

	if (scale<0)  scale	=0;
	
	m_startPoint.scaleBy(center.getX(),center.getY(),scale);
	m_endPoint.scaleBy(center.getX(),center.getY(),scale);
	m_controlPoint.scaleBy(center.getX(),center.getY(),scale);
 
	JFPoint newCenter	=Rect.newScaleCenter(center,basePoint,refPoint1,refPoint2,scale);

	//move center
	moveBy(newCenter.getX()-center.getX(),newCenter.getY()-center.getY());
   }

   /**
    *   Scale current object by a specified x and y scale.<br>
    *   This is a special scale method used to scale a shape in arbitrary x and y scale.<br>
    *   Please see AbstractShape.scaleBy for detailed description.
    *
    *   @param basePoint A base scale point for scaling reference.
    *   @param xScale  A scale percentage in x coordinate, default to 1.0
    *   @param yScale  A scale percentage in y coordinate, default to 1.0
    *
    */ 	
   public void scaleBy(JFPoint basePoint,double xScale, double yScale){
   	if (basePoint==null)
   		return;
   	double x	=basePoint.getX();
   	double y	=basePoint.getY();
   	
	m_startPoint.scaleBy(x,y,xScale,yScale);
	m_endPoint.scaleBy(x,y,xScale,yScale);
	m_controlPoint.scaleBy(x,y,xScale,yScale);
   }

   

   /**
    *   Move this arc by specific x and y coordinates.
    *
    *   @param x   X coordiate to moveby. 
    *
    *   @param y   Y coordiate to moveby.
    *
    */ 	
   public void moveBy(double x, double y){
   	m_startPoint.moveBy(x,y);
   	m_endPoint.moveBy(x,y);
   	m_controlPoint.moveBy(x,y);
   }

   /**
    *   Rotate this arc by an angle theta.
    *
    *   @param theta A rotate angle.
    *
    */ 	
   public void rotateBy(double theta){
   	//get center point of this rectangle.
   	JFPoint center	=getCenter();
   	//rotate by center
   	rotateBy(center,theta);
   }

   /**
    *   Rotate this arc by a specified point and an angle theta.
    *
    *   @param pnt  A rotate center point.
    *
    *   @param theta A rotate angle.
    *
    */ 	
   public void rotateBy(JFPoint pnt, double theta){
   	if (pnt!=null)
   		rotateBy(pnt.getX(),pnt.getY(),theta);
   }
	  
   /**
    *   Rotate this arc by a specified point and an angle theta.
    *
    *   @param baseX,&nbsp;baseY  A rotate center point.
    *
    *   @param theta A rotate angle.
    *
    */ 	
   public void rotateBy(double baseX, double baseY, double theta){
   	m_startPoint.rotateBy(baseX,baseY,theta);	
   	m_endPoint.rotateBy(baseX,baseY,theta);
   	m_controlPoint.rotateBy(baseX,baseY,theta);
   }


   /**
    *   Mirror this arc by a central x coordinate of this arc. We make a up-down flip here.
    */ 	
   public void mirrorBy(){
	JFPoint center	=getCenter();
	mirrorBy(center.getX()); 
   }


   /**
    *   Mirror this arc by a x coordinate. We make a left-right mirror here.
    *
    *   @param baseX  A mirror base x coordinate.
    *
    */ 	
   public void mirrorBy(double baseX){
   	m_startPoint.mirrorBy(baseX);
   	m_endPoint.mirrorBy(baseX);
   	m_controlPoint.mirrorBy(baseX);
   }

   /**
    *   Reverse this arc by a central y coordinate of this arc. We make a up-down flip here.
    */ 	
   public void flipBy(){
	JFPoint center	=getCenter();
	flipBy(center.getY()); 
   }


   /**
    *   Reverse this arc by a y coordinate. We make a up-down flip here.
    *
    *   @param baseY  A flip base y coordinate.
    *
    */ 	
   public void flipBy(double baseY){
   	m_startPoint.flipBy(baseY);
   	m_endPoint.flipBy(baseY);
   	m_controlPoint.flipBy(baseY);
   }


   /**
    *   Convert this object to String 
    * 
    *   @return  An string represents the content of the object
    *
    */ 	
   public String toString(){
  	StringBuffer buf =new StringBuffer();
  	buf.append(";startPoint[");  	buf.append(m_startPoint.toString()); buf.append("]");
  	buf.append(";endPoint[");  	buf.append(m_endPoint.toString()); buf.append("]");
  	buf.append(";controlPoint[");  	buf.append(m_controlPoint.toString()); buf.append("]");
  	buf.append(";arcType=");	buf.append(m_arcType);
  	
  	return buf.toString();
   }

 
   /**
    *   Creates a new object of the same class and with the same contents as this object.
    * 
    *   @return  A clone of this instance.
    *
    */ 	
  public Object clone() throws CloneNotSupportedException{
  	try{
  		return new Arc(this);
  		
	}catch(Exception e){
		throw new CloneNotSupportedException(e.getMessage());
	}
  }


   /**
    *   Returns the hashcode for this Object.
    * 
    *   @return hash code for this Point2D.
    *
    */ 	
  public int hashCode(){
       	
  	
  	return 	m_startPoint.hashCode() ^
  		m_endPoint.hashCode() ^
  		m_controlPoint.hashCode() ^
  		m_arcType;
  }


   /**
    *   Determines whether or not two objects are equal. 
    * 
    * 	@param obj  an object to be compared with this object 
    * 
    *   @return true if the object to be compared is an instance of Port and has the same values; false otherwise.
    *
    */ 	
  public boolean equals(Object obj){

      if (obj == this)
             	return true;

      if (!(obj instanceof Arc))
            	return false;

      Arc	arc	=(Arc)obj;
      
      return	(m_startPoint.equals(arc.m_startPoint)) &&
      		(m_endPoint.equals(arc.m_endPoint)) &&
      		(m_controlPoint.equals(arc.m_controlPoint)) &&
      		(m_arcType==arc.m_arcType);
  }



}

⌨️ 快捷键说明

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