Search in sources :

Example 1 with GeoPolygon

use of org.apache.lucene.spatial3d.geom.GeoPolygon in project lucene-solr by apache.

the class TestGeo3DPoint method makePoly.

/** Cook up a random Polygon that makes sense, with possible nested polygon within.
    * This is part of testing more complex polygons with nested holes.  Picking random points
    * doesn't do it because it's almost impossible to come up with nested ones of the proper 
    * clockwise/counterclockwise rotation that way.
    */
protected static Polygon makePoly(final PlanetModel pm, final GeoPoint pole, final boolean clockwiseDesired, final boolean createHoles) {
    // Polygon edges will be arranged around the provided pole, and holes will each have a pole selected within the parent
    // polygon.
    final int pointCount = TestUtil.nextInt(random(), 3, 10);
    // The point angles we pick next.  The only requirement is that they are not all on one side of the pole.
    // We arrange that by picking the next point within what's left of the remaining angle, but never more than 180 degrees,
    // and never less than what is needed to insure that the remaining point choices are less than 180 degrees always.
    // These are all picked in the context of the pole,
    final double[] angles = new double[pointCount];
    final double[] arcDistance = new double[pointCount];
    // Pick a set of points
    while (true) {
        double accumulatedAngle = 0.0;
        for (int i = 0; i < pointCount; i++) {
            final int remainingEdgeCount = pointCount - i;
            final double remainingAngle = 2.0 * Math.PI - accumulatedAngle;
            if (remainingEdgeCount == 1) {
                angles[i] = remainingAngle;
            } else {
                // The maximum angle is 180 degrees, or what's left when you give a minimal amount to each edge.
                double maximumAngle = remainingAngle - (remainingEdgeCount - 1) * MINIMUM_EDGE_ANGLE;
                if (maximumAngle > Math.PI) {
                    maximumAngle = Math.PI;
                }
                // The minimum angle is MINIMUM_EDGE_ANGLE, or enough to be sure nobody afterwards needs more than
                // 180 degrees.  And since we have three points to start with, we already know that.
                final double minimumAngle = MINIMUM_EDGE_ANGLE;
                // Pick the angle
                final double angle = random().nextDouble() * (maximumAngle - minimumAngle) + minimumAngle;
                angles[i] = angle;
                accumulatedAngle += angle;
            }
            // Pick the arc distance randomly; not quite the full range though
            arcDistance[i] = random().nextDouble() * (Math.PI * 0.5 - MINIMUM_ARC_ANGLE) + MINIMUM_ARC_ANGLE;
        }
        if (clockwiseDesired) {
            // Reverse the signs
            for (int i = 0; i < pointCount; i++) {
                angles[i] = -angles[i];
            }
        }
        // Now, use the pole's information plus angles and arcs to create GeoPoints in the right order.
        final List<GeoPoint> polyPoints = convertToPoints(pm, pole, angles, arcDistance);
        // Next, do some holes.  No more than 2 of these.  The poles for holes must always be within the polygon, so we're
        // going to use Geo3D to help us select those given the points we just made.
        final int holeCount = createHoles ? TestUtil.nextInt(random(), 0, 2) : 0;
        final List<Polygon> holeList = new ArrayList<>();
        /* Hole logic is broken and needs rethinking
      
      // Create the geo3d polygon, so we can test out our poles.
      final GeoPolygon poly;
      try {
        poly = GeoPolygonFactory.makeGeoPolygon(pm, polyPoints, null);
      } catch (IllegalArgumentException e) {
        // This is what happens when three adjacent points are colinear, so try again.
        continue;
      }
            
      for (int i = 0; i < holeCount; i++) {
        // Choose a pole.  The poly has to be within the polygon, but it also cannot be on the polygon edge.
        // If we can't find a good pole we have to give it up and not do the hole.
        for (int k = 0; k < 500; k++) {
          final GeoPoint poleChoice = new GeoPoint(pm, toRadians(GeoTestUtil.nextLatitude()), toRadians(GeoTestUtil.nextLongitude()));
          if (!poly.isWithin(poleChoice)) {
            continue;
          }
          // We have a pole within the polygon.  Now try 100 times to build a polygon that does not intersect the outside ring.
          // After that we give up and pick a new pole.
          boolean foundOne = false;
          for (int j = 0; j < 100; j++) {
            final Polygon insidePoly = makePoly(pm, poleChoice, !clockwiseDesired, false);
            // Verify that the inside polygon is OK.  If not, discard and repeat.
            if (!verifyPolygon(pm, insidePoly, poly)) {
              continue;
            }
            holeList.add(insidePoly);
            foundOne = true;
          }
          if (foundOne) {
            break;
          }
        }
      }
      */
        final Polygon[] holes = holeList.toArray(new Polygon[0]);
        // Finally, build the polygon and return it
        final double[] lats = new double[polyPoints.size() + 1];
        final double[] lons = new double[polyPoints.size() + 1];
        for (int i = 0; i < polyPoints.size(); i++) {
            lats[i] = polyPoints.get(i).getLatitude() * 180.0 / Math.PI;
            lons[i] = polyPoints.get(i).getLongitude() * 180.0 / Math.PI;
        }
        lats[polyPoints.size()] = lats[0];
        lons[polyPoints.size()] = lons[0];
        return new Polygon(lats, lons, holes);
    }
}
Also used : GeoPoint(org.apache.lucene.spatial3d.geom.GeoPoint) ArrayList(java.util.ArrayList) GeoPolygon(org.apache.lucene.spatial3d.geom.GeoPolygon) Polygon(org.apache.lucene.geo.Polygon) GeoPoint(org.apache.lucene.spatial3d.geom.GeoPoint)

Example 2 with GeoPolygon

use of org.apache.lucene.spatial3d.geom.GeoPolygon in project lucene-solr by apache.

the class Geo3DUtil method fromPolygon.

/**
    * Convert a set of Polygon objects into a GeoPolygon.
    * @param polygons are the Polygon objects.
    * @return the GeoPolygon.
    */
static GeoPolygon fromPolygon(final Polygon... polygons) {
    //System.err.println("Creating polygon...");
    if (polygons.length < 1) {
        throw new IllegalArgumentException("need at least one polygon");
    }
    final GeoPolygon shape;
    if (polygons.length == 1) {
        final GeoPolygon component = fromPolygon(polygons[0]);
        if (component == null) {
            // Polygon is degenerate
            shape = new GeoCompositePolygon();
        } else {
            shape = component;
        }
    } else {
        final GeoCompositePolygon poly = new GeoCompositePolygon();
        for (final Polygon p : polygons) {
            final GeoPolygon component = fromPolygon(p);
            if (component != null) {
                poly.addShape(component);
            }
        }
        shape = poly;
    }
    return shape;
//System.err.println("...done");
}
Also used : GeoCompositePolygon(org.apache.lucene.spatial3d.geom.GeoCompositePolygon) GeoPolygon(org.apache.lucene.spatial3d.geom.GeoPolygon) Polygon(org.apache.lucene.geo.Polygon) GeoPolygon(org.apache.lucene.spatial3d.geom.GeoPolygon) GeoCompositePolygon(org.apache.lucene.spatial3d.geom.GeoCompositePolygon)

Aggregations

Polygon (org.apache.lucene.geo.Polygon)2 GeoPolygon (org.apache.lucene.spatial3d.geom.GeoPolygon)2 ArrayList (java.util.ArrayList)1 GeoCompositePolygon (org.apache.lucene.spatial3d.geom.GeoCompositePolygon)1 GeoPoint (org.apache.lucene.spatial3d.geom.GeoPoint)1