From 603a0ebd00d80f116827e229185c4efab1b4a036 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Mon, 18 May 2020 10:40:05 -0700 Subject: [PATCH 01/15] Add spatial types to azure.core --- sdk/core/Azure.Core/src/Spatial/Point.cs | 111 +++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 sdk/core/Azure.Core/src/Spatial/Point.cs diff --git a/sdk/core/Azure.Core/src/Spatial/Point.cs b/sdk/core/Azure.Core/src/Spatial/Point.cs new file mode 100644 index 0000000000000..7c71bff274e87 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/Point.cs @@ -0,0 +1,111 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +#pragma warning disable 1591 + +namespace Azure.Core.Spatial +{ + + /// + /// + /// + public readonly struct Position + { + /// + /// + /// + public double? Altitude { get; } + /// + /// + /// + public double Longitude { get; } + /// + /// + /// + public double Latitude { get; } + + /// + /// + /// + /// + /// + public Position(double longitude, double latitude) : this(longitude, latitude, null) + { + } + + /// + /// + /// + /// + /// + /// + public Position(double longitude, double latitude, double? altitude) + { + Longitude = longitude; + Latitude = latitude; + Altitude = altitude; + } + } + + public readonly struct CoordinateReferenceSystem + { + + } + + public readonly struct BoundingBox + { + + } + + public class Geometry + { + public GeomertyMetadata? Metadata { get; } + + public Geometry(GeomertyMetadata? metadata) + { + Metadata = metadata; + } + } + + public class GeomertyMetadata + { + public GeomertyMetadata(BoundingBox? boundingBox, CoordinateReferenceSystem? coordinateReferenceSystem, IReadOnlyDictionary? additionalProperties) + { + AdditionalProperties = additionalProperties; + BoundingBox = boundingBox; + CoordinateReferenceSystem = coordinateReferenceSystem; + } + + public IDictionary AdditionalProperties { get; } + public BoundingBox? BoundingBox { get; } + public CoordinateReferenceSystem CoordinateReferenceSystem { get; set; } + } + + public class Point + { + public Point(Position position) + { + Position = position; + } + + public Position Position { get; } + } + + public class LinearRing + { + public LinearRing(IEnumerable positions) + { + Positions = positions.ToList(); + } + + public IReadOnlyList Positions { get; } + } + + public class Polygon + { + public Polygon(IEnumerable rings) + { + + } + } +} \ No newline at end of file From 3fff5efa273e5525b412c7dd9df2144e8b674904 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 19 May 2020 12:35:46 -0700 Subject: [PATCH 02/15] Prograss --- sdk/core/Azure.Core/src/Azure.Core.csproj | 1 + .../src/Spatial/GeoJsonConverter.cs | 263 ++++++++++++++++++ sdk/core/Azure.Core/src/Spatial/Geometry.cs | 12 + .../src/Spatial/GeometryCollection.cs | 28 ++ sdk/core/Azure.Core/src/Spatial/LineString.cs | 34 +++ .../Azure.Core/src/Spatial/MultiLineString.cs | 28 ++ sdk/core/Azure.Core/src/Spatial/MultiPoint.cs | 28 ++ .../Azure.Core/src/Spatial/MultiPolygon.cs | 28 ++ sdk/core/Azure.Core/src/Spatial/Point.cs | 99 +------ sdk/core/Azure.Core/src/Spatial/Polygon.cs | 28 ++ sdk/core/Azure.Core/src/Spatial/Position.cs | 88 ++++++ sdk/core/Azure.Core/tests/SpatialTests.cs | 46 +++ 12 files changed, 592 insertions(+), 91 deletions(-) create mode 100644 sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/Geometry.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/LineString.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/MultiLineString.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/MultiPoint.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/Polygon.cs create mode 100644 sdk/core/Azure.Core/src/Spatial/Position.cs create mode 100644 sdk/core/Azure.Core/tests/SpatialTests.cs diff --git a/sdk/core/Azure.Core/src/Azure.Core.csproj b/sdk/core/Azure.Core/src/Azure.Core.csproj index 5b97b75e44784..d4c2a5e59e416 100644 --- a/sdk/core/Azure.Core/src/Azure.Core.csproj +++ b/sdk/core/Azure.Core/src/Azure.Core.csproj @@ -17,6 +17,7 @@ + diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs new file mode 100644 index 0000000000000..53c0c30f8f5fe --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -0,0 +1,263 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public class GeoJsonConverter : JsonConverter + { + private const string PointType = "Point"; + private const string LineStringType = "LineString"; + private const string MultiPointType = "MultiPoint"; + private const string PolygonType = "Polygon"; + private const string MultiLineStringType = "MultiLineString"; + private const string MultiPolygonType = "MultiPolygon"; + private const string GeometryCollectionType = "GeometryCollection"; + private const string TypeProperty = "type"; + + /// + public override Geometry Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var document = JsonDocument.ParseValue(ref reader); + return Read(document.RootElement); + } + + internal static Geometry Read(JsonElement element) + { + var typeProperty = GetRequiredProperty(element, TypeProperty); + + var type = typeProperty.GetString(); + + if (type == GeometryCollectionType) + { + var geometries = new List(); + foreach (var geometry in GetRequiredProperty(element, "geometries").EnumerateArray()) + { + geometries.Add(Read(geometry)); + } + + return new GeometryCollection(geometries); + } + + var coordinates = GetRequiredProperty(element, "coordinates"); + + switch (type) + { + case PointType: + return new Point(ReadCoordinate(coordinates)); + case LineStringType: + return new LineString(ReadCoordinates(coordinates)); + case MultiPointType: + var points = new List(); + foreach (var coordinate in ReadCoordinates(coordinates)) + { + points.Add(new Point(coordinate)); + } + + return new MultiPoint(points); + + case PolygonType: + var rings = new List(); + foreach (var ringArray in coordinates.EnumerateArray()) + { + rings.Add(new LineString(ReadCoordinates(ringArray))); + } + + return new Polygon(rings); + + case MultiLineStringType: + var lineStrings = new List(); + foreach (var ringArray in coordinates.EnumerateArray()) + { + lineStrings.Add(new LineString(ReadCoordinates(ringArray))); + } + + return new MultiLineString(lineStrings); + + case MultiPolygonType: + + var polygons = new List(); + foreach (var polygon in coordinates.EnumerateArray()) + { + var polygonRings = new List(); + foreach (var ringArray in polygon.EnumerateArray()) + { + polygonRings.Add(new LineString(ReadCoordinates(ringArray))); + } + + polygons.Add(new Polygon(polygonRings)); + } + + return new MultiPolygon(polygons); + + default: + throw new NotSupportedException($"Unsupported geometry type '{type}' "); + } + } + + private static IEnumerable ReadCoordinates(JsonElement coordinates) + { + foreach (JsonElement coordinate in coordinates.EnumerateArray()) + { + yield return ReadCoordinate(coordinate); + } + } + + private static Position ReadCoordinate(JsonElement coordinate) + { + var arrayLength = coordinate.GetArrayLength(); + if (arrayLength < 2 || arrayLength > 3) + { + throw new JsonException("Only 2 or 3 element coordinates supported"); + } + + var lon = coordinate[0].GetDouble(); + var lat = coordinate[1].GetDouble(); + double? altitude = null; + + if (arrayLength > 2) + { + altitude = coordinate[2].GetDouble(); + } + + return new Position(lon, lat, altitude); + } + + /// + /// + /// + /// + /// + /// + public override void Write(Utf8JsonWriter writer, Geometry value, JsonSerializerOptions options) + { + Write(writer, value); + } + + internal static void Write(Utf8JsonWriter writer, Geometry value) + { + void WriteType(string type) + { + writer.WriteString(TypeProperty, type); + } + + void WritePosition(Position type) + { + writer.WriteStartArray(); + writer.WriteNumberValue(type.Longitude); + writer.WriteNumberValue(type.Latitude); + if (type.Altitude != null) + { + writer.WriteNumberValue(type.Altitude.Value); + } + + writer.WriteEndArray(); + } + + void WritePositions(IEnumerable positions) + { + writer.WriteStartArray(); + foreach (var position in positions) + { + WritePosition(position); + } + + writer.WriteEndArray(); + } + + writer.WriteStartObject(); + switch (value) + { + case Point point: + WriteType(PointType); + writer.WritePropertyName("coordinates"); + WritePosition(point.Position); + break; + + case LineString lineString: + WriteType(LineStringType); + writer.WritePropertyName("coordinates"); + WritePositions(lineString.Positions); + break; + + case Polygon polygon: + WriteType(PolygonType); + writer.WritePropertyName("coordinates"); + foreach (var ring in polygon.Rings) + { + WritePositions(ring.Positions); + } + break; + + case MultiPoint multiPoint: + WriteType(MultiPointType); + writer.WritePropertyName("coordinates"); + writer.WriteStartArray(); + foreach (var point in multiPoint.Points) + { + WritePosition(point.Position); + } + writer.WriteEndArray(); + break; + + case MultiLineString multiLineString: + WriteType(MultiPointType); + writer.WritePropertyName("coordinates"); + writer.WriteStartArray(); + foreach (var lineString in multiLineString.LineStrings) + { + WritePositions(lineString.Positions); + } + writer.WriteEndArray(); + break; + + case MultiPolygon multiPolygon: + WriteType(MultiPointType); + writer.WritePropertyName("coordinates"); + writer.WriteStartArray(); + foreach (var polygon in multiPolygon.Polygons) + { + foreach (var polygonRing in polygon.Rings) + { + WritePositions(polygonRing.Positions); + } + } + writer.WriteEndArray(); + break; + + case GeometryCollection geometryCollection: + WriteType(GeometryCollectionType); + writer.WritePropertyName("geometries"); + writer.WriteStartArray(); + foreach (var geometry in geometryCollection.Geometries) + { + Write(writer, geometry); + } + writer.WriteEndArray(); + break; + + default: + throw new NotSupportedException($"Geometry type '{value?.GetType()}' not supported"); + } + + writer.WriteEndObject(); + } + + private static JsonElement GetRequiredProperty(JsonElement element, string name) + { + if (!element.TryGetProperty(name, out JsonElement property)) + { + throw new JsonException($"GeoJSON object expected to have '{name}' property."); + } + + return property; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs new file mode 100644 index 0000000000000..1a0e4bdf269f3 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public class Geometry + { + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs new file mode 100644 index 0000000000000..9937047e9bfd6 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public sealed class GeometryCollection : Geometry + { + /// + /// + /// + /// + public GeometryCollection(IEnumerable geometries) + { + Geometries = geometries.ToArray(); + } + + /// + /// + /// + public IReadOnlyList Geometries { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/LineString.cs b/sdk/core/Azure.Core/src/Spatial/LineString.cs new file mode 100644 index 0000000000000..2fe7a2777cec6 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/LineString.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public sealed class LineString : Geometry + { + /// + /// + /// + /// + public LineString(IEnumerable positions) + { + Positions = positions.ToArray(); + } + + /// + /// + /// + public IReadOnlyList Positions { get; } + + /// + public override string ToString() + { + return $"LineString: {Positions.Count} points"; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/MultiLineString.cs b/sdk/core/Azure.Core/src/Spatial/MultiLineString.cs new file mode 100644 index 0000000000000..eb219c9dd05cd --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/MultiLineString.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public sealed class MultiLineString : Geometry + { + /// + /// + /// + /// + public MultiLineString(IEnumerable lineStrings) + { + LineStrings = lineStrings.ToArray(); + } + + /// + /// + /// + public IReadOnlyList LineStrings { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPoint.cs b/sdk/core/Azure.Core/src/Spatial/MultiPoint.cs new file mode 100644 index 0000000000000..ca15318f63e08 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/MultiPoint.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public sealed class MultiPoint : Geometry + { + /// + /// + /// + /// + public MultiPoint(IEnumerable points) + { + Points = points.ToArray(); + } + + /// + /// + /// + public IReadOnlyList Points { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs b/sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs new file mode 100644 index 0000000000000..27030b1619315 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public sealed class MultiPolygon : Geometry + { + /// + /// + /// + /// + public MultiPolygon(IEnumerable polygons) + { + Polygons = polygons.ToArray(); + } + + /// + /// + /// + public IReadOnlyList Polygons { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Point.cs b/sdk/core/Azure.Core/src/Spatial/Point.cs index 7c71bff274e87..ce328543b9a06 100644 --- a/sdk/core/Azure.Core/src/Spatial/Point.cs +++ b/sdk/core/Azure.Core/src/Spatial/Point.cs @@ -1,111 +1,28 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -#pragma warning disable 1591 +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. namespace Azure.Core.Spatial { - /// /// /// - public readonly struct Position + public sealed class Point : Geometry { /// /// /// - public double? Altitude { get; } - /// - /// - /// - public double Longitude { get; } - /// - /// - /// - public double Latitude { get; } - - /// - /// - /// - /// - /// - public Position(double longitude, double latitude) : this(longitude, latitude, null) + /// + public Point(Position position) { + Position = position; } /// /// /// - /// - /// - /// - public Position(double longitude, double latitude, double? altitude) - { - Longitude = longitude; - Latitude = latitude; - Altitude = altitude; - } - } - - public readonly struct CoordinateReferenceSystem - { - - } - - public readonly struct BoundingBox - { - - } - - public class Geometry - { - public GeomertyMetadata? Metadata { get; } - - public Geometry(GeomertyMetadata? metadata) - { - Metadata = metadata; - } - } - - public class GeomertyMetadata - { - public GeomertyMetadata(BoundingBox? boundingBox, CoordinateReferenceSystem? coordinateReferenceSystem, IReadOnlyDictionary? additionalProperties) - { - AdditionalProperties = additionalProperties; - BoundingBox = boundingBox; - CoordinateReferenceSystem = coordinateReferenceSystem; - } - - public IDictionary AdditionalProperties { get; } - public BoundingBox? BoundingBox { get; } - public CoordinateReferenceSystem CoordinateReferenceSystem { get; set; } - } - - public class Point - { - public Point(Position position) - { - Position = position; - } - public Position Position { get; } - } - - public class LinearRing - { - public LinearRing(IEnumerable positions) - { - Positions = positions.ToList(); - } - public IReadOnlyList Positions { get; } - } - - public class Polygon - { - public Polygon(IEnumerable rings) - { - - } + /// + public override string ToString() => $"Point: {Position}"; } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Polygon.cs b/sdk/core/Azure.Core/src/Spatial/Polygon.cs new file mode 100644 index 0000000000000..e1a1981d40771 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/Polygon.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public sealed class Polygon : Geometry + { + /// + /// + /// + /// + public Polygon(IEnumerable rings) + { + Rings = rings.ToArray(); + } + + /// + /// + /// + public IReadOnlyList Rings { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Position.cs b/sdk/core/Azure.Core/src/Spatial/Position.cs new file mode 100644 index 0000000000000..511c644b507b2 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/Position.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public readonly struct Position : IEquatable + { + /// + /// + /// + public double? Altitude { get; } + + /// + /// + /// + public double Longitude { get; } + + /// + /// + /// + public double Latitude { get; } + + /// + /// + /// + /// + /// + public Position(double longitude, double latitude) : this(longitude, latitude, null) + { + } + + /// + /// + /// + /// + /// + /// + public Position(double longitude, double latitude, double? altitude) + { + Longitude = longitude; + Latitude = latitude; + Altitude = altitude; + } + + + /// + public bool Equals(Position other) + { + return Nullable.Equals(Altitude, other.Altitude) && Longitude.Equals(other.Longitude) && Latitude.Equals(other.Latitude); + } + + /// + public override bool Equals(object? obj) + { + return obj is Position other && Equals(other); + } + + /// + public override int GetHashCode() => HashCodeBuilder.Combine(Longitude, Latitude, Altitude); + + /// + /// + /// + /// + /// + /// + public static bool operator ==(Position left, Position right) + { + return left.Equals(right); + } + + /// + /// + /// + /// + /// + /// + public static bool operator !=(Position left, Position right) + { + return !left.Equals(right); + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs new file mode 100644 index 0000000000000..8b36ae420697c --- /dev/null +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.IO; +using System.Text.Json; +using Azure.Core.Spatial; +using NUnit.Framework; + +namespace Azure.Core.Tests +{ + public class SpatialTests + { + [Test] + public void CanRoundripGeometryCollection() + { + var input = "{ \"type\": \"GeometryCollection\", \"geometries\": [{ \"type\": \"Point\", \"coordinates\": [100.1, 0.2] }, { \"type\": \"LineString\", \"coordinates\": [ [101.3, 0.4], [102.5, 1.6] ] }] }"; + + var collection = AssertRoundtrip(input); + var point = (Point) collection.Geometries[0]; + Assert.AreEqual(new Position(100.1, 0.2), point.Position); + + var lineString = (LineString) collection.Geometries[1]; + Assert.AreEqual(new Position(101.3, 0.4), lineString.Positions[0]); + Assert.AreEqual(new Position(102.5, 1.6), lineString.Positions[1]); + + Assert.AreEqual(2, collection.Geometries.Count); + } + + private T AssertRoundtrip(string json) where T: Geometry + { + var element = JsonDocument.Parse(json).RootElement; + var geometry = GeoJsonConverter.Read(element); + + var memoryStreamOutput = new MemoryStream(); + using (Utf8JsonWriter writer = new Utf8JsonWriter(memoryStreamOutput)) + { + GeoJsonConverter.Write(writer, geometry); + } + + var element2 = JsonDocument.Parse(memoryStreamOutput.ToArray()).RootElement; + var geometry2 = GeoJsonConverter.Read(element2); + + return (T)geometry2; + } + } +} \ No newline at end of file From 23a28eeeb6cf61a10f79adb4bc0db9122b2388f5 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 19 May 2020 13:29:13 -0700 Subject: [PATCH 03/15] More progress --- .../src/Spatial/GeoJsonConverter.cs | 54 +++++++++---------- .../{LineString.cs => GeoLineString.cs} | 6 +-- ...ltiLineString.cs => GeoMultiLineString.cs} | 6 +-- .../{MultiPoint.cs => GeoMultiPoint.cs} | 6 +-- .../{MultiPolygon.cs => GeoMultiPolygon.cs} | 6 +-- .../src/Spatial/{Point.cs => GeoPoint.cs} | 6 +-- .../src/Spatial/{Polygon.cs => GeoPolygon.cs} | 6 +-- .../Spatial/{Position.cs => GeoPosition.cs} | 14 ++--- sdk/core/Azure.Core/tests/SpatialTests.cs | 10 ++-- 9 files changed, 57 insertions(+), 57 deletions(-) rename sdk/core/Azure.Core/src/Spatial/{LineString.cs => GeoLineString.cs} (77%) rename sdk/core/Azure.Core/src/Spatial/{MultiLineString.cs => GeoMultiLineString.cs} (71%) rename sdk/core/Azure.Core/src/Spatial/{MultiPoint.cs => GeoMultiPoint.cs} (73%) rename sdk/core/Azure.Core/src/Spatial/{MultiPolygon.cs => GeoMultiPolygon.cs} (72%) rename sdk/core/Azure.Core/src/Spatial/{Point.cs => GeoPoint.cs} (78%) rename sdk/core/Azure.Core/src/Spatial/{Polygon.cs => GeoPolygon.cs} (73%) rename sdk/core/Azure.Core/src/Spatial/{Position.cs => GeoPosition.cs} (78%) diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 53c0c30f8f5fe..3946296098c5d 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -51,58 +51,58 @@ internal static Geometry Read(JsonElement element) switch (type) { case PointType: - return new Point(ReadCoordinate(coordinates)); + return new GeoPoint(ReadCoordinate(coordinates)); case LineStringType: - return new LineString(ReadCoordinates(coordinates)); + return new GeoLineString(ReadCoordinates(coordinates)); case MultiPointType: - var points = new List(); + var points = new List(); foreach (var coordinate in ReadCoordinates(coordinates)) { - points.Add(new Point(coordinate)); + points.Add(new GeoPoint(coordinate)); } - return new MultiPoint(points); + return new GeoMultiPoint(points); case PolygonType: - var rings = new List(); + var rings = new List(); foreach (var ringArray in coordinates.EnumerateArray()) { - rings.Add(new LineString(ReadCoordinates(ringArray))); + rings.Add(new GeoLineString(ReadCoordinates(ringArray))); } - return new Polygon(rings); + return new GeoPolygon(rings); case MultiLineStringType: - var lineStrings = new List(); + var lineStrings = new List(); foreach (var ringArray in coordinates.EnumerateArray()) { - lineStrings.Add(new LineString(ReadCoordinates(ringArray))); + lineStrings.Add(new GeoLineString(ReadCoordinates(ringArray))); } - return new MultiLineString(lineStrings); + return new GeoMultiLineString(lineStrings); case MultiPolygonType: - var polygons = new List(); + var polygons = new List(); foreach (var polygon in coordinates.EnumerateArray()) { - var polygonRings = new List(); + var polygonRings = new List(); foreach (var ringArray in polygon.EnumerateArray()) { - polygonRings.Add(new LineString(ReadCoordinates(ringArray))); + polygonRings.Add(new GeoLineString(ReadCoordinates(ringArray))); } - polygons.Add(new Polygon(polygonRings)); + polygons.Add(new GeoPolygon(polygonRings)); } - return new MultiPolygon(polygons); + return new GeoMultiPolygon(polygons); default: throw new NotSupportedException($"Unsupported geometry type '{type}' "); } } - private static IEnumerable ReadCoordinates(JsonElement coordinates) + private static IEnumerable ReadCoordinates(JsonElement coordinates) { foreach (JsonElement coordinate in coordinates.EnumerateArray()) { @@ -110,7 +110,7 @@ private static IEnumerable ReadCoordinates(JsonElement coordinates) } } - private static Position ReadCoordinate(JsonElement coordinate) + private static GeoPosition ReadCoordinate(JsonElement coordinate) { var arrayLength = coordinate.GetArrayLength(); if (arrayLength < 2 || arrayLength > 3) @@ -127,7 +127,7 @@ private static Position ReadCoordinate(JsonElement coordinate) altitude = coordinate[2].GetDouble(); } - return new Position(lon, lat, altitude); + return new GeoPosition(lon, lat, altitude); } /// @@ -148,7 +148,7 @@ void WriteType(string type) writer.WriteString(TypeProperty, type); } - void WritePosition(Position type) + void WritePosition(GeoPosition type) { writer.WriteStartArray(); writer.WriteNumberValue(type.Longitude); @@ -161,7 +161,7 @@ void WritePosition(Position type) writer.WriteEndArray(); } - void WritePositions(IEnumerable positions) + void WritePositions(IEnumerable positions) { writer.WriteStartArray(); foreach (var position in positions) @@ -175,19 +175,19 @@ void WritePositions(IEnumerable positions) writer.WriteStartObject(); switch (value) { - case Point point: + case GeoPoint point: WriteType(PointType); writer.WritePropertyName("coordinates"); WritePosition(point.Position); break; - case LineString lineString: + case GeoLineString lineString: WriteType(LineStringType); writer.WritePropertyName("coordinates"); WritePositions(lineString.Positions); break; - case Polygon polygon: + case GeoPolygon polygon: WriteType(PolygonType); writer.WritePropertyName("coordinates"); foreach (var ring in polygon.Rings) @@ -196,7 +196,7 @@ void WritePositions(IEnumerable positions) } break; - case MultiPoint multiPoint: + case GeoMultiPoint multiPoint: WriteType(MultiPointType); writer.WritePropertyName("coordinates"); writer.WriteStartArray(); @@ -207,7 +207,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case MultiLineString multiLineString: + case GeoMultiLineString multiLineString: WriteType(MultiPointType); writer.WritePropertyName("coordinates"); writer.WriteStartArray(); @@ -218,7 +218,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case MultiPolygon multiPolygon: + case GeoMultiPolygon multiPolygon: WriteType(MultiPointType); writer.WritePropertyName("coordinates"); writer.WriteStartArray(); diff --git a/sdk/core/Azure.Core/src/Spatial/LineString.cs b/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs similarity index 77% rename from sdk/core/Azure.Core/src/Spatial/LineString.cs rename to sdk/core/Azure.Core/src/Spatial/GeoLineString.cs index 2fe7a2777cec6..4a522db1b40ab 100644 --- a/sdk/core/Azure.Core/src/Spatial/LineString.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class LineString : Geometry + public sealed class GeoLineString : Geometry { /// /// /// /// - public LineString(IEnumerable positions) + public GeoLineString(IEnumerable positions) { Positions = positions.ToArray(); } @@ -23,7 +23,7 @@ public LineString(IEnumerable positions) /// /// /// - public IReadOnlyList Positions { get; } + public IReadOnlyList Positions { get; } /// public override string ToString() diff --git a/sdk/core/Azure.Core/src/Spatial/MultiLineString.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs similarity index 71% rename from sdk/core/Azure.Core/src/Spatial/MultiLineString.cs rename to sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs index eb219c9dd05cd..51c6a638715d4 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiLineString.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class MultiLineString : Geometry + public sealed class GeoMultiLineString : Geometry { /// /// /// /// - public MultiLineString(IEnumerable lineStrings) + public GeoMultiLineString(IEnumerable lineStrings) { LineStrings = lineStrings.ToArray(); } @@ -23,6 +23,6 @@ public MultiLineString(IEnumerable lineStrings) /// /// /// - public IReadOnlyList LineStrings { get; } + public IReadOnlyList LineStrings { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPoint.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs similarity index 73% rename from sdk/core/Azure.Core/src/Spatial/MultiPoint.cs rename to sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs index ca15318f63e08..0d09dcf223dc4 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPoint.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class MultiPoint : Geometry + public sealed class GeoMultiPoint : Geometry { /// /// /// /// - public MultiPoint(IEnumerable points) + public GeoMultiPoint(IEnumerable points) { Points = points.ToArray(); } @@ -23,6 +23,6 @@ public MultiPoint(IEnumerable points) /// /// /// - public IReadOnlyList Points { get; } + public IReadOnlyList Points { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs similarity index 72% rename from sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs rename to sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs index 27030b1619315..41dd521008a53 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPolygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class MultiPolygon : Geometry + public sealed class GeoMultiPolygon : Geometry { /// /// /// /// - public MultiPolygon(IEnumerable polygons) + public GeoMultiPolygon(IEnumerable polygons) { Polygons = polygons.ToArray(); } @@ -23,6 +23,6 @@ public MultiPolygon(IEnumerable polygons) /// /// /// - public IReadOnlyList Polygons { get; } + public IReadOnlyList Polygons { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Point.cs b/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs similarity index 78% rename from sdk/core/Azure.Core/src/Spatial/Point.cs rename to sdk/core/Azure.Core/src/Spatial/GeoPoint.cs index ce328543b9a06..6e8cacd01338f 100644 --- a/sdk/core/Azure.Core/src/Spatial/Point.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs @@ -6,13 +6,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class Point : Geometry + public sealed class GeoPoint : Geometry { /// /// /// /// - public Point(Position position) + public GeoPoint(GeoPosition position) { Position = position; } @@ -20,7 +20,7 @@ public Point(Position position) /// /// /// - public Position Position { get; } + public GeoPosition Position { get; } /// public override string ToString() => $"Point: {Position}"; diff --git a/sdk/core/Azure.Core/src/Spatial/Polygon.cs b/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs similarity index 73% rename from sdk/core/Azure.Core/src/Spatial/Polygon.cs rename to sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs index e1a1981d40771..16a56c568f52c 100644 --- a/sdk/core/Azure.Core/src/Spatial/Polygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class Polygon : Geometry + public sealed class GeoPolygon : Geometry { /// /// /// /// - public Polygon(IEnumerable rings) + public GeoPolygon(IEnumerable rings) { Rings = rings.ToArray(); } @@ -23,6 +23,6 @@ public Polygon(IEnumerable rings) /// /// /// - public IReadOnlyList Rings { get; } + public IReadOnlyList Rings { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Position.cs b/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs similarity index 78% rename from sdk/core/Azure.Core/src/Spatial/Position.cs rename to sdk/core/Azure.Core/src/Spatial/GeoPosition.cs index 511c644b507b2..62e3b54f80151 100644 --- a/sdk/core/Azure.Core/src/Spatial/Position.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs @@ -8,7 +8,7 @@ namespace Azure.Core.Spatial /// /// /// - public readonly struct Position : IEquatable + public readonly struct GeoPosition : IEquatable { /// /// @@ -30,7 +30,7 @@ namespace Azure.Core.Spatial /// /// /// - public Position(double longitude, double latitude) : this(longitude, latitude, null) + public GeoPosition(double longitude, double latitude) : this(longitude, latitude, null) { } @@ -40,7 +40,7 @@ public Position(double longitude, double latitude) : this(longitude, latitude, n /// /// /// - public Position(double longitude, double latitude, double? altitude) + public GeoPosition(double longitude, double latitude, double? altitude) { Longitude = longitude; Latitude = latitude; @@ -49,7 +49,7 @@ public Position(double longitude, double latitude, double? altitude) /// - public bool Equals(Position other) + public bool Equals(GeoPosition other) { return Nullable.Equals(Altitude, other.Altitude) && Longitude.Equals(other.Longitude) && Latitude.Equals(other.Latitude); } @@ -57,7 +57,7 @@ public bool Equals(Position other) /// public override bool Equals(object? obj) { - return obj is Position other && Equals(other); + return obj is GeoPosition other && Equals(other); } /// @@ -69,7 +69,7 @@ public override bool Equals(object? obj) /// /// /// - public static bool operator ==(Position left, Position right) + public static bool operator ==(GeoPosition left, GeoPosition right) { return left.Equals(right); } @@ -80,7 +80,7 @@ public override bool Equals(object? obj) /// /// /// - public static bool operator !=(Position left, Position right) + public static bool operator !=(GeoPosition left, GeoPosition right) { return !left.Equals(right); } diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index 8b36ae420697c..d4da85f9d1286 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -16,12 +16,12 @@ public void CanRoundripGeometryCollection() var input = "{ \"type\": \"GeometryCollection\", \"geometries\": [{ \"type\": \"Point\", \"coordinates\": [100.1, 0.2] }, { \"type\": \"LineString\", \"coordinates\": [ [101.3, 0.4], [102.5, 1.6] ] }] }"; var collection = AssertRoundtrip(input); - var point = (Point) collection.Geometries[0]; - Assert.AreEqual(new Position(100.1, 0.2), point.Position); + var point = (GeoPoint) collection.Geometries[0]; + Assert.AreEqual(new GeoPosition(100.1, 0.2), point.Position); - var lineString = (LineString) collection.Geometries[1]; - Assert.AreEqual(new Position(101.3, 0.4), lineString.Positions[0]); - Assert.AreEqual(new Position(102.5, 1.6), lineString.Positions[1]); + var lineString = (GeoLineString) collection.Geometries[1]; + Assert.AreEqual(new GeoPosition(101.3, 0.4), lineString.Positions[0]); + Assert.AreEqual(new GeoPosition(102.5, 1.6), lineString.Positions[1]); Assert.AreEqual(2, collection.Geometries.Count); } From dd7aafd521de3491d0baa2e6dd577cc831261ce4 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Tue, 19 May 2020 15:39:19 -0700 Subject: [PATCH 04/15] Tests --- .../src/Spatial/GeoJsonConverter.cs | 4 +- sdk/core/Azure.Core/tests/SpatialTests.cs | 99 +++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 3946296098c5d..8def430c1b5ca 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -190,10 +190,12 @@ void WritePositions(IEnumerable positions) case GeoPolygon polygon: WriteType(PolygonType); writer.WritePropertyName("coordinates"); + writer.WriteStartArray(); foreach (var ring in polygon.Rings) { WritePositions(ring.Positions); } + writer.WriteEndArray(); break; case GeoMultiPoint multiPoint: @@ -208,7 +210,7 @@ void WritePositions(IEnumerable positions) break; case GeoMultiLineString multiLineString: - WriteType(MultiPointType); + WriteType(MultiLineStringType); writer.WritePropertyName("coordinates"); writer.WriteStartArray(); foreach (var lineString in multiLineString.LineStrings) diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index d4da85f9d1286..ed494a8fcb441 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -10,6 +10,103 @@ namespace Azure.Core.Tests { public class SpatialTests { + [Test] + public void CanRoundripPoint() + { + var input = "{ \"type\": \"Point\", \"coordinates\": [100.1, 0.2] }"; + + var point = AssertRoundtrip(input); + Assert.AreEqual(new GeoPosition(100.1, 0.2), point.Position); + } + + [Test] + public void CanRoundripPolygon() + { + var input = " { \"type\": \"Polygon\", \"coordinates\": [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] ] }"; + + var polygon = AssertRoundtrip(input); + Assert.AreEqual(1, polygon.Rings.Count); + + CollectionAssert.AreEqual(new[] + { + P(100.0, 0.0), + P(101.0, 0.0), + P(101.0, 1.0), + P(100.0, 1.0), + P(100.0, 0.0), + }, polygon.Rings[0].Positions); + } + + [Test] + public void CanRoundripPolygonHoles() + { + var input = "{ \"type\": \"Polygon\", \"coordinates\": [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ], " + + "[ [100.8, 0.8], [100.8, 0.2], [100.2, 0.2], [100.2, 0.8], [100.8, 0.8] ] ] }"; + + var polygon = AssertRoundtrip(input); + Assert.AreEqual(2, polygon.Rings.Count); + + CollectionAssert.AreEqual(new[] + { + P(100.0, 0.0), + P(101.0, 0.0), + P(101.0, 1.0), + P(100.0, 1.0), + P(100.0, 0.0), + }, polygon.Rings[0].Positions); + + CollectionAssert.AreEqual(new[] + { + P(100.8, 0.8), + P(100.8, 0.2), + P(100.2, 0.2), + P(100.2, 0.8), + P(100.8, 0.8), + }, polygon.Rings[1].Positions); + } + + [Test] + public void CanRoundripMultiPoint() + { + var input = "{ \"type\": \"MultiPoint\", \"coordinates\": [ [100.0, 0.0], [101.0, 1.0] ] }"; + + var multipoint = AssertRoundtrip(input); + Assert.AreEqual(2, multipoint.Points.Count); + + Assert.AreEqual(P(100.0, 0.0), multipoint.Points[0].Position); + Assert.AreEqual(P(101.0, 1.0), multipoint.Points[1].Position); + } + + [Test] + public void CanRoundripMultiLineString() + { + var input = "{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [100.0, 0.0], [101.0, 1.0] ], [ [102.0, 2.0], [103.0, 3.0] ] ] }"; + + var polygon = AssertRoundtrip(input); + Assert.AreEqual(2, polygon.LineStrings.Count); + + CollectionAssert.AreEqual(new[] + { + P(100.0, 0.0), + P(101.0, 1.0) + }, polygon.LineStrings[0].Positions); + + CollectionAssert.AreEqual(new[] + { + P(102.0, 2.0), + P(103.0, 3.0) + }, polygon.LineStrings[1].Positions); + } + + [Test] + public void CanRoundripMultiPolygon() + { + var input = " { \"type\": \"MultiPolygon\", \"coordinates\": [ [ [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0] ] ], [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ], [ [100.2, 0.2], [100.2, 0.8], [100.8, 0.8], [100.8, 0.2], [100.2, 0.2] ] ] ] }"; + + var point = AssertRoundtrip(input); + Assert.AreEqual(new GeoPosition(100.1, 0.2), point.Position); + } + [Test] public void CanRoundripGeometryCollection() { @@ -26,6 +123,8 @@ public void CanRoundripGeometryCollection() Assert.AreEqual(2, collection.Geometries.Count); } + private GeoPosition P(double lon, double lat, double? alt = null) => new GeoPosition(lon, lat, alt); + private T AssertRoundtrip(string json) where T: Geometry { var element = JsonDocument.Parse(json).RootElement; From b65d0c0f4d35263f0978c9bef33090e5676cc699 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 10:36:19 -0700 Subject: [PATCH 05/15] bbox and properties --- .../src/Spatial/GeoJsonConverter.cs | 243 +++++++++++++++--- .../Azure.Core/src/Spatial/GeoLineString.cs | 11 +- .../src/Spatial/GeoMultiLineString.cs | 11 +- .../Azure.Core/src/Spatial/GeoMultiPoint.cs | 11 +- .../Azure.Core/src/Spatial/GeoMultiPolygon.cs | 11 +- sdk/core/Azure.Core/src/Spatial/GeoPoint.cs | 11 +- sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs | 11 +- .../Azure.Core/src/Spatial/GeoPosition.cs | 14 + sdk/core/Azure.Core/src/Spatial/Geometry.cs | 41 +++ .../src/Spatial/GeometryCollection.cs | 11 +- .../src/Spatial/GeometryProperties.cs | 37 +++ sdk/core/Azure.Core/tests/SpatialTests.cs | 174 ++++++++++--- 12 files changed, 513 insertions(+), 73 deletions(-) create mode 100644 sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 8def430c1b5ca..8105196ca49be 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -21,6 +21,9 @@ public class GeoJsonConverter : JsonConverter private const string MultiPolygonType = "MultiPolygon"; private const string GeometryCollectionType = "GeometryCollection"; private const string TypeProperty = "type"; + private const string GeometriesProperty = "geometries"; + private const string CoordinatesProperty = "coordinates"; + private const string BBoxProperty = "bbox"; /// public override Geometry Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) @@ -31,63 +34,64 @@ public override Geometry Read(ref Utf8JsonReader reader, Type typeToConvert, Jso internal static Geometry Read(JsonElement element) { - var typeProperty = GetRequiredProperty(element, TypeProperty); + JsonElement typeProperty = GetRequiredProperty(element, TypeProperty); - var type = typeProperty.GetString(); + string type = typeProperty.GetString(); if (type == GeometryCollectionType) { var geometries = new List(); - foreach (var geometry in GetRequiredProperty(element, "geometries").EnumerateArray()) + foreach (var geometry in GetRequiredProperty(element, GeometriesProperty).EnumerateArray()) { geometries.Add(Read(geometry)); } - return new GeometryCollection(geometries); + return new GeometryCollection(geometries, ReadProperties(element, GeometriesProperty)); } - var coordinates = GetRequiredProperty(element, "coordinates"); + JsonElement coordinates = GetRequiredProperty(element, CoordinatesProperty); + GeometryProperties? properties = ReadProperties(element); switch (type) { case PointType: - return new GeoPoint(ReadCoordinate(coordinates)); + return new GeoPoint(ReadCoordinate(coordinates), properties); case LineStringType: - return new GeoLineString(ReadCoordinates(coordinates)); + return new GeoLineString(ReadCoordinates(coordinates), properties); case MultiPointType: var points = new List(); - foreach (var coordinate in ReadCoordinates(coordinates)) + foreach (GeoPosition coordinate in ReadCoordinates(coordinates)) { points.Add(new GeoPoint(coordinate)); } - return new GeoMultiPoint(points); + return new GeoMultiPoint(points, properties); case PolygonType: var rings = new List(); - foreach (var ringArray in coordinates.EnumerateArray()) + foreach (JsonElement ringArray in coordinates.EnumerateArray()) { rings.Add(new GeoLineString(ReadCoordinates(ringArray))); } - return new GeoPolygon(rings); + return new GeoPolygon(rings, properties); case MultiLineStringType: var lineStrings = new List(); - foreach (var ringArray in coordinates.EnumerateArray()) + foreach (JsonElement ringArray in coordinates.EnumerateArray()) { lineStrings.Add(new GeoLineString(ReadCoordinates(ringArray))); } - return new GeoMultiLineString(lineStrings); + return new GeoMultiLineString(lineStrings, properties); case MultiPolygonType: var polygons = new List(); - foreach (var polygon in coordinates.EnumerateArray()) + foreach (JsonElement polygon in coordinates.EnumerateArray()) { var polygonRings = new List(); - foreach (var ringArray in polygon.EnumerateArray()) + foreach (JsonElement ringArray in polygon.EnumerateArray()) { polygonRings.Add(new GeoLineString(ReadCoordinates(ringArray))); } @@ -95,13 +99,118 @@ internal static Geometry Read(JsonElement element) polygons.Add(new GeoPolygon(polygonRings)); } - return new GeoMultiPolygon(polygons); + return new GeoMultiPolygon(polygons, properties); default: throw new NotSupportedException($"Unsupported geometry type '{type}' "); } } + private static GeometryProperties? ReadProperties(in JsonElement element, string knownProperty = CoordinatesProperty) + { + GeoBoundingBox? bbox = null; + + if (element.TryGetProperty(BBoxProperty, out JsonElement bboxElement)) + { + var arrayLength = bboxElement.GetArrayLength(); + + switch (arrayLength) + { + case 4: + bbox = new GeoBoundingBox( + new GeoPosition( + bboxElement[0].GetDouble(), + bboxElement[1].GetDouble() + ), + new GeoPosition( + bboxElement[2].GetDouble(), + bboxElement[3].GetDouble() + ) + ); + break; + case 6: + bbox = new GeoBoundingBox( + new GeoPosition( + bboxElement[0].GetDouble(), + bboxElement[1].GetDouble(), + bboxElement[2].GetDouble() + ), + new GeoPosition( + bboxElement[3].GetDouble(), + bboxElement[4].GetDouble(), + bboxElement[5].GetDouble() + ) + ); + break; + default: + throw new JsonException("Only 2 or 3 element coordinates supported"); + } + } + + Dictionary? additionalProperties = null; + foreach (var property in element.EnumerateObject()) + { + additionalProperties ??= new Dictionary(); + var propertyName = property.Name; + if (propertyName.Equals(TypeProperty, StringComparison.Ordinal) || + propertyName.Equals(BBoxProperty, StringComparison.Ordinal) || + propertyName.Equals(knownProperty, StringComparison.Ordinal)) + { + continue; + } + additionalProperties.Add(propertyName, ReadAdditionalPropertyValue(property.Value)); + } + + if (bbox != null || additionalProperties != null) + { + return new GeometryProperties(bbox, additionalProperties); + } + + return null; + } + + private static object? ReadAdditionalPropertyValue(in JsonElement element) + { + switch (element.ValueKind) + { + case JsonValueKind.String: + return element.GetString(); + case JsonValueKind.Number: + if (element.TryGetInt32(out int intValue)) + { + return intValue; + } + if (element.TryGetInt64(out long longValue)) + { + return longValue; + } + return element.GetDouble(); + case JsonValueKind.True: + return true; + case JsonValueKind.False: + return false; + case JsonValueKind.Undefined: + case JsonValueKind.Null: + return null; + case JsonValueKind.Object: + var dictionary = new Dictionary(); + foreach (JsonProperty jsonProperty in element.EnumerateObject()) + { + dictionary.Add(jsonProperty.Name, ReadAdditionalPropertyValue(jsonProperty.Value)); + } + return dictionary; + case JsonValueKind.Array: + var list = new List(); + foreach (JsonElement item in element.EnumerateArray()) + { + list.Add(ReadAdditionalPropertyValue(item)); + } + return list.ToArray(); + default: + throw new NotSupportedException("Not supported value kind " + element.ValueKind); + } + } + private static IEnumerable ReadCoordinates(JsonElement coordinates) { foreach (JsonElement coordinate in coordinates.EnumerateArray()) @@ -143,6 +252,16 @@ public override void Write(Utf8JsonWriter writer, Geometry value, JsonSerializer internal static void Write(Utf8JsonWriter writer, Geometry value) { + void WritePositionValues(GeoPosition type) + { + writer.WriteNumberValue(type.Longitude); + writer.WriteNumberValue(type.Latitude); + if (type.Altitude != null) + { + writer.WriteNumberValue(type.Altitude.Value); + } + } + void WriteType(string type) { writer.WriteString(TypeProperty, type); @@ -151,12 +270,7 @@ void WriteType(string type) void WritePosition(GeoPosition type) { writer.WriteStartArray(); - writer.WriteNumberValue(type.Longitude); - writer.WriteNumberValue(type.Latitude); - if (type.Altitude != null) - { - writer.WriteNumberValue(type.Altitude.Value); - } + WritePositionValues(type); writer.WriteEndArray(); } @@ -177,71 +291,78 @@ void WritePositions(IEnumerable positions) { case GeoPoint point: WriteType(PointType); - writer.WritePropertyName("coordinates"); + writer.WritePropertyName(CoordinatesProperty); WritePosition(point.Position); break; case GeoLineString lineString: WriteType(LineStringType); - writer.WritePropertyName("coordinates"); + writer.WritePropertyName(CoordinatesProperty); WritePositions(lineString.Positions); break; case GeoPolygon polygon: WriteType(PolygonType); - writer.WritePropertyName("coordinates"); + writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); foreach (var ring in polygon.Rings) { WritePositions(ring.Positions); } + writer.WriteEndArray(); break; case GeoMultiPoint multiPoint: WriteType(MultiPointType); - writer.WritePropertyName("coordinates"); + writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); foreach (var point in multiPoint.Points) { WritePosition(point.Position); } + writer.WriteEndArray(); break; case GeoMultiLineString multiLineString: WriteType(MultiLineStringType); - writer.WritePropertyName("coordinates"); + writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); foreach (var lineString in multiLineString.LineStrings) { WritePositions(lineString.Positions); } + writer.WriteEndArray(); break; case GeoMultiPolygon multiPolygon: - WriteType(MultiPointType); - writer.WritePropertyName("coordinates"); + WriteType(MultiPolygonType); + writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); foreach (var polygon in multiPolygon.Polygons) { + writer.WriteStartArray(); foreach (var polygonRing in polygon.Rings) { WritePositions(polygonRing.Positions); } + writer.WriteEndArray(); } + writer.WriteEndArray(); break; case GeometryCollection geometryCollection: WriteType(GeometryCollectionType); - writer.WritePropertyName("geometries"); + writer.WritePropertyName(GeometriesProperty); writer.WriteStartArray(); foreach (var geometry in geometryCollection.Geometries) { Write(writer, geometry); } + writer.WriteEndArray(); break; @@ -249,8 +370,70 @@ void WritePositions(IEnumerable positions) throw new NotSupportedException($"Geometry type '{value?.GetType()}' not supported"); } + if (value.Properties.BoundingBox is GeoBoundingBox bbox) + { + writer.WritePropertyName(BBoxProperty); + writer.WriteStartArray(); + WritePositionValues(bbox.Min); + WritePositionValues(bbox.Max); + writer.WriteEndArray(); + } + + foreach (var additionalProperty in value.Properties.AdditionalProperties) + { + writer.WritePropertyName(additionalProperty.Key); + WriteAdditionalPropertyValue(writer, additionalProperty.Value); + } + writer.WriteEndObject(); } + private static void WriteAdditionalPropertyValue(Utf8JsonWriter writer, object? value) + { + switch (value) + { + case null: + writer.WriteNullValue(); + break; + case int i: + writer.WriteNumberValue(i); + break; + case double d: + writer.WriteNumberValue(d); + break; + case float f: + writer.WriteNumberValue(f); + break; + case long l: + writer.WriteNumberValue(l); + break; + case string s: + writer.WriteStringValue(s); + break; + case bool b: + writer.WriteBooleanValue(b); + break; + case IEnumerable> enumerable: + writer.WriteStartObject(); + foreach (KeyValuePair pair in enumerable) + { + writer.WritePropertyName(pair.Key); + WriteAdditionalPropertyValue(writer, pair.Value); + } + writer.WriteEndObject(); + break; + case IEnumerable objectEnumerable: + writer.WriteStartArray(); + foreach (object? item in objectEnumerable) + { + WriteAdditionalPropertyValue(writer, item); + } + writer.WriteEndArray(); + break; + + default: + throw new NotSupportedException("Not supported type " + value.GetType()); + } + } private static JsonElement GetRequiredProperty(JsonElement element, string name) { diff --git a/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs b/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs index 4a522db1b40ab..157d0b443fed1 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs @@ -15,7 +15,16 @@ public sealed class GeoLineString : Geometry /// /// /// - public GeoLineString(IEnumerable positions) + public GeoLineString(IEnumerable positions): this(positions, null) + { + } + + /// + /// + /// + /// + /// + public GeoLineString(IEnumerable positions, GeometryProperties? properties): base(properties) { Positions = positions.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs index 51c6a638715d4..94f5a2770521e 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs @@ -15,7 +15,16 @@ public sealed class GeoMultiLineString : Geometry /// /// /// - public GeoMultiLineString(IEnumerable lineStrings) + public GeoMultiLineString(IEnumerable lineStrings): this(lineStrings, null) + { + } + + /// + /// + /// + /// + /// + public GeoMultiLineString(IEnumerable lineStrings, GeometryProperties? properties): base(properties) { LineStrings = lineStrings.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs index 0d09dcf223dc4..8aa6e0df9348e 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs @@ -15,7 +15,16 @@ public sealed class GeoMultiPoint : Geometry /// /// /// - public GeoMultiPoint(IEnumerable points) + public GeoMultiPoint(IEnumerable points): this(points, null) + { + } + + /// + /// + /// + /// + /// + public GeoMultiPoint(IEnumerable points, GeometryProperties? properties): base(properties) { Points = points.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs index 41dd521008a53..9b6829255e5d1 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs @@ -15,7 +15,16 @@ public sealed class GeoMultiPolygon : Geometry /// /// /// - public GeoMultiPolygon(IEnumerable polygons) + public GeoMultiPolygon(IEnumerable polygons): this(polygons, null) + { + } + + /// + /// + /// + /// + /// + public GeoMultiPolygon(IEnumerable polygons, GeometryProperties? properties): base(properties) { Polygons = polygons.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs b/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs index 6e8cacd01338f..f85f7dd25adb8 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs @@ -12,7 +12,16 @@ public sealed class GeoPoint : Geometry /// /// /// - public GeoPoint(GeoPosition position) + public GeoPoint(GeoPosition position): this(position, null) + { + } + + /// + /// + /// + /// + /// + public GeoPoint(GeoPosition position, GeometryProperties? properties): base(properties) { Position = position; } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs b/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs index 16a56c568f52c..ea68e6861ac27 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs @@ -15,7 +15,16 @@ public sealed class GeoPolygon : Geometry /// /// /// - public GeoPolygon(IEnumerable rings) + public GeoPolygon(IEnumerable rings): this(rings, null) + { + } + + /// + /// + /// + /// + /// + public GeoPolygon(IEnumerable rings, GeometryProperties? properties): base(properties) { Rings = rings.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs b/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs index 62e3b54f80151..87b2dd43fd1df 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs @@ -84,5 +84,19 @@ public override bool Equals(object? obj) { return !left.Equals(right); } + + /// + /// + /// + /// + public override string ToString() + { + if (Altitude == null) + { + return $"[{Longitude:G17}, {Latitude:G17}]"; + } + + return $"[{Longitude:G17}, {Latitude:G17}, {Altitude.Value:G17}]"; + } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs index 1a0e4bdf269f3..1dd0473a03d3a 100644 --- a/sdk/core/Azure.Core/src/Spatial/Geometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -8,5 +8,46 @@ namespace Azure.Core.Spatial /// public class Geometry { + private protected GeometryProperties DefaultProperties = new GeometryProperties(); + + /// + /// + /// + public GeometryProperties Properties { get; } + + /// + /// + /// + /// + public Geometry(GeometryProperties? properties) + { + Properties = properties ?? DefaultProperties; + } + } + + /// + /// + /// + public readonly struct GeoBoundingBox + { + /// + /// + /// + /// + /// + public GeoBoundingBox(GeoPosition min, GeoPosition max) + { + Min = min; + Max = max; + } + + /// + /// + /// + public GeoPosition Min { get; } + /// + /// + /// + public GeoPosition Max { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs index 9937047e9bfd6..793f6268cdce9 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs @@ -15,7 +15,16 @@ public sealed class GeometryCollection : Geometry /// /// /// - public GeometryCollection(IEnumerable geometries) + public GeometryCollection(IEnumerable geometries): this(geometries, null) + { + } + + /// + /// + /// + /// + /// + public GeometryCollection(IEnumerable geometries, GeometryProperties? properties): base(properties) { Geometries = geometries.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs b/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs new file mode 100644 index 0000000000000..0471986b62f3a --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public class GeometryProperties + { + private static readonly IReadOnlyDictionary EmptyReadonlyDictionary = new ReadOnlyDictionary(new Dictionary()); + + /// + /// + /// + /// + /// + public GeometryProperties(GeoBoundingBox? boundingBox = null, IReadOnlyDictionary? additionalProperties = null) + { + BoundingBox = boundingBox; + AdditionalProperties = additionalProperties ?? EmptyReadonlyDictionary; + } + + /// + /// + /// + public GeoBoundingBox? BoundingBox { get; } + + /// + /// + /// + public IReadOnlyDictionary AdditionalProperties { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index ed494a8fcb441..1ed41af4711f6 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -8,122 +8,224 @@ namespace Azure.Core.Tests { + [TestFixture(2)] + [TestFixture(3)] public class SpatialTests { + private readonly int _points; + + public SpatialTests(int points) + { + _points = points; + } + [Test] public void CanRoundripPoint() { - var input = "{ \"type\": \"Point\", \"coordinates\": [100.1, 0.2] }"; + var input = $"{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}] }}"; + + var point = AssertRoundtrip(input); + Assert.AreEqual(P(0), point.Position); + } + + [Test] + public void CanRoundripBBox() + { + var input = $"{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}], \"bbox\": [ {PS(1)}, {PS(2)} ] }}"; var point = AssertRoundtrip(input); - Assert.AreEqual(new GeoPosition(100.1, 0.2), point.Position); + Assert.AreEqual(P(0), point.Position); + Assert.AreEqual(P(1), point.Properties.BoundingBox.Value.Min); + Assert.AreEqual(P(2), point.Properties.BoundingBox.Value.Max); + } + + [Test] + public void CanRoundripAdditionalProperties() + { + var input = $"{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}]," + + $" \"additionalNumber\": 1," + + $" \"additionalNumber2\": 2.2," + + $" \"additionalNumber3\": 9999999999999999999," + + $" \"additionalString\": \"hello\", " + + $" \"additionalBool\": true, " + + $" \"additionalNull\": null, " + + $" \"additionalArray\": [1, 2.2, 9999999999999999999, \"hello\", true, null]" + + $" }}"; + + var point = AssertRoundtrip(input); + Assert.AreEqual(P(0), point.Position); + Assert.AreEqual(1, point.Properties.AdditionalProperties["additionalNumber"]); + Assert.AreEqual(2.2, point.Properties.AdditionalProperties["additionalNumber2"]); + Assert.AreEqual(9999999999999999999L, point.Properties.AdditionalProperties["additionalNumber3"]); + Assert.AreEqual("hello", point.Properties.AdditionalProperties["additionalString"]); + Assert.AreEqual(null, point.Properties.AdditionalProperties["additionalNull"]); + Assert.AreEqual(true, point.Properties.AdditionalProperties["additionalBool"]); + Assert.AreEqual(new object[] {1, 2.2, 9999999999999999999L, "hello", true, null}, point.Properties.AdditionalProperties["additionalArray"]); } [Test] public void CanRoundripPolygon() { - var input = " { \"type\": \"Polygon\", \"coordinates\": [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] ] }"; + var input = $" {{ \"type\": \"Polygon\", \"coordinates\": [ [ [{PS(0)}], [{PS(1)}], [{PS(2)}], [{PS(3)}], [{PS(4)}] ] ] }}"; var polygon = AssertRoundtrip(input); Assert.AreEqual(1, polygon.Rings.Count); CollectionAssert.AreEqual(new[] { - P(100.0, 0.0), - P(101.0, 0.0), - P(101.0, 1.0), - P(100.0, 1.0), - P(100.0, 0.0), + P(0), + P(1), + P(2), + P(3), + P(4), }, polygon.Rings[0].Positions); } [Test] public void CanRoundripPolygonHoles() { - var input = "{ \"type\": \"Polygon\", \"coordinates\": [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ], " + - "[ [100.8, 0.8], [100.8, 0.2], [100.2, 0.2], [100.2, 0.8], [100.8, 0.8] ] ] }"; + var input = $"{{ \"type\": \"Polygon\", \"coordinates\": [" + + $" [ [{PS(0)}], [{PS(1)}], [{PS(2)}], [{PS(3)}], [{PS(4)}] ]," + + $" [ [{PS(5)}], [{PS(6)}], [{PS(7)}], [{PS(8)}], [{PS(9)}] ]" + + $" ] }}"; var polygon = AssertRoundtrip(input); Assert.AreEqual(2, polygon.Rings.Count); CollectionAssert.AreEqual(new[] { - P(100.0, 0.0), - P(101.0, 0.0), - P(101.0, 1.0), - P(100.0, 1.0), - P(100.0, 0.0), + P(0), + P(1), + P(2), + P(3), + P(4), }, polygon.Rings[0].Positions); CollectionAssert.AreEqual(new[] { - P(100.8, 0.8), - P(100.8, 0.2), - P(100.2, 0.2), - P(100.2, 0.8), - P(100.8, 0.8), + P(5), + P(6), + P(7), + P(8), + P(9), }, polygon.Rings[1].Positions); } [Test] public void CanRoundripMultiPoint() { - var input = "{ \"type\": \"MultiPoint\", \"coordinates\": [ [100.0, 0.0], [101.0, 1.0] ] }"; + var input = $"{{ \"type\": \"MultiPoint\", \"coordinates\": [ [{PS(0)}], [{PS(1)}] ] }}"; var multipoint = AssertRoundtrip(input); Assert.AreEqual(2, multipoint.Points.Count); - Assert.AreEqual(P(100.0, 0.0), multipoint.Points[0].Position); - Assert.AreEqual(P(101.0, 1.0), multipoint.Points[1].Position); + Assert.AreEqual(P(0), multipoint.Points[0].Position); + Assert.AreEqual(P(1), multipoint.Points[1].Position); } [Test] public void CanRoundripMultiLineString() { - var input = "{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [100.0, 0.0], [101.0, 1.0] ], [ [102.0, 2.0], [103.0, 3.0] ] ] }"; + var input = $"{{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [{PS(0)}], [{PS(1)}] ], [ [{PS(2)}], [{PS(3)}] ] ] }}"; var polygon = AssertRoundtrip(input); Assert.AreEqual(2, polygon.LineStrings.Count); CollectionAssert.AreEqual(new[] { - P(100.0, 0.0), - P(101.0, 1.0) + P(0), + P(1) }, polygon.LineStrings[0].Positions); CollectionAssert.AreEqual(new[] { - P(102.0, 2.0), - P(103.0, 3.0) + P(2), + P(3) }, polygon.LineStrings[1].Positions); } [Test] public void CanRoundripMultiPolygon() { - var input = " { \"type\": \"MultiPolygon\", \"coordinates\": [ [ [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0] ] ], [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ], [ [100.2, 0.2], [100.2, 0.8], [100.8, 0.8], [100.8, 0.2], [100.2, 0.2] ] ] ] }"; + var input = $" {{ \"type\": \"MultiPolygon\", \"coordinates\": [" + + $" [ [ [{PS(0)}], [{PS(1)}], [{PS(2)}], [{PS(3)}], [{PS(4)}] ] ]," + + $" [" + + $" [ [{PS(0)}], [{PS(1)}], [{PS(2)}], [{PS(3)}], [{PS(4)}] ]," + + $" [ [{PS(5)}], [{PS(6)}], [{PS(7)}], [{PS(8)}], [{PS(9)}] ]" + + $" ] ]}}"; - var point = AssertRoundtrip(input); - Assert.AreEqual(new GeoPosition(100.1, 0.2), point.Position); + var multiPolygon = AssertRoundtrip(input); + + var polygon = multiPolygon.Polygons[0]; + + Assert.AreEqual(1, polygon.Rings.Count); + + CollectionAssert.AreEqual(new[] + { + P(0), + P(1), + P(2), + P(3), + P(4), + }, polygon.Rings[0].Positions); + + polygon = multiPolygon.Polygons[1]; + Assert.AreEqual(2, polygon.Rings.Count); + + CollectionAssert.AreEqual(new[] + { + P(0), + P(1), + P(2), + P(3), + P(4), + }, polygon.Rings[0].Positions); + + CollectionAssert.AreEqual(new[] + { + P(5), + P(6), + P(7), + P(8), + P(9), + }, polygon.Rings[1].Positions); } [Test] public void CanRoundripGeometryCollection() { - var input = "{ \"type\": \"GeometryCollection\", \"geometries\": [{ \"type\": \"Point\", \"coordinates\": [100.1, 0.2] }, { \"type\": \"LineString\", \"coordinates\": [ [101.3, 0.4], [102.5, 1.6] ] }] }"; + var input = $"{{ \"type\": \"GeometryCollection\", \"geometries\": [{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}] }}, {{ \"type\": \"LineString\", \"coordinates\": [ [{PS(1)}], [{PS(2)}] ] }}] }}"; var collection = AssertRoundtrip(input); var point = (GeoPoint) collection.Geometries[0]; - Assert.AreEqual(new GeoPosition(100.1, 0.2), point.Position); + Assert.AreEqual(P(0), point.Position); var lineString = (GeoLineString) collection.Geometries[1]; - Assert.AreEqual(new GeoPosition(101.3, 0.4), lineString.Positions[0]); - Assert.AreEqual(new GeoPosition(102.5, 1.6), lineString.Positions[1]); + Assert.AreEqual(P(1), lineString.Positions[0]); + Assert.AreEqual(P(2), lineString.Positions[1]); Assert.AreEqual(2, collection.Geometries.Count); } - private GeoPosition P(double lon, double lat, double? alt = null) => new GeoPosition(lon, lat, alt); + private string PS(int number) + { + if (_points == 2) + { + return $"{1.1 * number:G17}, {2.2 * number:G17}"; + } + + return $"{1.1 * number:G17}, {2.2 * number:G17}, {3.3 * number:G17}"; + } + + private GeoPosition P(int number) + { + if (_points == 2) + { + return new GeoPosition(1.1 * number, 2.2 * number); + } + + return new GeoPosition(1.1 * number, 2.2 * number, 3.3 * number); + } private T AssertRoundtrip(string json) where T: Geometry { From 2671c9221ae978e43dd930b1a3d783d34ba3988b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 10:41:10 -0700 Subject: [PATCH 06/15] More renames --- .../src/Spatial/GeoJsonConverter.cs | 22 +++++++++---------- .../Spatial/{GeoLineString.cs => GeoLine.cs} | 6 ++--- ...{GeoMultiLineString.cs => GeoMultiLine.cs} | 10 ++++----- sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs | 6 ++--- sdk/core/Azure.Core/tests/SpatialTests.cs | 10 ++++----- 5 files changed, 27 insertions(+), 27 deletions(-) rename sdk/core/Azure.Core/src/Spatial/{GeoLineString.cs => GeoLine.cs} (77%) rename sdk/core/Azure.Core/src/Spatial/{GeoMultiLineString.cs => GeoMultiLine.cs} (60%) diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 8105196ca49be..29871d495971a 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -57,7 +57,7 @@ internal static Geometry Read(JsonElement element) case PointType: return new GeoPoint(ReadCoordinate(coordinates), properties); case LineStringType: - return new GeoLineString(ReadCoordinates(coordinates), properties); + return new GeoLine(ReadCoordinates(coordinates), properties); case MultiPointType: var points = new List(); foreach (GeoPosition coordinate in ReadCoordinates(coordinates)) @@ -68,32 +68,32 @@ internal static Geometry Read(JsonElement element) return new GeoMultiPoint(points, properties); case PolygonType: - var rings = new List(); + var rings = new List(); foreach (JsonElement ringArray in coordinates.EnumerateArray()) { - rings.Add(new GeoLineString(ReadCoordinates(ringArray))); + rings.Add(new GeoLine(ReadCoordinates(ringArray))); } return new GeoPolygon(rings, properties); case MultiLineStringType: - var lineStrings = new List(); + var lineStrings = new List(); foreach (JsonElement ringArray in coordinates.EnumerateArray()) { - lineStrings.Add(new GeoLineString(ReadCoordinates(ringArray))); + lineStrings.Add(new GeoLine(ReadCoordinates(ringArray))); } - return new GeoMultiLineString(lineStrings, properties); + return new GeoMultiLine(lineStrings, properties); case MultiPolygonType: var polygons = new List(); foreach (JsonElement polygon in coordinates.EnumerateArray()) { - var polygonRings = new List(); + var polygonRings = new List(); foreach (JsonElement ringArray in polygon.EnumerateArray()) { - polygonRings.Add(new GeoLineString(ReadCoordinates(ringArray))); + polygonRings.Add(new GeoLine(ReadCoordinates(ringArray))); } polygons.Add(new GeoPolygon(polygonRings)); @@ -295,7 +295,7 @@ void WritePositions(IEnumerable positions) WritePosition(point.Position); break; - case GeoLineString lineString: + case GeoLine lineString: WriteType(LineStringType); writer.WritePropertyName(CoordinatesProperty); WritePositions(lineString.Positions); @@ -325,11 +325,11 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeoMultiLineString multiLineString: + case GeoMultiLine multiLineString: WriteType(MultiLineStringType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); - foreach (var lineString in multiLineString.LineStrings) + foreach (var lineString in multiLineString.Lines) { WritePositions(lineString.Positions); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs b/sdk/core/Azure.Core/src/Spatial/GeoLine.cs similarity index 77% rename from sdk/core/Azure.Core/src/Spatial/GeoLineString.cs rename to sdk/core/Azure.Core/src/Spatial/GeoLine.cs index 157d0b443fed1..56585254b4889 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoLineString.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoLine.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoLineString : Geometry + public sealed class GeoLine : Geometry { /// /// /// /// - public GeoLineString(IEnumerable positions): this(positions, null) + public GeoLine(IEnumerable positions): this(positions, null) { } @@ -24,7 +24,7 @@ public GeoLineString(IEnumerable positions): this(positions, null) /// /// /// - public GeoLineString(IEnumerable positions, GeometryProperties? properties): base(properties) + public GeoLine(IEnumerable positions, GeometryProperties? properties): base(properties) { Positions = positions.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs b/sdk/core/Azure.Core/src/Spatial/GeoMultiLine.cs similarity index 60% rename from sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs rename to sdk/core/Azure.Core/src/Spatial/GeoMultiLine.cs index 94f5a2770521e..4c3a2b9ee239c 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiLineString.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoMultiLine.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoMultiLineString : Geometry + public sealed class GeoMultiLine : Geometry { /// /// /// /// - public GeoMultiLineString(IEnumerable lineStrings): this(lineStrings, null) + public GeoMultiLine(IEnumerable lineStrings): this(lineStrings, null) { } @@ -24,14 +24,14 @@ public GeoMultiLineString(IEnumerable lineStrings): this(lineStri /// /// /// - public GeoMultiLineString(IEnumerable lineStrings, GeometryProperties? properties): base(properties) + public GeoMultiLine(IEnumerable lineStrings, GeometryProperties? properties): base(properties) { - LineStrings = lineStrings.ToArray(); + Lines = lineStrings.ToArray(); } /// /// /// - public IReadOnlyList LineStrings { get; } + public IReadOnlyList Lines { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs b/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs index ea68e6861ac27..71fad16a23b93 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs @@ -15,7 +15,7 @@ public sealed class GeoPolygon : Geometry /// /// /// - public GeoPolygon(IEnumerable rings): this(rings, null) + public GeoPolygon(IEnumerable rings): this(rings, null) { } @@ -24,7 +24,7 @@ public GeoPolygon(IEnumerable rings): this(rings, null) /// /// /// - public GeoPolygon(IEnumerable rings, GeometryProperties? properties): base(properties) + public GeoPolygon(IEnumerable rings, GeometryProperties? properties): base(properties) { Rings = rings.ToArray(); } @@ -32,6 +32,6 @@ public GeoPolygon(IEnumerable rings, GeometryProperties? properti /// /// /// - public IReadOnlyList Rings { get; } + public IReadOnlyList Rings { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index 1ed41af4711f6..b8e7ae1dcdb6e 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -128,20 +128,20 @@ public void CanRoundripMultiLineString() { var input = $"{{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [{PS(0)}], [{PS(1)}] ], [ [{PS(2)}], [{PS(3)}] ] ] }}"; - var polygon = AssertRoundtrip(input); - Assert.AreEqual(2, polygon.LineStrings.Count); + var polygon = AssertRoundtrip(input); + Assert.AreEqual(2, polygon.Lines.Count); CollectionAssert.AreEqual(new[] { P(0), P(1) - }, polygon.LineStrings[0].Positions); + }, polygon.Lines[0].Positions); CollectionAssert.AreEqual(new[] { P(2), P(3) - }, polygon.LineStrings[1].Positions); + }, polygon.Lines[1].Positions); } [Test] @@ -200,7 +200,7 @@ public void CanRoundripGeometryCollection() var point = (GeoPoint) collection.Geometries[0]; Assert.AreEqual(P(0), point.Position); - var lineString = (GeoLineString) collection.Geometries[1]; + var lineString = (GeoLine) collection.Geometries[1]; Assert.AreEqual(P(1), lineString.Positions[0]); Assert.AreEqual(P(2), lineString.Positions[1]); From ee974ba3ce5c579bd925ca3f015878f7e6d8f8e0 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 11:03:10 -0700 Subject: [PATCH 07/15] Renames --- .../src/Spatial/GeoJsonConverter.cs | 92 ++++++++++--------- sdk/core/Azure.Core/src/Spatial/Geometry.cs | 45 +++++++-- .../{GeoMultiLine.cs => GeometryMultiLine.cs} | 8 +- ...GeoMultiPoint.cs => GeometryMultiPoint.cs} | 8 +- .../src/Spatial/GeometryProperties.cs | 4 +- .../Spatial/{GeoLine.cs => LineGeometry.cs} | 8 +- ...ultiPolygon.cs => MultiPolygonGeometry.cs} | 8 +- .../Spatial/{GeoPoint.cs => PointGeometry.cs} | 8 +- .../{GeoPolygon.cs => PolygonGeometry.cs} | 8 +- .../{GeoPosition.cs => PositionGeometry.cs} | 14 +-- sdk/core/Azure.Core/tests/SpatialTests.cs | 36 +++++--- 11 files changed, 136 insertions(+), 103 deletions(-) rename sdk/core/Azure.Core/src/Spatial/{GeoMultiLine.cs => GeometryMultiLine.cs} (65%) rename sdk/core/Azure.Core/src/Spatial/{GeoMultiPoint.cs => GeometryMultiPoint.cs} (65%) rename sdk/core/Azure.Core/src/Spatial/{GeoLine.cs => LineGeometry.cs} (70%) rename sdk/core/Azure.Core/src/Spatial/{GeoMultiPolygon.cs => MultiPolygonGeometry.cs} (64%) rename sdk/core/Azure.Core/src/Spatial/{GeoPoint.cs => PointGeometry.cs} (70%) rename sdk/core/Azure.Core/src/Spatial/{GeoPolygon.cs => PolygonGeometry.cs} (66%) rename sdk/core/Azure.Core/src/Spatial/{GeoPosition.cs => PositionGeometry.cs} (79%) diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 29871d495971a..4fc96ef2ee453 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -55,51 +55,51 @@ internal static Geometry Read(JsonElement element) switch (type) { case PointType: - return new GeoPoint(ReadCoordinate(coordinates), properties); + return new PointGeometry(ReadCoordinate(coordinates), properties); case LineStringType: - return new GeoLine(ReadCoordinates(coordinates), properties); + return new LineGeometry(ReadCoordinates(coordinates), properties); case MultiPointType: - var points = new List(); - foreach (GeoPosition coordinate in ReadCoordinates(coordinates)) + var points = new List(); + foreach (PositionGeometry coordinate in ReadCoordinates(coordinates)) { - points.Add(new GeoPoint(coordinate)); + points.Add(new PointGeometry(coordinate)); } - return new GeoMultiPoint(points, properties); + return new GeometryMultiPoint(points, properties); case PolygonType: - var rings = new List(); + var rings = new List(); foreach (JsonElement ringArray in coordinates.EnumerateArray()) { - rings.Add(new GeoLine(ReadCoordinates(ringArray))); + rings.Add(new LineGeometry(ReadCoordinates(ringArray))); } - return new GeoPolygon(rings, properties); + return new PolygonGeometry(rings, properties); case MultiLineStringType: - var lineStrings = new List(); + var lineStrings = new List(); foreach (JsonElement ringArray in coordinates.EnumerateArray()) { - lineStrings.Add(new GeoLine(ReadCoordinates(ringArray))); + lineStrings.Add(new LineGeometry(ReadCoordinates(ringArray))); } - return new GeoMultiLine(lineStrings, properties); + return new GeometryMultiLine(lineStrings, properties); case MultiPolygonType: - var polygons = new List(); + var polygons = new List(); foreach (JsonElement polygon in coordinates.EnumerateArray()) { - var polygonRings = new List(); + var polygonRings = new List(); foreach (JsonElement ringArray in polygon.EnumerateArray()) { - polygonRings.Add(new GeoLine(ReadCoordinates(ringArray))); + polygonRings.Add(new LineGeometry(ReadCoordinates(ringArray))); } - polygons.Add(new GeoPolygon(polygonRings)); + polygons.Add(new PolygonGeometry(polygonRings)); } - return new GeoMultiPolygon(polygons, properties); + return new MultiPolygonGeometry(polygons, properties); default: throw new NotSupportedException($"Unsupported geometry type '{type}' "); @@ -108,7 +108,7 @@ internal static Geometry Read(JsonElement element) private static GeometryProperties? ReadProperties(in JsonElement element, string knownProperty = CoordinatesProperty) { - GeoBoundingBox? bbox = null; + GeometryBoundingBox? bbox = null; if (element.TryGetProperty(BBoxProperty, out JsonElement bboxElement)) { @@ -117,29 +117,21 @@ internal static Geometry Read(JsonElement element) switch (arrayLength) { case 4: - bbox = new GeoBoundingBox( - new GeoPosition( + bbox = new GeometryBoundingBox( bboxElement[0].GetDouble(), - bboxElement[1].GetDouble() - ), - new GeoPosition( + bboxElement[1].GetDouble(), bboxElement[2].GetDouble(), bboxElement[3].GetDouble() - ) ); break; case 6: - bbox = new GeoBoundingBox( - new GeoPosition( + bbox = new GeometryBoundingBox( bboxElement[0].GetDouble(), bboxElement[1].GetDouble(), - bboxElement[2].GetDouble() - ), - new GeoPosition( bboxElement[3].GetDouble(), bboxElement[4].GetDouble(), + bboxElement[2].GetDouble(), bboxElement[5].GetDouble() - ) ); break; default: @@ -211,7 +203,7 @@ internal static Geometry Read(JsonElement element) } } - private static IEnumerable ReadCoordinates(JsonElement coordinates) + private static IEnumerable ReadCoordinates(JsonElement coordinates) { foreach (JsonElement coordinate in coordinates.EnumerateArray()) { @@ -219,7 +211,7 @@ private static IEnumerable ReadCoordinates(JsonElement coordinates) } } - private static GeoPosition ReadCoordinate(JsonElement coordinate) + private static PositionGeometry ReadCoordinate(JsonElement coordinate) { var arrayLength = coordinate.GetArrayLength(); if (arrayLength < 2 || arrayLength > 3) @@ -236,7 +228,7 @@ private static GeoPosition ReadCoordinate(JsonElement coordinate) altitude = coordinate[2].GetDouble(); } - return new GeoPosition(lon, lat, altitude); + return new PositionGeometry(lon, lat, altitude); } /// @@ -252,7 +244,7 @@ public override void Write(Utf8JsonWriter writer, Geometry value, JsonSerializer internal static void Write(Utf8JsonWriter writer, Geometry value) { - void WritePositionValues(GeoPosition type) + void WritePositionValues(PositionGeometry type) { writer.WriteNumberValue(type.Longitude); writer.WriteNumberValue(type.Latitude); @@ -267,7 +259,7 @@ void WriteType(string type) writer.WriteString(TypeProperty, type); } - void WritePosition(GeoPosition type) + void WritePosition(PositionGeometry type) { writer.WriteStartArray(); WritePositionValues(type); @@ -275,7 +267,7 @@ void WritePosition(GeoPosition type) writer.WriteEndArray(); } - void WritePositions(IEnumerable positions) + void WritePositions(IEnumerable positions) { writer.WriteStartArray(); foreach (var position in positions) @@ -289,19 +281,19 @@ void WritePositions(IEnumerable positions) writer.WriteStartObject(); switch (value) { - case GeoPoint point: + case PointGeometry point: WriteType(PointType); writer.WritePropertyName(CoordinatesProperty); WritePosition(point.Position); break; - case GeoLine lineString: + case LineGeometry lineString: WriteType(LineStringType); writer.WritePropertyName(CoordinatesProperty); WritePositions(lineString.Positions); break; - case GeoPolygon polygon: + case PolygonGeometry polygon: WriteType(PolygonType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); @@ -313,7 +305,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeoMultiPoint multiPoint: + case GeometryMultiPoint multiPoint: WriteType(MultiPointType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); @@ -325,7 +317,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeoMultiLine multiLineString: + case GeometryMultiLine multiLineString: WriteType(MultiLineStringType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); @@ -337,7 +329,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeoMultiPolygon multiPolygon: + case MultiPolygonGeometry multiPolygon: WriteType(MultiPolygonType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); @@ -370,12 +362,22 @@ void WritePositions(IEnumerable positions) throw new NotSupportedException($"Geometry type '{value?.GetType()}' not supported"); } - if (value.Properties.BoundingBox is GeoBoundingBox bbox) + if (value.Properties.BoundingBox is GeometryBoundingBox bbox) { writer.WritePropertyName(BBoxProperty); writer.WriteStartArray(); - WritePositionValues(bbox.Min); - WritePositionValues(bbox.Max); + writer.WriteNumberValue(bbox.West); + writer.WriteNumberValue(bbox.South); + if (bbox.MinAltitude != null) + { + writer.WriteNumberValue(bbox.MinAltitude.Value); + } + writer.WriteNumberValue(bbox.East); + writer.WriteNumberValue(bbox.North); + if (bbox.MaxAltitude != null) + { + writer.WriteNumberValue(bbox.MaxAltitude.Value); + } writer.WriteEndArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs index 1dd0473a03d3a..4ed4ec6af5738 100644 --- a/sdk/core/Azure.Core/src/Spatial/Geometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -28,26 +28,51 @@ public Geometry(GeometryProperties? properties) /// /// /// - public readonly struct GeoBoundingBox + public readonly struct GeometryBoundingBox { /// /// /// - /// - /// - public GeoBoundingBox(GeoPosition min, GeoPosition max) - { - Min = min; - Max = max; - } + public double West { get; } + /// + /// + /// + public double South { get; } + /// + /// + /// + public double East { get; } + /// + /// + /// + public double North { get; } + /// + /// + /// + public double? MinAltitude { get; } + /// + /// + /// + public double? MaxAltitude { get; } /// /// /// - public GeoPosition Min { get; } + public GeometryBoundingBox(double west, double south, double east, double north) : this(west, south, east, north, null, null) + { + } + /// /// /// - public GeoPosition Max { get; } + public GeometryBoundingBox(double west, double south, double east, double north, double? minAltitude, double? maxAltitude) + { + West = west; + South = south; + East = east; + North = north; + MinAltitude = minAltitude; + MaxAltitude = maxAltitude; + } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiLine.cs b/sdk/core/Azure.Core/src/Spatial/GeometryMultiLine.cs similarity index 65% rename from sdk/core/Azure.Core/src/Spatial/GeoMultiLine.cs rename to sdk/core/Azure.Core/src/Spatial/GeometryMultiLine.cs index 4c3a2b9ee239c..af5c1ca61f0cc 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiLine.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryMultiLine.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoMultiLine : Geometry + public sealed class GeometryMultiLine : Geometry { /// /// /// /// - public GeoMultiLine(IEnumerable lineStrings): this(lineStrings, null) + public GeometryMultiLine(IEnumerable lineStrings): this(lineStrings, null) { } @@ -24,7 +24,7 @@ public GeoMultiLine(IEnumerable lineStrings): this(lineStrings, null) /// /// /// - public GeoMultiLine(IEnumerable lineStrings, GeometryProperties? properties): base(properties) + public GeometryMultiLine(IEnumerable lineStrings, GeometryProperties? properties): base(properties) { Lines = lineStrings.ToArray(); } @@ -32,6 +32,6 @@ public GeoMultiLine(IEnumerable lineStrings, GeometryProperties? proper /// /// /// - public IReadOnlyList Lines { get; } + public IReadOnlyList Lines { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs b/sdk/core/Azure.Core/src/Spatial/GeometryMultiPoint.cs similarity index 65% rename from sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs rename to sdk/core/Azure.Core/src/Spatial/GeometryMultiPoint.cs index 8aa6e0df9348e..d31f67c187a28 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiPoint.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryMultiPoint.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoMultiPoint : Geometry + public sealed class GeometryMultiPoint : Geometry { /// /// /// /// - public GeoMultiPoint(IEnumerable points): this(points, null) + public GeometryMultiPoint(IEnumerable points): this(points, null) { } @@ -24,7 +24,7 @@ public GeoMultiPoint(IEnumerable points): this(points, null) /// /// /// - public GeoMultiPoint(IEnumerable points, GeometryProperties? properties): base(properties) + public GeometryMultiPoint(IEnumerable points, GeometryProperties? properties): base(properties) { Points = points.ToArray(); } @@ -32,6 +32,6 @@ public GeoMultiPoint(IEnumerable points, GeometryProperties? propertie /// /// /// - public IReadOnlyList Points { get; } + public IReadOnlyList Points { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs b/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs index 0471986b62f3a..c018bc1c8e6b6 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs @@ -18,7 +18,7 @@ public class GeometryProperties /// /// /// - public GeometryProperties(GeoBoundingBox? boundingBox = null, IReadOnlyDictionary? additionalProperties = null) + public GeometryProperties(GeometryBoundingBox? boundingBox = null, IReadOnlyDictionary? additionalProperties = null) { BoundingBox = boundingBox; AdditionalProperties = additionalProperties ?? EmptyReadonlyDictionary; @@ -27,7 +27,7 @@ public GeometryProperties(GeoBoundingBox? boundingBox = null, IReadOnlyDictionar /// /// /// - public GeoBoundingBox? BoundingBox { get; } + public GeometryBoundingBox? BoundingBox { get; } /// /// diff --git a/sdk/core/Azure.Core/src/Spatial/GeoLine.cs b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs similarity index 70% rename from sdk/core/Azure.Core/src/Spatial/GeoLine.cs rename to sdk/core/Azure.Core/src/Spatial/LineGeometry.cs index 56585254b4889..2b19c989c032b 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoLine.cs +++ b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoLine : Geometry + public sealed class LineGeometry : Geometry { /// /// /// /// - public GeoLine(IEnumerable positions): this(positions, null) + public LineGeometry(IEnumerable positions): this(positions, null) { } @@ -24,7 +24,7 @@ public GeoLine(IEnumerable positions): this(positions, null) /// /// /// - public GeoLine(IEnumerable positions, GeometryProperties? properties): base(properties) + public LineGeometry(IEnumerable positions, GeometryProperties? properties): base(properties) { Positions = positions.ToArray(); } @@ -32,7 +32,7 @@ public GeoLine(IEnumerable positions, GeometryProperties? propertie /// /// /// - public IReadOnlyList Positions { get; } + public IReadOnlyList Positions { get; } /// public override string ToString() diff --git a/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs b/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs similarity index 64% rename from sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs rename to sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs index 9b6829255e5d1..cc4bc186c0103 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoMultiPolygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoMultiPolygon : Geometry + public sealed class MultiPolygonGeometry : Geometry { /// /// /// /// - public GeoMultiPolygon(IEnumerable polygons): this(polygons, null) + public MultiPolygonGeometry(IEnumerable polygons): this(polygons, null) { } @@ -24,7 +24,7 @@ public GeoMultiPolygon(IEnumerable polygons): this(polygons, null) /// /// /// - public GeoMultiPolygon(IEnumerable polygons, GeometryProperties? properties): base(properties) + public MultiPolygonGeometry(IEnumerable polygons, GeometryProperties? properties): base(properties) { Polygons = polygons.ToArray(); } @@ -32,6 +32,6 @@ public GeoMultiPolygon(IEnumerable polygons, GeometryProperties? pro /// /// /// - public IReadOnlyList Polygons { get; } + public IReadOnlyList Polygons { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs b/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs similarity index 70% rename from sdk/core/Azure.Core/src/Spatial/GeoPoint.cs rename to sdk/core/Azure.Core/src/Spatial/PointGeometry.cs index f85f7dd25adb8..37517e996c6f7 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPoint.cs +++ b/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs @@ -6,13 +6,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoPoint : Geometry + public sealed class PointGeometry : Geometry { /// /// /// /// - public GeoPoint(GeoPosition position): this(position, null) + public PointGeometry(PositionGeometry position): this(position, null) { } @@ -21,7 +21,7 @@ public GeoPoint(GeoPosition position): this(position, null) /// /// /// - public GeoPoint(GeoPosition position, GeometryProperties? properties): base(properties) + public PointGeometry(PositionGeometry position, GeometryProperties? properties): base(properties) { Position = position; } @@ -29,7 +29,7 @@ public GeoPoint(GeoPosition position, GeometryProperties? properties): base(prop /// /// /// - public GeoPosition Position { get; } + public PositionGeometry Position { get; } /// public override string ToString() => $"Point: {Position}"; diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs b/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs similarity index 66% rename from sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs rename to sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs index 71fad16a23b93..f2cccf08ea47b 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPolygon.cs +++ b/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeoPolygon : Geometry + public sealed class PolygonGeometry : Geometry { /// /// /// /// - public GeoPolygon(IEnumerable rings): this(rings, null) + public PolygonGeometry(IEnumerable rings): this(rings, null) { } @@ -24,7 +24,7 @@ public GeoPolygon(IEnumerable rings): this(rings, null) /// /// /// - public GeoPolygon(IEnumerable rings, GeometryProperties? properties): base(properties) + public PolygonGeometry(IEnumerable rings, GeometryProperties? properties): base(properties) { Rings = rings.ToArray(); } @@ -32,6 +32,6 @@ public GeoPolygon(IEnumerable rings, GeometryProperties? properties): b /// /// /// - public IReadOnlyList Rings { get; } + public IReadOnlyList Rings { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs b/sdk/core/Azure.Core/src/Spatial/PositionGeometry.cs similarity index 79% rename from sdk/core/Azure.Core/src/Spatial/GeoPosition.cs rename to sdk/core/Azure.Core/src/Spatial/PositionGeometry.cs index 87b2dd43fd1df..db0f75bfc5ece 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoPosition.cs +++ b/sdk/core/Azure.Core/src/Spatial/PositionGeometry.cs @@ -8,7 +8,7 @@ namespace Azure.Core.Spatial /// /// /// - public readonly struct GeoPosition : IEquatable + public readonly struct PositionGeometry : IEquatable { /// /// @@ -30,7 +30,7 @@ namespace Azure.Core.Spatial /// /// /// - public GeoPosition(double longitude, double latitude) : this(longitude, latitude, null) + public PositionGeometry(double longitude, double latitude) : this(longitude, latitude, null) { } @@ -40,7 +40,7 @@ public GeoPosition(double longitude, double latitude) : this(longitude, latitude /// /// /// - public GeoPosition(double longitude, double latitude, double? altitude) + public PositionGeometry(double longitude, double latitude, double? altitude) { Longitude = longitude; Latitude = latitude; @@ -49,7 +49,7 @@ public GeoPosition(double longitude, double latitude, double? altitude) /// - public bool Equals(GeoPosition other) + public bool Equals(PositionGeometry other) { return Nullable.Equals(Altitude, other.Altitude) && Longitude.Equals(other.Longitude) && Latitude.Equals(other.Latitude); } @@ -57,7 +57,7 @@ public bool Equals(GeoPosition other) /// public override bool Equals(object? obj) { - return obj is GeoPosition other && Equals(other); + return obj is PositionGeometry other && Equals(other); } /// @@ -69,7 +69,7 @@ public override bool Equals(object? obj) /// /// /// - public static bool operator ==(GeoPosition left, GeoPosition right) + public static bool operator ==(PositionGeometry left, PositionGeometry right) { return left.Equals(right); } @@ -80,7 +80,7 @@ public override bool Equals(object? obj) /// /// /// - public static bool operator !=(GeoPosition left, GeoPosition right) + public static bool operator !=(PositionGeometry left, PositionGeometry right) { return !left.Equals(right); } diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index b8e7ae1dcdb6e..9d7d79c53ff23 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -24,7 +24,7 @@ public void CanRoundripPoint() { var input = $"{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}] }}"; - var point = AssertRoundtrip(input); + var point = AssertRoundtrip(input); Assert.AreEqual(P(0), point.Position); } @@ -33,10 +33,16 @@ public void CanRoundripBBox() { var input = $"{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}], \"bbox\": [ {PS(1)}, {PS(2)} ] }}"; - var point = AssertRoundtrip(input); + var point = AssertRoundtrip(input); Assert.AreEqual(P(0), point.Position); - Assert.AreEqual(P(1), point.Properties.BoundingBox.Value.Min); - Assert.AreEqual(P(2), point.Properties.BoundingBox.Value.Max); + Assert.AreEqual(P(1).Longitude, point.Properties.BoundingBox.Value.West); + Assert.AreEqual(P(1).Latitude, point.Properties.BoundingBox.Value.South); + + Assert.AreEqual(P(2).Longitude, point.Properties.BoundingBox.Value.East); + Assert.AreEqual(P(2).Latitude, point.Properties.BoundingBox.Value.North); + + Assert.AreEqual(P(1).Altitude, point.Properties.BoundingBox.Value.MinAltitude); + Assert.AreEqual(P(2).Altitude, point.Properties.BoundingBox.Value.MaxAltitude); } [Test] @@ -52,7 +58,7 @@ public void CanRoundripAdditionalProperties() $" \"additionalArray\": [1, 2.2, 9999999999999999999, \"hello\", true, null]" + $" }}"; - var point = AssertRoundtrip(input); + var point = AssertRoundtrip(input); Assert.AreEqual(P(0), point.Position); Assert.AreEqual(1, point.Properties.AdditionalProperties["additionalNumber"]); Assert.AreEqual(2.2, point.Properties.AdditionalProperties["additionalNumber2"]); @@ -68,7 +74,7 @@ public void CanRoundripPolygon() { var input = $" {{ \"type\": \"Polygon\", \"coordinates\": [ [ [{PS(0)}], [{PS(1)}], [{PS(2)}], [{PS(3)}], [{PS(4)}] ] ] }}"; - var polygon = AssertRoundtrip(input); + var polygon = AssertRoundtrip(input); Assert.AreEqual(1, polygon.Rings.Count); CollectionAssert.AreEqual(new[] @@ -89,7 +95,7 @@ public void CanRoundripPolygonHoles() $" [ [{PS(5)}], [{PS(6)}], [{PS(7)}], [{PS(8)}], [{PS(9)}] ]" + $" ] }}"; - var polygon = AssertRoundtrip(input); + var polygon = AssertRoundtrip(input); Assert.AreEqual(2, polygon.Rings.Count); CollectionAssert.AreEqual(new[] @@ -116,7 +122,7 @@ public void CanRoundripMultiPoint() { var input = $"{{ \"type\": \"MultiPoint\", \"coordinates\": [ [{PS(0)}], [{PS(1)}] ] }}"; - var multipoint = AssertRoundtrip(input); + var multipoint = AssertRoundtrip(input); Assert.AreEqual(2, multipoint.Points.Count); Assert.AreEqual(P(0), multipoint.Points[0].Position); @@ -128,7 +134,7 @@ public void CanRoundripMultiLineString() { var input = $"{{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [{PS(0)}], [{PS(1)}] ], [ [{PS(2)}], [{PS(3)}] ] ] }}"; - var polygon = AssertRoundtrip(input); + var polygon = AssertRoundtrip(input); Assert.AreEqual(2, polygon.Lines.Count); CollectionAssert.AreEqual(new[] @@ -154,7 +160,7 @@ public void CanRoundripMultiPolygon() $" [ [{PS(5)}], [{PS(6)}], [{PS(7)}], [{PS(8)}], [{PS(9)}] ]" + $" ] ]}}"; - var multiPolygon = AssertRoundtrip(input); + var multiPolygon = AssertRoundtrip(input); var polygon = multiPolygon.Polygons[0]; @@ -197,10 +203,10 @@ public void CanRoundripGeometryCollection() var input = $"{{ \"type\": \"GeometryCollection\", \"geometries\": [{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}] }}, {{ \"type\": \"LineString\", \"coordinates\": [ [{PS(1)}], [{PS(2)}] ] }}] }}"; var collection = AssertRoundtrip(input); - var point = (GeoPoint) collection.Geometries[0]; + var point = (PointGeometry) collection.Geometries[0]; Assert.AreEqual(P(0), point.Position); - var lineString = (GeoLine) collection.Geometries[1]; + var lineString = (LineGeometry) collection.Geometries[1]; Assert.AreEqual(P(1), lineString.Positions[0]); Assert.AreEqual(P(2), lineString.Positions[1]); @@ -217,14 +223,14 @@ private string PS(int number) return $"{1.1 * number:G17}, {2.2 * number:G17}, {3.3 * number:G17}"; } - private GeoPosition P(int number) + private PositionGeometry P(int number) { if (_points == 2) { - return new GeoPosition(1.1 * number, 2.2 * number); + return new PositionGeometry(1.1 * number, 2.2 * number); } - return new GeoPosition(1.1 * number, 2.2 * number, 3.3 * number); + return new PositionGeometry(1.1 * number, 2.2 * number, 3.3 * number); } private T AssertRoundtrip(string json) where T: Geometry From 63a5a80f7f0836a92da6514a25a3ad406d04a4f2 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 11:10:05 -0700 Subject: [PATCH 08/15] Renames --- sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs | 8 ++++---- sdk/core/Azure.Core/src/Spatial/Geometry.cs | 2 +- .../{GeometryMultiLine.cs => MultiLineGeometry.cs} | 6 +++--- .../{GeometryMultiPoint.cs => MultiPointGeometry.cs} | 6 +++--- sdk/core/Azure.Core/tests/SpatialTests.cs | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) rename sdk/core/Azure.Core/src/Spatial/{GeometryMultiLine.cs => MultiLineGeometry.cs} (81%) rename sdk/core/Azure.Core/src/Spatial/{GeometryMultiPoint.cs => MultiPointGeometry.cs} (80%) diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 4fc96ef2ee453..0722496dbbeb7 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -65,7 +65,7 @@ internal static Geometry Read(JsonElement element) points.Add(new PointGeometry(coordinate)); } - return new GeometryMultiPoint(points, properties); + return new MultiPointGeometry(points, properties); case PolygonType: var rings = new List(); @@ -83,7 +83,7 @@ internal static Geometry Read(JsonElement element) lineStrings.Add(new LineGeometry(ReadCoordinates(ringArray))); } - return new GeometryMultiLine(lineStrings, properties); + return new MultiLineGeometry(lineStrings, properties); case MultiPolygonType: @@ -305,7 +305,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeometryMultiPoint multiPoint: + case MultiPointGeometry multiPoint: WriteType(MultiPointType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); @@ -317,7 +317,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeometryMultiLine multiLineString: + case MultiLineGeometry multiLineString: WriteType(MultiLineStringType); writer.WritePropertyName(CoordinatesProperty); writer.WriteStartArray(); diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs index 4ed4ec6af5738..875ae2dd5cc22 100644 --- a/sdk/core/Azure.Core/src/Spatial/Geometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -8,7 +8,7 @@ namespace Azure.Core.Spatial /// public class Geometry { - private protected GeometryProperties DefaultProperties = new GeometryProperties(); + private static readonly GeometryProperties DefaultProperties = new GeometryProperties(); /// /// diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryMultiLine.cs b/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs similarity index 81% rename from sdk/core/Azure.Core/src/Spatial/GeometryMultiLine.cs rename to sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs index af5c1ca61f0cc..d508bc4ac12dc 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryMultiLine.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeometryMultiLine : Geometry + public sealed class MultiLineGeometry : Geometry { /// /// /// /// - public GeometryMultiLine(IEnumerable lineStrings): this(lineStrings, null) + public MultiLineGeometry(IEnumerable lineStrings): this(lineStrings, null) { } @@ -24,7 +24,7 @@ public GeometryMultiLine(IEnumerable lineStrings): this(lineString /// /// /// - public GeometryMultiLine(IEnumerable lineStrings, GeometryProperties? properties): base(properties) + public MultiLineGeometry(IEnumerable lineStrings, GeometryProperties? properties): base(properties) { Lines = lineStrings.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryMultiPoint.cs b/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs similarity index 80% rename from sdk/core/Azure.Core/src/Spatial/GeometryMultiPoint.cs rename to sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs index d31f67c187a28..545b1c8410895 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryMultiPoint.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs @@ -9,13 +9,13 @@ namespace Azure.Core.Spatial /// /// /// - public sealed class GeometryMultiPoint : Geometry + public sealed class MultiPointGeometry : Geometry { /// /// /// /// - public GeometryMultiPoint(IEnumerable points): this(points, null) + public MultiPointGeometry(IEnumerable points): this(points, null) { } @@ -24,7 +24,7 @@ public GeometryMultiPoint(IEnumerable points): this(points, null) /// /// /// - public GeometryMultiPoint(IEnumerable points, GeometryProperties? properties): base(properties) + public MultiPointGeometry(IEnumerable points, GeometryProperties? properties): base(properties) { Points = points.ToArray(); } diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index 9d7d79c53ff23..a540eb7a19169 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -122,7 +122,7 @@ public void CanRoundripMultiPoint() { var input = $"{{ \"type\": \"MultiPoint\", \"coordinates\": [ [{PS(0)}], [{PS(1)}] ] }}"; - var multipoint = AssertRoundtrip(input); + var multipoint = AssertRoundtrip(input); Assert.AreEqual(2, multipoint.Points.Count); Assert.AreEqual(P(0), multipoint.Points[0].Position); @@ -134,7 +134,7 @@ public void CanRoundripMultiLineString() { var input = $"{{ \"type\": \"MultiLineString\", \"coordinates\": [ [ [{PS(0)}], [{PS(1)}] ], [ [{PS(2)}], [{PS(3)}] ] ] }}"; - var polygon = AssertRoundtrip(input); + var polygon = AssertRoundtrip(input); Assert.AreEqual(2, polygon.Lines.Count); CollectionAssert.AreEqual(new[] From 0af4dd1263817c60aa68b2e1853610b4bec711d4 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 11:36:03 -0700 Subject: [PATCH 09/15] Cleanup --- sdk/core/Azure.Core/src/Spatial/Geometry.cs | 51 ----------------- .../src/Spatial/GeometryBoundingBox.cs | 56 +++++++++++++++++++ .../Azure.Core/src/Spatial/LineGeometry.cs | 6 -- 3 files changed, 56 insertions(+), 57 deletions(-) create mode 100644 sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs index 875ae2dd5cc22..aa825d81c0d34 100644 --- a/sdk/core/Azure.Core/src/Spatial/Geometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -24,55 +24,4 @@ public Geometry(GeometryProperties? properties) Properties = properties ?? DefaultProperties; } } - - /// - /// - /// - public readonly struct GeometryBoundingBox - { - /// - /// - /// - public double West { get; } - /// - /// - /// - public double South { get; } - /// - /// - /// - public double East { get; } - /// - /// - /// - public double North { get; } - /// - /// - /// - public double? MinAltitude { get; } - /// - /// - /// - public double? MaxAltitude { get; } - - /// - /// - /// - public GeometryBoundingBox(double west, double south, double east, double north) : this(west, south, east, north, null, null) - { - } - - /// - /// - /// - public GeometryBoundingBox(double west, double south, double east, double north, double? minAltitude, double? maxAltitude) - { - West = west; - South = south; - East = east; - North = north; - MinAltitude = minAltitude; - MaxAltitude = maxAltitude; - } - } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs b/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs new file mode 100644 index 0000000000000..271b24c616654 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.Core.Spatial +{ + /// + /// + /// + public readonly struct GeometryBoundingBox + { + /// + /// + /// + public double West { get; } + /// + /// + /// + public double South { get; } + /// + /// + /// + public double East { get; } + /// + /// + /// + public double North { get; } + /// + /// + /// + public double? MinAltitude { get; } + /// + /// + /// + public double? MaxAltitude { get; } + + /// + /// + /// + public GeometryBoundingBox(double west, double south, double east, double north) : this(west, south, east, north, null, null) + { + } + + /// + /// + /// + public GeometryBoundingBox(double west, double south, double east, double north, double? minAltitude, double? maxAltitude) + { + West = west; + South = south; + East = east; + North = north; + MinAltitude = minAltitude; + MaxAltitude = maxAltitude; + } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs index 2b19c989c032b..81580055b36a0 100644 --- a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs @@ -33,11 +33,5 @@ public LineGeometry(IEnumerable positions, GeometryProperties? /// /// public IReadOnlyList Positions { get; } - - /// - public override string ToString() - { - return $"LineString: {Positions.Count} points"; - } } } \ No newline at end of file From c955687639dd80c54e3787a2787f7d374bda53c5 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 11:49:01 -0700 Subject: [PATCH 10/15] Some comments --- .../src/Spatial/GeoJsonConverter.cs | 2 +- sdk/core/Azure.Core/src/Spatial/Geometry.cs | 10 ++++---- .../src/Spatial/GeometryBoundingBox.cs | 23 +++++++++++-------- .../src/Spatial/GeometryCollection.cs | 2 +- .../src/Spatial/GeometryProperties.cs | 12 +++++----- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs index 0722496dbbeb7..40db4d717d6b8 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs @@ -9,7 +9,7 @@ namespace Azure.Core.Spatial { /// - /// + /// Converts a value from and to JSON. /// public class GeoJsonConverter : JsonConverter { diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs index aa825d81c0d34..c5599b793081d 100644 --- a/sdk/core/Azure.Core/src/Spatial/Geometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -4,22 +4,22 @@ namespace Azure.Core.Spatial { /// - /// + /// A base type for all spatial types. /// public class Geometry { private static readonly GeometryProperties DefaultProperties = new GeometryProperties(); /// - /// + /// The associated with this instance. /// public GeometryProperties Properties { get; } /// - /// + /// Initializes a new instance of . /// - /// - public Geometry(GeometryProperties? properties) + /// The to use. + protected Geometry(GeometryProperties? properties) { Properties = properties ?? DefaultProperties; } diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs b/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs index 271b24c616654..926d3b3c25225 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs @@ -4,44 +4,49 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents information about the coordinate range of the . /// public readonly struct GeometryBoundingBox { /// - /// + /// The westmost value of coordinates. /// public double West { get; } + /// - /// + /// The southmost value of coordinates. /// public double South { get; } + /// - /// + /// The eastmost value of coordinates. /// public double East { get; } + /// - /// + /// The northmost value of coordinates. /// public double North { get; } + /// - /// + /// The minimum altitude value of coordinates. /// public double? MinAltitude { get; } + /// - /// + /// The maximum altitude value of coordinates. /// public double? MaxAltitude { get; } /// - /// + /// Initializes a new instance of . /// public GeometryBoundingBox(double west, double south, double east, double north) : this(west, south, east, north, null, null) { } /// - /// + /// Initializes a new instance of . /// public GeometryBoundingBox(double west, double south, double east, double north, double? minAltitude, double? maxAltitude) { diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs index 793f6268cdce9..e591daa3973b2 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs @@ -7,7 +7,7 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a geometry that is composed of multiple geometries. /// public sealed class GeometryCollection : Geometry { diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs b/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs index c018bc1c8e6b6..1f5df04d36899 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs @@ -7,17 +7,17 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents additional information that can be associated with . /// public class GeometryProperties { private static readonly IReadOnlyDictionary EmptyReadonlyDictionary = new ReadOnlyDictionary(new Dictionary()); /// - /// + /// Initializes a new instance of class. /// - /// - /// + /// The to use. + /// The set of additional properties associated with the . public GeometryProperties(GeometryBoundingBox? boundingBox = null, IReadOnlyDictionary? additionalProperties = null) { BoundingBox = boundingBox; @@ -25,12 +25,12 @@ public GeometryProperties(GeometryBoundingBox? boundingBox = null, IReadOnlyDict } /// - /// + /// Represents information about the coordinate range of the . /// public GeometryBoundingBox? BoundingBox { get; } /// - /// + /// Gets a dictionary of additional properties associated with the . /// public IReadOnlyDictionary AdditionalProperties { get; } } From f8fbeaa1d6de712d44fc329180a26f543ce3add5 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 14:26:40 -0700 Subject: [PATCH 11/15] Renames and API fixes. --- .../src/Spatial/CollectionGeometry.cs | 39 ++++++++++++ sdk/core/Azure.Core/src/Spatial/Geometry.cs | 8 ++- .../src/Spatial/GeometryCollection.cs | 37 ----------- ...nConverter.cs => GeometryJsonConverter.cs} | 63 +++++++++---------- ...ositionGeometry.cs => GeometryPosition.cs} | 26 ++++---- .../Azure.Core/src/Spatial/LineGeometry.cs | 12 ++-- .../src/Spatial/MultiLineGeometry.cs | 6 +- .../src/Spatial/MultiPointGeometry.cs | 6 +- .../src/Spatial/MultiPolygonGeometry.cs | 6 +- .../Azure.Core/src/Spatial/PointGeometry.cs | 11 ++-- .../Azure.Core/src/Spatial/PolygonGeometry.cs | 14 +++-- sdk/core/Azure.Core/tests/SpatialTests.cs | 14 ++--- 12 files changed, 124 insertions(+), 118 deletions(-) create mode 100644 sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs delete mode 100644 sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs rename sdk/core/Azure.Core/src/Spatial/{GeoJsonConverter.cs => GeometryJsonConverter.cs} (91%) rename sdk/core/Azure.Core/src/Spatial/{PositionGeometry.cs => GeometryPosition.cs} (71%) diff --git a/sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs b/sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs new file mode 100644 index 0000000000000..cb289ce00b470 --- /dev/null +++ b/sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; +using System.Linq; + +namespace Azure.Core.Spatial +{ + /// + /// Represents a geometry that is composed of multiple geometries. + /// + public sealed class CollectionGeometry : Geometry + { + /// + /// Initializes new instance of . + /// + /// The list of inner geometries. + public CollectionGeometry(IEnumerable geometries): this(geometries, DefaultProperties) + { + } + + /// + /// Initializes new instance of . + /// + /// The list of inner geometries. + /// The associated with the geometry. + public CollectionGeometry(IEnumerable geometries, GeometryProperties properties): base(properties) + { + Argument.AssertNotNull(geometries, nameof(geometries)); + + Geometries = geometries.ToArray(); + } + + /// + /// Gets the list of geometry is composed of. + /// + public IReadOnlyList Geometries { get; } + } +} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core/src/Spatial/Geometry.cs index c5599b793081d..e326c7f65c32d 100644 --- a/sdk/core/Azure.Core/src/Spatial/Geometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/Geometry.cs @@ -8,7 +8,7 @@ namespace Azure.Core.Spatial /// public class Geometry { - private static readonly GeometryProperties DefaultProperties = new GeometryProperties(); + internal static readonly GeometryProperties DefaultProperties = new GeometryProperties(); /// /// The associated with this instance. @@ -19,9 +19,11 @@ public class Geometry /// Initializes a new instance of . /// /// The to use. - protected Geometry(GeometryProperties? properties) + protected Geometry(GeometryProperties properties) { - Properties = properties ?? DefaultProperties; + Argument.AssertNotNull(properties, nameof(properties)); + + Properties = properties; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs b/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs deleted file mode 100644 index e591daa3973b2..0000000000000 --- a/sdk/core/Azure.Core/src/Spatial/GeometryCollection.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Linq; - -namespace Azure.Core.Spatial -{ - /// - /// Represents a geometry that is composed of multiple geometries. - /// - public sealed class GeometryCollection : Geometry - { - /// - /// - /// - /// - public GeometryCollection(IEnumerable geometries): this(geometries, null) - { - } - - /// - /// - /// - /// - /// - public GeometryCollection(IEnumerable geometries, GeometryProperties? properties): base(properties) - { - Geometries = geometries.ToArray(); - } - - /// - /// - /// - public IReadOnlyList Geometries { get; } - } -} \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs b/sdk/core/Azure.Core/src/Spatial/GeometryJsonConverter.cs similarity index 91% rename from sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs rename to sdk/core/Azure.Core/src/Spatial/GeometryJsonConverter.cs index 40db4d717d6b8..a808abf3c91da 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeoJsonConverter.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryJsonConverter.cs @@ -9,9 +9,9 @@ namespace Azure.Core.Spatial { /// - /// Converts a value from and to JSON. + /// Converts a value from and to JSON in GeoJSON format. /// - public class GeoJsonConverter : JsonConverter + public class GeometryJsonConverter : JsonConverter { private const string PointType = "Point"; private const string LineStringType = "LineString"; @@ -32,6 +32,12 @@ public override Geometry Read(ref Utf8JsonReader reader, Type typeToConvert, Jso return Read(document.RootElement); } + /// + public override void Write(Utf8JsonWriter writer, Geometry value, JsonSerializerOptions options) + { + Write(writer, value); + } + internal static Geometry Read(JsonElement element) { JsonElement typeProperty = GetRequiredProperty(element, TypeProperty); @@ -46,7 +52,7 @@ internal static Geometry Read(JsonElement element) geometries.Add(Read(geometry)); } - return new GeometryCollection(geometries, ReadProperties(element, GeometriesProperty)); + return new CollectionGeometry(geometries, ReadProperties(element, GeometriesProperty)); } JsonElement coordinates = GetRequiredProperty(element, CoordinatesProperty); @@ -60,7 +66,7 @@ internal static Geometry Read(JsonElement element) return new LineGeometry(ReadCoordinates(coordinates), properties); case MultiPointType: var points = new List(); - foreach (PositionGeometry coordinate in ReadCoordinates(coordinates)) + foreach (GeometryPosition coordinate in ReadCoordinates(coordinates)) { points.Add(new PointGeometry(coordinate)); } @@ -106,7 +112,7 @@ internal static Geometry Read(JsonElement element) } } - private static GeometryProperties? ReadProperties(in JsonElement element, string knownProperty = CoordinatesProperty) + private static GeometryProperties ReadProperties(in JsonElement element, string knownProperty = CoordinatesProperty) { GeometryBoundingBox? bbox = null; @@ -118,20 +124,20 @@ internal static Geometry Read(JsonElement element) { case 4: bbox = new GeometryBoundingBox( - bboxElement[0].GetDouble(), - bboxElement[1].GetDouble(), - bboxElement[2].GetDouble(), - bboxElement[3].GetDouble() + bboxElement[0].GetDouble(), + bboxElement[1].GetDouble(), + bboxElement[2].GetDouble(), + bboxElement[3].GetDouble() ); break; case 6: bbox = new GeometryBoundingBox( - bboxElement[0].GetDouble(), - bboxElement[1].GetDouble(), - bboxElement[3].GetDouble(), - bboxElement[4].GetDouble(), - bboxElement[2].GetDouble(), - bboxElement[5].GetDouble() + bboxElement[0].GetDouble(), + bboxElement[1].GetDouble(), + bboxElement[3].GetDouble(), + bboxElement[4].GetDouble(), + bboxElement[2].GetDouble(), + bboxElement[5].GetDouble() ); break; default: @@ -158,7 +164,7 @@ internal static Geometry Read(JsonElement element) return new GeometryProperties(bbox, additionalProperties); } - return null; + return Geometry.DefaultProperties; } private static object? ReadAdditionalPropertyValue(in JsonElement element) @@ -203,7 +209,7 @@ internal static Geometry Read(JsonElement element) } } - private static IEnumerable ReadCoordinates(JsonElement coordinates) + private static IEnumerable ReadCoordinates(JsonElement coordinates) { foreach (JsonElement coordinate in coordinates.EnumerateArray()) { @@ -211,7 +217,7 @@ private static IEnumerable ReadCoordinates(JsonElement coordin } } - private static PositionGeometry ReadCoordinate(JsonElement coordinate) + private static GeometryPosition ReadCoordinate(JsonElement coordinate) { var arrayLength = coordinate.GetArrayLength(); if (arrayLength < 2 || arrayLength > 3) @@ -228,23 +234,12 @@ private static PositionGeometry ReadCoordinate(JsonElement coordinate) altitude = coordinate[2].GetDouble(); } - return new PositionGeometry(lon, lat, altitude); - } - - /// - /// - /// - /// - /// - /// - public override void Write(Utf8JsonWriter writer, Geometry value, JsonSerializerOptions options) - { - Write(writer, value); + return new GeometryPosition(lon, lat, altitude); } internal static void Write(Utf8JsonWriter writer, Geometry value) { - void WritePositionValues(PositionGeometry type) + void WritePositionValues(GeometryPosition type) { writer.WriteNumberValue(type.Longitude); writer.WriteNumberValue(type.Latitude); @@ -259,7 +254,7 @@ void WriteType(string type) writer.WriteString(TypeProperty, type); } - void WritePosition(PositionGeometry type) + void WritePosition(GeometryPosition type) { writer.WriteStartArray(); WritePositionValues(type); @@ -267,7 +262,7 @@ void WritePosition(PositionGeometry type) writer.WriteEndArray(); } - void WritePositions(IEnumerable positions) + void WritePositions(IEnumerable positions) { writer.WriteStartArray(); foreach (var position in positions) @@ -346,7 +341,7 @@ void WritePositions(IEnumerable positions) writer.WriteEndArray(); break; - case GeometryCollection geometryCollection: + case CollectionGeometry geometryCollection: WriteType(GeometryCollectionType); writer.WritePropertyName(GeometriesProperty); writer.WriteStartArray(); diff --git a/sdk/core/Azure.Core/src/Spatial/PositionGeometry.cs b/sdk/core/Azure.Core/src/Spatial/GeometryPosition.cs similarity index 71% rename from sdk/core/Azure.Core/src/Spatial/PositionGeometry.cs rename to sdk/core/Azure.Core/src/Spatial/GeometryPosition.cs index db0f75bfc5ece..660781f647721 100644 --- a/sdk/core/Azure.Core/src/Spatial/PositionGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryPosition.cs @@ -8,29 +8,29 @@ namespace Azure.Core.Spatial /// /// /// - public readonly struct PositionGeometry : IEquatable + public readonly struct GeometryPosition : IEquatable { /// - /// + /// Gets the altitude of the position. /// public double? Altitude { get; } /// - /// + /// Gets the longitude of the position. /// public double Longitude { get; } /// - /// + /// Gets the latitude of the position. /// public double Latitude { get; } /// - /// + /// Initializes a new instance of . /// - /// - /// - public PositionGeometry(double longitude, double latitude) : this(longitude, latitude, null) + /// The longitude of the position. + /// The latitude of the position. + public GeometryPosition(double longitude, double latitude) : this(longitude, latitude, null) { } @@ -40,7 +40,7 @@ public PositionGeometry(double longitude, double latitude) : this(longitude, lat /// /// /// - public PositionGeometry(double longitude, double latitude, double? altitude) + public GeometryPosition(double longitude, double latitude, double? altitude) { Longitude = longitude; Latitude = latitude; @@ -49,7 +49,7 @@ public PositionGeometry(double longitude, double latitude, double? altitude) /// - public bool Equals(PositionGeometry other) + public bool Equals(GeometryPosition other) { return Nullable.Equals(Altitude, other.Altitude) && Longitude.Equals(other.Longitude) && Latitude.Equals(other.Latitude); } @@ -57,7 +57,7 @@ public bool Equals(PositionGeometry other) /// public override bool Equals(object? obj) { - return obj is PositionGeometry other && Equals(other); + return obj is GeometryPosition other && Equals(other); } /// @@ -69,7 +69,7 @@ public override bool Equals(object? obj) /// /// /// - public static bool operator ==(PositionGeometry left, PositionGeometry right) + public static bool operator ==(GeometryPosition left, GeometryPosition right) { return left.Equals(right); } @@ -80,7 +80,7 @@ public override bool Equals(object? obj) /// /// /// - public static bool operator !=(PositionGeometry left, PositionGeometry right) + public static bool operator !=(GeometryPosition left, GeometryPosition right) { return !left.Equals(right); } diff --git a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs index 81580055b36a0..29d8526351879 100644 --- a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs @@ -12,26 +12,28 @@ namespace Azure.Core.Spatial public sealed class LineGeometry : Geometry { /// - /// + /// Initializes new instance of . /// /// - public LineGeometry(IEnumerable positions): this(positions, null) + public LineGeometry(IEnumerable positions): this(positions, DefaultProperties) { } /// - /// + /// Initializes new instance of . /// /// /// - public LineGeometry(IEnumerable positions, GeometryProperties? properties): base(properties) + public LineGeometry(IEnumerable positions, GeometryProperties properties): base(properties) { + Argument.AssertNotNull(positions, nameof(positions)); + Positions = positions.ToArray(); } /// /// /// - public IReadOnlyList Positions { get; } + public IReadOnlyList Positions { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs b/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs index d508bc4ac12dc..4471212570d05 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs @@ -15,7 +15,7 @@ public sealed class MultiLineGeometry : Geometry /// /// /// - public MultiLineGeometry(IEnumerable lineStrings): this(lineStrings, null) + public MultiLineGeometry(IEnumerable lineStrings): this(lineStrings, DefaultProperties) { } @@ -24,8 +24,10 @@ public MultiLineGeometry(IEnumerable lineStrings): this(lineString /// /// /// - public MultiLineGeometry(IEnumerable lineStrings, GeometryProperties? properties): base(properties) + public MultiLineGeometry(IEnumerable lineStrings, GeometryProperties properties): base(properties) { + Argument.AssertNotNull(lineStrings, nameof(lineStrings)); + Lines = lineStrings.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs b/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs index 545b1c8410895..db090ee122f91 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs @@ -15,7 +15,7 @@ public sealed class MultiPointGeometry : Geometry /// /// /// - public MultiPointGeometry(IEnumerable points): this(points, null) + public MultiPointGeometry(IEnumerable points): this(points, DefaultProperties) { } @@ -24,8 +24,10 @@ public MultiPointGeometry(IEnumerable points): this(points, null) /// /// /// - public MultiPointGeometry(IEnumerable points, GeometryProperties? properties): base(properties) + public MultiPointGeometry(IEnumerable points, GeometryProperties properties): base(properties) { + Argument.AssertNotNull(points, nameof(points)); + Points = points.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs b/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs index cc4bc186c0103..7acb10c0e73e3 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs @@ -15,7 +15,7 @@ public sealed class MultiPolygonGeometry : Geometry /// /// /// - public MultiPolygonGeometry(IEnumerable polygons): this(polygons, null) + public MultiPolygonGeometry(IEnumerable polygons): this(polygons, DefaultProperties) { } @@ -24,8 +24,10 @@ public MultiPolygonGeometry(IEnumerable polygons): this(polygon /// /// /// - public MultiPolygonGeometry(IEnumerable polygons, GeometryProperties? properties): base(properties) + public MultiPolygonGeometry(IEnumerable polygons, GeometryProperties properties): base(properties) { + Argument.AssertNotNull(polygons, nameof(polygons)); + Polygons = polygons.ToArray(); } diff --git a/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs b/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs index 37517e996c6f7..18581490e3158 100644 --- a/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs @@ -12,7 +12,7 @@ public sealed class PointGeometry : Geometry /// /// /// - public PointGeometry(PositionGeometry position): this(position, null) + public PointGeometry(GeometryPosition position): this(position, DefaultProperties) { } @@ -21,17 +21,14 @@ public PointGeometry(PositionGeometry position): this(position, null) /// /// /// - public PointGeometry(PositionGeometry position, GeometryProperties? properties): base(properties) + public PointGeometry(GeometryPosition position, GeometryProperties properties): base(properties) { Position = position; } /// - /// + /// Gets position of the point. /// - public PositionGeometry Position { get; } - - /// - public override string ToString() => $"Point: {Position}"; + public GeometryPosition Position { get; } } } \ No newline at end of file diff --git a/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs b/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs index f2cccf08ea47b..4d1c73d44d483 100644 --- a/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs @@ -7,30 +7,32 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a polygon consisting of outer ring and optional inner rings. /// public sealed class PolygonGeometry : Geometry { /// - /// + /// Initializes new instance of . /// /// - public PolygonGeometry(IEnumerable rings): this(rings, null) + public PolygonGeometry(IEnumerable rings): this(rings, DefaultProperties) { } /// - /// + /// Initializes new instance of . /// /// /// - public PolygonGeometry(IEnumerable rings, GeometryProperties? properties): base(properties) + public PolygonGeometry(IEnumerable rings, GeometryProperties properties): base(properties) { + Argument.AssertNotNull(rings, nameof(rings)); + Rings = rings.ToArray(); } /// - /// + /// Gets a set of rings that form the polygon. /// public IReadOnlyList Rings { get; } } diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core/tests/SpatialTests.cs index a540eb7a19169..411c4250b0e52 100644 --- a/sdk/core/Azure.Core/tests/SpatialTests.cs +++ b/sdk/core/Azure.Core/tests/SpatialTests.cs @@ -202,7 +202,7 @@ public void CanRoundripGeometryCollection() { var input = $"{{ \"type\": \"GeometryCollection\", \"geometries\": [{{ \"type\": \"Point\", \"coordinates\": [{PS(0)}] }}, {{ \"type\": \"LineString\", \"coordinates\": [ [{PS(1)}], [{PS(2)}] ] }}] }}"; - var collection = AssertRoundtrip(input); + var collection = AssertRoundtrip(input); var point = (PointGeometry) collection.Geometries[0]; Assert.AreEqual(P(0), point.Position); @@ -223,29 +223,29 @@ private string PS(int number) return $"{1.1 * number:G17}, {2.2 * number:G17}, {3.3 * number:G17}"; } - private PositionGeometry P(int number) + private GeometryPosition P(int number) { if (_points == 2) { - return new PositionGeometry(1.1 * number, 2.2 * number); + return new GeometryPosition(1.1 * number, 2.2 * number); } - return new PositionGeometry(1.1 * number, 2.2 * number, 3.3 * number); + return new GeometryPosition(1.1 * number, 2.2 * number, 3.3 * number); } private T AssertRoundtrip(string json) where T: Geometry { var element = JsonDocument.Parse(json).RootElement; - var geometry = GeoJsonConverter.Read(element); + var geometry = GeometryJsonConverter.Read(element); var memoryStreamOutput = new MemoryStream(); using (Utf8JsonWriter writer = new Utf8JsonWriter(memoryStreamOutput)) { - GeoJsonConverter.Write(writer, geometry); + GeometryJsonConverter.Write(writer, geometry); } var element2 = JsonDocument.Parse(memoryStreamOutput.ToArray()).RootElement; - var geometry2 = GeoJsonConverter.Read(element2); + var geometry2 = GeometryJsonConverter.Read(element2); return (T)geometry2; } From 4944ea1f2b9b16076f063b7bf07bf88e61867d41 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 14:32:18 -0700 Subject: [PATCH 12/15] Operators. --- .../src/Spatial/GeometryBoundingBox.cs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs b/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs index 926d3b3c25225..a72fa5c665d29 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs +++ b/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs @@ -1,12 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; + namespace Azure.Core.Spatial { /// /// Represents information about the coordinate range of the . /// - public readonly struct GeometryBoundingBox + public readonly struct GeometryBoundingBox : IEquatable { /// /// The westmost value of coordinates. @@ -57,5 +59,28 @@ public GeometryBoundingBox(double west, double south, double east, double north, MinAltitude = minAltitude; MaxAltitude = maxAltitude; } + + /// + public bool Equals(GeometryBoundingBox other) + { + return West.Equals(other.West) && + South.Equals(other.South) && + East.Equals(other.East) && + North.Equals(other.North) && + Nullable.Equals(MinAltitude, other.MinAltitude) && + Nullable.Equals(MaxAltitude, other.MaxAltitude); + } + + /// + public override bool Equals(object? obj) + { + return obj is GeometryBoundingBox other && Equals(other); + } + + /// + public override int GetHashCode() + { + return HashCodeBuilder.Combine(West, South, East, North, MinAltitude, MaxAltitude); + } } } \ No newline at end of file From 200e31d410686a91d5f33980008cc0e3f2d0416b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 20 May 2020 15:08:29 -0700 Subject: [PATCH 13/15] Docs --- sdk/core/Azure.Core/src/Spatial/LineGeometry.cs | 2 +- sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs | 6 +++--- sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs | 6 +++--- sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs | 6 +++--- sdk/core/Azure.Core/src/Spatial/PointGeometry.cs | 6 +++--- sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs index 29d8526351879..f248dca4f3293 100644 --- a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs @@ -23,7 +23,7 @@ public LineGeometry(IEnumerable positions): this(positions, De /// Initializes new instance of . /// /// - /// + /// The associated with the geometry. public LineGeometry(IEnumerable positions, GeometryProperties properties): base(properties) { Argument.AssertNotNull(positions, nameof(positions)); diff --git a/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs b/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs index 4471212570d05..5ce226b6547ee 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs @@ -12,7 +12,7 @@ namespace Azure.Core.Spatial public sealed class MultiLineGeometry : Geometry { /// - /// + /// Initializes new instance of . /// /// public MultiLineGeometry(IEnumerable lineStrings): this(lineStrings, DefaultProperties) @@ -20,10 +20,10 @@ public MultiLineGeometry(IEnumerable lineStrings): this(lineString } /// - /// + /// Initializes new instance of . /// /// - /// + /// The associated with the geometry. public MultiLineGeometry(IEnumerable lineStrings, GeometryProperties properties): base(properties) { Argument.AssertNotNull(lineStrings, nameof(lineStrings)); diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs b/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs index db090ee122f91..7e11d6a595367 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs @@ -12,7 +12,7 @@ namespace Azure.Core.Spatial public sealed class MultiPointGeometry : Geometry { /// - /// + /// Initializes new instance of . /// /// public MultiPointGeometry(IEnumerable points): this(points, DefaultProperties) @@ -20,10 +20,10 @@ public MultiPointGeometry(IEnumerable points): this(points, Defau } /// - /// + /// Initializes new instance of . /// /// - /// + /// The associated with the geometry. public MultiPointGeometry(IEnumerable points, GeometryProperties properties): base(properties) { Argument.AssertNotNull(points, nameof(points)); diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs b/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs index 7acb10c0e73e3..b1bee65893ca6 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs @@ -12,7 +12,7 @@ namespace Azure.Core.Spatial public sealed class MultiPolygonGeometry : Geometry { /// - /// + /// Initializes new instance of . /// /// public MultiPolygonGeometry(IEnumerable polygons): this(polygons, DefaultProperties) @@ -20,10 +20,10 @@ public MultiPolygonGeometry(IEnumerable polygons): this(polygon } /// - /// + /// Initializes new instance of . /// /// - /// + /// The associated with the geometry. public MultiPolygonGeometry(IEnumerable polygons, GeometryProperties properties): base(properties) { Argument.AssertNotNull(polygons, nameof(polygons)); diff --git a/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs b/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs index 18581490e3158..c15879d641a46 100644 --- a/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs @@ -9,7 +9,7 @@ namespace Azure.Core.Spatial public sealed class PointGeometry : Geometry { /// - /// + /// Initializes new instance of . /// /// public PointGeometry(GeometryPosition position): this(position, DefaultProperties) @@ -17,10 +17,10 @@ public PointGeometry(GeometryPosition position): this(position, DefaultPropertie } /// - /// + /// Initializes new instance of . /// /// - /// + /// The associated with the geometry. public PointGeometry(GeometryPosition position, GeometryProperties properties): base(properties) { Position = position; diff --git a/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs b/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs index 4d1c73d44d483..63cb9361904ea 100644 --- a/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs +++ b/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs @@ -23,7 +23,7 @@ public PolygonGeometry(IEnumerable rings): this(rings, DefaultProp /// Initializes new instance of . /// /// - /// + /// The associated with the geometry. public PolygonGeometry(IEnumerable rings, GeometryProperties properties): base(properties) { Argument.AssertNotNull(rings, nameof(rings)); From 2f21ab863f247753124012c8b992c3406df35738 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 21 May 2020 16:57:30 -0700 Subject: [PATCH 14/15] Move and comments --- .../src/Azure.Core.Experimental.csproj | 8 ++++- .../src/Properties/AssemblyInfo.cs | 6 ++++ .../src/Spatial/CollectionGeometry.cs | 4 +-- .../src/Spatial/Geometry.cs | 0 .../src/Spatial/GeometryBoundingBox.cs | 0 .../src/Spatial/GeometryJsonConverter.cs | 0 .../src/Spatial/GeometryPosition.cs | 32 ++++++++----------- .../src/Spatial/GeometryProperties.cs | 0 .../src/Spatial/LineGeometry.cs | 6 ++-- .../src/Spatial/MultiLineGeometry.cs | 14 ++++---- .../src/Spatial/MultiPointGeometry.cs | 6 ++-- .../src/Spatial/MultiPolygonGeometry.cs | 6 ++-- .../src/Spatial/PointGeometry.cs | 6 ++-- .../src/Spatial/PolygonGeometry.cs | 4 +-- .../tests/SpatialTests.cs | 0 sdk/core/Azure.Core/Azure.Core.All.sln | 28 ++++++++++++++++ sdk/core/Azure.Core/src/Azure.Core.csproj | 1 - 17 files changed, 78 insertions(+), 43 deletions(-) create mode 100644 sdk/core/Azure.Core.Experimental/src/Properties/AssemblyInfo.cs rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/CollectionGeometry.cs (88%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/Geometry.cs (100%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/GeometryBoundingBox.cs (100%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/GeometryJsonConverter.cs (100%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/GeometryPosition.cs (69%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/GeometryProperties.cs (100%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/LineGeometry.cs (78%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/MultiLineGeometry.cs (59%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/MultiPointGeometry.cs (82%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/MultiPolygonGeometry.cs (82%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/PointGeometry.cs (84%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/src/Spatial/PolygonGeometry.cs (80%) rename sdk/core/{Azure.Core => Azure.Core.Experimental}/tests/SpatialTests.cs (100%) diff --git a/sdk/core/Azure.Core.Experimental/src/Azure.Core.Experimental.csproj b/sdk/core/Azure.Core.Experimental/src/Azure.Core.Experimental.csproj index 1e23e8f8beb72..e12146ed578dd 100644 --- a/sdk/core/Azure.Core.Experimental/src/Azure.Core.Experimental.csproj +++ b/sdk/core/Azure.Core.Experimental/src/Azure.Core.Experimental.csproj @@ -7,10 +7,16 @@ enable $(RequiredTargetFrameworks) false + $(NoWarn);AZC0001;AZC0012 + + + + + + - diff --git a/sdk/core/Azure.Core.Experimental/src/Properties/AssemblyInfo.cs b/sdk/core/Azure.Core.Experimental/src/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000..d425518410eb3 --- /dev/null +++ b/sdk/core/Azure.Core.Experimental/src/Properties/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Azure.Core.Experimental.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100d15ddcb29688295338af4b7686603fe614abd555e09efba8fb88ee09e1f7b1ccaeed2e8f823fa9eef3fdd60217fc012ea67d2479751a0b8c087a4185541b851bd8b16f8d91b840e51b1cb0ba6fe647997e57429265e85ef62d565db50a69ae1647d54d7bd855e4db3d8a91510e5bcbd0edfbbecaa20a7bd9ae74593daa7b11b4")] diff --git a/sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/CollectionGeometry.cs similarity index 88% rename from sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/CollectionGeometry.cs index cb289ce00b470..1493d09097e64 100644 --- a/sdk/core/Azure.Core/src/Spatial/CollectionGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/CollectionGeometry.cs @@ -14,7 +14,7 @@ public sealed class CollectionGeometry : Geometry /// /// Initializes new instance of . /// - /// The list of inner geometries. + /// The collection of inner geometries. public CollectionGeometry(IEnumerable geometries): this(geometries, DefaultProperties) { } @@ -22,7 +22,7 @@ public CollectionGeometry(IEnumerable geometries): this(geometries, De /// /// Initializes new instance of . /// - /// The list of inner geometries. + /// The collection of inner geometries. /// The associated with the geometry. public CollectionGeometry(IEnumerable geometries, GeometryProperties properties): base(properties) { diff --git a/sdk/core/Azure.Core/src/Spatial/Geometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/Geometry.cs similarity index 100% rename from sdk/core/Azure.Core/src/Spatial/Geometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/Geometry.cs diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/GeometryBoundingBox.cs similarity index 100% rename from sdk/core/Azure.Core/src/Spatial/GeometryBoundingBox.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/GeometryBoundingBox.cs diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryJsonConverter.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/GeometryJsonConverter.cs similarity index 100% rename from sdk/core/Azure.Core/src/Spatial/GeometryJsonConverter.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/GeometryJsonConverter.cs diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryPosition.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/GeometryPosition.cs similarity index 69% rename from sdk/core/Azure.Core/src/Spatial/GeometryPosition.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/GeometryPosition.cs index 660781f647721..8c5a86940448b 100644 --- a/sdk/core/Azure.Core/src/Spatial/GeometryPosition.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/GeometryPosition.cs @@ -6,7 +6,7 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a position that is a part of geometry. /// public readonly struct GeometryPosition : IEquatable { @@ -35,11 +35,11 @@ public GeometryPosition(double longitude, double latitude) : this(longitude, lat } /// - /// + /// Initializes a new instance of . /// - /// - /// - /// + /// The longitude of the position. + /// The latitude of the position. + /// The altitude of the position. public GeometryPosition(double longitude, double latitude, double? altitude) { Longitude = longitude; @@ -47,7 +47,6 @@ public GeometryPosition(double longitude, double latitude, double? altitude) Altitude = altitude; } - /// public bool Equals(GeometryPosition other) { @@ -64,31 +63,28 @@ public override bool Equals(object? obj) public override int GetHashCode() => HashCodeBuilder.Combine(Longitude, Latitude, Altitude); /// - /// + /// Determines whether two specified positions have the same value. /// - /// - /// - /// + /// The first position to compare. + /// The first position to compare. + /// true if the value of left is the same as the value of b; otherwise, false. public static bool operator ==(GeometryPosition left, GeometryPosition right) { return left.Equals(right); } /// - /// + /// Determines whether two specified positions have the same value. /// - /// - /// - /// + /// The first position to compare. + /// The first position to compare. + /// false if the value of left is the same as the value of b; otherwise, true. public static bool operator !=(GeometryPosition left, GeometryPosition right) { return !left.Equals(right); } - /// - /// - /// - /// + /// public override string ToString() { if (Altitude == null) diff --git a/sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/GeometryProperties.cs similarity index 100% rename from sdk/core/Azure.Core/src/Spatial/GeometryProperties.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/GeometryProperties.cs diff --git a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/LineGeometry.cs similarity index 78% rename from sdk/core/Azure.Core/src/Spatial/LineGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/LineGeometry.cs index f248dca4f3293..b6760e9fc2d53 100644 --- a/sdk/core/Azure.Core/src/Spatial/LineGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/LineGeometry.cs @@ -7,14 +7,14 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a line geometry that consists of multiple coordinates. /// public sealed class LineGeometry : Geometry { /// /// Initializes new instance of . /// - /// + /// The collection of that make up the line. public LineGeometry(IEnumerable positions): this(positions, DefaultProperties) { } @@ -22,7 +22,7 @@ public LineGeometry(IEnumerable positions): this(positions, De /// /// Initializes new instance of . /// - /// + /// The collection of that make up the line. /// The associated with the geometry. public LineGeometry(IEnumerable positions, GeometryProperties properties): base(properties) { diff --git a/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/MultiLineGeometry.cs similarity index 59% rename from sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/MultiLineGeometry.cs index 5ce226b6547ee..508b4b62f5a7a 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiLineGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/MultiLineGeometry.cs @@ -7,28 +7,28 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a geometry that is composed of multiple . /// public sealed class MultiLineGeometry : Geometry { /// /// Initializes new instance of . /// - /// - public MultiLineGeometry(IEnumerable lineStrings): this(lineStrings, DefaultProperties) + /// The collection of inner lines. + public MultiLineGeometry(IEnumerable lines): this(lines, DefaultProperties) { } /// /// Initializes new instance of . /// - /// + /// The collection of inner lines. /// The associated with the geometry. - public MultiLineGeometry(IEnumerable lineStrings, GeometryProperties properties): base(properties) + public MultiLineGeometry(IEnumerable lines, GeometryProperties properties): base(properties) { - Argument.AssertNotNull(lineStrings, nameof(lineStrings)); + Argument.AssertNotNull(lines, nameof(lines)); - Lines = lineStrings.ToArray(); + Lines = lines.ToArray(); } /// diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/MultiPointGeometry.cs similarity index 82% rename from sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/MultiPointGeometry.cs index 7e11d6a595367..c2e8facb209be 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPointGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/MultiPointGeometry.cs @@ -7,14 +7,14 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a geometry that is composed of multiple . /// public sealed class MultiPointGeometry : Geometry { /// /// Initializes new instance of . /// - /// + /// The collection of inner points. public MultiPointGeometry(IEnumerable points): this(points, DefaultProperties) { } @@ -22,7 +22,7 @@ public MultiPointGeometry(IEnumerable points): this(points, Defau /// /// Initializes new instance of . /// - /// + /// The collection of inner points. /// The associated with the geometry. public MultiPointGeometry(IEnumerable points, GeometryProperties properties): base(properties) { diff --git a/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/MultiPolygonGeometry.cs similarity index 82% rename from sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/MultiPolygonGeometry.cs index b1bee65893ca6..a051945b5ebe0 100644 --- a/sdk/core/Azure.Core/src/Spatial/MultiPolygonGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/MultiPolygonGeometry.cs @@ -7,14 +7,14 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a geometry that is composed of multiple . /// public sealed class MultiPolygonGeometry : Geometry { /// /// Initializes new instance of . /// - /// + /// The collection of inner polygons. public MultiPolygonGeometry(IEnumerable polygons): this(polygons, DefaultProperties) { } @@ -22,7 +22,7 @@ public MultiPolygonGeometry(IEnumerable polygons): this(polygon /// /// Initializes new instance of . /// - /// + /// The collection of inner geometries. /// The associated with the geometry. public MultiPolygonGeometry(IEnumerable polygons, GeometryProperties properties): base(properties) { diff --git a/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/PointGeometry.cs similarity index 84% rename from sdk/core/Azure.Core/src/Spatial/PointGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/PointGeometry.cs index c15879d641a46..fcf762096d33f 100644 --- a/sdk/core/Azure.Core/src/Spatial/PointGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/PointGeometry.cs @@ -4,14 +4,14 @@ namespace Azure.Core.Spatial { /// - /// + /// Represents a point geometry. /// public sealed class PointGeometry : Geometry { /// /// Initializes new instance of . /// - /// + /// The position of the point. public PointGeometry(GeometryPosition position): this(position, DefaultProperties) { } @@ -19,7 +19,7 @@ public PointGeometry(GeometryPosition position): this(position, DefaultPropertie /// /// Initializes new instance of . /// - /// + /// The position of the point. /// The associated with the geometry. public PointGeometry(GeometryPosition position, GeometryProperties properties): base(properties) { diff --git a/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs b/sdk/core/Azure.Core.Experimental/src/Spatial/PolygonGeometry.cs similarity index 80% rename from sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs rename to sdk/core/Azure.Core.Experimental/src/Spatial/PolygonGeometry.cs index 63cb9361904ea..1d4d0eef03f4c 100644 --- a/sdk/core/Azure.Core/src/Spatial/PolygonGeometry.cs +++ b/sdk/core/Azure.Core.Experimental/src/Spatial/PolygonGeometry.cs @@ -14,7 +14,7 @@ public sealed class PolygonGeometry : Geometry /// /// Initializes new instance of . /// - /// + /// The collection of rings that make up the polygon, first ring is the outer ring others are inner rings. public PolygonGeometry(IEnumerable rings): this(rings, DefaultProperties) { } @@ -22,7 +22,7 @@ public PolygonGeometry(IEnumerable rings): this(rings, DefaultProp /// /// Initializes new instance of . /// - /// + /// The collection of rings that make up the polygon, first ring is the outer ring others are inner rings. /// The associated with the geometry. public PolygonGeometry(IEnumerable rings, GeometryProperties properties): base(properties) { diff --git a/sdk/core/Azure.Core/tests/SpatialTests.cs b/sdk/core/Azure.Core.Experimental/tests/SpatialTests.cs similarity index 100% rename from sdk/core/Azure.Core/tests/SpatialTests.cs rename to sdk/core/Azure.Core.Experimental/tests/SpatialTests.cs diff --git a/sdk/core/Azure.Core/Azure.Core.All.sln b/sdk/core/Azure.Core/Azure.Core.All.sln index 3aa3735c4c1ef..8eb1f9e45d5be 100644 --- a/sdk/core/Azure.Core/Azure.Core.All.sln +++ b/sdk/core/Azure.Core/Azure.Core.All.sln @@ -131,6 +131,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Extensions.Azure. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.TestFramework", "..\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{BB8D02AF-F5C3-4D85-8B3E-884BFB820AB3}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Experimental", "..\Azure.Core.Experimental\src\Azure.Core.Experimental.csproj", "{D667DC89-2570-47AB-B6BA-FB977F64F59F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Experimental.Tests", "..\Azure.Core.Experimental\tests\Azure.Core.Experimental.Tests.csproj", "{E17E480E-E791-4EB5-9C85-7949CF259A87}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\keyvault\Azure.Security.KeyVault.Shared\src\Azure.Security.KeyVault.Shared.projitems*{359ffa3a-4f5d-411c-8978-28e58f50eea3}*SharedItemsImports = 5 @@ -917,6 +921,30 @@ Global {BB8D02AF-F5C3-4D85-8B3E-884BFB820AB3}.Release|x64.Build.0 = Release|Any CPU {BB8D02AF-F5C3-4D85-8B3E-884BFB820AB3}.Release|x86.ActiveCfg = Release|Any CPU {BB8D02AF-F5C3-4D85-8B3E-884BFB820AB3}.Release|x86.Build.0 = Release|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Debug|x64.ActiveCfg = Debug|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Debug|x64.Build.0 = Debug|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Debug|x86.ActiveCfg = Debug|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Debug|x86.Build.0 = Debug|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Release|Any CPU.Build.0 = Release|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Release|x64.ActiveCfg = Release|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Release|x64.Build.0 = Release|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Release|x86.ActiveCfg = Release|Any CPU + {D667DC89-2570-47AB-B6BA-FB977F64F59F}.Release|x86.Build.0 = Release|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Debug|x64.ActiveCfg = Debug|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Debug|x64.Build.0 = Debug|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Debug|x86.ActiveCfg = Debug|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Debug|x86.Build.0 = Debug|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Release|Any CPU.Build.0 = Release|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Release|x64.ActiveCfg = Release|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Release|x64.Build.0 = Release|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Release|x86.ActiveCfg = Release|Any CPU + {E17E480E-E791-4EB5-9C85-7949CF259A87}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sdk/core/Azure.Core/src/Azure.Core.csproj b/sdk/core/Azure.Core/src/Azure.Core.csproj index d4c2a5e59e416..5b97b75e44784 100644 --- a/sdk/core/Azure.Core/src/Azure.Core.csproj +++ b/sdk/core/Azure.Core/src/Azure.Core.csproj @@ -17,7 +17,6 @@ - From 261ed45f24a6d738f4bdd4b9e72fa0acb3be49cc Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Thu, 21 May 2020 17:04:01 -0700 Subject: [PATCH 15/15] Export api --- .../Azure.Core.Experimental.netstandard2.0.cs | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs diff --git a/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs b/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs new file mode 100644 index 0000000000000..8dd0b7d6fa5f8 --- /dev/null +++ b/sdk/core/Azure.Core.Experimental/api/Azure.Core.Experimental.netstandard2.0.cs @@ -0,0 +1,94 @@ +namespace Azure.Core.Spatial +{ + public sealed partial class CollectionGeometry : Azure.Core.Spatial.Geometry + { + public CollectionGeometry(System.Collections.Generic.IEnumerable geometries) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public CollectionGeometry(System.Collections.Generic.IEnumerable geometries, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public System.Collections.Generic.IReadOnlyList Geometries { get { throw null; } } + } + public partial class Geometry + { + protected Geometry(Azure.Core.Spatial.GeometryProperties properties) { } + public Azure.Core.Spatial.GeometryProperties Properties { get { throw null; } } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct GeometryBoundingBox : System.IEquatable + { + private readonly int _dummyPrimitive; + public GeometryBoundingBox(double west, double south, double east, double north) { throw null; } + public GeometryBoundingBox(double west, double south, double east, double north, double? minAltitude, double? maxAltitude) { throw null; } + public double East { get { throw null; } } + public double? MaxAltitude { get { throw null; } } + public double? MinAltitude { get { throw null; } } + public double North { get { throw null; } } + public double South { get { throw null; } } + public double West { get { throw null; } } + public bool Equals(Azure.Core.Spatial.GeometryBoundingBox other) { throw null; } + public override bool Equals(object? obj) { throw null; } + public override int GetHashCode() { throw null; } + } + public partial class GeometryJsonConverter : System.Text.Json.Serialization.JsonConverter + { + public GeometryJsonConverter() { } + public override Azure.Core.Spatial.Geometry Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Spatial.Geometry value, System.Text.Json.JsonSerializerOptions options) { } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct GeometryPosition : System.IEquatable + { + private readonly int _dummyPrimitive; + public GeometryPosition(double longitude, double latitude) { throw null; } + public GeometryPosition(double longitude, double latitude, double? altitude) { throw null; } + public double? Altitude { get { throw null; } } + public double Latitude { get { throw null; } } + public double Longitude { get { throw null; } } + public bool Equals(Azure.Core.Spatial.GeometryPosition other) { throw null; } + public override bool Equals(object? obj) { throw null; } + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Spatial.GeometryPosition left, Azure.Core.Spatial.GeometryPosition right) { throw null; } + public static bool operator !=(Azure.Core.Spatial.GeometryPosition left, Azure.Core.Spatial.GeometryPosition right) { throw null; } + public override string ToString() { throw null; } + } + public partial class GeometryProperties + { + public GeometryProperties(Azure.Core.Spatial.GeometryBoundingBox? boundingBox = default(Azure.Core.Spatial.GeometryBoundingBox?), System.Collections.Generic.IReadOnlyDictionary? additionalProperties = null) { } + public System.Collections.Generic.IReadOnlyDictionary AdditionalProperties { get { throw null; } } + public Azure.Core.Spatial.GeometryBoundingBox? BoundingBox { get { throw null; } } + } + public sealed partial class LineGeometry : Azure.Core.Spatial.Geometry + { + public LineGeometry(System.Collections.Generic.IEnumerable positions) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public LineGeometry(System.Collections.Generic.IEnumerable positions, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public System.Collections.Generic.IReadOnlyList Positions { get { throw null; } } + } + public sealed partial class MultiLineGeometry : Azure.Core.Spatial.Geometry + { + public MultiLineGeometry(System.Collections.Generic.IEnumerable lines) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public MultiLineGeometry(System.Collections.Generic.IEnumerable lines, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public System.Collections.Generic.IReadOnlyList Lines { get { throw null; } } + } + public sealed partial class MultiPointGeometry : Azure.Core.Spatial.Geometry + { + public MultiPointGeometry(System.Collections.Generic.IEnumerable points) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public MultiPointGeometry(System.Collections.Generic.IEnumerable points, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public System.Collections.Generic.IReadOnlyList Points { get { throw null; } } + } + public sealed partial class MultiPolygonGeometry : Azure.Core.Spatial.Geometry + { + public MultiPolygonGeometry(System.Collections.Generic.IEnumerable polygons) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public MultiPolygonGeometry(System.Collections.Generic.IEnumerable polygons, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public System.Collections.Generic.IReadOnlyList Polygons { get { throw null; } } + } + public sealed partial class PointGeometry : Azure.Core.Spatial.Geometry + { + public PointGeometry(Azure.Core.Spatial.GeometryPosition position) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public PointGeometry(Azure.Core.Spatial.GeometryPosition position, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public Azure.Core.Spatial.GeometryPosition Position { get { throw null; } } + } + public sealed partial class PolygonGeometry : Azure.Core.Spatial.Geometry + { + public PolygonGeometry(System.Collections.Generic.IEnumerable rings) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public PolygonGeometry(System.Collections.Generic.IEnumerable rings, Azure.Core.Spatial.GeometryProperties properties) : base (default(Azure.Core.Spatial.GeometryProperties)) { } + public System.Collections.Generic.IReadOnlyList Rings { get { throw null; } } + } +}