Browse Source

Merge pull request #14482 from cbuescher/remove-internal-linestring-builder

Remove InternalLineStringBuilder and InternalPolygonBuilder
Christoph Büscher 10 years ago
parent
commit
aa1507d349

+ 4 - 9
core/src/main/java/org/elasticsearch/common/geo/builders/BaseLineStringBuilder.java

@@ -23,7 +23,6 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 
-import com.spatial4j.core.shape.ShapeCollection;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 
 import com.spatial4j.core.shape.Shape;
@@ -34,11 +33,7 @@ import com.vividsolutions.jts.geom.LineString;
 
 public abstract class BaseLineStringBuilder<E extends BaseLineStringBuilder<E>> extends PointCollection<E> {
 
-    protected BaseLineStringBuilder() {
-        this(new ArrayList<Coordinate>());
-    }
-
-    protected BaseLineStringBuilder(ArrayList<Coordinate> points) {
+    public BaseLineStringBuilder(ArrayList<Coordinate> points) {
         super(points);
     }
 
@@ -78,15 +73,15 @@ public abstract class BaseLineStringBuilder<E extends BaseLineStringBuilder<E>>
 
     /**
      * Decompose a linestring given as array of coordinates at a vertical line.
-     * 
+     *
      * @param dateline x-axis intercept of the vertical line
      * @param coordinates coordinates forming the linestring
-     * @return array of linestrings given as coordinate arrays 
+     * @return array of linestrings given as coordinate arrays
      */
     protected static Coordinate[][] decompose(double dateline, Coordinate[] coordinates) {
         int offset = 0;
         ArrayList<Coordinate[]> parts = new ArrayList<>();
-        
+
         double shift = coordinates[0].x > DATELINE ? DATELINE : (coordinates[0].x < -DATELINE ? -DATELINE : 0);
 
         for (int i = 1; i < coordinates.length; i++) {

+ 37 - 75
core/src/main/java/org/elasticsearch/common/geo/builders/BasePolygonBuilder.java

@@ -42,8 +42,8 @@ import java.util.Iterator;
  * The {@link BasePolygonBuilder} implements the groundwork to create polygons. This contains
  * Methods to wrap polygons at the dateline and building shapes from the data held by the
  * builder.
- * Since this Builder can be embedded to other builders (i.e. {@link MultiPolygonBuilder}) 
- * the class of the embedding builder is given by the generic argument <code>E</code>  
+ * Since this Builder can be embedded to other builders (i.e. {@link MultiPolygonBuilder})
+ * the class of the embedding builder is given by the generic argument <code>E</code>
 
  * @param <E> type of the embedding class
  */
@@ -51,11 +51,11 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
 
     public static final GeoShapeType TYPE = GeoShapeType.POLYGON;
 
-    // Linear ring defining the shell of the polygon
-    protected Ring<E> shell; 
+    // line string defining the shell of the polygon
+    protected LineStringBuilder shell;
 
-    // List of linear rings defining the holes of the polygon 
-    protected final ArrayList<BaseLineStringBuilder<?>> holes = new ArrayList<>();
+    // List of line strings defining the holes of the polygon
+    protected final ArrayList<LineStringBuilder> holes = new ArrayList<>();
 
     public BasePolygonBuilder(Orientation orientation) {
         super(orientation);
@@ -65,7 +65,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
     private E thisRef() {
         return (E)this;
     }
-    
+
     public E point(double longitude, double latitude) {
         shell.point(longitude, latitude);
         return thisRef();
@@ -96,27 +96,17 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
      * @param hole linear ring defining the hole
      * @return this
      */
-    public E hole(BaseLineStringBuilder<?> hole) {
+    public E hole(LineStringBuilder hole) {
         holes.add(hole);
         return thisRef();
     }
 
-    /**
-     * build new hole to the polygon
-     * @return this
-     */
-    public Ring<E> hole() {
-        Ring<E> hole = new Ring<>(thisRef());
-        this.holes.add(hole);
-        return hole;
-    }
-
     /**
      * Close the shell of the polygon
-     * @return parent
      */
-    public ShapeBuilder close() {
-        return shell.close();
+    public BasePolygonBuilder close() {
+        shell.close();
+        return this;
     }
 
     /**
@@ -138,11 +128,11 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
      * within the polygon.
      * This Method also wraps the polygons at the dateline. In order to this fact the result may
      * contains more polygons and less holes than defined in the builder it self.
-     * 
+     *
      * @return coordinates of the polygon
      */
     public Coordinate[][][] coordinates() {
-        int numEdges = shell.points.size()-1; // Last point is repeated 
+        int numEdges = shell.points.size()-1; // Last point is repeated
         for (int i = 0; i < holes.size(); i++) {
             numEdges += holes.get(i).points.size()-1;
             validateHole(shell, this.holes.get(i));
@@ -172,12 +162,12 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
 
     protected XContentBuilder coordinatesArray(XContentBuilder builder, Params params) throws IOException {
         shell.coordinatesToXcontent(builder, true);
-        for(BaseLineStringBuilder<?> hole : holes) {
+        for(BaseLineStringBuilder hole : holes) {
             hole.coordinatesToXcontent(builder, true);
         }
         return builder;
     }
-    
+
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();
@@ -188,7 +178,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
         builder.endObject();
         return builder;
     }
-    
+
     public Geometry buildGeometry(GeometryFactory factory, boolean fixDateline) {
         if(fixDateline) {
             Coordinate[][][] polygons = coordinates();
@@ -207,7 +197,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
     protected Polygon toPolygon(GeometryFactory factory) {
         final LinearRing shell = linearRing(factory, this.shell.points);
         final LinearRing[] holes = new LinearRing[this.holes.size()];
-        Iterator<BaseLineStringBuilder<?>> iterator = this.holes.iterator();
+        Iterator<LineStringBuilder> iterator = this.holes.iterator();
         for (int i = 0; iterator.hasNext(); i++) {
             holes[i] = linearRing(factory, iterator.next().points);
         }
@@ -226,7 +216,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
     protected static Polygon polygon(GeometryFactory factory, Coordinate[][] polygon) {
         LinearRing shell = factory.createLinearRing(polygon[0]);
         LinearRing[] holes;
-        
+
         if(polygon.length > 1) {
             holes = new LinearRing[polygon.length-1];
             for (int i = 0; i < holes.length; i++) {
@@ -243,7 +233,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
      * in turn contains an array of linestrings. These line Strings are represented as an array of
      * coordinates. The first linestring will be the shell of the polygon the others define holes
      * within the polygon.
-     *      
+     *
      * @param factory {@link GeometryFactory} to use
      * @param polygons definition of polygons
      * @return a new Multipolygon
@@ -258,19 +248,19 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
 
     /**
      * This method sets the component id of all edges in a ring to a given id and shifts the
-     * coordinates of this component according to the dateline 
-     * 
+     * coordinates of this component according to the dateline
+     *
      * @param edge An arbitrary edge of the component
      * @param id id to apply to the component
      * @param edges a list of edges to which all edges of the component will be added (could be <code>null</code>)
      * @return number of edges that belong to this component
      */
     private static int component(final Edge edge, final int id, final ArrayList<Edge> edges) {
-        // find a coordinate that is not part of the dateline 
+        // find a coordinate that is not part of the dateline
         Edge any = edge;
         while(any.coordinate.x == +DATELINE || any.coordinate.x == -DATELINE) {
             if((any = any.next) == edge) {
-                break;   
+                break;
             }
         }
 
@@ -362,7 +352,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
         }
 
         return result;
-    } 
+    }
 
     private static final Coordinate[][] EMPTY = new Coordinate[0][];
 
@@ -378,7 +368,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
         }
 
         return points;
-    } 
+    }
 
     private static Edge[] edges(Edge[] edges, int numHoles, ArrayList<ArrayList<Coordinate[]>> components) {
         ArrayList<Edge> mainEdges = new ArrayList<>(edges.length);
@@ -412,7 +402,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
         }
         for (int i = 0; i < numHoles; i++) {
             final Edge current = new Edge(holes[i].coordinate, holes[i].next);
-            // the edge intersects with itself at its own coordinate.  We need intersect to be set this way so the binary search 
+            // the edge intersects with itself at its own coordinate.  We need intersect to be set this way so the binary search
             // will get the correct position in the edge list and therefore the correct component to add the hole
             current.intersect = current.coordinate;
             final int intersections = intersections(current.coordinate.x, edges);
@@ -457,20 +447,20 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
                 holes[e2.component-1] = holes[numHoles];
                 holes[numHoles] = null;
             }
-            // only connect edges if intersections are pairwise 
+            // only connect edges if intersections are pairwise
             // 1. per the comment above, the edge array is sorted by y-value of the intersection
-            // with the dateline.  Two edges have the same y intercept when they cross the 
+            // with the dateline.  Two edges have the same y intercept when they cross the
             // dateline thus they appear sequentially (pairwise) in the edge array. Two edges
             // do not have the same y intercept when we're forming a multi-poly from a poly
-            // that wraps the dateline (but there are 2 ordered intercepts).  
-            // The connect method creates a new edge for these paired edges in the linked list. 
-            // For boundary conditions (e.g., intersect but not crossing) there is no sibling edge 
+            // that wraps the dateline (but there are 2 ordered intercepts).
+            // The connect method creates a new edge for these paired edges in the linked list.
+            // For boundary conditions (e.g., intersect but not crossing) there is no sibling edge
             // to connect. Thus the first logic check enforces the pairwise rule
             // 2. the second logic check ensures the two candidate edges aren't already connected by an
             //    existing edge along the dateline - this is necessary due to a logic change in
-            //    ShapeBuilder.intersection that computes dateline edges as valid intersect points 
+            //    ShapeBuilder.intersection that computes dateline edges as valid intersect points
             //    in support of OGC standards
-            if (e1.intersect != Edge.MAX_COORDINATE && e2.intersect != Edge.MAX_COORDINATE 
+            if (e1.intersect != Edge.MAX_COORDINATE && e2.intersect != Edge.MAX_COORDINATE
                     && !(e1.next.next.coordinate.equals3D(e2.coordinate) && Math.abs(e1.next.coordinate.x) == DATELINE
                     && Math.abs(e2.coordinate.x) == DATELINE) ) {
                 connect(e1, e2);
@@ -489,7 +479,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
             // NOTE: the order of the object creation is crucial here! Don't change it!
             // first edge has no point on dateline
             Edge e1 = new Edge(in.intersect, in.next);
-            
+
             if(out.intersect != out.next.coordinate) {
                 // second edge has no point on dateline
                 Edge e2 = new Edge(out.intersect, out.next);
@@ -507,7 +497,7 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
                 // second edge has no point on dateline
                 Edge e1 = new Edge(out.intersect, out.next);
                 in.next = new Edge(in.intersect, e1, in.intersect);
-                
+
             } else {
                 // second edge intersects with dateline
                 in.next = new Edge(in.intersect, out.next, in.intersect);
@@ -516,8 +506,8 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
         }
     }
 
-    private static int createEdges(int component, Orientation orientation, BaseLineStringBuilder<?> shell,
-                                   BaseLineStringBuilder<?> hole,
+    private static int createEdges(int component, Orientation orientation, BaseLineStringBuilder shell,
+                                   BaseLineStringBuilder hole,
                                    Edge[] edges, int offset) {
         // inner rings (holes) have an opposite direction than the outer rings
         // XOR will invert the orientation for outer ring cases (Truth Table:, T/T = F, T/F = T, F/T = T, F/F = F)
@@ -527,32 +517,4 @@ public abstract class BasePolygonBuilder<E extends BasePolygonBuilder<E>> extend
         Edge.ring(component, direction, orientation == Orientation.LEFT, shell, points, 0, edges, offset, points.length-1);
         return points.length-1;
     }
-
-    public static class Ring<P extends ShapeBuilder> extends BaseLineStringBuilder<Ring<P>> {
-
-        private final P parent;
-
-        protected Ring(P parent) {
-            this(parent, new ArrayList<Coordinate>());
-        }
-
-        protected Ring(P parent, ArrayList<Coordinate> points) {
-            super(points);
-            this.parent = parent;
-        }
-
-        public P close() {
-            Coordinate start = points.get(0);
-            Coordinate end = points.get(points.size()-1);
-            if(start.x != end.x || start.y != end.y) {
-                points.add(start);
-            }
-            return parent;
-        }
-
-        @Override
-        public GeoShapeType type() {
-            return null;
-        }
-    }
 }

+ 12 - 12
core/src/main/java/org/elasticsearch/common/geo/builders/GeometryCollectionBuilder.java

@@ -29,7 +29,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 public class GeometryCollectionBuilder extends ShapeBuilder {
-    
+
     public static final GeoShapeType TYPE = GeoShapeType.GEOMETRYCOLLECTION;
 
     protected final ArrayList<ShapeBuilder> shapes = new ArrayList<>();
@@ -46,42 +46,42 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
         this.shapes.add(shape);
         return this;
     }
-    
+
     public GeometryCollectionBuilder point(PointBuilder point) {
         this.shapes.add(point);
         return this;
     }
-    
+
     public GeometryCollectionBuilder multiPoint(MultiPointBuilder multiPoint) {
         this.shapes.add(multiPoint);
         return this;
     }
-    
-    public GeometryCollectionBuilder line(BaseLineStringBuilder<?> line) {
+
+    public GeometryCollectionBuilder line(BaseLineStringBuilder line) {
         this.shapes.add(line);
         return this;
     }
-    
+
     public GeometryCollectionBuilder multiLine(MultiLineStringBuilder multiLine) {
         this.shapes.add(multiLine);
         return this;
     }
-    
+
     public GeometryCollectionBuilder polygon(BasePolygonBuilder<?> polygon) {
         this.shapes.add(polygon);
         return this;
     }
-    
+
     public GeometryCollectionBuilder multiPolygon(MultiPolygonBuilder multiPolygon) {
         this.shapes.add(multiPolygon);
         return this;
     }
-    
+
     public GeometryCollectionBuilder envelope(EnvelopeBuilder envelope) {
         this.shapes.add(envelope);
         return this;
     }
-    
+
     public GeometryCollectionBuilder circle(CircleBuilder circle) {
         this.shapes.add(circle);
         return this;
@@ -120,11 +120,11 @@ public class GeometryCollectionBuilder extends ShapeBuilder {
     public Shape build() {
 
         List<Shape> shapes = new ArrayList<>(this.shapes.size());
-        
+
         for (ShapeBuilder shape : this.shapes) {
             shapes.add(shape.build());
         }
-            
+
         if (shapes.size() == 1)
             return shapes.get(0);
         else

+ 23 - 0
core/src/main/java/org/elasticsearch/common/geo/builders/LineStringBuilder.java

@@ -19,12 +19,23 @@
 
 package org.elasticsearch.common.geo.builders;
 
+import com.vividsolutions.jts.geom.Coordinate;
+
 import org.elasticsearch.common.xcontent.XContentBuilder;
 
 import java.io.IOException;
+import java.util.ArrayList;
 
 public class LineStringBuilder extends BaseLineStringBuilder<LineStringBuilder> {
 
+    public LineStringBuilder() {
+        this(new ArrayList<Coordinate>());
+    }
+
+    public LineStringBuilder(ArrayList<Coordinate> points) {
+        super(points);
+    }
+
     public static final GeoShapeType TYPE = GeoShapeType.LINESTRING;
 
     @Override
@@ -42,4 +53,16 @@ public class LineStringBuilder extends BaseLineStringBuilder<LineStringBuilder>
         return TYPE;
     }
 
+    /**
+     * Closes the current lineString by adding the starting point as the end point
+     */
+    public LineStringBuilder close() {
+        Coordinate start = points.get(0);
+        Coordinate end = points.get(points.size()-1);
+        if(start.x != end.x || start.y != end.y) {
+            points.add(start);
+        }
+        return this;
+    }
+
 }

+ 5 - 35
core/src/main/java/org/elasticsearch/common/geo/builders/MultiLineStringBuilder.java

@@ -22,7 +22,6 @@ package org.elasticsearch.common.geo.builders;
 import org.elasticsearch.common.xcontent.XContentBuilder;
 
 import com.spatial4j.core.shape.Shape;
-import com.spatial4j.core.shape.jts.JtsGeometry;
 import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Geometry;
 import com.vividsolutions.jts.geom.LineString;
@@ -35,15 +34,9 @@ public class MultiLineStringBuilder extends ShapeBuilder {
 
     public static final GeoShapeType TYPE = GeoShapeType.MULTILINESTRING;
 
-    private final ArrayList<BaseLineStringBuilder<?>> lines = new ArrayList<>();
+    private final ArrayList<LineStringBuilder> lines = new ArrayList<>();
 
-    public InternalLineStringBuilder linestring() {
-        InternalLineStringBuilder line = new InternalLineStringBuilder(this);
-        this.lines.add(line);
-        return line;
-    }
-
-    public MultiLineStringBuilder linestring(BaseLineStringBuilder<?> line) {
+    public MultiLineStringBuilder linestring(LineStringBuilder line) {
         this.lines.add(line);
         return this;
     }
@@ -67,7 +60,7 @@ public class MultiLineStringBuilder extends ShapeBuilder {
         builder.field(FIELD_TYPE, TYPE.shapename);
         builder.field(FIELD_COORDINATES);
         builder.startArray();
-        for(BaseLineStringBuilder<?> line : lines) {
+        for(BaseLineStringBuilder line : lines) {
             line.coordinatesToXcontent(builder, false);
         }
         builder.endArray();
@@ -80,7 +73,7 @@ public class MultiLineStringBuilder extends ShapeBuilder {
         final Geometry geometry;
         if(wrapdateline) {
             ArrayList<LineString> parts = new ArrayList<>();
-            for (BaseLineStringBuilder<?> line : lines) {
+            for (BaseLineStringBuilder line : lines) {
                 BaseLineStringBuilder.decompose(FACTORY, line.coordinates(false), parts);
             }
             if(parts.size() == 1) {
@@ -91,7 +84,7 @@ public class MultiLineStringBuilder extends ShapeBuilder {
             }
         } else {
             LineString[] lineStrings = new LineString[lines.size()];
-            Iterator<BaseLineStringBuilder<?>> iterator = lines.iterator();
+            Iterator<LineStringBuilder> iterator = lines.iterator();
             for (int i = 0; iterator.hasNext(); i++) {
                 lineStrings[i] = FACTORY.createLineString(iterator.next().coordinates(false));
             }
@@ -99,27 +92,4 @@ public class MultiLineStringBuilder extends ShapeBuilder {
         }
         return jtsGeometry(geometry);
     }
-
-    public static class InternalLineStringBuilder extends BaseLineStringBuilder<InternalLineStringBuilder> {
-
-        private final MultiLineStringBuilder collection;
-        
-        public InternalLineStringBuilder(MultiLineStringBuilder collection) {
-            super();
-            this.collection = collection;
-        }
-        
-        public MultiLineStringBuilder end() {
-            return collection;
-        }
-
-        public Coordinate[] coordinates() {
-            return super.coordinates(false);
-        }
-
-        @Override
-        public GeoShapeType type() {
-            return null;
-        }
-    }
 }

+ 1 - 26
core/src/main/java/org/elasticsearch/common/geo/builders/MultiPolygonBuilder.java

@@ -48,16 +48,6 @@ public class MultiPolygonBuilder extends ShapeBuilder {
         return this;
     }
 
-    public InternalPolygonBuilder polygon() {
-        return polygon(Orientation.RIGHT);
-    }
-
-    public InternalPolygonBuilder polygon(Orientation orientation) {
-        InternalPolygonBuilder polygon = new InternalPolygonBuilder(this, orientation);
-        this.polygon(polygon);
-        return polygon;
-    }
-
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         builder.startObject();
@@ -81,7 +71,7 @@ public class MultiPolygonBuilder extends ShapeBuilder {
     public Shape build() {
 
         List<Shape> shapes = new ArrayList<>(this.polygons.size());
-        
+
         if(wrapdateline) {
             for (BasePolygonBuilder<?> polygon : this.polygons) {
                 for(Coordinate[][] part : polygon.coordinates()) {
@@ -100,20 +90,5 @@ public class MultiPolygonBuilder extends ShapeBuilder {
         //note: ShapeCollection is probably faster than a Multi* geom.
     }
 
-    public static class InternalPolygonBuilder extends BasePolygonBuilder<InternalPolygonBuilder> {
 
-        private final MultiPolygonBuilder collection;
-
-        private InternalPolygonBuilder(MultiPolygonBuilder collection, Orientation orientation) {
-            super(orientation);
-            this.collection = collection;
-            this.shell = new Ring<>(this);
-        }
-
-        @Override
-        public MultiPolygonBuilder close() {
-            super.close();
-            return collection;
-        }
-    }
 }

+ 9 - 9
core/src/main/java/org/elasticsearch/common/geo/builders/PointCollection.java

@@ -29,7 +29,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
 import com.vividsolutions.jts.geom.Coordinate;
 
 /**
- * The {@link PointCollection} is an abstract base implementation for all GeoShapes. It simply handles a set of points. 
+ * The {@link PointCollection} is an abstract base implementation for all GeoShapes. It simply handles a set of points.
  */
 public abstract class PointCollection<E extends PointCollection<E>> extends ShapeBuilder {
 
@@ -43,7 +43,7 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
     protected PointCollection(ArrayList<Coordinate> points) {
         this.points = points;
     }
-    
+
     @SuppressWarnings("unchecked")
     private E thisRef() {
         return (E)this;
@@ -57,7 +57,7 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
      */
     public E point(double longitude, double latitude) {
         return this.point(coordinate(longitude, latitude));
-    } 
+    }
 
     /**
      * Add a new point to the collection
@@ -71,7 +71,7 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
 
     /**
      * Add a array of points to the collection
-     * 
+     *
      * @param coordinates array of {@link Coordinate}s to add
      * @return this
      */
@@ -81,7 +81,7 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
 
     /**
      * Add a collection of points to the collection
-     * 
+     *
      * @param coordinates array of {@link Coordinate}s to add
      * @return this
      */
@@ -92,7 +92,7 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
 
     /**
      * Copy all points to a new Array
-     * 
+     *
      * @param closed if set to true the first point of the array is repeated as last element
      * @return Array of coordinates
      */
@@ -106,9 +106,9 @@ public abstract class PointCollection<E extends PointCollection<E>> extends Shap
 
     /**
      * builds an array of coordinates to a {@link XContentBuilder}
-     * 
-     * @param builder builder to use 
-     * @param closed repeat the first point at the end of the array if it's not already defines as last element of the array  
+     *
+     * @param builder builder to use
+     * @param closed repeat the first point at the end of the array if it's not already defines as last element of the array
      * @return the builder
      */
     protected XContentBuilder coordinatesToXcontent(XContentBuilder builder, boolean closed) throws IOException {

+ 1 - 1
core/src/main/java/org/elasticsearch/common/geo/builders/PolygonBuilder.java

@@ -35,7 +35,7 @@ public class PolygonBuilder extends BasePolygonBuilder<PolygonBuilder> {
 
     protected PolygonBuilder(ArrayList<Coordinate> points, Orientation orientation) {
         super(orientation);
-        this.shell = new Ring<>(this, points);
+        this.shell = new LineStringBuilder(points);
     }
 
     @Override

+ 1 - 1
core/src/main/java/org/elasticsearch/common/geo/builders/ShapeBuilder.java

@@ -444,7 +444,7 @@ public abstract class ShapeBuilder extends ToXContentToBytes {
          *            number of points
          * @return Array of edges
          */
-        protected static Edge[] ring(int component, boolean direction, boolean handedness, BaseLineStringBuilder<?> shell,
+        protected static Edge[] ring(int component, boolean direction, boolean handedness, BaseLineStringBuilder shell,
                                      Coordinate[] points, int offset, Edge[] edges, int toffset, int length) {
             // calculate the direction of the points:
             // find the point a the top of the set and check its

+ 0 - 2
core/src/main/java/org/elasticsearch/index/search/geo/GeoDistanceRangeQuery.java

@@ -29,14 +29,12 @@ import org.apache.lucene.search.Query;
 import org.apache.lucene.search.Scorer;
 import org.apache.lucene.search.TwoPhaseIterator;
 import org.apache.lucene.search.Weight;
-import org.apache.lucene.util.Bits;
 import org.apache.lucene.util.NumericUtils;
 import org.elasticsearch.common.geo.GeoDistance;
 import org.elasticsearch.common.geo.GeoPoint;
 import org.elasticsearch.common.unit.DistanceUnit;
 import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
 import org.elasticsearch.index.fielddata.MultiGeoPointValues;
-import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;
 import org.elasticsearch.index.mapper.geo.GeoPointFieldMapperLegacy;
 
 import java.io.IOException;

+ 35 - 35
core/src/test/java/org/elasticsearch/common/geo/ShapeBuilderTests.java

@@ -29,6 +29,7 @@ import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.LineString;
 import com.vividsolutions.jts.geom.Polygon;
 
+import org.elasticsearch.common.geo.builders.LineStringBuilder;
 import org.elasticsearch.common.geo.builders.PolygonBuilder;
 import org.elasticsearch.common.geo.builders.ShapeBuilder;
 import org.elasticsearch.common.geo.builders.ShapeBuilders;
@@ -141,35 +142,34 @@ public class ShapeBuilderTests extends ESTestCase {
 
     public void testMultiLineString() {
         ShapeBuilders.newMultiLinestring()
-            .linestring()
+            .linestring(new LineStringBuilder()
                 .point(-100.0, 50.0)
                 .point(50.0, 50.0)
                 .point(50.0, 20.0)
                 .point(-100.0, 20.0)
-            .end()
-            .linestring()
+            )
+            .linestring(new LineStringBuilder()
                 .point(-100.0, 20.0)
                 .point(50.0, 20.0)
                 .point(50.0, 0.0)
                 .point(-100.0, 0.0)
-            .end()
+            )
             .build();
 
-
         // LineString that needs to be wrappped
         ShapeBuilders.newMultiLinestring()
-            .linestring()
+            .linestring(new LineStringBuilder()
                 .point(150.0, 60.0)
                 .point(200.0, 60.0)
                 .point(200.0, 40.0)
                 .point(150.0,  40.0)
-                .end()
-            .linestring()
+                )
+            .linestring(new LineStringBuilder()
                 .point(150.0, 20.0)
                 .point(200.0, 20.0)
                 .point(200.0, 0.0)
                 .point(150.0, 0.0)
-                .end()
+                )
             .build();
     }
 
@@ -251,7 +251,7 @@ public class ShapeBuilderTests extends ESTestCase {
             .point(174,0);
 
         // 3/4 of an embedded 'c', crossing dateline once
-        builder.hole()
+        builder.hole(new LineStringBuilder()
             .point(175, 1)
             .point(175, 7)
             .point(-178, 7)
@@ -260,15 +260,15 @@ public class ShapeBuilderTests extends ESTestCase {
             .point(176, 2)
             .point(179, 2)
             .point(179,1)
-            .point(175, 1);
+            .point(175, 1));
 
         // embedded hole right of the dateline
-        builder.hole()
+        builder.hole(new LineStringBuilder()
             .point(-179, 1)
             .point(-179, 2)
             .point(-177, 2)
             .point(-177,1)
-            .point(-179,1);
+            .point(-179,1));
 
         Shape shape = builder.close().build();
         assertMultiPolygon(shape);
@@ -292,7 +292,7 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(-186,0);
 
         // 3/4 of an embedded 'c', crossing dateline once
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(-185,1)
                 .point(-181,1)
                 .point(-181,2)
@@ -301,15 +301,15 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(-178,6)
                 .point(-178,7)
                 .point(-185,7)
-                .point(-185,1);
+                .point(-185,1));
 
         // embedded hole right of the dateline
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(-179,1)
                 .point(-177,1)
                 .point(-177,2)
                 .point(-179,2)
-                .point(-179,1);
+                .point(-179,1));
 
         Shape shape = builder.close().build();
         assertMultiPolygon(shape);
@@ -356,7 +356,7 @@ public class ShapeBuilderTests extends ESTestCase {
             .point(-85.0016455,37.1310491)
             .point(-85.0018514,37.1311314);
 
-        builder.hole()
+        builder.hole(new LineStringBuilder()
             .point(-85.0000002,37.1317672)
             .point(-85.0001983,37.1317538)
             .point(-85.0003378,37.1317582)
@@ -382,7 +382,7 @@ public class ShapeBuilderTests extends ESTestCase {
             .point(-84.9993527,37.1317788)
             .point(-84.9994931,37.1318061)
             .point(-84.9996815,37.1317979)
-            .point(-85.0000002,37.1317672);
+            .point(-85.0000002,37.1317672));
 
         Shape shape = builder.close().build();
         assertPolygon(shape);
@@ -398,12 +398,12 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(-6, 0)
                 .point(-4, 2);
 
-        builder.hole()
+        builder.hole(new LineStringBuilder()
             .point(4, 1)
             .point(4, -1)
             .point(-4, -1)
             .point(-4, 1)
-            .point(4, 1);
+            .point(4, 1));
 
         Shape shape = builder.close().build();
         assertPolygon(shape);
@@ -451,12 +451,12 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(176, -15)
                 .point(-177, -10)
                 .point(-177, 10);
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(176, 10)
                 .point(180, 5)
                 .point(180, -5)
                 .point(176, -10)
-                .point(176, 10);
+                .point(176, 10));
         Shape shape = builder.close().build();
         assertMultiPolygon(shape);
 
@@ -467,12 +467,12 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(179, -10)
                 .point(-176, -15)
                 .point(-172, 0);
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(-176, 10)
                 .point(-176, -10)
                 .point(-180, -5)
                 .point(-180, 5)
-                .point(-176, 10);
+                .point(-176, 10));
         shape = builder.close().build();
         assertMultiPolygon(shape);
     }
@@ -486,12 +486,12 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(166, -15)
                 .point(179, -10)
                 .point(179, 10);
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(-177, 10)
                 .point(-178, -10)
                 .point(-180, -5)
                 .point(-180, 5)
-                .point(-177, 10);
+                .point(-177, 10));
         Shape shape = builder.close().build();
         assertMultiPolygon(shape);
     }
@@ -505,12 +505,12 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(166, -15)
                 .point(179, -10)
                 .point(179, 10);
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(164, 0)
                 .point(175, 10)
                 .point(175, 5)
                 .point(179, -10)
-                .point(164, 0);
+                .point(164, 0));
         try {
             builder.close().build();
             fail("Expected InvalidShapeException");
@@ -528,17 +528,17 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(176, -15)
                 .point(-177, -10)
                 .point(-177, 10);
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(-177, 10)
                 .point(-178, -10)
                 .point(-180, -5)
                 .point(-180, 5)
-                .point(-177, 10);
-        builder.hole()
+                .point(-177, 10));
+        builder.hole(new LineStringBuilder()
                 .point(172, 0)
                 .point(176, 10)
                 .point(176, -5)
-                .point(172, 0);
+                .point(172, 0));
         Shape shape = builder.close().build();
         assertMultiPolygon(shape);
     }
@@ -552,12 +552,12 @@ public class ShapeBuilderTests extends ESTestCase {
                 .point(176, -15)
                 .point(-177, -10)
                 .point(-177, 10);
-        builder.hole()
+        builder.hole(new LineStringBuilder()
                 .point(-177, 10)
                 .point(172, 0)
                 .point(180, -5)
                 .point(176, -10)
-                .point(-177, 10);
+                .point(-177, 10));
         try {
             builder.close().build();
             fail("Expected InvalidShapeException");

+ 40 - 69
core/src/test/java/org/elasticsearch/search/geo/GeoFilterIT.java

@@ -41,7 +41,7 @@ import org.elasticsearch.common.Priority;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.bytes.BytesReference;
 import org.elasticsearch.common.geo.GeoPoint;
-import org.elasticsearch.common.geo.GeoUtils;
+import org.elasticsearch.common.geo.builders.LineStringBuilder;
 import org.elasticsearch.common.geo.builders.MultiPolygonBuilder;
 import org.elasticsearch.common.geo.builders.PolygonBuilder;
 import org.elasticsearch.common.geo.builders.ShapeBuilders;
@@ -129,17 +129,17 @@ public class GeoFilterIT extends ESIntegTestCase {
         // polygon with hole
         ShapeBuilders.newPolygon()
                 .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-                .hole()
+                .hole(new LineStringBuilder()
                 .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-                .close().close().build();
+                .close()).close().build();
 
         try {
             // polygon with overlapping hole
             ShapeBuilders.newPolygon()
                     .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-                    .hole()
+                    .hole(new LineStringBuilder()
                     .point(-5, -5).point(-5, 11).point(5, 11).point(5, -5)
-                    .close().close().build();
+                    .close()).close().build();
 
             fail("Self intersection not detected");
         } catch (InvalidShapeException e) {
@@ -149,12 +149,12 @@ public class GeoFilterIT extends ESIntegTestCase {
             // polygon with intersection holes
             ShapeBuilders.newPolygon()
                     .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-                    .hole()
+                    .hole(new LineStringBuilder()
                     .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-                    .close()
-                    .hole()
+                    .close())
+                    .hole(new LineStringBuilder()
                     .point(-5, -6).point(5, -6).point(5, -4).point(-5, -4)
-                    .close()
+                    .close())
                     .close().build();
             fail("Intersection of holes not detected");
         } catch (InvalidShapeException e) {
@@ -175,52 +175,27 @@ public class GeoFilterIT extends ESIntegTestCase {
         } catch (InvalidShapeException e) {
         }
 
-// Not specified
-//        try {
-//            // two overlapping polygons within a multipolygon
-//            ShapeBuilder.newMultiPolygon()
-//                .polygon()
-//                    .point(-10, -10)
-//                    .point(-10, 10)
-//                    .point(10, 10)
-//                    .point(10, -10)
-//                .close()
-//                .polygon()
-//                    .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-//                .close().build();
-//            fail("Polygon intersection not detected";
-//        } catch (InvalidShapeException e) {}
-
         // Multipolygon: polygon with hole and polygon within the whole
-        ShapeBuilders.newMultiPolygon()
-                .polygon()
-                .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-                .hole()
-                .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-                .close()
-                .close()
-                .polygon()
-                .point(-4, -4).point(-4, 4).point(4, 4).point(4, -4)
-                .close()
+        ShapeBuilders
+                .newMultiPolygon()
+                .polygon(new PolygonBuilder()
+                        .point(-10, -10)
+                        .point(-10, 10)
+                        .point(10, 10)
+                        .point(10, -10)
+                        .hole(new LineStringBuilder().point(-5, -5)
+                               .point(-5, 5)
+                               .point(5, 5)
+                               .point(5, -5)
+                               .close())
+                        .close())
+                .polygon(new PolygonBuilder()
+                        .point(-4, -4)
+                        .point(-4, 4)
+                        .point(4, 4)
+                        .point(4, -4)
+                        .close())
                 .build();
-
-// Not supported
-//        try {
-//            // Multipolygon: polygon with hole and polygon within the hole but overlapping
-//            ShapeBuilder.newMultiPolygon()
-//                .polygon()
-//                    .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-//                    .hole()
-//                        .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-//                    .close()
-//                .close()
-//                .polygon()
-//                    .point(-4, -4).point(-4, 6).point(4, 6).point(4, -4)
-//                .close()
-//                .build();
-//            fail("Polygon intersection not detected";
-//        } catch (InvalidShapeException e) {}
-
     }
 
     public void testShapeRelations() throws Exception {
@@ -248,15 +223,13 @@ public class GeoFilterIT extends ESIntegTestCase {
         // with a hole of size 5x5 equidistant from all sides. This hole in turn contains
         // the second polygon of size 4x4 equidistant from all sites
         MultiPolygonBuilder polygon = ShapeBuilders.newMultiPolygon()
-                .polygon()
-                .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-                .hole()
-                .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-                .close()
-                .close()
-                .polygon()
-                .point(-4, -4).point(-4, 4).point(4, 4).point(4, -4)
-                .close();
+                .polygon(new PolygonBuilder()
+                    .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
+                    .hole(new LineStringBuilder()
+                        .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5).close())
+                .close())
+                .polygon(new PolygonBuilder()
+                    .point(-4, -4).point(-4, 4).point(4, 4).point(4, -4).close());
 
         BytesReference data = jsonBuilder().startObject().field("area", polygon).endObject().bytes();
 
@@ -318,9 +291,8 @@ public class GeoFilterIT extends ESIntegTestCase {
         // Create a polygon that fills the empty area of the polygon defined above
         PolygonBuilder inverse = ShapeBuilders.newPolygon()
                 .point(-5, -5).point(-5, 5).point(5, 5).point(5, -5)
-                .hole()
-                .point(-4, -4).point(-4, 4).point(4, 4).point(4, -4)
-                .close()
+                .hole(new LineStringBuilder()
+                    .point(-4, -4).point(-4, 4).point(4, 4).point(4, -4).close())
                 .close();
 
         data = jsonBuilder().startObject().field("area", inverse).endObject().bytes();
@@ -338,9 +310,8 @@ public class GeoFilterIT extends ESIntegTestCase {
         // Create Polygon with hole and common edge
         PolygonBuilder builder = ShapeBuilders.newPolygon()
                 .point(-10, -10).point(-10, 10).point(10, 10).point(10, -10)
-                .hole()
-                .point(-5, -5).point(-5, 5).point(10, 5).point(10, -5)
-                .close()
+                .hole(new LineStringBuilder()
+                    .point(-5, -5).point(-5, 5).point(10, 5).point(10, -5).close())
                 .close();
 
         if (withinSupport) {
@@ -367,7 +338,7 @@ public class GeoFilterIT extends ESIntegTestCase {
         // Create a polygon crossing longitude 180 with hole.
         builder = ShapeBuilders.newPolygon()
                 .point(170, -10).point(190, -10).point(190, 10).point(170, 10)
-                .hole().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close()
+                    .hole(new LineStringBuilder().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close())
                 .close();
 
         data = jsonBuilder().startObject().field("area", builder).endObject().bytes();

+ 2 - 1
core/src/test/java/org/elasticsearch/search/geo/GeoShapeQueryTests.java

@@ -25,6 +25,7 @@ import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.common.geo.ShapeRelation;
 import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
 import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
+import org.elasticsearch.common.geo.builders.LineStringBuilder;
 import org.elasticsearch.common.geo.builders.ShapeBuilder;
 import org.elasticsearch.common.geo.builders.ShapeBuilders;
 import org.elasticsearch.common.xcontent.XContentBuilder;
@@ -193,7 +194,7 @@ public class GeoShapeQueryTests extends ESSingleNodeTestCase {
     public void testReusableBuilder() throws IOException {
         ShapeBuilder polygon = ShapeBuilders.newPolygon()
                 .point(170, -10).point(190, -10).point(190, 10).point(170, 10)
-                .hole().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close()
+                .hole(new LineStringBuilder().point(175, -5).point(185, -5).point(185, 5).point(175, 5).close())
                 .close();
         assertUnmodified(polygon);
 

+ 1 - 2
core/src/test/java/org/elasticsearch/test/geo/RandomShapeGenerator.java

@@ -31,7 +31,6 @@ import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Geometry;
 
 import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.common.geo.builders.BaseLineStringBuilder;
 import org.elasticsearch.common.geo.builders.GeometryCollectionBuilder;
 import org.elasticsearch.common.geo.builders.LineStringBuilder;
 import org.elasticsearch.common.geo.builders.MultiLineStringBuilder;
@@ -198,7 +197,7 @@ public class RandomShapeGenerator extends RandomGeoGenerator {
             case MULTILINESTRING:
                 MultiLineStringBuilder mlsb = new MultiLineStringBuilder();
                 for (int i=0; i<RandomInts.randomIntBetween(r, 1, 10); ++i) {
-                    mlsb.linestring((BaseLineStringBuilder) createShape(r, nearPoint, within, ShapeType.LINESTRING, false));
+                    mlsb.linestring((LineStringBuilder) createShape(r, nearPoint, within, ShapeType.LINESTRING, false));
                 }
                 return mlsb;
             case POLYGON: