mirror of https://github.com/apache/lucene.git
LUCENE-7192: Permit adjacent points in a polygon to be coplanar.
This commit is contained in:
parent
9b65416e60
commit
771680cfd0
|
@ -46,8 +46,6 @@ class GeoConcavePolygon extends GeoBasePolygon {
|
|||
protected GeoPoint[][] notableEdgePoints = null;
|
||||
/** A point which is on the boundary of the polygon */
|
||||
protected GeoPoint[] edgePoints = null;
|
||||
/** Tracking the maximum distance we go at any one time, so to be sure it's legal */
|
||||
protected double fullDistance = 0.0;
|
||||
/** Set to true when the polygon is complete */
|
||||
protected boolean isDone = false;
|
||||
/** A bounds object for each sided plane */
|
||||
|
@ -189,10 +187,21 @@ class GeoConcavePolygon extends GeoBasePolygon {
|
|||
for (int i = 0; i < points.size(); i++) {
|
||||
final GeoPoint start = points.get(i);
|
||||
final GeoPoint end = points.get(legalIndex(i + 1));
|
||||
final double distance = start.arcDistance(end);
|
||||
if (distance > fullDistance)
|
||||
fullDistance = distance;
|
||||
final GeoPoint check = points.get(legalIndex(i + 2));
|
||||
// We have to find the next point that is not on the plane between start and end.
|
||||
// If there is no such point, it's an error.
|
||||
final Plane planeToFind = new Plane(start, end);
|
||||
int endPointIndex = -1;
|
||||
for (int j = 0; j < points.size(); j++) {
|
||||
final int index = legalIndex(j + i + 2);
|
||||
if (!planeToFind.evaluateIsZero(points.get(index))) {
|
||||
endPointIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (endPointIndex == -1) {
|
||||
throw new IllegalArgumentException("Polygon points are all coplanar");
|
||||
}
|
||||
final GeoPoint check = points.get(endPointIndex);
|
||||
// Here note the flip of the sense of the sided plane!!
|
||||
final SidedPlane sp = new SidedPlane(check, false, start, end);
|
||||
//System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
|
||||
|
|
|
@ -44,8 +44,6 @@ class GeoConvexPolygon extends GeoBasePolygon {
|
|||
protected GeoPoint[][] notableEdgePoints = null;
|
||||
/** A point which is on the boundary of the polygon */
|
||||
protected GeoPoint[] edgePoints = null;
|
||||
/** Tracking the maximum distance we go at any one time, so to be sure it's legal */
|
||||
protected double fullDistance = 0.0;
|
||||
/** Set to true when the polygon is complete */
|
||||
protected boolean isDone = false;
|
||||
/** A bounds object for each sided plane */
|
||||
|
@ -185,10 +183,21 @@ class GeoConvexPolygon extends GeoBasePolygon {
|
|||
for (int i = 0; i < points.size(); i++) {
|
||||
final GeoPoint start = points.get(i);
|
||||
final GeoPoint end = points.get(legalIndex(i + 1));
|
||||
final double distance = start.arcDistance(end);
|
||||
if (distance > fullDistance)
|
||||
fullDistance = distance;
|
||||
final GeoPoint check = points.get(legalIndex(i + 2));
|
||||
// We have to find the next point that is not on the plane between start and end.
|
||||
// If there is no such point, it's an error.
|
||||
final Plane planeToFind = new Plane(start, end);
|
||||
int endPointIndex = -1;
|
||||
for (int j = 0; j < points.size(); j++) {
|
||||
final int index = legalIndex(j + i + 2);
|
||||
if (!planeToFind.evaluateIsZero(points.get(index))) {
|
||||
endPointIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (endPointIndex == -1) {
|
||||
throw new IllegalArgumentException("Polygon points are all coplanar");
|
||||
}
|
||||
final GeoPoint check = points.get(endPointIndex);
|
||||
final SidedPlane sp = new SidedPlane(check, start, end);
|
||||
//System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
|
||||
edges[i] = sp;
|
||||
|
|
|
@ -714,12 +714,17 @@ public class GeoPolygonFactory {
|
|||
// the start point of the first edge and the end point of the last edge. If the first edge start point is the same as the last edge end point,
|
||||
// it's a degenerate case and we want to just clean out the edge buffer entirely.
|
||||
|
||||
final List<GeoPoint> points = new ArrayList<GeoPoint>(includedEdges.size());
|
||||
final BitSet internalEdges = new BitSet(includedEdges.size()-1);
|
||||
final List<GeoPoint> points = new ArrayList<GeoPoint>(includedEdges.size()+1);
|
||||
final BitSet internalEdges = new BitSet(includedEdges.size());
|
||||
final boolean returnIsInternal;
|
||||
|
||||
if (firstEdge.startPoint == lastEdge.endPoint) {
|
||||
// Degenerate case!! There is no return edge -- or rather, we already have it.
|
||||
if (includedEdges.size() < 3) {
|
||||
// This means we found a degenerate cycle of edges. If we emit a polygon at this point it
|
||||
// has no contents, so we've clearly done something wrong, but not sure what.
|
||||
throw new IllegalArgumentException("polygon was illegal (degenerate illegal two-edge cyclical polygon encountered in processing)");
|
||||
}
|
||||
Edge edge = firstEdge;
|
||||
points.add(edge.startPoint);
|
||||
int i = 0;
|
||||
|
@ -945,8 +950,39 @@ public class GeoPolygonFactory {
|
|||
// Get the next point
|
||||
final GeoPoint newPoint = pointList.get(endIndex);
|
||||
// Build the new edge
|
||||
final boolean isNewPointWithin = currentEdge.plane.isWithin(newPoint);
|
||||
final SidedPlane newPlane = new SidedPlane(currentEdge.startPoint, isNewPointWithin, pointList.get(startIndex), newPoint);
|
||||
// We have to be sure that the point we use as a check does not lie on the plane.
|
||||
// In order to meet that goal, we need to go hunting for a point that meets the criteria. If we don't
|
||||
// find one, we've got a linear "polygon" that we cannot use.
|
||||
|
||||
// We need to know the sidedness of the new plane. The point we're going to be presenting to it has
|
||||
// a certain relationship with the sided plane we already have for the current edge. If the current edge
|
||||
// is colinear with the new edge, then we want to maintain the same relationship. If the new edge
|
||||
// is not colinear, then we can use the new point's relationship with the current edge as our guide.
|
||||
|
||||
final boolean isNewPointWithin;
|
||||
final GeoPoint pointToPresent;
|
||||
if (currentEdge.plane.evaluateIsZero(newPoint)) {
|
||||
// The new point is colinear with the current edge. We'll have to look for the first point that isn't.
|
||||
int checkPointIndex = -1;
|
||||
final Plane checkPlane = new Plane(pointList.get(startIndex), newPoint);
|
||||
for (int i = 0; i < pointList.size(); i++) {
|
||||
final int index = getLegalIndex(startIndex - 1 - i, pointList.size());
|
||||
if (!checkPlane.evaluateIsZero(pointList.get(index))) {
|
||||
checkPointIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (checkPointIndex == -1) {
|
||||
throw new IllegalArgumentException("polygon is illegal (linear)");
|
||||
}
|
||||
pointToPresent = pointList.get(checkPointIndex);
|
||||
isNewPointWithin = currentEdge.plane.isWithin(pointToPresent);
|
||||
} else {
|
||||
isNewPointWithin = currentEdge.plane.isWithin(newPoint);
|
||||
pointToPresent = currentEdge.startPoint;
|
||||
}
|
||||
|
||||
final SidedPlane newPlane = new SidedPlane(pointToPresent, isNewPointWithin, pointList.get(startIndex), newPoint);
|
||||
/*
|
||||
System.out.println("For next plane, the following points are in/out:");
|
||||
for (final GeoPoint p: pointList) {
|
||||
|
|
Loading…
Reference in New Issue