/** * Add a shallow copy of the polygon to the multipolygon. This will apply the orientation of the * {@link MultiPolygonBuilder} to the polygon if polygon has different orientation. */ public MultiPolygonBuilder polygon(PolygonBuilder polygon) { PolygonBuilder pb = new PolygonBuilder(new CoordinatesBuilder().coordinates(polygon.shell().coordinates(false)), this.orientation); for (LineStringBuilder hole : polygon.holes()) { pb.hole(hole); } this.polygons.add(pb); return this; }
private static Coordinate[][][] compose(Edge[] edges, Edge[] holes, int numHoles) { final List<List<Coordinate[]>> components = new ArrayList<>(); assign(holes, holes(holes, numHoles), numHoles, edges(edges, numHoles, components), components); return buildCoordinates(components); }
private static Coordinate[][] holes(Edge[] holes, int numHoles) { if (numHoles == 0) { return EMPTY; } final Coordinate[][] points = new Coordinate[numHoles][]; for (int i = 0; i < numHoles; i++) { int length = component(holes[i], -(i+1), null); // mark as visited by inverting the sign points[i] = coordinates(holes[i], new Coordinate[length+1]); } return points; }
public Geometry buildS4JGeometry(GeometryFactory factory, boolean fixDateline) { if(fixDateline) { Coordinate[][][] polygons = coordinates(); return polygons.length == 1 ? polygonS4J(factory, polygons[0]) : multipolygonS4J(factory, polygons); } else { return toPolygonS4J(factory); } }
@Override public Object buildLucene() { if (wrapdateline) { Coordinate[][][] polygons = coordinates(); return polygons.length == 1 ? polygonLucene(polygons[0]) : multipolygonLucene(polygons); } return toPolygonLucene(); }
/** * The coordinates setup by the builder will be assembled to a polygon. The result will consist of * a set of polygons. Each of these components holds a list of linestrings defining the polygon: the * first set of coordinates will be used as the shell of the polygon. The others are defined to holes * 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.coordinates.size()-1; // Last point is repeated for (int i = 0; i < holes.size(); i++) { numEdges += holes.get(i).coordinates.size()-1; validateHole(shell, this.holes.get(i)); } Edge[] edges = new Edge[numEdges]; Edge[] holeComponents = new Edge[holes.size()]; final AtomicBoolean translated = new AtomicBoolean(false); int offset = createEdges(0, orientation, shell, null, edges, 0, translated); for (int i = 0; i < holes.size(); i++) { int length = createEdges(i+1, orientation, shell, this.holes.get(i), edges, offset, translated); holeComponents[i] = edges[offset]; offset += length; } int numHoles = holeComponents.length; numHoles = merge(edges, 0, intersections(+DATELINE, edges), holeComponents, numHoles); numHoles = merge(edges, 0, intersections(-DATELINE, edges), holeComponents, numHoles); return compose(edges, holeComponents, numHoles); }
@Override public ShapeBuilder getBuilder(CoordinateNode coordinates, DistanceUnit.Distance radius, Orientation orientation, boolean coerce) { validate(coordinates, coerce); // build shell LineStringBuilder shell = LineStringBuilder.class.cast(LINESTRING.getBuilder(coordinates.children.get(0), radius, orientation, coerce)); // build polygon with shell and holes PolygonBuilder polygon = new PolygonBuilder(shell, orientation); for (int i = 1; i < coordinates.children.size(); ++i) { CoordinateNode child = coordinates.children.get(i); LineStringBuilder hole = LineStringBuilder.class.cast(LINESTRING.getBuilder(child, radius, orientation, coerce)); polygon.hole(hole); } return polygon; }
public Geometry buildGeometry(GeometryFactory factory, boolean fixDateline) { if(fixDateline) { Coordinate[][][] polygons = coordinates(); return polygons.length == 1 ? polygon(factory, polygons[0]) : multipolygon(factory, polygons); } else { return toPolygon(factory); } }
final int top = top(points, offset, length); final int prev = (offset + ((top + length - 1) % length)); final int next = (offset + ((top + 1) % length)); double[] range = range(points, offset, length); final double rng = range[1] - range[0]; translate(points); return concat(component, direction ^ orientation, points, offset, edges, toffset, length);
/** * Add a new hole to the polygon * @param hole linear ring defining the hole * @return this */ public PolygonBuilder hole(LineStringBuilder hole) { return this.hole(hole, false); }
Coordinate[] points, int offset, Edge[] edges, int toffset, int length, final AtomicBoolean translated) { boolean orientation = getOrientation(points, offset, length); double[] range = range(points, offset, length); final double rng = range[1] - range[0]; translate(points); return concat(component, direction ^ orientation, points, offset, edges, toffset, length);
/** * Create a new PolygonBuilder * @return a new {@link PolygonBuilder} */ public static PolygonBuilder newPolygon(CoordinatesBuilder shell) { return new PolygonBuilder(shell); }
@Override public Shape build() { List<Shape> shapes = new ArrayList<>(this.polygons.size()); if(wrapdateline) { for (PolygonBuilder polygon : this.polygons) { for(Coordinate[][] part : polygon.coordinates()) { shapes.add(jtsGeometry(PolygonBuilder.polygon(FACTORY, part))); } } } else { for (PolygonBuilder polygon : this.polygons) { shapes.add(jtsGeometry(polygon.toPolygon(FACTORY))); } } if (shapes.size() == 1) return shapes.get(0); else return new XShapeCollection<>(shapes, SPATIAL_CONTEXT); //note: ShapeCollection is probably faster than a Multi* geom. }
@Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); builder.field(ShapeParser.FIELD_TYPE.getPreferredName(), TYPE.shapeName()); builder.field(ShapeParser.FIELD_ORIENTATION.getPreferredName(), orientation.name().toLowerCase(Locale.ROOT)); builder.startArray(ShapeParser.FIELD_COORDINATES.getPreferredName()); coordinatesArray(builder, params); builder.endArray(); builder.endObject(); return builder; }
&& !(e1.next.next.coordinate.equals3D(e2.coordinate) && Math.abs(e1.next.coordinate.x) == DATELINE && Math.abs(e2.coordinate.x) == DATELINE) ) { connect(e1, e2);
@Override public Shape buildS4J() { List<Shape> shapes = new ArrayList<>(this.polygons.size()); if(wrapdateline) { for (PolygonBuilder polygon : this.polygons) { for(Coordinate[][] part : polygon.coordinates()) { shapes.add(jtsGeometry(PolygonBuilder.polygonS4J(FACTORY, part))); } } } else { for (PolygonBuilder polygon : this.polygons) { shapes.add(jtsGeometry(polygon.toPolygonS4J(FACTORY))); } } if (shapes.size() == 1) return shapes.get(0); else return new XShapeCollection<>(shapes, SPATIAL_CONTEXT); //note: ShapeCollection is probably faster than a Multi* geom. }
/** * The coordinates setup by the builder will be assembled to a polygon. The result will consist of * a set of polygons. Each of these components holds a list of linestrings defining the polygon: the * first set of coordinates will be used as the shell of the polygon. The others are defined to holes * 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.coordinates.size()-1; // Last point is repeated for (int i = 0; i < holes.size(); i++) { numEdges += holes.get(i).coordinates.size()-1; validateHole(shell, this.holes.get(i)); } Edge[] edges = new Edge[numEdges]; Edge[] holeComponents = new Edge[holes.size()]; final AtomicBoolean translated = new AtomicBoolean(false); int offset = createEdges(0, orientation, shell, null, edges, 0, translated); for (int i = 0; i < holes.size(); i++) { int length = createEdges(i+1, orientation, shell, this.holes.get(i), edges, offset, translated); holeComponents[i] = edges[offset]; offset += length; } int numHoles = holeComponents.length; numHoles = merge(edges, 0, intersections(+DATELINE, edges), holeComponents, numHoles); numHoles = merge(edges, 0, intersections(-DATELINE, edges), holeComponents, numHoles); return compose(edges, holeComponents, numHoles); }
private static PolygonBuilder parsePolygon(StreamTokenizer stream, final boolean ignoreZValue, final boolean coerce) throws IOException, ElasticsearchParseException { if (nextEmptyOrOpen(stream).equals(EMPTY)) { return null; } PolygonBuilder builder = new PolygonBuilder(parseLinearRing(stream, ignoreZValue, coerce), BaseGeoShapeFieldMapper.Defaults.ORIENTATION.value()); while (nextCloserOrComma(stream).equals(COMMA)) { builder.hole(parseLinearRing(stream, ignoreZValue, coerce)); } return builder; }
public Geometry buildGeometry(GeometryFactory factory, boolean fixDateline) { if(fixDateline) { Coordinate[][][] polygons = coordinates(); return polygons.length == 1 ? polygon(factory, polygons[0]) : multipolygon(factory, polygons); } else { return toPolygon(factory); } }
final int top = top(points, offset, length); final int prev = (offset + ((top + length - 1) % length)); final int next = (offset + ((top + 1) % length)); double[] range = range(points, offset, length); final double rng = range[1] - range[0]; translate(points); return concat(component, direction ^ orientation, points, offset, edges, toffset, length);