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;
|
protected GeoPoint[][] notableEdgePoints = null;
|
||||||
/** A point which is on the boundary of the polygon */
|
/** A point which is on the boundary of the polygon */
|
||||||
protected GeoPoint[] edgePoints = null;
|
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 */
|
/** Set to true when the polygon is complete */
|
||||||
protected boolean isDone = false;
|
protected boolean isDone = false;
|
||||||
/** A bounds object for each sided plane */
|
/** A bounds object for each sided plane */
|
||||||
|
@ -189,10 +187,21 @@ class GeoConcavePolygon extends GeoBasePolygon {
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
final GeoPoint start = points.get(i);
|
final GeoPoint start = points.get(i);
|
||||||
final GeoPoint end = points.get(legalIndex(i + 1));
|
final GeoPoint end = points.get(legalIndex(i + 1));
|
||||||
final double distance = start.arcDistance(end);
|
// We have to find the next point that is not on the plane between start and end.
|
||||||
if (distance > fullDistance)
|
// If there is no such point, it's an error.
|
||||||
fullDistance = distance;
|
final Plane planeToFind = new Plane(start, end);
|
||||||
final GeoPoint check = points.get(legalIndex(i + 2));
|
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!!
|
// Here note the flip of the sense of the sided plane!!
|
||||||
final SidedPlane sp = new SidedPlane(check, false, start, end);
|
final SidedPlane sp = new SidedPlane(check, false, start, end);
|
||||||
//System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
|
//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;
|
protected GeoPoint[][] notableEdgePoints = null;
|
||||||
/** A point which is on the boundary of the polygon */
|
/** A point which is on the boundary of the polygon */
|
||||||
protected GeoPoint[] edgePoints = null;
|
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 */
|
/** Set to true when the polygon is complete */
|
||||||
protected boolean isDone = false;
|
protected boolean isDone = false;
|
||||||
/** A bounds object for each sided plane */
|
/** A bounds object for each sided plane */
|
||||||
|
@ -185,10 +183,21 @@ class GeoConvexPolygon extends GeoBasePolygon {
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
final GeoPoint start = points.get(i);
|
final GeoPoint start = points.get(i);
|
||||||
final GeoPoint end = points.get(legalIndex(i + 1));
|
final GeoPoint end = points.get(legalIndex(i + 1));
|
||||||
final double distance = start.arcDistance(end);
|
// We have to find the next point that is not on the plane between start and end.
|
||||||
if (distance > fullDistance)
|
// If there is no such point, it's an error.
|
||||||
fullDistance = distance;
|
final Plane planeToFind = new Plane(start, end);
|
||||||
final GeoPoint check = points.get(legalIndex(i + 2));
|
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);
|
final SidedPlane sp = new SidedPlane(check, start, end);
|
||||||
//System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
|
//System.out.println("Created edge "+sp+" using start="+start+" end="+end+" check="+check);
|
||||||
edges[i] = sp;
|
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,
|
// 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.
|
// 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 List<GeoPoint> points = new ArrayList<GeoPoint>(includedEdges.size()+1);
|
||||||
final BitSet internalEdges = new BitSet(includedEdges.size()-1);
|
final BitSet internalEdges = new BitSet(includedEdges.size());
|
||||||
final boolean returnIsInternal;
|
final boolean returnIsInternal;
|
||||||
|
|
||||||
if (firstEdge.startPoint == lastEdge.endPoint) {
|
if (firstEdge.startPoint == lastEdge.endPoint) {
|
||||||
// Degenerate case!! There is no return edge -- or rather, we already have it.
|
// 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;
|
Edge edge = firstEdge;
|
||||||
points.add(edge.startPoint);
|
points.add(edge.startPoint);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -945,8 +950,39 @@ public class GeoPolygonFactory {
|
||||||
// Get the next point
|
// Get the next point
|
||||||
final GeoPoint newPoint = pointList.get(endIndex);
|
final GeoPoint newPoint = pointList.get(endIndex);
|
||||||
// Build the new edge
|
// Build the new edge
|
||||||
final boolean isNewPointWithin = currentEdge.plane.isWithin(newPoint);
|
// We have to be sure that the point we use as a check does not lie on the plane.
|
||||||
final SidedPlane newPlane = new SidedPlane(currentEdge.startPoint, isNewPointWithin, pointList.get(startIndex), newPoint);
|
// 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:");
|
System.out.println("For next plane, the following points are in/out:");
|
||||||
for (final GeoPoint p: pointList) {
|
for (final GeoPoint p: pointList) {
|
||||||
|
|
Loading…
Reference in New Issue