📄 geopolygon.java
字号:
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 + -