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

📄 geopolygon.java

📁 geotools的源码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
                                GeoPolygon temp = (GeoPolygon)fillers.elementAt(k);
                                if(temp == hole || temp == multiPartTest){continue;}
                                if(DEBUG)System.out.println("Removing hole filler");
                                fills.addElement(temp);
                            }
                        }
                    }
	                                
	            }
	        }
	    }
	    if(DEBUG)System.out.println("Next Stage");        
	    for(int i=0;i<fills.size();i++){
	        outList.removeElement(fills.elementAt(i));
	    }
	    GeoPolygon d = new GeoPolygon(id,-1,-1);
	    for(int i=0;i<polys.size();i++){
	        GeoPolygon temp = (GeoPolygon)polys.elementAt(i);
	        
	        
	        if(!temp.isOnOutside(polys)){
	            //System.out.println("removing "+temp.getID());
	            outList.removeElement(temp);
	        }
	    }
	    Vector toDo = (Vector)outList.clone();
	    
	    //System.out.println(""+(polys.size()-outList.size())+" polygons removed");
	    //find first outside point on first outside polygon
	    GeoPolygon activePolygon = (GeoPolygon)outList.elementAt(0);
	    
	    Vector activePoints = activePolygon.getPoints();
	    
	    boolean found = false;
	    Vector conList = activePolygon.getContiguityList(polys);
	    GeoPoint p1=null,p2=null;
	    int activeIndex=-1;
	    for(int i=0;i<activePoints.size()-1 && !found;i++){
	        
	        activeIndex = i+1;
	        p1 = (GeoPoint)activePoints.elementAt(i);
	        p2 = (GeoPoint)activePoints.elementAt(i+1);
	        found = true;
	        if(!activePolygon.isOnOutside(p1,p2,conList)){
	            found=false;
	            //continue;
	        }
	        if(found == true){if(DEBUG)System.out.println("Found outside point on first outside polygon");}

	    }
	    if(DEBUG)System.out.println("Start trace from "+p1);
	    GeoPoint start = p1;
	    d.addPoint(p1);
	    d.addPoint(p2);
	    GeoPoint last = null;
	    GeoPoint next = null,activePoint;
	    int direction =1;
	    boolean finished = false;
	    while(!finished){
	        toDo.removeElement(activePolygon);
	        //System.out.println("Active polygon is "+activePolygon.getID());

	        //wrap move off end/begining of point list to begining/end
	        if(direction==1){if(activeIndex==activePoints.size()-1)activeIndex=0;}
	        else{if(activeIndex==0)activeIndex=activePoints.size()-1;}

	        activePoint = (GeoPoint)activePoints.elementAt(activeIndex);
	        int nextIndex = activeIndex+direction;
	        if(nextIndex<0){nextIndex=activePoints.size()-2;}
	        if(nextIndex==activePoints.size()){nextIndex=0;}
	        next = (GeoPoint)activePoints.elementAt(nextIndex);
	        //System.out.println(""+activePolygon.getID()+" "+activeIndex+" "+nextIndex);
	        found = true;
	        for(int j=0;j<conList.size();j++){
	            GeoPolygon conPol = (GeoPolygon)conList.elementAt(j);
	            if(conPol==activePolygon)if(DEBUG)System.out.println("Testing aginst self!");
	            if(conPol.areConsecutive(activePoint,next)){
	                found = false;
	                //not outside line
	                continue;
	            }
	        }
	        if(found){
	            //still on the outside.
	            //System.out.println("Still on outside");
	            if(next.equals(start)){//we are done for now, move following code to a clean up section

	                finished=true;
	            }
	            d.addPoint(next);

	            activeIndex+=direction;
	            last = activePoint;
	        }
	        else{
	            //build list of all outside polygons that contiain this point
	            boolean done = false;
	            for(int i=0;i<polys.size()&&!done;i++){
	                GeoPolygon test = (GeoPolygon)polys.elementAt(i);
	                if(test==activePolygon)continue;
	                if(!outList.contains(test))continue;
	                Vector testPoints = test.getPoints();
	               // if(testPoints.size()<3)continue;
	                if(!testPoints.contains(activePoint))continue;

	                //ok, we have found an outside polygon that also contains the active point.
	                //is it the start of an outside edge and if so in which direction

	                if(DEBUG)System.out.println("This polygon has "+testPoints.size()+ "points");

	                int testIndex = testPoints.indexOf(activePoint);
	                //System.out.println("test point found at "+testIndex);
	                //lets try forwards
	                int forwardIndex = testIndex+1;
	                if(testIndex==testPoints.size()-1){
	                    forwardIndex=0;
	                }
	                GeoPoint forward = (GeoPoint)testPoints.elementAt(forwardIndex);
	                //is edge outside
	                boolean fudge = false;
	                if(activePoint.equals(forward)){
	                    if(DEBUG)System.err.println("active and forward are the same");
	                   // fudge = true;
	                    //forward = (GeoPoint)testPoints.elementAt(forwardIndex+1);
	                }
	                if(test.isOnOutside(activePoint,forward,polys)){
	                    //System.out.println("Found the next point by goind forwards");
	                    activeIndex=testIndex;
	                    activePolygon=test;
	                    activePoints=activePolygon.getPoints();
	                    direction = 1;
	                    conList = activePolygon.getContiguityList(polys);
	                    done=true;
	                }
	                else
	                {
	                    //lets try backwards
	                    if(testIndex==0)testIndex=testPoints.size()-1;
	                    GeoPoint backward = (GeoPoint)testPoints.elementAt(testIndex-1);
	                    if(activePoint.equals(backward)){
	                        
	                        if(DEBUG)System.err.println("active and backward are the same");
	                      //  backward = (GeoPoint)testPoints.elementAt(testIndex-2);
	                    }
	                    if(test.isOnOutside(activePoint,backward,polys)){
	                        //System.out.println("Found next point by going backwards");
	                        activeIndex=testIndex;
	                        activePolygon=test;
	                        activePoints=activePolygon.getPoints();
	                        direction = -1;
	                        conList = activePolygon.getContiguityList(polys);
	                        done = true;
	                    }
	                }
	                if(done){last = activePoint;}
	            }
	            if(!done){if(DEBUG)System.err.println("Error? none of the posible polygons contained outside lines. ABORT");return d;}
	        }



	    }//while !finished
	    //re-add any empty holes that were in some of the origional polygons.
	    if(toDo.size()>0){
	       if(DEBUG)System.out.println("Finished with "+toDo.size());
	       d.addSubPart(dissolve(id,toDo));
	    }

	    d.calculateCentroidLocation();
	    return d;
	   }

	   /**
	    * Combines this polygon with the provided polygon to create a new single polygon with the combined outline of both.
	    * <br> both polygons must be contiguous.
	    * @param gp the GeoPolygon to disolve into this one.
	    * @return GeoPolygon the resulting disolved polygon.
	    */
	   public GeoPolygon dissolve(GeoPolygon gp){
	    if(!isContiguous(gp)){throw new IllegalArgumentException("Polygon is not Contiguous, dissolve imposible");}

	    Vector a = getPoints();
	    Vector b = gp.getPoints();
	    int lastA = a.size()-2; // one for 0 counting one for duplicate final point.
	    int lastB = b.size()-2;

	    GeoPolygon d = new GeoPolygon();// construct with same id as this polygon?
	    //find first non shared point
	    int indexA = 0,indexB=0,start = 0;
	    while(b.contains(a.elementAt(indexA))){indexA++;}
	    start = indexA;
	    //System.out.println("Starting at "+indexA);
	    boolean done = false,first = true;
	    final int A=0,B=1,A2B=2,B2A=3;
	    int direction =1;
	    int state = A;
	    while(!done){
	       // System.out.println(""+indexA+" "+indexB+" "+state);
	        switch(state){
	            case A:
	                if(indexA==start && !first){done=true;continue;}
	                first = false;
	                d.addPoint((GeoPoint)a.elementAt(indexA));
	                indexA=(indexA+1)%(lastA+1);
	                if(b.contains(a.elementAt(indexA))){
	                    state=A2B;
	                }
	                break;
	            case B:  
	                d.addPoint((GeoPoint)b.elementAt(indexB));
	                indexB+=1*direction;
	                indexB%=(lastB+1);
	                if(indexB<0)indexB=lastB;
	                if(a.contains(b.elementAt(indexB))){
	                    state = B2A;
	                }
	                break;
	            case A2B:
	                //add the last point of a
	                d.addPoint((GeoPoint)a.elementAt(indexA));
	                //which way round B do we go?
	                int join = b.indexOf(a.elementAt(indexA));
	                if(a.contains(b.elementAt((join+1)%lastB))){
	                    direction = -1;
	                }
	                else{
	                    direction = 1;
	                }
	                indexB = join+direction;
	                state = B;
	                break;
	            case B2A:
	                indexA = a.indexOf(b.elementAt(indexB));
	                state = A;
	                break;
	        }
	        
	    }
	    
	    d.addPoint((GeoPoint)a.elementAt(start));
	    d.calculateCentroidLocation();
	    return d;
	        
	        
	    
	   }
	  /**
	   * Tests to see if a point is contained by this polygon.
	   * @param p The GeoPoint to test.
	   * @return boolean true if point is contained by this polygon.
	   */
	   public boolean contains(GeoPoint p){

	    /*if(!getMultiPartBounds().contains(p)){
	        return false;
	    }*/
	    
	  if(getBounds().contains(p)){
	        
	    
	   
	   
	   
	    /* Start andys code */
	     int number_of_lines_crossed = 0;                                // holds lines intersecting with 
		    number_of_lines_crossed = 0;                                  // set lines crossed = 0 for each polygon
		                                                        // lets us know which part start we're looking for	   
		   for(int i=0;i<npoints-1;i++){
			//GeoPoint A = new GeoPoint();
			//GeoPoint B = new GeoPoint();        
			//A.y = ypoints[i];                                       // get y-coordinate
			//A.x = xpoints[i];                                       // get x-coordinate 
			//B.y = ypoints[i+1];                                     // get next y-coordinate
			//B.x = xpoints[i+1];                                     // get next x-coordinate
			
			if (p.y!=ypoints[i+1]&&(p.y <= Math.max(ypoints[i],ypoints[i+1])) && (p.y >= Math.min(ypoints[i],ypoints[i+1])) && ((xpoints[i] >= p.x) || (xpoints[i+1] >= p.x))) {         // if polygon contains a suitable value
			    if(((xpoints[i] >= p.x) && (xpoints[i+1] >= p.x))){
			        number_of_lines_crossed++;//simple case
			    }
			    else{
			        double gradient;                                          //   calc. gradient
			        if (xpoints[i] > xpoints[i+1]) 
				        gradient = ((xpoints[i] - xpoints[i+1])/(ypoints[i] - ypoints[i+1]));
    			    else 										
				        gradient = ((xpoints[i+1] - xpoints[i])/(ypoints[i+1] - ypoints[i]));				
		            double x_intersection_axis = (xpoints[i] - (gradient * ypoints[i]));                     // calc. intersect with x-axis
			        double x_intersection_line = (gradient*p.y) + x_intersection_axis;  // calc. intersect with y=const
					                                                                       //  line extending from location 
			        if ((x_intersection_line <= Math.max(xpoints[i],xpoints[i+1])) &&                          // check intersect inside polygon 
				        (x_intersection_line >= Math.min(xpoints[i],xpoints[i+1])) && (x_intersection_line >= p.x)) {
				        number_of_lines_crossed++;                                               // increment line counter
			        } // end check for inside polygon
			    }
			} // end of if polygon points suitable
		    } // end of run through points in polygon

		    if ((number_of_lines_crossed != 0) &&				// if number of polygon lines crossed
			(((number_of_lines_crossed % 2) == 1))) {                       //   by a line in one direction from the
			return true;		                                        //   initial location is odd, the location

		    				                                        //   lies in that polygon

		 }	// end of run through polygons

	  } 
	  if(this.isMultiPart()){
        for(int i=0;i<this.subParts.size();i++){
            if(((GeoPolygon)subParts.elementAt(i)).contains(p)){return true;}
        }
      }
      return false;                                                         // return stuffing if things get this far

	} // end of method whichPolygon


    /**
     * Calcualtes and returns the perimiter of this polygon
     * @deprecated miss spelling use getPerimeter instead.
     * @see getPerimeter
     * @return double the perimiter of this polygon
     */
     public double getPerimiter(){
        double dist = 0;
        int i;
        for(i=0;i<npoints-1;i++){
            dist+=Math.sqrt(((xpoints[i]-xpoints[i+1])*(xpoints[i]-xpoints[i+1]))+((ypoints[i]-ypoints[i+1])*(ypoints[i]-ypoints[i+1])));
        }
       return dist;
     }
     
     /**
      * Calculates and returns the length of the segment between the specifed points
      * @param start int of the index of the start point
      * @param end int of the index of the end point
      * @return double length of segment
      */
      public double getSegmentLength(int start,int end){
        double dist = 0;
        if(end<start){end = npoints+end;}
        int index,next;
        for(int i=start;i<end;i++){
            
            index = (i%npoints);
            next = (i+1)%npoints;
            
            dist+=Math.sqrt(((xpoints[index]-xpoints[next])*(xpoints[index]-xpoints[next]))+((ypoints[index]-ypoints[next])*(ypoints[index]-ypoints[next])));
            //System.out.println("index "+index+" "+next+" "+npoints+" x "+xpoints[index]+" y "+ypoints[index]+" dist "+ dist);
        }
        return dist;
      }
	public String toString(){
	 StringBuffer sb = new StringBuffer();
	 sb.append("GeoPolygon : [id ");
	 sb.append(id);
	 sb.append("] ");
	 for(int i=0;i<npoints;i++){
	    sb.append("{");
	    sb.append(xpoints[i]);
	    sb.append(",");
	    sb.append(ypoints[i]);
	    sb.append("} ");
	 }
	 return sb.toString();
	    
	}
	   public boolean contains(double x,double y){
	    GeoPoint p = new GeoPoint(x,y);
	    return contains(p);
	   }

}				
				
/*
 * $Log: GeoPolygon.java,v $
 * Revision 1.19  2001/08/01 12:32:18  ianturton
 * modification submited by Michael Becke <becke@u.washington.edu> to reduce
 * memory usage.
 *
 *
 *
 */
   
	
	

⌨️ 快捷键说明

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