forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Geo: deprecate ShapeBuilder in QueryBuilders
Removes unnecessary now timeline decompositions from shape builders and deprecates ShapeBuilders in QueryBuilder in favor of libs/geo shapes. Relates to elastic#40908
- Loading branch information
Showing
13 changed files
with
656 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
307 changes: 307 additions & 0 deletions
307
server/src/main/java/org/elasticsearch/common/geo/GeometryIO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,307 @@ | ||
/* | ||
* Licensed to Elasticsearch under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch 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.elasticsearch.common.geo; | ||
|
||
import org.elasticsearch.common.io.stream.StreamInput; | ||
import org.elasticsearch.common.io.stream.StreamOutput; | ||
import org.elasticsearch.geo.geometry.Circle; | ||
import org.elasticsearch.geo.geometry.Geometry; | ||
import org.elasticsearch.geo.geometry.GeometryCollection; | ||
import org.elasticsearch.geo.geometry.GeometryVisitor; | ||
import org.elasticsearch.geo.geometry.Line; | ||
import org.elasticsearch.geo.geometry.LinearRing; | ||
import org.elasticsearch.geo.geometry.MultiLine; | ||
import org.elasticsearch.geo.geometry.MultiPoint; | ||
import org.elasticsearch.geo.geometry.MultiPolygon; | ||
import org.elasticsearch.geo.geometry.Point; | ||
import org.elasticsearch.geo.geometry.Polygon; | ||
import org.elasticsearch.geo.geometry.Rectangle; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Locale; | ||
|
||
/** | ||
* Utility class for binary serializtion/deserialization of libs/geo classes | ||
*/ | ||
public final class GeometryIO { | ||
|
||
public static void writeGeometry(StreamOutput out, Geometry geometry) throws IOException { | ||
out.writeString(GeoJson.getGeoJsonName(geometry).toLowerCase(Locale.ROOT)); | ||
geometry.visit(new GeometryVisitor<Void, IOException>() { | ||
@Override | ||
public Void visit(Circle circle) throws IOException { | ||
throw new UnsupportedOperationException("circle is not supported"); | ||
} | ||
|
||
@Override | ||
public Void visit(GeometryCollection<?> collection) throws IOException { | ||
out.writeVInt(collection.size()); | ||
for (Geometry shape : collection) { | ||
writeGeometry(out, shape); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(Line line) throws IOException { | ||
writeCoordinates(line); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(LinearRing ring) { | ||
throw new UnsupportedOperationException("linear ring is not supported"); | ||
} | ||
|
||
@Override | ||
public Void visit(MultiLine multiLine) throws IOException { | ||
out.writeVInt(multiLine.size()); | ||
for (Line line : multiLine) { | ||
visit(line); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(MultiPoint multiPoint) throws IOException { | ||
out.writeVInt(multiPoint.size()); | ||
for (int i = 0; i < multiPoint.size(); i++) { | ||
Point point = multiPoint.get(i); | ||
writeCoordinate(point.getLat(), point.getLon(), point.getAlt()); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(MultiPolygon multiPolygon) throws IOException { | ||
out.writeBoolean(true); // Orientation for BWC with ShapeBuilder | ||
out.writeVInt(multiPolygon.size()); | ||
for (int i = 0; i < multiPolygon.size(); i++) { | ||
visit(multiPolygon.get(i)); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(Point point) throws IOException { | ||
out.writeVInt(1); // Number of points For BWC with Shape Builder | ||
writeCoordinate(point.getLat(), point.getLon(), point.getAlt()); | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(Polygon polygon) throws IOException { | ||
writeCoordinates(polygon.getPolygon()); | ||
out.writeBoolean(true); // Orientation for BWC with ShapeBuilder | ||
out.writeVInt(polygon.getNumberOfHoles()); | ||
for (int i = 0; i < polygon.getNumberOfHoles(); i++) { | ||
writeCoordinates(polygon.getHole(i)); | ||
} | ||
return null; | ||
} | ||
|
||
@Override | ||
public Void visit(Rectangle rectangle) throws IOException { | ||
writeCoordinate(rectangle.getMaxLat(), rectangle.getMinLon(), rectangle.getMinAlt()); // top left | ||
writeCoordinate(rectangle.getMinLat(), rectangle.getMaxLon(), rectangle.getMaxAlt()); // bottom right | ||
return null; | ||
} | ||
|
||
private void writeCoordinate(double lat, double lon, double alt) throws IOException { | ||
out.writeDouble(lon); | ||
out.writeDouble(lat); | ||
out.writeOptionalDouble(Double.isNaN(alt) ? null : alt); | ||
} | ||
|
||
private void writeCoordinates(Line line) throws IOException { | ||
out.writeVInt(line.length()); | ||
for (int i = 0; i < line.length(); i++) { | ||
writeCoordinate(line.getLat(i), line.getLon(i), line.getAlt(i)); | ||
} | ||
} | ||
|
||
}); | ||
} | ||
|
||
public static Geometry readGeometry(StreamInput in) throws IOException { | ||
String type = in.readString(); | ||
switch (type) { | ||
case "geometrycollection": | ||
return readGeometryCollection(in); | ||
case "polygon": | ||
return readPolygon(in); | ||
case "point": | ||
return readPoint(in); | ||
case "linestring": | ||
return readLine(in); | ||
case "multilinestring": | ||
return readMultiLine(in); | ||
case "multipoint": | ||
return readMultiPoint(in); | ||
case "multipolygon": | ||
return readMultiPolygon(in); | ||
case "envelope": | ||
return readRectangle(in); | ||
default: | ||
throw new UnsupportedOperationException("unsupported shape type " + type); | ||
} | ||
} | ||
|
||
private static GeometryCollection<Geometry> readGeometryCollection(StreamInput in) throws IOException { | ||
int size = in.readVInt(); | ||
List<Geometry> shapes = new ArrayList<>(size); | ||
for (int i = 0; i < size; i++) { | ||
shapes.add(readGeometry(in)); | ||
} | ||
return new GeometryCollection<>(shapes); | ||
} | ||
|
||
private static Polygon readPolygon(StreamInput in) throws IOException { | ||
double[][] shellComponents = readLineComponents(in); | ||
boolean orientation = in.readBoolean(); | ||
LinearRing shell = buildLinearRing(shellComponents, orientation); | ||
int numberOfHoles = in.readVInt(); | ||
if (numberOfHoles > 0) { | ||
List<LinearRing> holes = new ArrayList<>(numberOfHoles); | ||
for (int i = 0; i < numberOfHoles; i++) { | ||
holes.add(buildLinearRing(readLineComponents(in), orientation)); | ||
} | ||
return new Polygon(shell, holes); | ||
} else { | ||
return new Polygon(shell); | ||
} | ||
} | ||
|
||
private static double[][] readLineComponents(StreamInput in) throws IOException { | ||
int len = in.readVInt(); | ||
double[] lat = new double[len]; | ||
double[] lon = new double[len]; | ||
double[] alt = new double[len]; | ||
for (int i = 0; i < len; i++) { | ||
lon[i] = in.readDouble(); | ||
lat[i] = in.readDouble(); | ||
alt[i] = readAlt(in); | ||
} | ||
if (Double.isNaN(alt[0])) { | ||
return new double[][]{lat, lon}; | ||
} else { | ||
return new double[][]{lat, lon, alt}; | ||
} | ||
} | ||
|
||
private static void reverse(double[][] arr) { | ||
for (double[] carr : arr) { | ||
int len = carr.length; | ||
for (int j = 0; j < len / 2; j++) { | ||
double temp = carr[j]; | ||
carr[j] = carr[len - j - 1]; | ||
carr[len - j - 1] = temp; | ||
} | ||
} | ||
} | ||
|
||
private static LinearRing buildLinearRing(double[][] arr, boolean orientation) { | ||
if (orientation == false) { | ||
reverse(arr); | ||
} | ||
if (arr.length == 3) { | ||
return new LinearRing(arr[0], arr[1], arr[2]); | ||
} else { | ||
return new LinearRing(arr[0], arr[1]); | ||
} | ||
} | ||
|
||
private static Point readPoint(StreamInput in) throws IOException { | ||
int size = in.readVInt(); // For BWC with Shape Builder | ||
if (size != 1) { | ||
throw new IOException("Unexpected point count " + size); | ||
} | ||
double lon = in.readDouble(); | ||
double lat = in.readDouble(); | ||
double alt = readAlt(in); | ||
return new Point(lat, lon, alt); | ||
} | ||
|
||
private static Line readLine(StreamInput in) throws IOException { | ||
double[][] coords = readLineComponents(in); | ||
if (coords.length == 3) { | ||
return new Line(coords[0], coords[1], coords[2]); | ||
} else { | ||
return new Line(coords[0], coords[1]); | ||
} | ||
} | ||
|
||
private static MultiLine readMultiLine(StreamInput in) throws IOException { | ||
int size = in.readVInt(); | ||
List<Line> lines = new ArrayList<>(size); | ||
for (int i = 0; i < size; i++) { | ||
lines.add(readLine(in)); | ||
} | ||
return new MultiLine(lines); | ||
} | ||
|
||
private static MultiPoint readMultiPoint(StreamInput in) throws IOException { | ||
int size = in.readVInt(); | ||
List<Point> points = new ArrayList<>(size); | ||
for (int i = 0; i < size; i++) { | ||
double lon = in.readDouble(); | ||
double lat = in.readDouble(); | ||
double alt = readAlt(in); | ||
points.add(new Point(lat, lon, alt)); | ||
} | ||
return new MultiPoint(points); | ||
} | ||
|
||
|
||
private static MultiPolygon readMultiPolygon(StreamInput in) throws IOException { | ||
in.readBoolean(); // orientation for BWC | ||
int size = in.readVInt(); | ||
List<Polygon> polygons = new ArrayList<>(size); | ||
for (int i = 0; i < size; i++) { | ||
polygons.add(readPolygon(in)); | ||
} | ||
return new MultiPolygon(polygons); | ||
} | ||
|
||
private static Rectangle readRectangle(StreamInput in) throws IOException { | ||
// top left | ||
double minLon = in.readDouble(); | ||
double maxLat = in.readDouble(); | ||
double minAlt = readAlt(in); | ||
|
||
// bottom right | ||
double maxLon = in.readDouble(); | ||
double minLat = in.readDouble(); | ||
double maxAlt = readAlt(in); | ||
|
||
return new Rectangle(minLat, maxLat, minLon, maxLon, minAlt, maxAlt); | ||
} | ||
|
||
private static double readAlt(StreamInput in) throws IOException { | ||
Double alt = in.readOptionalDouble(); | ||
if (alt == null) { | ||
return Double.NaN; | ||
} else { | ||
return alt; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.