rect.java

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

JAVA
1,488
字号
    *   @return True if the point is inside this rectangle, false otherwise.
    *
    */ 	
   public boolean contains(double x, double y){


	//if regular rectangle.
	if (m_leftTop.getX()==m_leftBottom.getX() &&
	    m_leftTop.getY()==m_rightTop.getY() &&	
	    m_rightTop.getX()==m_rightBottom.getX() &&
	    m_leftBottom.getY()==m_rightBottom.getY()){

		double x0 = getX();
		double y0 = getY();
		return (x >= x0 &&
			y >= y0 &&
			x <= x0 + getWidth() &&
			y <= y0 + getHeight());	

	//rectangle has been rotated or scaled.
	}else{


		//each side of rectangle
		LineSeg     	side=null;
		
		//radial line from this point to left
		LineSeg	radialLine = new LineSeg(x,y,x-GeomConst.LARGE_VALUE,y);
		
		//intersect points' number between radial line and rectangle
		int		intersectPoints =0;
		
		//test each side of rectangle
		for (int i = SIDETYPE_LEFT; i<=SIDETYPE_BOTTOM; i++){
		
			//Because of getSide method will be overridden by subclasses, so here
			//we get side directly by each corner point.
   			switch(i){
   				case  SIDETYPE_LEFT: //the line constructed by left-top vertex and left-bottom vertex
   					side 	=new LineSeg(m_leftBottom,m_leftTop);
   					break;
   					
   				case  SIDETYPE_TOP: //the line constructed by left-top vertex and right-top vertex
   					side    =new LineSeg(m_leftTop,m_rightTop);
   					break;

   				case  SIDETYPE_RIGHT: //the line constructed by right-top vertex and right-bottom vertex
   					side	=new LineSeg(m_rightTop,m_rightBottom);
   					break;
   			
   				case  SIDETYPE_BOTTOM: //the line constructed by left-bottom vertex and right-bottom vertex
   					side	=new LineSeg(m_rightBottom,m_leftBottom);
   					break;
   					
   				default:	
   					continue;
   			}

		
			//point is on one side of rectangle
			if (side.contains(x,y))
				return true;
		
			//this side of rectangle is not a horizontal line
			else if (side.getY1()!=side.getY2()){
				//if one endpoint of side is on radial line
				if (radialLine.contains(side.getX1(),side.getY1())){
					if (side.getY1()>side.getY2()){
						intersectPoints++;
					}
				}else if (radialLine.contains(side.getX2(),side.getY2())){
					if (side.getY1()<side.getY2()){
						intersectPoints++;
					}
				
				//if radialLine intersects the side
				}else{
			         	if (radialLine.intersects(side)){
						intersectPoints++;
					}
				}
			}
		}
		
		//if count mod 2 = 1 return true
		return intersectPoints%2==1;
	}
   	
   }

   /**
    *   Pick a line segment of this rectangle by a point with a pickoffset.
    *   @param x   X coordinate of this point.
    *   @param y   Y coordinate of this point.
    *   @param pickOffset An analog pick offset that great equal than 0.
    *
    *   @return A line segment picked.
    *
    */ 	
   public LineSeg pickLine(double x, double y,double pickOffset){
   	LineSeg line	=new LineSeg();

	line.setPoint1(m_leftTop);
	line.setPoint2(m_rightTop);
  	if (line.contains(x,y,pickOffset))  return line;
  	
	line.setPoint1(m_rightTop);
	line.setPoint2(m_rightBottom);
  	if (line.contains(x,y,pickOffset))  return line;

	line.setPoint1(m_rightBottom);
	line.setPoint2(m_leftBottom);
  	if (line.contains(x,y,pickOffset))  return line;

	line.setPoint1(m_leftBottom);
	line.setPoint2(m_leftTop);
  	if (line.contains(x,y,pickOffset))  return line;
  	
  	return null;
   }



   /**
    *   Test if current rectangle can add a port according to the position x,y.
    *   @param x   X coordinate of the port.
    *   @param y   Y coordinate of the port.
    *   @param startPoint,endPoint,portPoint Three major parameters of a port.
    *
    *   @return True if can add a new port, false otherwise.
    *
    */ 	
   public boolean canAddPort(double x, double y,JFPoint startPoint, JFPoint endPoint, JFPoint portPoint){
	LineSeg line	=pickLine(x,y,GeomConst.PICK_OFFSET);
	if (line==null)
		return false;
	
	startPoint.setValue(line.getPoint1());
	endPoint.setValue(line.getPoint2());
	portPoint.setValue(line.uprightFoot(x,y));
	return true;
   }


    /**
     * Tests if the specified point intersects any side of this rectangle.
     *
     * @param pnt the specified point.
     *	
     * @param pickOffset An analog offset for 'pick' this line.
     *
     * @return <code>true</code> if the specified point intersects one side of this rectangle.
     * false otherwise.
     */
    public boolean intersects(JFPoint pnt, int pickOffset) {
    	return intersects(pnt.getX(),pnt.getY(),pickOffset);
    }

    /**
     * Tests if the specified point intersects any side of this rectangle.
     *
     * @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 one side of this rectangle.
     * false otherwise.
     */
    public boolean intersects(double x1, double y1, int pickOffset) {
    	
    	LineSeg line	=new LineSeg();

    	line.setPoint1(m_leftTop);
    	line.setPoint2(m_rightTop);
    	if (line.contains(x1,y1,pickOffset)) 	return true;
    	
    	line.setPoint1(m_leftTop);
    	line.setPoint2(m_leftBottom);
    	if (line.contains(x1,y1,pickOffset)) 	return true;

    	line.setPoint1(m_leftBottom);
    	line.setPoint2(m_rightBottom);
    	if (line.contains(x1,y1,pickOffset)) 	return true;

    	line.setPoint1(m_rightBottom);
    	line.setPoint2(m_rightTop);
    	if (line.contains(x1,y1,pickOffset)) 	return true;
    	
    	return false;
    }


    /**
     * Tests if the specified line segment intersects the interior of this
     * <code>Rect</code>.
     * @param x1,&nbsp;y1 the first endpoint of the specified
     * line segment
     * @param x2,&nbsp;y2 the second endpoint of the specified
     * line segment
     * @return <code>true</code> if the specified line segment intersects
     * the interior of this <code>Rect</code>; <code>false</code>
     * otherwise.
     */
    public boolean intersects(double x1, double y1, double x2, double y2) {
	return intersects(new LineSeg(x1,y1,x2,y2));
    }


    /**
     * Tests if the specified line segment intersects the interior of this
     * <code>Rect</code>.
     * @param line the specified {@link LineSeg} to test for intersection
     * with the interior of this <code>Rect</code>
     * @return <code>true</code> if the specified <code>LineSeg</code>
     * intersects the interior of this <code>Rect</code>;
     * <code>false</code> otherwise.
     */
    public boolean intersects(LineSeg line) {
    	if (line==null)
    		return false;
    	else
    		return  line.intersects(m_leftTop.getX(),m_leftTop.getY(),m_rightTop.getX(),m_rightTop.getY()) || //if the line intersects the top line of this rectangle.
    			line.intersects(m_leftTop.getX(),m_leftTop.getY(),m_leftBottom.getX(),m_leftBottom.getY()) || //if the line intersects the left line of this rectangle.
    			line.intersects(m_rightTop.getX(),m_rightTop.getY(),m_rightBottom.getX(),m_rightBottom.getY()) || //if the line intersects the right line of this rectangle.
    			line.intersects(m_leftBottom.getX(),m_leftBottom.getY(),m_rightBottom.getX(),m_rightBottom.getY()); //if the line intersects the bottom line of this rectangle.
    }


    /**
     * Tests if the specified rectangle intersects the interior of this
     * <code>Rect</code>.
     * @param rect the specified {@link Rect} to test for intersection
     * with the interior of this <code>Rect</code>
     * @return <code>true</code> if the specified <code>Rect</code>
     * intersects the interior of this <code>Rect</code>;
     * <code>false</code> otherwise.
     */
    public boolean intersects(Rect rect) {
	
	LineSeg side	=null;
	//test if each side of rectangle intersects.
	for (int i = SIDETYPE_LEFT; i<=SIDETYPE_BOTTOM; i++){
		//Because of getSide method will be overridden by subclasses, so here
		//we get side directly by each corner point.
   		switch(i){
   			case  SIDETYPE_LEFT: //the line constructed by left-top vertex and left-bottom vertex
   				side 	=new LineSeg(rect.m_leftBottom,rect.m_leftTop);
   				break;
   					
   			case  SIDETYPE_TOP: //the line constructed by left-top vertex and right-top vertex
   				side    =new LineSeg(rect.m_leftTop,rect.m_rightTop);
   				break;

 			case  SIDETYPE_RIGHT: //the line constructed by right-top vertex and right-bottom vertex
   				side	=new LineSeg(rect.m_rightTop,rect.m_rightBottom);
   				break;
   			
   			case  SIDETYPE_BOTTOM: //the line constructed by left-bottom vertex and right-bottom vertex
   				side	=new LineSeg(rect.m_rightBottom,rect.m_leftBottom);
   				break;
   					
   			default:
   				continue;
   		}

		if (intersects(side))
			return true;
	}


	//test if current rectangle is inside the target rectangle.
	return  rect.contains(getVertex(VERTEXTYPE_LEFTTOP)) ||
	     	rect.contains(getVertex(VERTEXTYPE_RIGHTTOP)) ||
	     	rect.contains(getVertex(VERTEXTYPE_LEFTBOTTOM)) ||
	     	rect.contains(getVertex(VERTEXTYPE_RIGHTBOTTOM));
    }



   /**
    *   Convert this object to String 
    * 
    *   @return  An string represents the content of the object
    *
    */ 	
   public String toString(){
  	StringBuffer buf =new StringBuffer();
  	buf.append(";leftTop=");  	buf.append(m_leftTop.getX());  		buf.append(','); 	buf.append(m_leftTop.getY());
  	buf.append(";rightTop=");  	buf.append(m_rightTop.getX());  	buf.append(','); 	buf.append(m_rightTop.getY());
  	buf.append(";leftBottom=");  	buf.append(m_leftBottom.getX());  	buf.append(','); 	buf.append(m_leftBottom.getY());
  	buf.append(";rightBottom=");  	buf.append(m_rightBottom.getX());  	buf.append(','); 	buf.append(m_rightBottom.getY());
  	buf.append(super.toString());
  	
  	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 Rect(this);
  		
	}catch(Exception e){
		throw new CloneNotSupportedException(e.getMessage());
	}
  }


   /**
    *   Returns the hashcode for this Object.
    * 
    *   @return hash code for this Point2D.
    *
    */ 	
  public int hashCode(){
       	
  	long  x1   =Double.doubleToLongBits(m_leftTop.getX());
  	long  y1   =Double.doubleToLongBits(m_leftTop.getY());
  	
  	long  x2   =Double.doubleToLongBits(m_rightTop.getX());
  	long  y2   =Double.doubleToLongBits(m_rightTop.getY());
  	
  	long  x3   =Double.doubleToLongBits(m_leftBottom.getX());
  	long  y3   =Double.doubleToLongBits(m_leftBottom.getY());

  	long  x4   =Double.doubleToLongBits(m_rightBottom.getX());
  	long  y4   =Double.doubleToLongBits(m_rightBottom.getY());

  	return 	super.hashCode() ^ 
  		(int)(x1 ^ (x1 >>> 32)) ^ (int)(y1 ^ (y1 >>> 32))^
  		(int)(x2 ^ (x2 >>> 32)) ^ (int)(y2 ^ (y2 >>> 32))^
  		(int)(x3 ^ (x3 >>> 32)) ^ (int)(y3 ^ (y3 >>> 32))^
  		(int)(x4 ^ (x4 >>> 32)) ^ (int)(y4 ^ (y4 >>> 32));
  }


   /**
    *   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 (!super.equals(obj))
      		return false;	

      if (obj == this)
             	return true;

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

      Rect	rect	=(Rect)obj;
      
      return	m_leftTop.equals(rect.getVertex(VERTEXTYPE_LEFTTOP)) &&
      		m_rightTop.equals(rect.getVertex(VERTEXTYPE_RIGHTTOP)) &&
      		m_leftBottom.equals(rect.getVertex(VERTEXTYPE_LEFTBOTTOM)) &&
      		m_rightBottom.equals(rect.getVertex(VERTEXTYPE_RIGHTBOTTOM));
  }




}                                                                                                                                                                                                                                                       

⌨️ 快捷键说明

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