mirror of https://github.com/apache/lucene.git
LUCENE-8220: Switch over to using GeoComplexPolygon if we can't tile a polygon.
This commit is contained in:
parent
5e1d6f36f7
commit
273a829c46
|
@ -164,32 +164,44 @@ public class GeoPolygonFactory {
|
|||
return null;
|
||||
}
|
||||
|
||||
//First approximation to find a point
|
||||
final GeoPoint centerOfMass = getCenterOfMass(planetModel, filteredPointList);
|
||||
final Boolean isCenterOfMassInside = isInsidePolygon(centerOfMass, filteredPointList);
|
||||
if (isCenterOfMassInside != null) {
|
||||
return generateGeoPolygon(planetModel, filteredPointList, holes, centerOfMass, isCenterOfMassInside);
|
||||
}
|
||||
|
||||
//System.err.println("points="+pointList);
|
||||
// Create a random number generator. Effectively this furnishes us with a repeatable sequence
|
||||
// of points to use for poles.
|
||||
final Random generator = new Random(1234);
|
||||
for (int counter = 0; counter < 1000000; counter++) {
|
||||
//counter++;
|
||||
// Pick the next random pole
|
||||
final GeoPoint pole = pickPole(generator, planetModel, filteredPointList);
|
||||
// Is it inside or outside?
|
||||
final Boolean isPoleInside = isInsidePolygon(pole, filteredPointList);
|
||||
if (isPoleInside != null) {
|
||||
// Legal pole
|
||||
//System.out.println("Took "+counter+" iterations to find pole");
|
||||
//System.out.println("Pole = "+pole+"; isInside="+isPoleInside+"; pointList = "+pointList);
|
||||
return generateGeoPolygon(planetModel, filteredPointList, holes, pole, isPoleInside);
|
||||
try {
|
||||
//First approximation to find a point
|
||||
final GeoPoint centerOfMass = getCenterOfMass(planetModel, filteredPointList);
|
||||
final Boolean isCenterOfMassInside = isInsidePolygon(centerOfMass, filteredPointList);
|
||||
if (isCenterOfMassInside != null) {
|
||||
return generateGeoPolygon(planetModel, filteredPointList, holes, centerOfMass, isCenterOfMassInside);
|
||||
}
|
||||
// If pole choice was illegal, try another one
|
||||
|
||||
//System.err.println("points="+pointList);
|
||||
// Create a random number generator. Effectively this furnishes us with a repeatable sequence
|
||||
// of points to use for poles.
|
||||
final Random generator = new Random(1234);
|
||||
for (int counter = 0; counter < 1000000; counter++) {
|
||||
//counter++;
|
||||
// Pick the next random pole
|
||||
final GeoPoint pole = pickPole(generator, planetModel, filteredPointList);
|
||||
// Is it inside or outside?
|
||||
final Boolean isPoleInside = isInsidePolygon(pole, filteredPointList);
|
||||
if (isPoleInside != null) {
|
||||
// Legal pole
|
||||
//System.out.println("Took "+counter+" iterations to find pole");
|
||||
//System.out.println("Pole = "+pole+"; isInside="+isPoleInside+"; pointList = "+pointList);
|
||||
return generateGeoPolygon(planetModel, filteredPointList, holes, pole, isPoleInside);
|
||||
}
|
||||
// If pole choice was illegal, try another one
|
||||
}
|
||||
throw new IllegalArgumentException("cannot find a point that is inside the polygon "+filteredPointList);
|
||||
} catch (TileException e) {
|
||||
// Couldn't tile the polygon; use GeoComplexPolygon instead, if we can.
|
||||
if (holes != null && holes.size() > 0) {
|
||||
// We currently cannot get the list of points that went into making a hole back out, so don't allow this case.
|
||||
// In order to support it, we really need to change the API contract, which is a bigger deal.
|
||||
throw new IllegalArgumentException(e.getMessage());
|
||||
}
|
||||
final List<PolygonDescription> description = new ArrayList<>(1);
|
||||
description.add(new PolygonDescription(pointList));
|
||||
return makeLargeGeoPolygon(planetModel, description);
|
||||
}
|
||||
throw new IllegalArgumentException("cannot find a point that is inside the polygon "+filteredPointList);
|
||||
}
|
||||
|
||||
/** Generate a point at the center of mass of a list of points.
|
||||
|
@ -372,7 +384,7 @@ public class GeoPolygonFactory {
|
|||
final List<GeoPoint> filteredPointList,
|
||||
final List<GeoPolygon> holes,
|
||||
final GeoPoint testPoint,
|
||||
final boolean testPointInside) {
|
||||
final boolean testPointInside) throws TileException {
|
||||
// We will be trying twice to find the right GeoPolygon, using alternate siding choices for the first polygon
|
||||
// side. While this looks like it might be 2x as expensive as it could be, there's really no other choice I can
|
||||
// find.
|
||||
|
@ -750,7 +762,7 @@ public class GeoPolygonFactory {
|
|||
final int endPointIndex,
|
||||
final SidedPlane startingEdge,
|
||||
final List<GeoPolygon> holes,
|
||||
final GeoPoint testPoint) {
|
||||
final GeoPoint testPoint) throws TileException {
|
||||
|
||||
// It could be the case that we need a concave polygon. So we need to try and look for that case
|
||||
// as part of the general code for constructing complex polygons.
|
||||
|
@ -1003,7 +1015,7 @@ public class GeoPolygonFactory {
|
|||
|
||||
if (foundBadEdge) {
|
||||
// Unaddressed bad edge
|
||||
throw new IllegalArgumentException("Could not tile polygon; found a pathological coplanarity that couldn't be addressed");
|
||||
throw new TileException("Could not tile polygon; found a pathological coplanarity that couldn't be addressed");
|
||||
}
|
||||
|
||||
// No violations found: we know it's a legal concave polygon.
|
||||
|
@ -1686,4 +1698,11 @@ public class GeoPolygonFactory {
|
|||
public boolean value = false;
|
||||
}
|
||||
|
||||
/** Exception we throw when we can't tile a polygon due to numerical precision issues.
|
||||
*/
|
||||
private static class TileException extends Exception {
|
||||
public TileException(final String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.util.BitSet;
|
|||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.Ignore;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -623,7 +622,7 @@ shape:
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPolygonFactoryCase3() {
|
||||
public void testPolygonFactoryCase3() throws Exception {
|
||||
/*
|
||||
This one failed to be detected as convex:
|
||||
|
||||
|
@ -1102,7 +1101,6 @@ shape:
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCoplanarityTileConvex() throws Exception {
|
||||
// This test has been disabled because it is possible that the polygon specified actually intersects itself.
|
||||
//POLYGON((24.39398 65.77519,24.3941 65.77498,24.394024 65.77497,24.393976 65.77495,24.393963 65.77493,24.394068 65.774925,24.394156 65.77495,24.394201 65.77495,24.394234 65.77496,24.394266 65.77498,24.394318 65.77498,24.39434 65.774956,24.394377 65.77495,24.394451 65.77494,24.394476 65.77495,24.394457 65.77498,24.39398 65.77519))"
|
||||
|
@ -1123,12 +1121,11 @@ shape:
|
|||
points.add(new GeoPoint(PlanetModel.SPHERE, Geo3DUtil.fromDegrees(65.77494), Geo3DUtil.fromDegrees(24.394451)));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, Geo3DUtil.fromDegrees(65.77495), Geo3DUtil.fromDegrees(24.394476)));
|
||||
points.add(new GeoPoint(PlanetModel.SPHERE, Geo3DUtil.fromDegrees(65.77498), Geo3DUtil.fromDegrees(24.394457)));
|
||||
GeoCompositePolygon polygon = (GeoCompositePolygon)GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points);
|
||||
GeoPolygon polygon = GeoPolygonFactory.makeGeoPolygon(PlanetModel.SPHERE, points);
|
||||
assertTrue(polygon != null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testCoplanarityConcave() throws Exception {
|
||||
//POLYGON((-52.18851 64.53777,-52.18853 64.53828,-52.18675 64.53829,-52.18676 64.53855,-52.18736 64.53855,-52.18737 64.53881,-52.18677 64.53881,-52.18683 64.54009,-52.18919 64.53981,-52.18916 64.53905,-52.19093 64.53878,-52.19148 64.53775,-52.18851 64.53777))
|
||||
List<GeoPoint> points = new ArrayList<>();
|
||||
|
|
Loading…
Reference in New Issue