-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add support for geo_shape represented as Well-Known Text (WKT) #3377
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
05d591f
Add support for well known text (wkt) to geo bounding box queries
codebrain 71fb661
Move geo_shape queries into Tests project
russcam 006c8f7
Add support for Z values to GeoCoordinate
russcam c811c5d
Add support for WKT geo shapes
russcam 73e6e40
Use fixed index names in geo WKT tests
russcam 4127789
Update comment following PR review
russcam f70ba3d
Additional unit tests for reading and writing WKT
russcam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -24,8 +24,32 @@ public interface IGeoShape | |
| bool? IgnoreUnmapped { get; set; } | ||
| } | ||
|
|
||
| internal enum GeoShapeFormat | ||
| { | ||
| GeoJson, | ||
| WellKnownText | ||
| } | ||
|
|
||
| internal static class GeoShapeType | ||
| { | ||
| public const string Point = "POINT"; | ||
| public const string MultiPoint = "MULTIPOINT"; | ||
| public const string LineString = "LINESTRING"; | ||
| public const string MultiLineString = "MULTILINESTRING"; | ||
| public const string Polygon = "POLYGON"; | ||
| public const string MultiPolygon = "MULTIPOLYGON"; | ||
| public const string Circle = "CIRCLE"; | ||
| public const string Envelope = "ENVELOPE"; | ||
| public const string GeometryCollection = "GEOMETRYCOLLECTION"; | ||
|
|
||
| // WKT uses BBOX for envelope geo shape | ||
| internal const string BoundingBox = "BBOX"; | ||
| } | ||
|
|
||
| public abstract class GeoShapeBase : IGeoShape | ||
| { | ||
| internal GeoShapeFormat Format { get; set; } | ||
|
|
||
| protected GeoShapeBase(string type) => this.Type = type; | ||
|
|
||
| /// <inheritdoc /> | ||
|
|
@@ -38,52 +62,121 @@ public abstract class GeoShapeBase : IGeoShape | |
|
|
||
| internal class GeoShapeConverter : JsonConverter | ||
| { | ||
| public override bool CanWrite => false; | ||
| public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) | ||
| { | ||
| if (value == null) | ||
| { | ||
| writer.WriteNull(); | ||
| return; | ||
| } | ||
|
|
||
| public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => | ||
| throw new NotSupportedException(); | ||
| // IGeometryCollection needs to be handled separately because it does not | ||
| // implement IGeoShape, and can't because it would be a binary breaking change. | ||
| // This is fixed in next major release. | ||
| if (value is IGeometryCollection collection) | ||
| { | ||
| if (collection is GeometryCollection geometryCollection && geometryCollection.Format == GeoShapeFormat.WellKnownText) | ||
| { | ||
| writer.WriteValue(GeoWKTWriter.Write(collection)); | ||
| return; | ||
| } | ||
|
|
||
| writer.WriteStartObject(); | ||
| writer.WritePropertyName("type"); | ||
| writer.WriteValue(collection.Type); | ||
| writer.WritePropertyName("geometries"); | ||
| serializer.Serialize(writer, collection.Geometries); | ||
| writer.WriteEndObject(); | ||
| } | ||
| else if (value is IGeoShape shape) | ||
| { | ||
| if (value is GeoShapeBase shapeBase && shapeBase.Format == GeoShapeFormat.WellKnownText) | ||
| { | ||
| writer.WriteValue(GeoWKTWriter.Write(shapeBase)); | ||
| return; | ||
| } | ||
|
|
||
| writer.WriteStartObject(); | ||
| writer.WritePropertyName("type"); | ||
| writer.WriteValue(shape.Type); | ||
| writer.WritePropertyName("coordinates"); | ||
| switch (shape) | ||
| { | ||
| case IPointGeoShape point: | ||
| serializer.Serialize(writer, point.Coordinates); | ||
| break; | ||
| case IMultiPointGeoShape multiPoint: | ||
| serializer.Serialize(writer, multiPoint.Coordinates); | ||
| break; | ||
| case ILineStringGeoShape lineString: | ||
| serializer.Serialize(writer, lineString.Coordinates); | ||
| break; | ||
| case IMultiLineStringGeoShape multiLineString: | ||
| serializer.Serialize(writer, multiLineString.Coordinates); | ||
| break; | ||
| case IPolygonGeoShape polygon: | ||
| serializer.Serialize(writer, polygon.Coordinates); | ||
| break; | ||
| case IMultiPolygonGeoShape multiPolyon: | ||
| serializer.Serialize(writer, multiPolyon.Coordinates); | ||
| break; | ||
| case IEnvelopeGeoShape envelope: | ||
| serializer.Serialize(writer, envelope.Coordinates); | ||
| break; | ||
| case ICircleGeoShape circle: | ||
| serializer.Serialize(writer, circle.Coordinates); | ||
| writer.WritePropertyName("radius"); | ||
| writer.WriteValue(circle.Radius); | ||
| break; | ||
| } | ||
| writer.WriteEndObject(); | ||
| } | ||
| } | ||
|
|
||
| public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) | ||
| { | ||
| if (reader.TokenType == JsonToken.Null) | ||
| return null; | ||
|
|
||
| var shape = JObject.Load(reader); | ||
| return ReadJToken(shape, serializer); | ||
| switch (reader.TokenType) | ||
| { | ||
| case JsonToken.Null: | ||
| return null; | ||
| case JsonToken.String: | ||
| return GeoWKTReader.Read((string)reader.Value); | ||
| default: | ||
| var shape = JObject.Load(reader); | ||
| return ReadJToken(shape, serializer); | ||
| } | ||
| } | ||
|
|
||
| internal static object ReadJToken(JToken shape, JsonSerializer serializer) | ||
| { | ||
| var type = shape["type"]; | ||
| var typeName = type?.Value<string>(); | ||
| var typeName = shape["type"]?.Value<string>().ToUpperInvariant(); | ||
| switch (typeName) | ||
| { | ||
| case "circle": | ||
| var radius = shape["radius"]; | ||
| return ParseCircleGeoShape(shape, serializer, radius); | ||
| case "envelope": | ||
| case GeoShapeType.Circle: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ++ |
||
| return ParseCircleGeoShape(shape, serializer); | ||
| case GeoShapeType.Envelope: | ||
| return ParseEnvelopeGeoShape(shape, serializer); | ||
| case "linestring": | ||
| case GeoShapeType.LineString: | ||
| return ParseLineStringGeoShape(shape, serializer); | ||
| case "multilinestring": | ||
| case GeoShapeType.MultiLineString: | ||
| return ParseMultiLineStringGeoShape(shape, serializer); | ||
| case "point": | ||
| case GeoShapeType.Point: | ||
| return ParsePointGeoShape(shape, serializer); | ||
| case "multipoint": | ||
| case GeoShapeType.MultiPoint: | ||
| return ParseMultiPointGeoShape(shape, serializer); | ||
| case "polygon": | ||
| case GeoShapeType.Polygon: | ||
| return ParsePolygonGeoShape(shape, serializer); | ||
| case "multipolygon": | ||
| case GeoShapeType.MultiPolygon: | ||
| return ParseMultiPolygonGeoShape(shape, serializer); | ||
| case "geometrycollection": | ||
| case GeoShapeType.GeometryCollection: | ||
| return ParseGeometryCollection(shape, serializer); | ||
| default: | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| public override bool CanConvert(Type objectType) => typeof(IGeoShape).IsAssignableFrom(objectType) || | ||
| typeof(IGeometryCollection).IsAssignableFrom(objectType); | ||
| public override bool CanConvert(Type objectType) => | ||
| typeof(IGeoShape).IsAssignableFrom(objectType) || typeof(IGeometryCollection).IsAssignableFrom(objectType); | ||
|
|
||
| private static GeometryCollection ParseGeometryCollection(JToken shape, JsonSerializer serializer) | ||
| { | ||
|
|
@@ -128,11 +221,11 @@ private static LineStringGeoShape ParseLineStringGeoShape(JToken shape, JsonSeri | |
| private static EnvelopeGeoShape ParseEnvelopeGeoShape(JToken shape, JsonSerializer serializer) => | ||
| new EnvelopeGeoShape {Coordinates = GetCoordinates<IEnumerable<GeoCoordinate>>(shape, serializer)}; | ||
|
|
||
| private static CircleGeoShape ParseCircleGeoShape(JToken shape, JsonSerializer serializer, JToken radius) => | ||
| private static CircleGeoShape ParseCircleGeoShape(JToken shape, JsonSerializer serializer) => | ||
| new CircleGeoShape | ||
| { | ||
| Coordinates = GetCoordinates<GeoCoordinate>(shape, serializer), | ||
| Radius = radius?.Value<string>() | ||
| Radius = shape["radius"]?.Value<string>() | ||
| }; | ||
|
|
||
| private static T GetCoordinates<T>(JToken shape, JsonSerializer serializer) | ||
|
|
||
This file contains hidden or 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
This file contains hidden or 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.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe put something like "Fixed in 7.0" that way when we search in the code for TODOs in 7.0 we can find this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++