⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geopolygon.java

📁 geotools的源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			{
				reply.addElement(new GeoPoint(xpoints[i],ypoints[i]));
			}
			return reply;
		}
	}

	  public boolean equals(Object o){
            if(! (o instanceof GeoPolygon)){return false;}
            GeoPolygon b = (GeoPolygon)o;
            if(b.getID()!=this.getID()){return false;}

            return equalsIgnoreID(b);
         }

          public boolean equalsIgnoreID(GeoPolygon b){
            int iCount = 0;
            Object gpp1,gpp2;
            Vector vP1,vP2;

            vP1 = this.getPoints();
            vP2 = b.getPoints();

            if(vP1.size()!=vP2.size()){
                return false;
            }

            for(int i=0;i<vP1.size();i++){
                gpp1 = vP1.elementAt(i);
                for(int j=0;j<vP2.size();j++){
                    gpp2 = vP2.elementAt(j);
                    if(gpp1.equals(gpp2)){
                        iCount++;
                        break;
                    }
                }
            }
            if(iCount == vP1.size()){
                return true;
            }
            return false;
        }





	  /**
	   * Tests to see if the polygon is Clockwise<br>
	   * anti-clockwise polygons often represent holes<br>
	   * this is computed on the fly so might be expensive.<br>
	   * Addapted from C function writen by Paul Bourke.
	   * @return boolean true if polygon is clockwise.
	   */
	   public boolean isClockwise(){
	    if (npoints < 3) return false;
	    int j,k,count=0;
	    double z;
	    for (int i=0;i<npoints;i++){
	        j = (i + 1) % npoints;
	        k = (i + 2) % npoints;
            z  = (ypoints[j] - xpoints[i]) * (ypoints[k] - ypoints[j]);
            z -= (ypoints[j] - ypoints[i]) * (xpoints[k] - xpoints[j]);
            if (z < 0)
                count--;
            else if (z > 0)
                count++;
        }
        if (count > 0) return false;
        else if (count < 0) return true;
        else return false;//coliniar points?
       }


	   /**
	    * Calculates the area of the polygon
	    * the result is stored in the private member variable area<br>
	    * Must be called during construction and after any changes to the polygons point set.
	    * N.B. Polygons with anti-clockwise point storage will result in a negative area
	    * @author James Macgill
	    * @since 0.7.7.1 08/May/00
	    */
	    private void calculateArea(){
	     //move polygon to origin to remove negative y values and reduce coordinate sizes
	     GeoRectangle box = getBounds();
	     double xShift = 0-box.x;
	     double yShift = 0-box.y;
	     double area;
	     double total =0;
	     //Calculate area of each tapezoid formed by droping lines from each pair of point to the x-axis.
	     //x[i]<x[i-1] will contribute a negative area
	     for(int i=0;i<npoints-1;i++){
	        area = ((xpoints[i+1]+xShift)-(xpoints[i]+xShift))*(((ypoints[i+1]+yShift)+(ypoints[i]+yShift))/2d);
	        total+=area;
	     }
	     this.area = total;
	     //System.out.println("Area calculated");
	     areaDone=true;
	    }

	    /**
	     * Calculates a waighted centroid location for this polygon.<br>
	     * the result is stored in the private member variables xcent and ycent
	     * overwriting any values that may already be stored their.<br>
	     * area must be set before calling this method, e.g. a call to calculateArea should have been made
	     * during construction.<br>
	     * Polygons must have clockwise point encoding in order to have a centroid, holes (encoded
	     * with anti-clockwise points) have undefined behavior at this point.
	     * N.B. the centroid will be the 'center of mass' but this is not guaranteed to be inside the
	     * polygon.
	     * @author James Macgill JM
	     * @since 0.7.7.1 08/May/2000
	     * @see #calculateArea
	     */
	    protected void calculateCentroidLocation(){
	     GeoRectangle box = getBounds();
	     double xShift = 0-box.x;
	     double yShift = 0-box.y;
	     if(!areaDone)calculateArea();
	     if(area == 0){
	        //test and approx fix for polygons that are effectively lines or points.
	        xcent = (box.x+(box.width/2d));
	        ycent = (box.y+(box.height/2d));
	     }
	     else
	     {

	        double total =0;
	        double x=0,y=0,x1,x2,y1,y2;
	        for(int i=0;i<npoints-1;i++){
	            x1 = xpoints[i]+xShift;
	            x2 = xpoints[i+1]+xShift;
	            y1 = ypoints[i]+yShift;
	            y2 = ypoints[i+1]+yShift;
	            x+= ((y1-y2)*(Math.pow(x1,2)+(x1*x2)+Math.pow(x2,2))/(6*area));
	            y+= ((x2-x1)*(Math.pow(y1,2)+(y1*y2)+Math.pow(y2,2))/(6*area));
	        }
	        xcent = x-xShift;
	        ycent = y-yShift;
	     }
	    }

	   /**
	    * Will test the given polygon to see if it is adjacent to this polygon.
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * @param gp The GeoPolygon to test for contiguity
	    * @return boolean, true if this polygon and gp share two or more verteces that are consecetive in both polygons
	    */
	   public boolean isContiguous(GeoPolygon gp){
	    GeoRectangle bBox = getBounds();
	    GeoRectangle safe = new GeoRectangle(bBox.x-1,bBox.y-1,bBox.width+2,bBox.height+2);
	    if(!gp.getBounds().intersects(safe))return false;
	    Vector a = getPoints();
	    Vector b = gp.getPoints();
	    int aLast = a.size()-2; // one for 0 counting one for duplicate final point.
	    int bLast = b.size()-2;

	    for(int i=0;i<=aLast;i++){
	        if(b.contains(a.elementAt(i))){
	            int indexB = b.indexOf(a.elementAt(i));

	            int nextA = (i+1)%(a.size()-1);

	            if(b.contains(a.elementAt(nextA))){

	                int nextB = b.indexOf(a.elementAt(nextA));
	                if((indexB == 0 && nextB == bLast) || (indexB == bLast && nextB==0)) return true;//wrap round end.
	                if(Math.abs(indexB-nextB)==1)return true;//no break in chain
	                //keep trying.
	            }
	        }
	    }
	    if(subParts!=null){
	            for(int i=0;i<subParts.size();i++){
	                if(((GeoPolygon)subParts.elementAt(i)).isContiguous(gp))return true;
	            }
	    }

	     return false;
	   }

	   /**
	    * Calculates the length of all arcs that are common both to this polygon and to the polygon pased in.
	    * @param gp The polygon to measure shared lengths with
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * @return double the total length of all shared arcs between the two polygons, returns as 0 if there are no shared arcs/
	    */
	   public double getContiguousLength(GeoPolygon gp){
	    double dist = 0;
	    //int start = 0;

	    Vector a = getPoints();
	    Vector b = gp.getPoints();
	    int last = a.size()-1;//0 count
	    GeoPoint start = (GeoPoint)a.elementAt(0);
	    GeoPoint end;
	    for(int i=0;i<last;i++){
	        end = (GeoPoint)a.elementAt((i+1)%last);
	        if(gp.areConsecutive(start,end)){
	            dist+=Math.sqrt((start.x-end.x)*(start.x-end.x)+(start.y-end.y)*(start.y-end.y));
	        }
	        start = end;
	    }

	    if(subParts!=null){
	            for(int i=0;i<subParts.size();i++){
	                dist+=(((GeoPolygon)subParts.elementAt(i)).getContiguousLength(gp));
	            }
	        }
	    return dist;

	   }


	   /**
	    * Tests the two provied points to see if they apeare next to each other in any of this
	    * polygons arcs.  The test is regardless of order.
	    *
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * @param p1 the first point to test
	    * @param p2 the second point to test
	    * @return boolean true if p1 follows p2 or p2 follows p1, false in any other case, including p1 and/or p2 being absent from the polygon
	    *
	    */
	    public final boolean areConsecutive(GeoPoint p1,GeoPoint p2){

	        int i1 = storedPoints.indexOf(p1);
	        if(i1== -1) return false;
	        int i2 = storedPoints.indexOf(p2);
	        if( i2 == -1)return false;
	        if(Math.abs(i2-i1)==1){return true;}
	        if(i1 == storedPoints.size()-2 && i2 ==0) return true;
	        if(i2 == storedPoints.size()-2 && i1 ==0) return true;
	        if(subParts!=null){
	            for(int i=0;i<subParts.size();i++){
	                if(((GeoPolygon)subParts.elementAt(i)).areConsecutive(p1,p1))return true;
	            }
	        }
	        return false;
	    }



	   /**
	    * Provides a list of all of the polygons from the provided list that are adjacent to this one
	    *
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * @param polys a Vector of GeoPolgyons to test against for contiguity.
	    * @return Vector a sub set of polys that contains only the polygons that are adjacent to this one.
	    */
	   public Vector getContiguityList(Vector polys){
	        //build contiguity list
	        Vector list = new Vector();
	        for(int i=0;i<polys.size();i++){
	            if(this.isContiguous((GeoPolygon)polys.elementAt(i))){
	                list.addElement(polys.elementAt(i));
	            }
	        }
    	    list.removeElement(this);
    	    if(subParts!=null){
	            Vector subList;
	            for(int i=0;i<subParts.size();i++){
	                subList = (((GeoPolygon)subParts.elementAt(i)).getContiguityList(polys));
	                subList.removeElement(this);
	                for(int j=0;j<subList.size();j++){
	                    if(!list.contains(subList.elementAt(j))){list.addElement(subList.elementAt(j));}
	                }
	                if(DEBUG)System.out.println("Fixed multipart contiguity by adding "+subList.size());
	            }
	            
	        }
	       return list;
    	        
	   }
	   
	  

	   
	   /**
	    * Given the line described by the two points, this method tests to see if it is internal or external with regards to the set
	    * of polygons listed in the vector.
	    * <br>p1 and p2 SHOULD be points that are in this polygon.
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * @param p1 GeoPoint the first endpoint of the line to test
	    * @param p2 GeoPoint the second endpoint of the line to test
	    * @param polys A Vector of polygons to test the line agains for inside/outside ness.
	    */
	   public boolean isOnOutside(GeoPoint p1,GeoPoint p2,Vector polys){
	    boolean outside = true;
	    
	    for(int j=0;j<polys.size();j++){
	        GeoPolygon testPolygon = ((GeoPolygon)polys.elementAt(j));
	        if(testPolygon == this){continue;}
	        if(testPolygon.areConsecutive(p1,p2)){
	            outside = false;
	            j=polys.size();
	        }
	    }
	    return outside;
	   }
	   
	   /**
	    * Tests this polygon to see if contains at least one edge that is on the outside of the set of polygons
	    * described in the provided set.
	    *
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * @param polys A Vector of polygons to test against
	    * @param boolean true if any edge of this polygon is not contiguous with any of the polgyons listed in polys
	    */
	   public boolean isOnOutside(Vector polys){
	    
	        Vector points = getPoints();
    	    boolean done = false;
	        for(int i=0;i<points.size()-1 ;i++){
	            GeoPoint p1 = (GeoPoint)points.elementAt(i);
	            GeoPoint p2 = (GeoPoint)points.elementAt(i+1);
	            if(isOnOutside(p1,p2,polys)){return true;}
	        }
	        return false;
	   }
	    
	    public static GeoPolygon dissolve(Vector polys){
	       return dissolve(0,polys);
	    }
	   
	   /**
	    * A static method that will disolve all internal borders within the provided set to create a single polygon
	    * which describes the outline of all the given polygons combined.
	    * 
	    * <br>This code is somewhat experimental and has not been fully tested.
	    * in particular, if the polygons do not define a single clump then it will not work as expected.
	    * @param polys A Vector of GeoPolgyons to disolve.
	    * @param an id for this new polygon.
	    * @return GeoPolygon the disolved version of the polys set.
	    */
	   public static GeoPolygon dissolve(int id,Vector polys){
	    Vector outList = (Vector)polys.clone();
	    Vector holes = new Vector();Vector fills = new Vector();
	    int count = outList.size();
	    GeoPolygon multiPartTest;
	    for(int i=0;i<count;i++){
	        if(DEBUG)System.out.println("Element "+i+" of "+count);
	        //multiPartTest = (GeoPolygon)outList.elementAt(i);
	        multiPartTest = (GeoPolygon)polys.elementAt(i);
	        if(multiPartTest.isMultiPart() && 2==3){
	            if(DEBUG)System.out.println("Scary dissolve involving a multipart polygon!");
	            for(int j=1;j<=multiPartTest.getNumParts()-1;j++){
	                if(DEBUG)System.out.println("Area of part"+((GeoPolygon)multiPartTest.getPart(j)).getArea());
	                if(((GeoPolygon)multiPartTest.getPart(j)).getArea()>=0){
	                    if(multiPartTest.getPart(j).getPoints().size()<3)
	                    {
	                        if(DEBUG)System.err.println("Multipart polygon only had 2 points.");
	                    }

	                    outList.addElement(multiPartTest.getPart(j));

	                }
	                else{
	                    if(DEBUG)System.out.println("Hole");
	                    /* TODO JM: sort out holes properly by implementing cases 2 and 3, although a change in the represenation of
	                     * polygon toplogy may come first.
	                     * this part represents a hole.
	                     * There are three states that this hole could be in for this zone.
	                     * 1) Empty, with no polygons at all inside it.
	                     * 2) Filled, with polygons that belong to this zone.
	                     * 3) Semi-filled, with some or all of the polygons inside it not belonging to this zone.
	                     * 3 is a hard case that will need to be planed out carefully and proably requires
	                     * more constructive geometry methods than exist at the moment
	                     */

                        //Is the hole empty?
                        GeoPolygon hole = (GeoPolygon)multiPartTest.getPart(j);
                        Vector fillers = hole.getContiguityList(polys);
                        if(fillers.size()==0){
                            //case 1 from above.
                            //hole is only contiguous with the polygon to which it is a hole
                            //therefore keep it!
                            holes.addElement(hole);
                        }
                        else{
                            //case 2 or 3 from above.
                            //There is something attached to this hole, other than the polygon to which it is attached.
                            //for now we will assume a simple case 2 by removing all polygons attached to this hole
                            //this is the danger that a polygon will be attached to a polygon that is attached to this hole.
                            //TODO JM: implement case 2 properly and sort out case 3
                            holes.addElement(hole);
                            for(int k =0;k<fillers.size();k++){

⌨️ 快捷键说明

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