Skip to content

Commit f9943a3

Browse files
committed
Geo: deprecate ShapeBuilder in QueryBuilders (#44715)
Removes unnecessary now timeline decompositions from shape builders and deprecates ShapeBuilders in QueryBuilder in favor of libs/geo shapes. Relates to #40908
1 parent b3d8b39 commit f9943a3

File tree

13 files changed

+655
-184
lines changed

13 files changed

+655
-184
lines changed

server/src/main/java/org/elasticsearch/common/geo/GeoJson.java

+9-9
Original file line numberDiff line numberDiff line change
@@ -382,17 +382,17 @@ public static String getGeoJsonName(Geometry geometry) {
382382
return geometry.visit(new GeometryVisitor<String, RuntimeException>() {
383383
@Override
384384
public String visit(Circle circle) {
385-
return "Circle";
385+
return "circle";
386386
}
387387

388388
@Override
389389
public String visit(GeometryCollection<?> collection) {
390-
return "GeometryCollection";
390+
return "geometrycollection";
391391
}
392392

393393
@Override
394394
public String visit(Line line) {
395-
return "LineString";
395+
return "linestring";
396396
}
397397

398398
@Override
@@ -402,32 +402,32 @@ public String visit(LinearRing ring) {
402402

403403
@Override
404404
public String visit(MultiLine multiLine) {
405-
return "MultiLineString";
405+
return "multilinestring";
406406
}
407407

408408
@Override
409409
public String visit(MultiPoint multiPoint) {
410-
return "MultiPoint";
410+
return "multipoint";
411411
}
412412

413413
@Override
414414
public String visit(MultiPolygon multiPolygon) {
415-
return "MultiPolygon";
415+
return "multipolygon";
416416
}
417417

418418
@Override
419419
public String visit(Point point) {
420-
return "Point";
420+
return "point";
421421
}
422422

423423
@Override
424424
public String visit(Polygon polygon) {
425-
return "Polygon";
425+
return "polygon";
426426
}
427427

428428
@Override
429429
public String visit(Rectangle rectangle) {
430-
return "Envelope";
430+
return "envelope";
431431
}
432432
});
433433
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.common.geo;
21+
22+
import org.elasticsearch.common.io.stream.StreamInput;
23+
import org.elasticsearch.common.io.stream.StreamOutput;
24+
import org.elasticsearch.geo.geometry.Circle;
25+
import org.elasticsearch.geo.geometry.Geometry;
26+
import org.elasticsearch.geo.geometry.GeometryCollection;
27+
import org.elasticsearch.geo.geometry.GeometryVisitor;
28+
import org.elasticsearch.geo.geometry.Line;
29+
import org.elasticsearch.geo.geometry.LinearRing;
30+
import org.elasticsearch.geo.geometry.MultiLine;
31+
import org.elasticsearch.geo.geometry.MultiPoint;
32+
import org.elasticsearch.geo.geometry.MultiPolygon;
33+
import org.elasticsearch.geo.geometry.Point;
34+
import org.elasticsearch.geo.geometry.Polygon;
35+
import org.elasticsearch.geo.geometry.Rectangle;
36+
37+
import java.io.IOException;
38+
import java.util.ArrayList;
39+
import java.util.List;
40+
import java.util.Locale;
41+
42+
/**
43+
* Utility class for binary serializtion/deserialization of libs/geo classes
44+
*/
45+
public final class GeometryIO {
46+
47+
public static void writeGeometry(StreamOutput out, Geometry geometry) throws IOException {
48+
out.writeString(GeoJson.getGeoJsonName(geometry).toLowerCase(Locale.ROOT));
49+
geometry.visit(new GeometryVisitor<Void, IOException>() {
50+
@Override
51+
public Void visit(Circle circle) throws IOException {
52+
throw new UnsupportedOperationException("circle is not supported");
53+
}
54+
55+
@Override
56+
public Void visit(GeometryCollection<?> collection) throws IOException {
57+
out.writeVInt(collection.size());
58+
for (Geometry shape : collection) {
59+
writeGeometry(out, shape);
60+
}
61+
return null;
62+
}
63+
64+
@Override
65+
public Void visit(Line line) throws IOException {
66+
writeCoordinates(line);
67+
return null;
68+
}
69+
70+
@Override
71+
public Void visit(LinearRing ring) {
72+
throw new UnsupportedOperationException("linear ring is not supported");
73+
}
74+
75+
@Override
76+
public Void visit(MultiLine multiLine) throws IOException {
77+
out.writeVInt(multiLine.size());
78+
for (Line line : multiLine) {
79+
visit(line);
80+
}
81+
return null;
82+
}
83+
84+
@Override
85+
public Void visit(MultiPoint multiPoint) throws IOException {
86+
out.writeVInt(multiPoint.size());
87+
for (int i = 0; i < multiPoint.size(); i++) {
88+
Point point = multiPoint.get(i);
89+
writeCoordinate(point.getLat(), point.getLon(), point.getAlt());
90+
}
91+
return null;
92+
}
93+
94+
@Override
95+
public Void visit(MultiPolygon multiPolygon) throws IOException {
96+
out.writeBoolean(true); // Orientation for BWC with ShapeBuilder
97+
out.writeVInt(multiPolygon.size());
98+
for (int i = 0; i < multiPolygon.size(); i++) {
99+
visit(multiPolygon.get(i));
100+
}
101+
return null;
102+
}
103+
104+
@Override
105+
public Void visit(Point point) throws IOException {
106+
out.writeVInt(1); // Number of points For BWC with Shape Builder
107+
writeCoordinate(point.getLat(), point.getLon(), point.getAlt());
108+
return null;
109+
}
110+
111+
@Override
112+
public Void visit(Polygon polygon) throws IOException {
113+
writeCoordinates(polygon.getPolygon());
114+
out.writeBoolean(true); // Orientation for BWC with ShapeBuilder
115+
out.writeVInt(polygon.getNumberOfHoles());
116+
for (int i = 0; i < polygon.getNumberOfHoles(); i++) {
117+
writeCoordinates(polygon.getHole(i));
118+
}
119+
return null;
120+
}
121+
122+
@Override
123+
public Void visit(Rectangle rectangle) throws IOException {
124+
writeCoordinate(rectangle.getMaxLat(), rectangle.getMinLon(), rectangle.getMinAlt()); // top left
125+
writeCoordinate(rectangle.getMinLat(), rectangle.getMaxLon(), rectangle.getMaxAlt()); // bottom right
126+
return null;
127+
}
128+
129+
private void writeCoordinate(double lat, double lon, double alt) throws IOException {
130+
out.writeDouble(lon);
131+
out.writeDouble(lat);
132+
out.writeOptionalDouble(Double.isNaN(alt) ? null : alt);
133+
}
134+
135+
private void writeCoordinates(Line line) throws IOException {
136+
out.writeVInt(line.length());
137+
for (int i = 0; i < line.length(); i++) {
138+
writeCoordinate(line.getLat(i), line.getLon(i), line.getAlt(i));
139+
}
140+
}
141+
142+
});
143+
}
144+
145+
public static Geometry readGeometry(StreamInput in) throws IOException {
146+
String type = in.readString();
147+
switch (type) {
148+
case "geometrycollection":
149+
return readGeometryCollection(in);
150+
case "polygon":
151+
return readPolygon(in);
152+
case "point":
153+
return readPoint(in);
154+
case "linestring":
155+
return readLine(in);
156+
case "multilinestring":
157+
return readMultiLine(in);
158+
case "multipoint":
159+
return readMultiPoint(in);
160+
case "multipolygon":
161+
return readMultiPolygon(in);
162+
case "envelope":
163+
return readRectangle(in);
164+
default:
165+
throw new UnsupportedOperationException("unsupported shape type " + type);
166+
}
167+
}
168+
169+
private static GeometryCollection<Geometry> readGeometryCollection(StreamInput in) throws IOException {
170+
int size = in.readVInt();
171+
List<Geometry> shapes = new ArrayList<>(size);
172+
for (int i = 0; i < size; i++) {
173+
shapes.add(readGeometry(in));
174+
}
175+
return new GeometryCollection<>(shapes);
176+
}
177+
178+
private static Polygon readPolygon(StreamInput in) throws IOException {
179+
double[][] shellComponents = readLineComponents(in);
180+
boolean orientation = in.readBoolean();
181+
LinearRing shell = buildLinearRing(shellComponents, orientation);
182+
int numberOfHoles = in.readVInt();
183+
if (numberOfHoles > 0) {
184+
List<LinearRing> holes = new ArrayList<>(numberOfHoles);
185+
for (int i = 0; i < numberOfHoles; i++) {
186+
holes.add(buildLinearRing(readLineComponents(in), orientation));
187+
}
188+
return new Polygon(shell, holes);
189+
} else {
190+
return new Polygon(shell);
191+
}
192+
}
193+
194+
private static double[][] readLineComponents(StreamInput in) throws IOException {
195+
int len = in.readVInt();
196+
double[] lat = new double[len];
197+
double[] lon = new double[len];
198+
double[] alt = new double[len];
199+
for (int i = 0; i < len; i++) {
200+
lon[i] = in.readDouble();
201+
lat[i] = in.readDouble();
202+
alt[i] = readAlt(in);
203+
}
204+
if (Double.isNaN(alt[0])) {
205+
return new double[][]{lat, lon};
206+
} else {
207+
return new double[][]{lat, lon, alt};
208+
}
209+
}
210+
211+
private static void reverse(double[][] arr) {
212+
for (double[] carr : arr) {
213+
int len = carr.length;
214+
for (int j = 0; j < len / 2; j++) {
215+
double temp = carr[j];
216+
carr[j] = carr[len - j - 1];
217+
carr[len - j - 1] = temp;
218+
}
219+
}
220+
}
221+
222+
private static LinearRing buildLinearRing(double[][] arr, boolean orientation) {
223+
if (orientation == false) {
224+
reverse(arr);
225+
}
226+
if (arr.length == 3) {
227+
return new LinearRing(arr[0], arr[1], arr[2]);
228+
} else {
229+
return new LinearRing(arr[0], arr[1]);
230+
}
231+
}
232+
233+
private static Point readPoint(StreamInput in) throws IOException {
234+
int size = in.readVInt(); // For BWC with Shape Builder
235+
if (size != 1) {
236+
throw new IOException("Unexpected point count " + size);
237+
}
238+
double lon = in.readDouble();
239+
double lat = in.readDouble();
240+
double alt = readAlt(in);
241+
return new Point(lat, lon, alt);
242+
}
243+
244+
private static Line readLine(StreamInput in) throws IOException {
245+
double[][] coords = readLineComponents(in);
246+
if (coords.length == 3) {
247+
return new Line(coords[0], coords[1], coords[2]);
248+
} else {
249+
return new Line(coords[0], coords[1]);
250+
}
251+
}
252+
253+
private static MultiLine readMultiLine(StreamInput in) throws IOException {
254+
int size = in.readVInt();
255+
List<Line> lines = new ArrayList<>(size);
256+
for (int i = 0; i < size; i++) {
257+
lines.add(readLine(in));
258+
}
259+
return new MultiLine(lines);
260+
}
261+
262+
private static MultiPoint readMultiPoint(StreamInput in) throws IOException {
263+
int size = in.readVInt();
264+
List<Point> points = new ArrayList<>(size);
265+
for (int i = 0; i < size; i++) {
266+
double lon = in.readDouble();
267+
double lat = in.readDouble();
268+
double alt = readAlt(in);
269+
points.add(new Point(lat, lon, alt));
270+
}
271+
return new MultiPoint(points);
272+
}
273+
274+
275+
private static MultiPolygon readMultiPolygon(StreamInput in) throws IOException {
276+
in.readBoolean(); // orientation for BWC
277+
int size = in.readVInt();
278+
List<Polygon> polygons = new ArrayList<>(size);
279+
for (int i = 0; i < size; i++) {
280+
polygons.add(readPolygon(in));
281+
}
282+
return new MultiPolygon(polygons);
283+
}
284+
285+
private static Rectangle readRectangle(StreamInput in) throws IOException {
286+
// top left
287+
double minLon = in.readDouble();
288+
double maxLat = in.readDouble();
289+
double minAlt = readAlt(in);
290+
291+
// bottom right
292+
double maxLon = in.readDouble();
293+
double minLat = in.readDouble();
294+
double maxAlt = readAlt(in);
295+
296+
return new Rectangle(minLat, maxLat, minLon, maxLon, minAlt, maxAlt);
297+
}
298+
299+
private static double readAlt(StreamInput in) throws IOException {
300+
Double alt = in.readOptionalDouble();
301+
if (alt == null) {
302+
return Double.NaN;
303+
} else {
304+
return alt;
305+
}
306+
}
307+
}

server/src/main/java/org/elasticsearch/common/geo/GeometryIndexer.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ private List<Line> decompose(double dateline, double[] lons, double[] lats) {
245245

246246
for (int i = 1; i < lons.length; i++) {
247247
double t = intersection(lastLon, lons[i], dateline);
248+
lastLon = lons[i];
248249
if (Double.isNaN(t) == false) {
249250
double[] partLons = Arrays.copyOfRange(lons, offset, i + 1);
250251
double[] partLats = Arrays.copyOfRange(lats, offset, i + 1);
@@ -330,7 +331,7 @@ private void validateHole(LinearRing shell, LinearRing hole) {
330331
exterior.add(new Point(shell.getLat(i), shell.getLon(i)));
331332
}
332333
for (int i = 0; i < hole.length(); i++) {
333-
interior.remove(new Point(hole.getLat(i), hole.getLon(i)));
334+
interior.add(new Point(hole.getLat(i), hole.getLon(i)));
334335
}
335336
exterior.retainAll(interior);
336337
if (exterior.size() >= 2) {
@@ -645,7 +646,7 @@ private static Edge[] concat(int component, boolean direction, Point[] points, f
645646
edges[edgeOffset + i - 1].next = edges[edgeOffset + i] = new Edge(nextPoint, null);
646647
edges[edgeOffset + i - 1].component = component;
647648
} else {
648-
throw new InvalidShapeException("Provided shape has duplicate consecutive coordinates at: " + nextPoint);
649+
throw new InvalidShapeException("Provided shape has duplicate consecutive coordinates at: (" + nextPoint + ")");
649650
}
650651
}
651652

0 commit comments

Comments
 (0)