lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a.@apache.org
Subject [29/50] lucene-solr:jira/solr-11285: LUCENE-7906: Include missing file
Date Wed, 20 Sep 2017 08:46:45 GMT
LUCENE-7906: Include missing file


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/e44ee16c
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/e44ee16c
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/e44ee16c

Branch: refs/heads/jira/solr-11285
Commit: e44ee16c74832031556e0c2c2e0b9fd0588e968b
Parents: cd425d6
Author: Karl Wright <DaddyWri@gmail.com>
Authored: Mon Sep 11 10:48:03 2017 -0400
Committer: Karl Wright <DaddyWri@gmail.com>
Committed: Mon Sep 11 10:48:03 2017 -0400

----------------------------------------------------------------------
 .../geom/RandomGeo3dShapeGenerator.java         | 1019 ++++++++++++++++++
 1 file changed, 1019 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/e44ee16c/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java
----------------------------------------------------------------------
diff --git a/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java
b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java
new file mode 100644
index 0000000..72b7109
--- /dev/null
+++ b/lucene/spatial3d/src/test/org/apache/lucene/spatial3d/geom/RandomGeo3dShapeGenerator.java
@@ -0,0 +1,1019 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.apache.lucene.spatial3d.geom;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.lucene.util.LuceneTestCase;
+
+import static com.carrotsearch.randomizedtesting.RandomizedTest.randomDouble;
+
+/**
+ * Class for generating random Geo3dShapes. They can be generated under
+ * given constraints which are expressed as a shape and a relationship.
+ *
+ * note that convexity for polygons is defined as polygons that contains
+ * antipodal points, otherwise they are convex. Internally they can be
+ * created using GeoConvexPolygons and GeoConcavePolygons.
+ *
+ */
+public class RandomGeo3dShapeGenerator extends LuceneTestCase {
+
+  /* Max num of iterations to find right shape under given constrains */
+  final private static int MAX_SHAPE_ITERATIONS = 50;
+  /* Max num of iterations to find right point under given constrains */
+  final private static int MAX_POINT_ITERATIONS = 1000;
+
+  /* Supported shapes */
+  final protected static int CONVEX_POLYGON = 0;
+  final protected static int CONVEX_POLYGON_WITH_HOLES = 1;
+  final protected static int CONCAVE_POLYGON = 2;
+  final protected static int CONCAVE_POLYGON_WITH_HOLES = 3;
+  final protected static int COMPLEX_POLYGON = 4;
+  final protected static int CIRCLE = 5;
+  final protected static int RECTANGLE = 6;
+  final protected static int PATH = 7;
+  final protected static int COLLECTION = 8;
+  final protected static int POINT = 9;
+  final protected static int LINE = 10;
+
+  /* Helper shapes for generating constraints whch are just three sided polygons */
+  final protected static int CONVEX_SIMPLE_POLYGON = 500;
+  final protected static int CONCAVE_SIMPLE_POLYGON = 501;
+
+  /**
+   * Method that returns a random generated Planet model from the supported
+   * Planet models. currently SPHERE and WGS84
+   *
+   * @return a random generated Planet model
+   */
+  public PlanetModel randomPlanetModel() {
+    final int shapeType = random().nextInt(2);
+    switch (shapeType) {
+      case 0: {
+        return PlanetModel.SPHERE;
+      }
+      case 1: {
+        return PlanetModel.WGS84;
+      }
+      default:
+        throw new IllegalStateException("Unexpected planet model");
+    }
+  }
+
+  /**
+   * Method that returns a random generated a random Shape code from all
+   * supported shapes.
+   *
+   * @return a random generated shape code
+   */
+  public int randomShapeType(){
+    return random().nextInt(11);
+  }
+
+  /**
+   * Method that returns a random generated GeoAreaShape code from all
+   * supported GeoAreaShapes.
+   *
+   * We are removing Collections because it is difficult to create shapes
+   * with properties in some cases.
+   *
+   * @return a random generated polygon code
+   */
+  public int randomGeoAreaShapeType(){
+    return random().nextInt(11);
+  }
+
+  /**
+   * Method that returns a random generated a random Shape code from all
+   * convex supported shapes.
+   *
+   * @return a random generated convex shape code
+   */
+  public int randomConvexShapeType(){
+    int shapeType = randomShapeType();
+    while (isConcave(shapeType)){
+      shapeType = randomShapeType();
+    }
+    return shapeType;
+  }
+
+  /**
+   * Method that returns a random generated a random Shape code from all
+   * concave supported shapes.
+   *
+   * @return a random generated concave shape code
+   */
+  public int randomConcaveShapeType(){
+    int shapeType = randomShapeType();
+    while (!isConcave(shapeType)){
+      shapeType = randomShapeType();
+    }
+    return shapeType;
+  }
+
+  /**
+   * Check if a shape code represents a concave shape
+   *
+   * @return true if the shape represented by the code is concave
+   */
+  public boolean isConcave(int shapeType){
+    return (shapeType == CONCAVE_POLYGON);
+  }
+
+  /**
+   * Method that returns empty Constraints object..
+   *
+   * @return an empty Constraints object
+   */
+  public Constraints getEmptyConstraint(){
+    return new Constraints();
+  }
+
+  /**
+   * Method that returns a random generated GeoPoint.
+   *
+   * @param planetModel The planet model.
+   * @return The random generated GeoPoint.
+   */
+  public GeoPoint randomGeoPoint(PlanetModel planetModel) {
+    GeoPoint point = null;
+    while (point == null) {
+      point = randomGeoPoint(planetModel, getEmptyConstraint());
+    }
+    return point;
+  }
+
+  /**
+   * Method that returns a random generated GeoPoint under given constraints. Returns
+   * NULL if it cannot find a point under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPoint.
+   */
+  public GeoPoint randomGeoPoint(PlanetModel planetModel, Constraints constraints) {
+    int iterations = 0;
+    while (iterations < MAX_POINT_ITERATIONS) {
+      double lat = randomDouble();
+      if (Math.PI/2 - Math.abs(lat)  <0){
+        continue;
+      }
+      double lon =  randomDouble();
+      if (Math.PI - Math.abs(lat)   <0){
+        continue;
+      }
+      iterations++;
+      GeoPoint point = new GeoPoint(planetModel, lat, lon);
+      if (constraints.isWithin(point)) {
+        return point;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated GeoAreaShape.
+   *
+   * @param shapeType The GeoAreaShape code.
+   * @param planetModel The planet model.
+   * @return The random generated GeoAreaShape.
+   */
+  public GeoAreaShape randomGeoAreaShape(int shapeType, PlanetModel planetModel){
+    GeoAreaShape geoAreaShape = null;
+    while (geoAreaShape == null){
+      geoAreaShape = randomGeoAreaShape(shapeType,planetModel,new Constraints());
+    }
+    return geoAreaShape;
+  }
+
+  /**
+   * Method that returns a random generated GeoAreaShape under given constraints. Returns
+   * NULL if it cannot build the GeoAreaShape under the given constraints.
+   *
+   * @param shapeType The GeoAreaShape code.
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoAreaShape.
+   */
+  public GeoAreaShape randomGeoAreaShape(int shapeType, PlanetModel planetModel, Constraints
constraints){
+    return (GeoAreaShape)randomGeoShape(shapeType, planetModel, constraints);
+  }
+
+  /**
+   * Method that returns a random generated GeoShape.
+   *
+   * @param shapeType The shape code.
+   * @param planetModel The planet model.
+   * @return The random generated GeoShape.
+   */
+  public GeoShape randomGeoShape(int shapeType, PlanetModel planetModel){
+    GeoShape geoShape = null;
+    while (geoShape == null){
+      geoShape = randomGeoShape(shapeType,planetModel,new Constraints());
+    }
+    return geoShape;
+  }
+
+  /**
+   * Method that returns a random generated GeoShape under given constraints. Returns
+   * NULL if it cannot build the GeoShape under the given constraints.
+   *
+   * @param shapeType The polygon code.
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoShape.
+   */
+  public GeoShape randomGeoShape(int shapeType, PlanetModel planetModel, Constraints constraints){
+    switch (shapeType) {
+      case CONVEX_POLYGON: {
+        return convexPolygon(planetModel, constraints);
+      }
+      case CONVEX_POLYGON_WITH_HOLES: {
+        return convexPolygonWithHoles(planetModel, constraints);
+      }
+      case CONCAVE_POLYGON: {
+        return concavePolygon(planetModel, constraints);
+      }
+      case CONCAVE_POLYGON_WITH_HOLES: {
+        return concavePolygonWithHoles(planetModel, constraints);
+      }
+      case COMPLEX_POLYGON: {
+        return complexPolygon(planetModel, constraints);
+      }
+      case CIRCLE: {
+        return circle(planetModel, constraints);
+      }
+      case RECTANGLE: {
+        return rectangle(planetModel, constraints);
+      }
+      case PATH: {
+        return path(planetModel, constraints);
+      }
+      case COLLECTION: {
+        return collection(planetModel, constraints);
+      }
+      case POINT: {
+        return point(planetModel, constraints);
+      }
+      case LINE: {
+        return line(planetModel, constraints);
+      }
+      case CONVEX_SIMPLE_POLYGON: {
+        return simpleConvexPolygon(planetModel, constraints);
+      }
+      case CONCAVE_SIMPLE_POLYGON: {
+        return concaveSimplePolygon(planetModel, constraints);
+      }
+      default:
+        throw new IllegalStateException("Unexpected shape type");
+    }
+  }
+
+  /**
+   * Method that returns a random generated a GeoPointShape under given constraints. Returns
+   * NULL if it cannot build the GeoCircle under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPointShape.
+   */
+  private GeoPointShape point(PlanetModel planetModel , Constraints constraints) {
+    int iterations=0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      final GeoPoint point = randomGeoPoint(planetModel, constraints);
+      if (point == null){
+        continue;
+      }
+      try {
+
+        GeoPointShape pointShape = GeoPointShapeFactory.makeGeoPointShape(planetModel, point.getLatitude(),
point.getLongitude());
+        if (!constraints.valid(pointShape)) {
+          continue;
+        }
+        return pointShape;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a GeoCircle under given constraints. Returns
+   * NULL if it cannot build the GeoCircle under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoCircle.
+   */
+  private GeoCircle circle(PlanetModel planetModel , Constraints constraints) {
+    int iterations=0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      final GeoPoint center = randomGeoPoint(planetModel, constraints);
+      if (center == null){
+        continue;
+      }
+      final double radius = randomCutoffAngle();
+      try {
+
+        GeoCircle circle = GeoCircleFactory.makeGeoCircle(planetModel, center.getLatitude(),
center.getLongitude(), radius);
+        if (!constraints.valid(circle)) {
+          continue;
+        }
+        return circle;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a GeoBBox under given constraints. Returns
+   * NULL if it cannot build the GeoBBox under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoBBox.
+   */
+  private GeoBBox rectangle(PlanetModel planetModel, Constraints constraints) {
+
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      final GeoPoint point1 = randomGeoPoint(planetModel, constraints);
+      if (point1 == null){
+        continue;
+      }
+      final GeoPoint point2 = randomGeoPoint(planetModel, constraints);
+      if (point2 == null){
+        continue;
+      }
+
+      double minLat = Math.min(point1.getLatitude(), point2.getLatitude());
+      double maxLat = Math.max(point1.getLatitude(), point2.getLatitude());
+      double minLon = Math.min(point1.getLongitude(), point2.getLongitude());
+      double maxLon = Math.max(point1.getLongitude(), point2.getLongitude());
+
+      try {
+        GeoBBox bbox = GeoBBoxFactory.makeGeoBBox(planetModel, maxLat, minLat, minLon, maxLon);
+        if (!constraints.valid(bbox)) {
+          continue;
+        }
+        return bbox;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated degenerate GeoPath under given constraints. Returns
+   * NULL if it cannot build the degenerate GeoPath under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated degenerated GeoPath.
+   */
+  private GeoPath line(PlanetModel planetModel, Constraints constraints) {
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      int vertexCount =  random().nextInt(2) + 2;
+      List<GeoPoint> geoPoints = points(vertexCount, planetModel, constraints);
+      try {
+        GeoPath path = GeoPathFactory.makeGeoPath(planetModel, 0, geoPoints.toArray(new GeoPoint[geoPoints.size()]));
+        if (!constraints.valid(path)) {
+          continue;
+        }
+        return path;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a GeoPath under given constraints. Returns
+   * NULL if it cannot build the GeoPath under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPath.
+   */
+  private GeoPath path(PlanetModel planetModel, Constraints constraints) {
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      int vertexCount =  random().nextInt(2) + 2;
+      List<GeoPoint> geoPoints = points(vertexCount, planetModel, constraints);
+      double width =randomCutoffAngle();
+      try {
+        GeoPath path = GeoPathFactory.makeGeoPath(planetModel, width, geoPoints.toArray(new
GeoPoint[geoPoints.size()]));
+        if (!constraints.valid(path)) {
+          continue;
+        }
+        return path;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a GeoCompositeMembershipShape under given constraints.
Returns
+   * NULL if it cannot build the GGeoCompositeMembershipShape under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoCompositeMembershipShape.
+   */
+  private GeoCompositeAreaShape collection(PlanetModel planetModel, Constraints constraints)
{
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      int numberShapes =  random().nextInt(3) + 2;
+      GeoCompositeAreaShape collection = new GeoCompositeAreaShape(planetModel);
+      for(int i=0; i<numberShapes;i++){
+        GeoPolygon member = convexPolygon(planetModel, constraints);
+        if (member != null){
+          collection.addShape(member);
+        }
+      }
+      if (collection.shapes.size() ==0){
+        continue;
+      }
+      return collection;
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a convex GeoPolygon under given constraints.
Returns
+   * NULL if it cannot build the GePolygon under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon convexPolygon(PlanetModel planetModel, Constraints constraints) {
+    int vertexCount = random().nextInt(4) + 3;
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      List<GeoPoint> geoPoints = points(vertexCount,planetModel, constraints);
+      List<GeoPoint> orderedGeoPoints = orderPoints(geoPoints);
+      try {
+        GeoPolygon polygon = GeoPolygonFactory.makeGeoPolygon(planetModel, orderedGeoPoints);
+        if (!constraints.valid(polygon) || isConcave(planetModel, polygon)) {
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a convex GeoPolygon with holes under given constraints.
Returns
+   * NULL if it cannot build the GeoPolygon with holes under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon convexPolygonWithHoles(PlanetModel planetModel, Constraints constraints)
{
+    int vertexCount = random().nextInt(4) + 3;
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      List<GeoPoint> geoPoints = points(vertexCount,planetModel, constraints);
+      List<GeoPoint> orderedGeoPoints = orderPoints(geoPoints);
+      try {
+        GeoPolygon polygon = GeoPolygonFactory.makeGeoPolygon(planetModel, orderedGeoPoints);
+        //polygon should comply with all constraints except disjoint as we have holes
+        Constraints polygonConstraints = new Constraints();
+        polygonConstraints.putAll(constraints.getContains());
+        polygonConstraints.putAll(constraints.getWithin());
+        polygonConstraints.putAll(constraints.getDisjoint());
+        if (!polygonConstraints.valid(polygon) || isConcave(planetModel, polygon)){
+          continue;
+        }
+        //hole must overlap with polygon and comply with any CONTAINS constraint.
+        Constraints holeConstraints = new Constraints();
+        holeConstraints.putAll(constraints.getContains());
+        holeConstraints.put(polygon,GeoArea.OVERLAPS);
+        //Points must be with in the polygon and must comply
+        // CONTAINS and DISJOINT constraints
+        Constraints pointsConstraints = new Constraints();
+        pointsConstraints.put(polygon,GeoArea.WITHIN);
+        pointsConstraints.putAll(constraints.getContains());
+        pointsConstraints.putAll(constraints.getDisjoint());
+        List<GeoPolygon> holes = concavePolygonHoles(planetModel, holeConstraints,
pointsConstraints);
+        //we should have at least one hole
+        if (holes.size() == 0){
+          continue;
+        }
+        polygon = GeoPolygonFactory.makeGeoPolygon(planetModel,orderedGeoPoints,holes);
+        if (!constraints.valid(polygon) || isConcave(planetModel, polygon)){
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random list if concave GeoPolygons under given constraints. Method
+   * use to generate convex holes. Note that constraints for points and holes are different,
+   *
+   * @param planetModel The planet model.
+   * @param holeConstraints The given constraints that a hole must comply.
+   * @param pointConstraints The given constraints that a point must comply.
+   * @return The random generated GeoPolygon.
+   */
+  private List<GeoPolygon> concavePolygonHoles(PlanetModel planetModel,
+                                               Constraints holeConstraints,
+                                               Constraints pointConstraints) {
+    int iterations =0;
+    int holesCount = random().nextInt(3) + 1;
+    List<GeoPolygon> holes = new ArrayList<>();
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      int vertexCount = random().nextInt(3) + 3;
+      List<GeoPoint> geoPoints = points(vertexCount, planetModel, pointConstraints);
+      geoPoints = orderPoints(geoPoints);
+      Collections.reverse(geoPoints);
+      try {
+        GeoPolygon hole = GeoPolygonFactory.makeGeoPolygon(planetModel, geoPoints);
+        if (!holeConstraints.valid(hole) || isConvex(planetModel, hole)) {
+          continue;
+        }
+        holes.add(hole);
+        if (holes.size() == holesCount){
+          return holes;
+        }
+        pointConstraints.put(hole, GeoArea.DISJOINT);
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return holes;
+  }
+
+  /**
+   * Method that returns a random generated a concave GeoPolygon under given constraints.
Returns
+   * NULL if it cannot build the concave GeoPolygon under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon concavePolygon(PlanetModel planetModel, Constraints constraints) {
+
+    int vertexCount = random().nextInt(4) + 3;
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      List<GeoPoint> geoPoints = points(vertexCount,planetModel, constraints);
+      List<GeoPoint> orderedGeoPoints = orderPoints(geoPoints);
+      Collections.reverse(orderedGeoPoints);
+      try {
+        GeoPolygon polygon = GeoPolygonFactory.makeGeoPolygon(planetModel, orderedGeoPoints);
+        if (!constraints.valid(polygon) || isConvex(planetModel, polygon)) {
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a concave GeoPolygon with holes under given constraints.
Returns
+   * NULL if it cannot build the GeoPolygon under the given constraints. Note that the final
GeoPolygon is
+   * convex as the hole wraps the convex GeoPolygon.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon concavePolygonWithHoles(PlanetModel planetModel, Constraints constraints)
{
+    int vertexCount = random().nextInt(4) + 3;
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      //we first build the hole. We consider all constraints except
+      // disjoint as we have a hole
+      Constraints holeConstraints = new Constraints();
+      holeConstraints.putAll(constraints.getContains());
+      holeConstraints.putAll(constraints.getWithin());
+      holeConstraints.putAll(constraints.getOverlaps());
+      GeoPolygon hole = convexPolygon(planetModel, holeConstraints);
+      if (hole == null){
+        continue;
+      }
+      // Now we get points for polygon. Must we with in the hole
+      // and we add contain constraints
+      Constraints pointConstraints = new Constraints();
+      pointConstraints.put(hole, GeoArea.WITHIN);
+      pointConstraints.putAll(constraints.getContains());
+      List<GeoPoint> geoPoints = points(vertexCount,planetModel, pointConstraints);
+      List<GeoPoint> orderedGeoPoints = orderPoints(geoPoints);
+      Collections.reverse(orderedGeoPoints);
+      try {
+        GeoPolygon polygon = GeoPolygonFactory.makeGeoPolygon(planetModel, orderedGeoPoints,
Collections.singletonList(hole));
+        //final polygon must be convex
+        if (!constraints.valid(polygon) || isConcave(planetModel,polygon)) {
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated complex GeoPolygon under given constraints. Returns
+   * NULL if it cannot build the complex GeoPolygon under the given constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon complexPolygon(PlanetModel planetModel, Constraints constraints) {
+    int polygonsCount =random().nextInt(2) + 1;
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      List<GeoPolygonFactory.PolygonDescription> polDescription = new ArrayList<>();
+      while(polDescription.size() < polygonsCount){
+        int vertexCount = random().nextInt(14) + 3;
+        List<GeoPoint> geoPoints = points(vertexCount,planetModel, constraints);
+        orderPoints(geoPoints);
+        polDescription.add(new GeoPolygonFactory.PolygonDescription(geoPoints));
+      }
+      try {
+        GeoPolygon polygon = GeoPolygonFactory.makeLargeGeoPolygon(planetModel,polDescription);
+        if (!constraints.valid(polygon)) {
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a concave square GeoPolygon under given constraints.
Returns
+   * NULL if it cannot build the concave GeoPolygon under the given constraints. This shape
is an utility
+   * to build constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon simpleConvexPolygon(PlanetModel planetModel, Constraints constraints)
{
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      List<GeoPoint> points = points(3,planetModel,constraints);
+      points = orderPoints(points);
+      try {
+        GeoPolygon polygon =  GeoPolygonFactory.makeGeoConvexPolygon(planetModel, points);
+        if(!constraints.valid(polygon) || isConcave(planetModel,polygon)){
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random generated a convex square GeoPolygon under given constraints.
Returns
+   * NULL if it cannot build the convex GeoPolygon under the given constraints. This shape
is an utility
+   * to build constraints.
+   *
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated GeoPolygon.
+   */
+  private GeoPolygon concaveSimplePolygon(PlanetModel planetModel, Constraints constraints)
{
+    int iterations = 0;
+    while (iterations < MAX_SHAPE_ITERATIONS) {
+      iterations++;
+      List<GeoPoint> points = points(3, planetModel, constraints);
+      points = orderPoints(points);
+      Collections.reverse(points);
+      try {
+        GeoPolygon polygon =  GeoPolygonFactory.makeGeoConcavePolygon(planetModel, points);
+        if(!constraints.valid(polygon) || isConvex(planetModel, polygon)){
+          continue;
+        }
+        return polygon;
+      } catch (IllegalArgumentException e) {
+        continue;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Method that returns a random list of generated GeoPoints under given constraints. If
it cannot
+   * find a point it will add a point that might not comply with the constraints.
+   *
+   * @param count The number of points
+   * @param planetModel The planet model.
+   * @param constraints The given constraints.
+   * @return The random generated List of GeoPoints.
+   */
+  private List<GeoPoint> points(int count, PlanetModel planetModel, Constraints constraints){
+    List<GeoPoint> geoPoints = new ArrayList<>(count);
+    for(int i= 0; i< count; i++) {
+      GeoPoint point = randomGeoPoint(planetModel, constraints);
+      if (point == null){
+        point = randomGeoPoint(planetModel, new Constraints());
+      }
+      geoPoints.add(point);
+    }
+    return  geoPoints;
+  }
+
+  /**
+   * Check if a GeoPolygon is pure concave. Note that our definition for concavity is that
the polygon
+   * contains antipodal points.
+   *
+   * @param planetModel The planet model.
+   * @param shape The polygon to check.
+   * @return True if the polygon contains antipodal points.
+   */
+  private boolean isConcave(PlanetModel planetModel, GeoPolygon shape){
+    return (shape.isWithin(planetModel.NORTH_POLE) && shape.isWithin(planetModel.SOUTH_POLE))||
+        (shape.isWithin(planetModel.MAX_X_POLE) && shape.isWithin(planetModel.MIN_X_POLE))
||
+        (shape.isWithin(planetModel.MAX_Y_POLE) && shape.isWithin(planetModel.MIN_Y_POLE));
+  }
+
+  /**
+   * Check if a GeoPolygon is pure convex. Note that our definition for convexity is that
the polygon
+   * does not contain antipodal points.
+   *
+   * @param planetModel The planet model.
+   * @param shape The polygon to check.
+   * @return True if the polygon dies not contains antipodal points.
+   */
+  private boolean isConvex(PlanetModel planetModel, GeoPolygon shape){
+    return !isConcave(planetModel,shape);
+  }
+
+  /**
+   * Generates a random number between 0 and PI.
+   *
+   * @return the cutoff angle.
+   */
+  private double randomCutoffAngle() {
+    while(true) {
+      double radius = randomDouble();
+      if (radius <0 || radius > Math.PI){
+        continue;
+      }
+      return radius;
+    }
+  }
+
+  /**
+   * Method that orders a lit of points anti-clock-wise to prevent crossing edges.
+   *
+   * @param originalPoints The points to order.
+   * @return The list of ordered points anti-clockwise.
+   */
+  private List<GeoPoint> orderPoints(List<GeoPoint> originalPoints){
+    List<GeoPoint> points = new ArrayList<>(originalPoints.size());
+    points.addAll(originalPoints); //make a copy
+    GeoPoint lPoint = getPointLefLon(points);
+    points.remove(lPoint);
+    GeoPoint rPoint = getPointRigthLon(points);
+    points.remove(rPoint);
+    List<GeoPoint> APoints = getPointsBelowAndSort(points, lPoint);
+    List<GeoPoint> BPoints = getPointsAboveAndsort(points, lPoint);
+    List<GeoPoint> result = new ArrayList<>();
+    result.add(lPoint);
+    result.addAll(APoints);
+    result.add(rPoint);
+    result.addAll(BPoints);
+    return result;
+  }
+
+  private List<GeoPoint> getPointsAboveAndsort(List<GeoPoint> points,GeoPoint
lPoint) {
+    List<GeoPoint> BPoints = new ArrayList<>();
+    for (GeoPoint point : points){
+      if(point.getLatitude() > lPoint.getLatitude()){
+        BPoints.add(point);
+      }
+    }
+    Collections.sort(BPoints, new Comparator<GeoPoint>() {
+      public int compare(GeoPoint idx1, GeoPoint idx2) {
+        return Double.compare(idx1.getLongitude(), idx2.getLongitude());
+      }
+    });
+    return BPoints;
+  }
+
+  private List<GeoPoint> getPointsBelowAndSort(List<GeoPoint> points,GeoPoint
lPoint) {
+    List<GeoPoint> APoints = new ArrayList<>();
+    for (GeoPoint point : points){
+      if(point.getLatitude() < lPoint.getLatitude()){
+        APoints.add(point);
+      }
+    }
+    Collections.sort(APoints, new Comparator<GeoPoint>() {
+      public int compare(GeoPoint idx1, GeoPoint idx2) {
+        return Double.compare(idx1.getLongitude(), idx2.getLongitude());
+      }
+    });
+    return APoints;
+  }
+
+  private GeoPoint getPointLefLon(List<GeoPoint> points)  {
+    GeoPoint lPoint = null;
+    for (GeoPoint point : points){
+      if(lPoint == null ){
+        lPoint = point;
+      }
+      else{
+        if (lPoint.getLongitude() > point.getLongitude()){
+          lPoint = point;
+        }
+      }
+    }
+    return lPoint;
+  }
+
+  private GeoPoint getPointRigthLon(List<GeoPoint> points) {
+    GeoPoint rPoint = null;
+    for (GeoPoint point : points){
+      if(rPoint == null ){
+        rPoint = point;
+      }
+      else{
+        if (rPoint.getLongitude() < point.getLongitude()){
+          rPoint = point;
+        }
+      }
+    }
+    return rPoint;
+  }
+
+  /**
+   * Class that holds the constraints that are given to
+   * build shapes. It consists in a list of GeoAreaShapes
+   * and relationships the new shape needs to satisfy.
+   */
+  class Constraints extends HashMap<GeoAreaShape, Integer>{
+
+    /**
+     * Check if the shape is valid under the constraints.
+     *
+     * @param shape The shape to check
+     * @return true if the shape satisfy the constraints, else false.
+     */
+    public boolean valid(GeoShape shape) {
+      if (shape == null){
+        return false;
+      }
+      for (GeoAreaShape constraint : keySet()) {
+        if (constraint.getRelationship(shape) != get(constraint)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /**
+     * Check if a point is Within the constraints.
+     *
+     * @param point The point to check
+     * @return true if the point satisfy the constraints, else false.
+     */
+    public boolean isWithin(GeoPoint point) {
+      for (GeoShape constraint : keySet()) {
+        if (!(validPoint(point, constraint, get(constraint)))) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    /**
+     * Check if a point is Within one constraint given by a shape and a relationship.
+     *
+     * @param point The point to check
+     * @param shape The shape of the constraint
+     * @param relationship The relationship of the constraint.
+     * @return true if the point satisfy the constraint, else false.
+     */
+    private boolean validPoint(GeoPoint point, GeoShape shape, int relationship) {
+      //For GeoCompositeMembershipShape we only consider the first shape to help
+      // converging
+      if (relationship == GeoArea.WITHIN && shape instanceof GeoCompositeMembershipShape)
{
+        shape = (((GeoCompositeMembershipShape) shape).shapes.get(0));
+      }
+      switch (relationship) {
+        case GeoArea.DISJOINT:
+          return !shape.isWithin(point);
+        case GeoArea.OVERLAPS:
+          return true;
+        case GeoArea.CONTAINS:
+          return !shape.isWithin(point);
+        case GeoArea.WITHIN:
+          return shape.isWithin(point);
+        default:
+          return true;
+      }
+    }
+
+    /**
+     * Collect the CONTAINS constraints in the object
+     *
+     * @return the CONTAINS constraints.
+     */
+    public Constraints getContains(){
+      return getConstraintsOfType(GeoArea.CONTAINS);
+    }
+
+    /**
+     * Collect the WITHIN constraints in the object
+     *
+     * @return the WITHIN constraints.
+     */
+    public Constraints getWithin(){
+      return getConstraintsOfType(GeoArea.WITHIN);
+    }
+
+    /**
+     * Collect the OVERLAPS constraints in the object
+     *
+     * @return the OVERLAPS constraints.
+     */
+    public Constraints getOverlaps(){
+      return getConstraintsOfType(GeoArea.OVERLAPS);
+    }
+
+    /**
+     * Collect the DISJOINT constraints in the object
+     *
+     * @return the DISJOINT constraints.
+     */
+    public Constraints getDisjoint(){
+      return getConstraintsOfType(GeoArea.DISJOINT);
+    }
+
+    private Constraints getConstraintsOfType(int type){
+      Constraints constraints = new Constraints();
+      for (GeoAreaShape constraint : keySet()) {
+        if (type == get(constraint)) {
+          constraints.put(constraint, type);
+        }
+      }
+      return constraints;
+    }
+  }
+}


Mime
View raw message