From 3fd48b7a2c14a7e3c612a4da2f0b86deaa9673eb Mon Sep 17 00:00:00 2001 From: Joe Amenta Date: Fri, 23 Aug 2019 05:58:44 -0400 Subject: [PATCH 1/5] Updates for v2. (#8) - All CoordinateSystems types are gone (resolves #7) - The extension methods dealing with ID values on IFeature instances are gone - to be moved to GeoJSON - (I)AttributesTable now has GetOptionalValue (resolves #3) - FeatureCollection now inherits from Collection - [Serializable] is now implemented via ISerializable --- .travis.yml | 35 +++ Directory.Build.props | 10 + NetTopologySuite.Common.props | 73 ----- .../AttributeTableTest.cs | 14 - NetTopologySuite.Features.Test/FeatureTest.cs | 13 - .../FeaturesTestSetup.cs | 20 -- .../NetTopologySuite.Features.Test.csproj | 52 ---- NetTopologySuite.Features.nuspec | 84 ------ NetTopologySuite.Features.sln | 11 +- .../CoordinateSystems/CRSBase.cs | 24 -- .../CoordinateSystems/CRSType.cs | 21 -- .../CoordinateSystems/ICRSObject.cs | 13 - .../CoordinateSystems/LinkedCRS.cs | 36 --- .../CoordinateSystems/NamedCRS.cs | 31 --- .../Features/AttributesTable.cs | 257 ------------------ NetTopologySuite.Features/Features/Feature.cs | 81 ------ .../Features/FeatureCollection.cs | 144 ---------- .../Features/FeatureExtensions.cs | 48 ---- .../Features/IFeature.cs | 25 -- .../NetTopologySuite.Features.csproj | 51 ---- SharedAssemblyVersion.cs | 7 - src/Directory.Build.props | 99 +++++++ .../AttributesTable.cs | 184 +++++++++++++ src/NetTopologySuite.Features/Feature.cs | 86 ++++++ .../FeatureCollection.cs | 94 +++++++ .../IAttributesTable.cs | 139 +++++----- src/NetTopologySuite.Features/IFeature.cs | 25 ++ .../InternalExtensions.cs | 32 +++ .../NetTopologySuite.Features.csproj | 30 ++ test/Directory.Build.props | 16 ++ .../AttributesTableTest.cs | 187 +++++++++++++ .../FeatureCollectionTest.cs | 105 +++++++ .../FeatureTest.cs | 50 ++++ .../NetTopologySuite.Features.Test.csproj | 11 + 34 files changed, 1044 insertions(+), 1064 deletions(-) create mode 100644 .travis.yml create mode 100644 Directory.Build.props delete mode 100644 NetTopologySuite.Common.props delete mode 100644 NetTopologySuite.Features.Test/AttributeTableTest.cs delete mode 100644 NetTopologySuite.Features.Test/FeatureTest.cs delete mode 100644 NetTopologySuite.Features.Test/FeaturesTestSetup.cs delete mode 100644 NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj delete mode 100644 NetTopologySuite.Features.nuspec delete mode 100644 NetTopologySuite.Features/CoordinateSystems/CRSBase.cs delete mode 100644 NetTopologySuite.Features/CoordinateSystems/CRSType.cs delete mode 100644 NetTopologySuite.Features/CoordinateSystems/ICRSObject.cs delete mode 100644 NetTopologySuite.Features/CoordinateSystems/LinkedCRS.cs delete mode 100644 NetTopologySuite.Features/CoordinateSystems/NamedCRS.cs delete mode 100644 NetTopologySuite.Features/Features/AttributesTable.cs delete mode 100644 NetTopologySuite.Features/Features/Feature.cs delete mode 100644 NetTopologySuite.Features/Features/FeatureCollection.cs delete mode 100644 NetTopologySuite.Features/Features/FeatureExtensions.cs delete mode 100644 NetTopologySuite.Features/Features/IFeature.cs delete mode 100644 NetTopologySuite.Features/NetTopologySuite.Features.csproj delete mode 100644 SharedAssemblyVersion.cs create mode 100644 src/Directory.Build.props create mode 100644 src/NetTopologySuite.Features/AttributesTable.cs create mode 100644 src/NetTopologySuite.Features/Feature.cs create mode 100644 src/NetTopologySuite.Features/FeatureCollection.cs rename {NetTopologySuite.Features/Features => src/NetTopologySuite.Features}/IAttributesTable.cs (76%) create mode 100644 src/NetTopologySuite.Features/IFeature.cs create mode 100644 src/NetTopologySuite.Features/InternalExtensions.cs create mode 100644 src/NetTopologySuite.Features/NetTopologySuite.Features.csproj create mode 100644 test/Directory.Build.props create mode 100644 test/NetTopologySuite.Features.Test/AttributesTableTest.cs create mode 100644 test/NetTopologySuite.Features.Test/FeatureCollectionTest.cs create mode 100644 test/NetTopologySuite.Features.Test/FeatureTest.cs create mode 100644 test/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..4bfd0e9 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,35 @@ +language: csharp +mono: none +sudo: false +dotnet: 2.2 +dist: xenial + + +script: + - dotnet build -c Release + - dotnet test -c Release --no-build + - dotnet pack -c Release --no-build -p:NoWarn=NU5105 + + +deploy: + + + - on: + branch: master + provider: script + script: + - dotnet nuget push **/*.nupkg -s https://api.nuget.org/v3/index.json -k $NUGET_API_KEY + skip_cleanup: true + + + - on: + branch: develop + provider: script + script: + - dotnet nuget push **/*.nupkg -s https://www.myget.org/F/nettopologysuite/api/v2/package -k $MYGET_API_KEY + skip_cleanup: true + +env: + global: + - secure: LAI6KJjHA1usZL9Vm3BhLH2JpaukKFXe6OkWM9ahldsDbAqkScWfVIrBtQ0h0SteSpXTXTQDY35pFEuo3MUBmYcJo8NbgDd2f0u078lU6YFfQiHQnPqA8E1m6l+tCy8MTBHM2zePMYYOsyx4k0kOxZIjYK0RwhfmfDsG5QUjXYcABLK11z76vAl4ULIfYfvEnDF7hXbTOM+7XYS72Ve6q5LsNmS1kDGN1n6z8q6Phjac2254WTpUtSTv4u2wNnHYHIc7h7C3OBB6b7y5+pj6WEM2+r5ojs+Gq7QajK9VHNyYHRkUsCzbQKkSPrgskt10kKml3tcmdTCJshUq9nAE27qiCFc6OQO9iMtTh1m2ueZpeflyIhleGmMk12WHuqj1GmYH/8IQw75KzzezcyjuG19OJsL4QAT5FLMAdDfvckUgjY4+0bxPVI3hnWGnrvnrJA0aWXi9s7r+kT6SxI1MvZph7RqDlxC9/Mjt6lrzjMXvBJSf3vAyOGISF1bTOi+/bj586j7V0uagEYSy5tnj5+j/2wsbYcrb+5veVqYl0inPRYbrAAfaPnBux7ZJ/ZP7XggLnUVV0ZkSrqn1NLfEH6nZ30JCVbP9KX4Ztz00sIuHirqq5rhudHOSxL27+RNSX2RosnWDDMcNew6tRhOlSGZ1uZEekypnhvTK+0Ijzso= + - secure: gIlRSvxCO2AzEqiAzGVdowdkqyrlPw0BovjkyFC4HxRsvx7uc9RORv9lCRGR7ni7Z54QbG0DeLXK4PDxPAD6DlZpR8/2NsCLl1JSswRwQYddGsS1HBGTvUJE08RGlwdPYxhAUkz4jargs3EJnTq4TnqEkAzpYaLBSv4om2Q6VsoEe8Uat2iSoK0+NJD9EG++T0Szx2VsgF0M6ILIpYi0ICEqyK0Jb83ZW/78W5na4IN0ZnIOGoG0qeD5wMoOxq8OmnlSnKNJmsZI8LFEvMZu/QGb8YXz2aim+k0UE9kGa1sE/qweSyPtJuTIhUXqvefMZLfDzGIZVz1htvRRzcOQ1Cbh97T853UZiUHZgy+y5qFtuPxzXAt7eCvfTcjJjRDdXWRw7+NxyceEtQ1u4YSZ9yQLvwUyzhZukZXdclQ74k6GK2Wbohrt4lEADvnzm/PlCCYklv8b7TyKZdVRTILsFJ7eA3zZ8sXCbF8q2TG4BADJRkWxH+S/RdSeBkoiSlW43faFxUVHcC7yjBJshKbdBrQzncZG+7EFgUtw1hufXlwiSpWK0B01gYrsgYYPKYCbGidOJAMRjybyVYA8XfTPraeO7rw0b872jmGAv9TSVXvg+AwMGlnpOC+6n7Q+BL6qU/Q5Hnzi3YMg357qe2BgLJUGXwza/tEnJEeHbqXViZk= diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..7bcae2b --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,10 @@ + + + + + $(MSBuildThisFileDirectory) + + $(MSBuildThisFileDirectory)nts.snk + + + diff --git a/NetTopologySuite.Common.props b/NetTopologySuite.Common.props deleted file mode 100644 index 4e1eec6..0000000 --- a/NetTopologySuite.Common.props +++ /dev/null @@ -1,73 +0,0 @@ - - - - $(SolutionDir)$(Configuration)\$(Platform) - $(OutputPath)\$(TargetFramework)\$(AssemblyName).xml - false - 1.7.5 - 1.15.0 - - - - .NETFramework - Client - v3.5 - - - .NETFramework - Client - v4.0 - - - .NETFramework - Client - v4.0.3 - - - true - - full - - $(DefineConstants);COMPAT_SHAPEFILE_IMPORT_TO_SQL_SERVER - $(DefineConstants);FEATURE_FILE_IO - $(DefineConstants);HAS_SYSTEM_APPLICATIONEXCEPTION - $(DefineConstants);HAS_SYSTEM_ICLONEABLE - $(DefineConstants);HAS_SYSTEM_IO_MEMORYSTREAM_CTOR_PUBLICLYVISIBLE - $(DefineConstants);HAS_SYSTEM_RUNTIME_INTEROPSERVICES_COMVISIBLEATTRIBUTE - $(DefineConstants);HAS_SYSTEM_RUNTIME_INTEROPSERVICES_GUIDATTRIBUTE - $(DefineConstants);HAS_SYSTEM_SERIALIZABLEATTRIBUTE - $(DefineConstants);HAS_SYSTEM_TEXT_ENCODING_DEFAULT - $(DefineConstants);HAS_SYSTEM_TEXT_ENCODING_ASCII - $(DefineConstants);HAS_SYSTEM_TYPE_ISASSIGNABLEFROM - $(DefineConstants);HAS_SYSTEM_XML_XMLDOCUMENT - $(DefineConstants);SERIALIZATION_COMPAT_NETTOPOLOGYSUITE_FEATURE_ATTRIBUTESTABLE - - - $(DefineConstants);HAS_SYSTEM_XML_NAMESPACEHANDLING - $(DefineConstants);HAS_SYSTEM_STRING_ISNULLORWHITESPACE - - - $(DefineConstants);HAS_SYSTEM_REFLECTION_TYPEINFO - - - true - - - $(DefineConstants);HAS_SYSTEM_XML_NAMESPACEHANDLING - $(DefineConstants);HAS_SYSTEM_REFLECTION_TYPEINFO - $(DefineConstants);HAS_SYSTEM_STRING_ISNULLORWHITESPACE - - - $(DefineConstants);FEATURE_FILE_IO - $(DefineConstants);HAS_SYSTEM_IO_MEMORYSTREAM_CTOR_PUBLICLYVISIBLE - $(DefineConstants);HAS_SYSTEM_TEXT_ENCODING_ASCII - $(DefineConstants);HAS_SYSTEM_XML_XMLDOCUMENT - - - $(DefineConstants);HAS_SYSTEM_APPLICATIONEXCEPTION - $(DefineConstants);HAS_SYSTEM_ICLONEABLE - $(DefineConstants);HAS_SYSTEM_SERIALIZABLEATTRIBUTE - $(DefineConstants);HAS_SYSTEM_TEXT_ENCODING_DEFAULT - $(DefineConstants);HAS_SYSTEM_TYPE_ISASSIGNABLEFROM - - \ No newline at end of file diff --git a/NetTopologySuite.Features.Test/AttributeTableTest.cs b/NetTopologySuite.Features.Test/AttributeTableTest.cs deleted file mode 100644 index 5c4c028..0000000 --- a/NetTopologySuite.Features.Test/AttributeTableTest.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using NUnit.Framework; - -namespace NetTopologySuite.Features.Test -{ - /// - /// A test fixture for the class - /// - [TestOf(typeof(Features.AttributesTable))] - public class AttributeTableTest - { - - } -} diff --git a/NetTopologySuite.Features.Test/FeatureTest.cs b/NetTopologySuite.Features.Test/FeatureTest.cs deleted file mode 100644 index 8c7f583..0000000 --- a/NetTopologySuite.Features.Test/FeatureTest.cs +++ /dev/null @@ -1,13 +0,0 @@ -using NUnit.Framework; - -namespace NetTopologySuite.Features.Test -{ - /// - /// A test fixture for the class - /// - [TestOf(typeof(Features.Feature))] - public class FeatureTest - { - - } -} diff --git a/NetTopologySuite.Features.Test/FeaturesTestSetup.cs b/NetTopologySuite.Features.Test/FeaturesTestSetup.cs deleted file mode 100644 index 167ef64..0000000 --- a/NetTopologySuite.Features.Test/FeaturesTestSetup.cs +++ /dev/null @@ -1,20 +0,0 @@ -using GeoAPI; - -namespace NetTopologySuite.Features.Test -{ - /// - /// Utility class to make sure that NTS is set up and registered properly - /// - [NUnit.Framework.SetUpFixture] - public class FeaturesTestSetup - { - /// - /// Method to wire NTS - /// - [NUnit.Framework.OneTimeSetUp] - public void OneTimeSetUp() - { - GeometryServiceProvider.SetInstanceIfNotAlreadySetDirectly(NtsGeometryServices.Instance); - } - } -} diff --git a/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj b/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj deleted file mode 100644 index 5dba5c0..0000000 --- a/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj +++ /dev/null @@ -1,52 +0,0 @@ - - - - $(ProjectDir)..\ - net40;net403;net45;netstandard1.6;netstandard2.0 - true - $(SolutionDir)nts.snk - 659,168,1587 - NetTopologySuite.Features.Test - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/NetTopologySuite.Features.nuspec b/NetTopologySuite.Features.nuspec deleted file mode 100644 index 58cc407..0000000 --- a/NetTopologySuite.Features.nuspec +++ /dev/null @@ -1,84 +0,0 @@ - - - - NetTopologySuite.Features - $version$ - NTS - Topology Suite - Features - NetTopologySuite - Team - NetTopologySuite - Team - BSD-3-Clause - https://github.com/NetTopologySuite/NetTopologySuite.Features - https://raw.githubusercontent.com/NetTopologySuite/GeoAPI/develop/icon.png - true - - A feature is a combination of spatial object and attribute data. - For this package attribute data is stored in AttributeTable objects. - These are combined with IGeometry objects to form a Feature. - A FeatureCollection is a collection of features. - - A features packages for the NTS Topology Suite - NTS Topology OGC SFS - Copyright 2007-2015 - en-US - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/NetTopologySuite.Features.sln b/NetTopologySuite.Features.sln index 8176972..1b7d27d 100644 --- a/NetTopologySuite.Features.sln +++ b/NetTopologySuite.Features.sln @@ -1,20 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.2037 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29009.5 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTopologySuite.Features", "NetTopologySuite.Features\NetTopologySuite.Features.csproj", "{43865E17-0311-4F52-A8A9-00334DD8F76A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTopologySuite.Features", "src\NetTopologySuite.Features\NetTopologySuite.Features.csproj", "{43865E17-0311-4F52-A8A9-00334DD8F76A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8896CE87-BB66-4E1B-BE38-2491C949D7E5}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig .gitignore = .gitignore - NetTopologySuite.Common.props = NetTopologySuite.Common.props - NetTopologySuite.Features.nuspec = NetTopologySuite.Features.nuspec - SharedAssemblyVersion.cs = SharedAssemblyVersion.cs EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTopologySuite.Features.Test", "NetTopologySuite.Features.Test\NetTopologySuite.Features.Test.csproj", "{AB86A1F4-C37C-46FF-BF5D-0A44B175FE07}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTopologySuite.Features.Test", "test\NetTopologySuite.Features.Test\NetTopologySuite.Features.Test.csproj", "{AB86A1F4-C37C-46FF-BF5D-0A44B175FE07}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/NetTopologySuite.Features/CoordinateSystems/CRSBase.cs b/NetTopologySuite.Features/CoordinateSystems/CRSBase.cs deleted file mode 100644 index 8dc96fa..0000000 --- a/NetTopologySuite.Features/CoordinateSystems/CRSBase.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace NetTopologySuite.CoordinateSystems -{ - using System.Collections.Generic; - - /// - /// Base class for all ICRSObject implementing types - /// - //[JsonObject(MemberSerialization.OptIn)] - public abstract class CRSBase : ICRSObject - { - /// - /// Gets the type of the CRSBase object. - /// - //[JsonProperty(PropertyName = "type", Required = Required.Always)] - //[JsonConverter(typeof(CamelCaseStringEnumConverter))] - public CRSTypes Type { get; internal set; } - - /// - /// Gets the properties. - /// - //[JsonProperty(PropertyName = "properties", Required = Required.Always)] - public Dictionary Properties { get; internal set; } - } -} diff --git a/NetTopologySuite.Features/CoordinateSystems/CRSType.cs b/NetTopologySuite.Features/CoordinateSystems/CRSType.cs deleted file mode 100644 index e2fc418..0000000 --- a/NetTopologySuite.Features/CoordinateSystems/CRSType.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace NetTopologySuite.CoordinateSystems -{ - using System; - - /// - /// Defines the GeoJSON Coordinate Reference System Objects (CRS) types as defined in the geojson.org v1.0 spec. - /// - [Flags] - public enum CRSTypes - { - /// - /// Defines the Named CRS type. - /// - Name, - - /// - /// Defines the Linked CRS type. - /// - Link - } -} diff --git a/NetTopologySuite.Features/CoordinateSystems/ICRSObject.cs b/NetTopologySuite.Features/CoordinateSystems/ICRSObject.cs deleted file mode 100644 index a9b44ef..0000000 --- a/NetTopologySuite.Features/CoordinateSystems/ICRSObject.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace NetTopologySuite.CoordinateSystems -{ - /// - /// Base Interface for CRSBase Object types. - /// - public interface ICRSObject - { - /// - /// Gets the CRS type. - /// - CRSTypes Type { get; } - } -} diff --git a/NetTopologySuite.Features/CoordinateSystems/LinkedCRS.cs b/NetTopologySuite.Features/CoordinateSystems/LinkedCRS.cs deleted file mode 100644 index 6369915..0000000 --- a/NetTopologySuite.Features/CoordinateSystems/LinkedCRS.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace NetTopologySuite.CoordinateSystems -{ - using System; - using System.Collections.Generic; - - /// - /// Defines the Linked CRS type. - /// - public class LinkedCRS : CRSBase - { - /// - /// Initializes a new instance of the class. - /// - /// The mandatory href member must be a dereferenceable URI. - /// The optional type member will be put in the properties Dictionary as specified in the GeoJSON spec. - public LinkedCRS(string href, string type = "") : this(new Uri(href), type) { } - - /// - /// Initializes a new instance of the class. - /// - /// The mandatory href member must be a dereferenceable URI. - /// The optional type member will be put in the properties Dictionary as specified in the GeoJSON spec. - public LinkedCRS(Uri href, string type = "") - { - if (href == null) - throw new ArgumentNullException("href"); - - this.Properties = new Dictionary { { "href", href.ToString() } }; - - if (!string.IsNullOrEmpty(type)) - this.Properties.Add("type", type); - - this.Type = CRSTypes.Link; - } - } -} diff --git a/NetTopologySuite.Features/CoordinateSystems/NamedCRS.cs b/NetTopologySuite.Features/CoordinateSystems/NamedCRS.cs deleted file mode 100644 index 9da8e49..0000000 --- a/NetTopologySuite.Features/CoordinateSystems/NamedCRS.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace NetTopologySuite.CoordinateSystems -{ - using System; - using System.Collections.Generic; - - /// - /// Defines the Named CRS type. - /// - public class NamedCRS : CRSBase - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The mandatory name - /// member must be a string identifying a coordinate reference system. OGC CRS URNs such as - /// 'urn:ogc:def:crs:OGC:1.3:CRS84' shall be preferred over legacy identifiers such as 'EPSG:4326'. - /// - public NamedCRS(string name) - { - if (name == null) - throw new ArgumentNullException("name"); - - if (string.IsNullOrEmpty(name)) - throw new ArgumentOutOfRangeException("name", "May not be empty"); - - this.Properties = new Dictionary { { "name", name } }; - this.Type = CRSTypes.Name; - } - } -} diff --git a/NetTopologySuite.Features/Features/AttributesTable.cs b/NetTopologySuite.Features/Features/AttributesTable.cs deleted file mode 100644 index 14b4ec3..0000000 --- a/NetTopologySuite.Features/Features/AttributesTable.cs +++ /dev/null @@ -1,257 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -#if SERIALIZATION_COMPAT_NETTOPOLOGYSUITE_FEATURES_ATTRIBUTESTABLE -using Hashtable = System.Collections.Hashtable; -#else -using Hashtable = System.Collections.Generic.IDictionary; -#endif - -namespace NetTopologySuite.Features -{ - /// - /// Stores all attributes associated with a single Geometry feature. - /// -#if HAS_SYSTEM_SERIALIZABLEATTRIBUTE - [Serializable] -#endif - public class AttributesTable : IAttributesTable, IEnumerable - { - //private const string IndexField = "_NTS_ID_"; - //private const int IndexValue = 0; - - /// - /// Gets or sets a value indicating if setting with a - /// nonexistant index will throw an exception or if the attribute/value pair will - /// silently be added. - /// - public static bool AddAttributeWithIndexer { get; set; } - - private readonly Hashtable _attributes; - - /// - /// Creates an instance of this class - /// - public AttributesTable() - { - _attributes = -#if SERIALIZATION_COMPAT_NETTOPOLOGYSUITE_FEATURES_ATTRIBUTESTABLE - new System.Collections.Hashtable(); -#else - new Dictionary(); -#endif - } - - /* - /// - /// Creates an instance of this class using the provided enumeration of key/value pairs - /// - /// An enumeration of key/value pairs - /// If the enumeration contains invalid objects - public AttributesTable(IEnumerable attributes) : this() - { - foreach (var obj in attributes) - { - if (obj == null) - continue; - - if (obj.Length != 2) - throw new ArgumentException("Each entry in attributes has to have exactly two elements", "attributes"); - - if (!(obj[0] is string)) - throw new ArgumentException("The first element of each entry in attributes has to be a string.", "attributes"); - - Add((string)obj[0], obj[1]); - } - } - */ - - /// - /// Creates an instance of this class using the provided enumeration of key/value pairs - /// - /// An enumeration of key/value pairs - public AttributesTable(IEnumerable> attributes) : this() - { - foreach (var obj in attributes) - Add(obj.Key, obj.Value); - } - - /// - /// Creates an instance of this class using the provided enumeration of key/value pairs - /// - /// An attributes dictionary - /// If the attributes are null - public AttributesTable(Hashtable attributes) - { - if (attributes == null) - throw new ArgumentNullException("attributes"); - _attributes = attributes; - } - - /// - /// Gets a value indicating the number of attributes - /// - public int Count - { - get { return _attributes.Count; } - } - - /// - /// Returns a string array containing - /// all names of present attributes. - /// - /// - public string[] GetNames() - { - int index = 0; - string[] names = new string[_attributes.Count]; - foreach (string name in _attributes.Keys) - names[index++] = name; - return names; - } - - /// - /// Returns a object array containing - /// all values of present attributes. - /// - /// - public object[] GetValues() - { - var index = 0; - var values = new object[_attributes.Count]; - foreach (var val in _attributes.Values) - values[index++] = val; - return values; - } - - /// - /// Verifies if attribute specified already exists. - /// - /// The name of the attribute - /// true if the attribute exists, otherwise false. - public bool Exists(string attributeName) - { - return _attributes.ContainsKey(attributeName); - } - - /// - /// Build a field with the given value and add it to attributes table. - /// - /// Name of the new attribute. - /// Value for attribute (can be null). - /// If attribute already exists. - [Obsolete("Use Add method. This method is here to serve IAttributesTable interface")] - public void AddAttribute(string attributeName, object attributeValue) - { - Add(attributeName, attributeValue); - } - - /// - /// Delete the specified attribute from the table. - /// - /// - public virtual void DeleteAttribute(string attributeName) - { - if (!Exists(attributeName)) - throw new ArgumentException("Attribute " + attributeName + " does not exist!"); - _attributes.Remove(attributeName); - } - - /// - /// Return the System.Type of the specified attribute, - /// useful for casting values retrieved with GetValue methods. - /// - /// - /// - public Type GetType(string attributeName) - { - if (!Exists(attributeName)) - throw new ArgumentOutOfRangeException("Attribute " + attributeName + " does not exist!"); - - // if we have null, we can't determine the objects type, thus return typeof(object) - if (_attributes[attributeName] == null) - return typeof(object); - - return _attributes[attributeName].GetType(); - } - - /// - /// Get the value of the specified attribute. - /// - /// - /// - protected object GetValue(string attributeName) - { - if (!Exists(attributeName)) - throw new ArgumentException("Attribute " + attributeName + " does not exist!"); - return _attributes[attributeName]; - } - - /// - /// Set the value of the specified attribute. - /// - /// - /// - protected void SetValue(string attributeName, object attributeValue) - { - if (!Exists(attributeName)) - { - if (!AddAttributeWithIndexer) - throw new ArgumentException("Attribute " + attributeName + " does not exist!"); - Add(attributeName, attributeValue); - return; - } - _attributes[attributeName] = attributeValue; - } - - /// - /// Get / Set the value of the specified attribute. - /// - /// - /// - public object this[string attributeName] - { - get { return GetValue(attributeName); } - set { SetValue(attributeName, value); } - } - - /// - /// Method to merge this attribute table with another attribute table - /// - /// The other attribute table - /// A value indicating if values in this attribute table are preferable - /// over those in . The default is true. - /// - public void MergeWith(IAttributesTable other, bool preferThis = true) - { - foreach (var name in other.GetNames()) - { - if (!Exists(name)) - Add(name, other[name]); - else - { - if (!preferThis) - this[name] = other[name]; - } - } - } - - /// - /// Add a field with the given value and add it to attributes table. - /// - /// Name of the new attribute. - /// Value for attribute (can be null). - /// If attribute already exists. - public void Add(string attributeName, object attributeValue) - { - if (Exists(attributeName)) - throw new ArgumentException("Attribute " + attributeName + " already exists!"); - _attributes.Add(attributeName, attributeValue); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)_attributes).GetEnumerator(); - } - } -} diff --git a/NetTopologySuite.Features/Features/Feature.cs b/NetTopologySuite.Features/Features/Feature.cs deleted file mode 100644 index 8701649..0000000 --- a/NetTopologySuite.Features/Features/Feature.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using GeoAPI.Geometries; - -namespace NetTopologySuite.Features -{ - /// - /// Feature class - /// -#if HAS_SYSTEM_SERIALIZABLEATTRIBUTE - [Serializable] -#endif - public class Feature : IFeature - { - /// - /// Gets or sets a value indicating how bounding box on should be handled - /// - /// Default is false - public static bool ComputeBoundingBoxWhenItIsMissing { get; set; } - - private IGeometry _geometry; - private IAttributesTable _attributes; - private Envelope _boundingBox; - - /// - /// Creates an instace of this class - /// - /// The geometry - /// The attributes - public Feature(IGeometry geometry, IAttributesTable attributes) - : this() - { - _geometry = geometry; - _attributes = attributes; - } - - /// - /// Creates an instance of this class - /// - public Feature() { } - - /// - /// Geometry representation of the feature. - /// - public virtual IGeometry Geometry - { - get { return _geometry; } - set { _geometry = value; } - } - - /// - /// Attributes table of the feature. - /// - public virtual IAttributesTable Attributes - { - get { return _attributes; } - set { _attributes = value; } - } - - - /// - /// Gets or sets the (optional) Bounding box (bbox) Object. - /// - /// - /// A describing the bounding box or null. - /// - public Envelope BoundingBox - { - get - { - if (_boundingBox != null) - return new Envelope(_boundingBox); - - if (_geometry != null && ComputeBoundingBoxWhenItIsMissing) - return _geometry.EnvelopeInternal; - - return null; - } - set { _boundingBox = value; } - } - } -} diff --git a/NetTopologySuite.Features/Features/FeatureCollection.cs b/NetTopologySuite.Features/Features/FeatureCollection.cs deleted file mode 100644 index de56ab7..0000000 --- a/NetTopologySuite.Features/Features/FeatureCollection.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using GeoAPI.Geometries; -using NetTopologySuite.CoordinateSystems; - -namespace NetTopologySuite.Features -{ - /// - /// Represents a feature collection. - /// -#if HAS_SYSTEM_SERIALIZABLEATTRIBUTE - [Serializable] -#endif - public class FeatureCollection - { - /// - /// The bounding box of this - /// - private Envelope _boundingBox; - - /// - /// Gets the features. - /// - /// The features. - public Collection Features { get; private set; } - - /// - /// Gets the (mandatory) type of the GeoJSON Object. - /// - /// - /// The type of the object. - /// - public string Type { get; private set; } - - /// - /// Gets or sets the (optional) Coordinate Reference System Object. - /// - /// - /// The Coordinate Reference System Objects. - /// - public ICRSObject CRS { get; set; } - - /// - /// Returns the indexTh element in the collection. - /// - /// - //[JsonIgnore] - public IFeature this[int index] - { - get { return Features[index]; } - } - - /// - /// Returns the number of features contained by this . - /// - public int Count - { - get { return Features.Count; } - } - - /// - /// Initializes a new instance of the class. - /// - /// The features. - public FeatureCollection(Collection features) - { - Type = "FeatureCollection"; - Features = features ?? new Collection(); - } - - /// - /// Initializes a new instance of the class. - /// - public FeatureCollection() : this(null) { } - - /// - /// Adds the specified feature. - /// - /// The feature. - public void Add(IFeature feature) - { - Features.Add(feature); - } - - /// - /// Removes the specified feature. - /// - /// The feature. - /// true if item is successfully removed; otherwise, false. This method also returns - /// false if item was not found in the collection. - public bool Remove(IFeature feature) - { - return Features.Remove(feature); - } - - /// - /// Removes the element at the specified index of the collection. - /// - /// The index. - public void RemoveAt(int index) - { - Features.RemoveAt(index); - } - - /// - /// Gets or sets the (optional) Bounding box (bbox) Object. - /// - /// - /// A describing the bounding box or null. - /// - public Envelope BoundingBox - { - get - { - if (_boundingBox == null) - _boundingBox = ComputeBoundingBox(); - if (_boundingBox != null) - return new Envelope(_boundingBox); - return null; - } - set { _boundingBox = value; } - } - - /// - /// Function to compute the bounding box (when it isn't set) - /// - /// A bounding box for this - private Envelope ComputeBoundingBox() - { - if (!Feature.ComputeBoundingBoxWhenItIsMissing) - return null; - - var res = new Envelope(); - foreach (var feature in Features) - { - if (feature.BoundingBox != null) - res.ExpandToInclude(feature.BoundingBox); - else if (feature.Geometry != null) - res.ExpandToInclude(feature.Geometry.EnvelopeInternal); - } - return res; - } - } -} diff --git a/NetTopologySuite.Features/Features/FeatureExtensions.cs b/NetTopologySuite.Features/Features/FeatureExtensions.cs deleted file mode 100644 index 11d52c1..0000000 --- a/NetTopologySuite.Features/Features/FeatureExtensions.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; - -namespace NetTopologySuite.Features -{ - /// - /// Extension methods for s. - /// - public static class FeatureExtensions - { - static FeatureExtensions() - { - // According to GeoJSON name of the feature's identifier - IdAttributeName = "id"; - } - - /// - /// Gets or sets a name that is used to retrieve the ID of a feature from the attribute table - /// - public static string IdAttributeName { get; set; } - - /// - /// Function to get a feature's ID - /// - /// The feature - /// The feature's ID if one has been assigned, otherwise null - /// Thrown, if is null - public static object ID(IFeature feature) - { - return HasID(feature) - ? feature.Attributes[IdAttributeName] - : null; - } - - /// - /// Function to evaluate if a feature has an ID - /// - /// The feature - /// true if has an identifier assigned, otherwise false - /// Thrown, if is null - public static bool HasID(IFeature feature) - { - if (feature == null) - throw new ArgumentNullException("feature"); - - return feature.Attributes.Exists(IdAttributeName); - } - } -} diff --git a/NetTopologySuite.Features/Features/IFeature.cs b/NetTopologySuite.Features/Features/IFeature.cs deleted file mode 100644 index a33988c..0000000 --- a/NetTopologySuite.Features/Features/IFeature.cs +++ /dev/null @@ -1,25 +0,0 @@ -using GeoAPI.Geometries; - -namespace NetTopologySuite.Features -{ - /// - /// Interface for feature classes - /// - public interface IFeature - { - /// - /// Gets or sets the attributes for the feature - /// - IAttributesTable Attributes { get; set; } - - /// - /// Gets or sets the feature's geometry - /// - IGeometry Geometry { get; set; } - - /// - /// Gets or sets the feature's geometry - /// - Envelope BoundingBox { get; set; } - } -} diff --git a/NetTopologySuite.Features/NetTopologySuite.Features.csproj b/NetTopologySuite.Features/NetTopologySuite.Features.csproj deleted file mode 100644 index 3760894..0000000 --- a/NetTopologySuite.Features/NetTopologySuite.Features.csproj +++ /dev/null @@ -1,51 +0,0 @@ - - - - $(ProjectDir)..\ - net35-client;net40-client;net403-client;net45;netstandard1.0;netstandard1.3;netstandard2.0 - true - $(SolutionDir)nts.snk - 659,168,1587 - NetTopologySuite - false - https://github.com/NetTopologySuite/NetTopologySuite.Features - git - https://github.com/NetTopologySuite/NetTopologySuite.Features - NetTopologySuite - Team - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SharedAssemblyVersion.cs b/SharedAssemblyVersion.cs deleted file mode 100644 index 793183f..0000000 --- a/SharedAssemblyVersion.cs +++ /dev/null @@ -1,7 +0,0 @@ -// This is now the main source of versioning information. -// -> Change the version # here. - -using System.Reflection; - -[assembly: AssemblyVersion("1.15.0")] -[assembly: AssemblyFileVersion("1.15.1")] diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..d1163fe --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,99 @@ + + + + + + + true + + + + + true + true + ci.travis.$(TRAVIS_BUILD_NUMBER) + + true + + + + + true + true + ci.teamcity.$(BUILD_NUMBER) + + + + + true + true + ci.appveyor.$(APPVEYOR_BUILD_NUMBER) + + + + + local + + + + + 2 + 0 + 0 + + $([System.DateTime]::UtcNow.Ticks) + $([System.DateTime]::op_Subtraction($([System.DateTime]::new($(NtsBuildTimestamp)).Date),$([System.DateTime]::new(621355968000000000))).TotalDays.ToString("00000")) + + + $([System.DateTime]::new($(NtsBuildTimestamp)).TimeOfDay.TotalMinutes.ToString("0000")) + + $(NtsMajorVersion).$(NtsMinorVersion).$(NtsPatchVersion) + pre.$(NtsDaysSinceEpoch)$(NtsMinutesSinceStartOfUtcDay)+$(NtsBuildMetadata) + + + + + + + $(NtsMajorVersion).0.0.0 + $(NtsMajorVersion).$(NtsMinorVersion).$(NtsPatchVersion).$(NtsBuildNumber) + $(NtsMajorVersion).$(NtsMinorVersion).$(NtsPatchVersion) (compatible with JTS $(JTSCompatibilityLevel)) + + NetTopologySuite - Team + + $(Company) + Copyright © $([System.DateTime]::UtcNow.Year) $(CopyrightPeople) + + + + true + true + true + snupkg + + + + + + + + diff --git a/src/NetTopologySuite.Features/AttributesTable.cs b/src/NetTopologySuite.Features/AttributesTable.cs new file mode 100644 index 0000000..91d8f57 --- /dev/null +++ b/src/NetTopologySuite.Features/AttributesTable.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; + +namespace NetTopologySuite.Features +{ + /// + /// Stores all attributes associated with a single Geometry feature. + /// + [Serializable] + public sealed class AttributesTable : IAttributesTable, IEnumerable>, ISerializable + { + private readonly Dictionary _attributes; + + /// + /// Gets or sets a value indicating if setting with a + /// nonexistant index will throw an exception or if the attribute/value pair will + /// silently be added. + /// + public static bool AddAttributeWithIndexer { get; set; } + + /// + /// Creates an instance of this class. + /// + public AttributesTable() + { + _attributes = new Dictionary(); + } + + /// + /// Creates an instance of this class using the provided enumeration of key/value pairs + /// + /// An enumeration of key/value pairs + public AttributesTable(IEnumerable> attributes) + : this() + { + foreach (var kvp in attributes) + { + Add(kvp.Key, kvp.Value); + } + } + + /// + /// Creates an instance of this class using the provided enumeration of key/value pairs + /// + /// An attributes dictionary + /// If the attributes are null + public AttributesTable(Dictionary attributes) + { + _attributes = attributes ?? throw new ArgumentNullException(nameof(attributes)); + } + + private AttributesTable(SerializationInfo info, StreamingContext context) + { + _attributes = (Dictionary)info.GetValue("_attributes", typeof(Dictionary)); + } + + /// + public int Count => _attributes.Count; + + /// + public object this[string attributeName] + { + get => GetValue(attributeName); + set => SetValue(attributeName, value); + } + + /// + public string[] GetNames() + { + return _attributes.Keys.ToArray(); + } + + /// + public object[] GetValues() + { + return _attributes.Values.ToArray(); + } + + /// + public bool Exists(string attributeName) + { + return _attributes.ContainsKey(attributeName); + } + + /// + public void DeleteAttribute(string attributeName) + { + if (!_attributes.Remove(attributeName)) + { + throw new ArgumentException($"Attribute {attributeName} does not exist!", nameof(attributeName)); + } + } + + /// + public Type GetType(string attributeName) + { + return _attributes.TryGetValue(attributeName, out object value) + ? value?.GetType() ?? typeof(object) + : throw new ArgumentOutOfRangeException($"Attribute {attributeName} does not exist!", nameof(attributeName)); + } + + /// + /// Method to merge this attribute table with another attribute table + /// + /// The other attribute table + /// A value indicating if values in this attribute table are preferable + /// over those in . The default is true. + /// + public void MergeWith(IAttributesTable other, bool preferThis = true) + { + foreach (string name in other.GetNames()) + { + if (!(preferThis && Exists(name))) + { + _attributes[name] = other[name]; + } + } + } + + /// + public void Add(string attributeName, object attributeValue) + { + if (Exists(attributeName)) + { + throw new ArgumentException($"Attribute {attributeName} already exists!", nameof(attributeName)); + } + + _attributes.Add(attributeName, attributeValue); + } + + /// + public object GetOptionalValue(string attributeName) + { + _attributes.TryGetValue(attributeName, out object value); + return value; + } + + /// + public Dictionary.Enumerator GetEnumerator() + { + return _attributes.GetEnumerator(); + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + return ((IEnumerable>)_attributes).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_attributes).GetEnumerator(); + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info is null) + { + throw new ArgumentNullException(nameof(info)); + } + + info.AddValue("_attributes", _attributes); + } + + private object GetValue(string attributeName) + { + return _attributes.TryGetValue(attributeName, out object value) + ? value + : throw new ArgumentException($"Attribute {attributeName} does not exist!", nameof(attributeName)); + } + + private void SetValue(string attributeName, object value) + { + if (!AddAttributeWithIndexer && !Exists(attributeName)) + { + throw new ArgumentException($"Attribute {attributeName} does not exist!", nameof(attributeName)); + } + + _attributes[attributeName] = value; + } + } +} diff --git a/src/NetTopologySuite.Features/Feature.cs b/src/NetTopologySuite.Features/Feature.cs new file mode 100644 index 0000000..3305502 --- /dev/null +++ b/src/NetTopologySuite.Features/Feature.cs @@ -0,0 +1,86 @@ +using System; +using System.Runtime.Serialization; + +using NetTopologySuite.Geometries; + +namespace NetTopologySuite.Features +{ + /// + /// Standard implementation of . + /// + [Serializable] + public sealed class Feature : IFeature, ISerializable + { + private Envelope _boundingBox; + + private IAttributesTable _attributes; + + /// + /// Initializes a new instance of the class. + /// + public Feature() + { + _attributes = new AttributesTable(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The geometry + /// The attributes + public Feature(Geometry geometry, IAttributesTable attributes) + { + Geometry = geometry; + _attributes = attributes ?? throw new ArgumentNullException(nameof(attributes)); + } + + private Feature(SerializationInfo info, StreamingContext context) + { + _boundingBox = info.GetBoundingBox(); + Attributes = (IAttributesTable)info.GetValue("attributes", typeof(IAttributesTable)); + Geometry = (Geometry)info.GetValue("geometry", typeof(Geometry)); + } + + /// + /// Gets or sets a value indicating how bounding box on should be handled + /// + /// Default is false + public static bool ComputeBoundingBoxWhenItIsMissing { get; set; } + + /// + public Geometry Geometry { get; set; } + + /// + public IAttributesTable Attributes + { + get => _attributes; + set => _attributes = value ?? throw new ArgumentNullException(nameof(value)); + } + + /// + public Envelope BoundingBox + { + get + { + if (_boundingBox is null) + { + if (ComputeBoundingBoxWhenItIsMissing) + { + _boundingBox = Geometry?.EnvelopeInternal; + } + } + + return _boundingBox?.Copy(); + } + + set => _boundingBox = value; + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddBoundingBox(_boundingBox); + info.AddValue("attributes", Attributes); + info.AddValue("geometry", Geometry); + } + } +} diff --git a/src/NetTopologySuite.Features/FeatureCollection.cs b/src/NetTopologySuite.Features/FeatureCollection.cs new file mode 100644 index 0000000..3ef0158 --- /dev/null +++ b/src/NetTopologySuite.Features/FeatureCollection.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; + +using NetTopologySuite.Geometries; + +namespace NetTopologySuite.Features +{ + /// + /// Represents a feature collection. + /// + [Serializable] + public sealed class FeatureCollection : Collection, ISerializable + { + /// + /// The bounding box of this + /// + private Envelope _boundingBox; + + /// + /// Initializes a new instance of the class. + /// + public FeatureCollection() + : base(new List()) + { + } + + private FeatureCollection(SerializationInfo info, StreamingContext context) + : base((List)info.GetValue("features", typeof(List))) + { + _boundingBox = info.GetBoundingBox(); + } + + /// + /// Gets or sets the (optional) Bounding box (bbox) Object. + /// + /// + /// A describing the bounding box or . + /// + public Envelope BoundingBox + { + get + { + if (_boundingBox is null) + { + _boundingBox = ComputeBoundingBox(); + } + + return _boundingBox?.Copy(); + } + + set => _boundingBox = value; + } + + /// + /// Function to compute the bounding box (when it isn't set) + /// + /// A bounding box for this + private Envelope ComputeBoundingBox() + { + if (!Feature.ComputeBoundingBoxWhenItIsMissing) + { + return null; + } + + var res = new Envelope(); + foreach (var feature in (List)Items) + { + if (feature is null) + { + continue; + } + + if (!(feature.BoundingBox is null)) + { + res.ExpandToInclude(feature.BoundingBox); + } + else if (!(feature.Geometry is null)) + { + res.ExpandToInclude(feature.Geometry.EnvelopeInternal); + } + } + + return res; + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddBoundingBox(_boundingBox); + info.AddValue("features", Items); + } + } +} diff --git a/NetTopologySuite.Features/Features/IAttributesTable.cs b/src/NetTopologySuite.Features/IAttributesTable.cs similarity index 76% rename from NetTopologySuite.Features/Features/IAttributesTable.cs rename to src/NetTopologySuite.Features/IAttributesTable.cs index b6ae0bc..767a6ec 100644 --- a/NetTopologySuite.Features/Features/IAttributesTable.cs +++ b/src/NetTopologySuite.Features/IAttributesTable.cs @@ -1,63 +1,76 @@ -using System; - -namespace NetTopologySuite.Features -{ - /// - /// Interface definition for an object capable of storing 's attribute data - /// - public interface IAttributesTable - { - /// - /// Method to add the attribute "" from the attribute table. - /// - /// The name (or key) of the attribute - /// - void AddAttribute(string attributeName, object value); - - /// - /// Method to delete the attribute "" from the attribute table. - /// - /// The name (or key) of the attribute - void DeleteAttribute(string attributeName); - - /// - /// Function to query the of the Attribute "" - /// - /// The name (or key) of the attribute - /// The of the specified attribute - Type GetType(string attributeName); - - /// - /// Gets or sets the attribute value for the specified . - /// - /// The name (or key) of the attribute - /// The attribute value - object this[string attributeName] { get; set; } - - /// - /// Function to verify if attribute data for the specified does exist. - /// - /// The name of the attribute - /// true if the attribute data exists, otherwise false. - bool Exists(string attributeName); - - /// - /// Gets a value indicating the number of attributes - /// - int Count { get; } - - /// - /// Function to retrieve the names (or keys) of the feature's attributes - /// - /// - /// Returns an array of values - string[] GetNames(); - - /// - /// Function to retrieve the attribute data of the feature - /// - /// - /// Returns an array of values - object[] GetValues(); - } -} +using System; + +namespace NetTopologySuite.Features +{ + /// + /// Interface definition for an object capable of storing 's attribute data + /// + public interface IAttributesTable + { + /// + /// Method to add the attribute "" from the attribute table. + /// + /// The name (or key) of the attribute + /// + void Add(string attributeName, object value); + + /// + /// Method to delete the attribute "" from the attribute table. + /// + /// The name (or key) of the attribute + void DeleteAttribute(string attributeName); + + /// + /// Function to query the of the Attribute "" + /// + /// The name (or key) of the attribute + /// The of the specified attribute + Type GetType(string attributeName); + + /// + /// Gets or sets the attribute value for the specified . + /// + /// The name (or key) of the attribute + /// The attribute value + object this[string attributeName] { get; set; } + + /// + /// Function to verify if attribute data for the specified does exist. + /// + /// The name of the attribute + /// true if the attribute data exists, otherwise false. + bool Exists(string attributeName); + + /// + /// Gets a value indicating the number of attributes + /// + int Count { get; } + + /// + /// Function to retrieve the names (or keys) of the feature's attributes + /// + /// + /// Returns an array of values + /// + string[] GetNames(); + + /// + /// Function to retrieve the attribute data of the feature + /// + /// + /// Returns an array of values + /// + object[] GetValues(); + + /// + /// Gets the value associated with the attribute for the specified name, or + /// if the attribute does not exist. + /// + /// The name (or key) of the attribute. + /// + /// The value associated with , or + /// if the attribute does not exist. + /// + object GetOptionalValue(string attributeName); + } +} diff --git a/src/NetTopologySuite.Features/IFeature.cs b/src/NetTopologySuite.Features/IFeature.cs new file mode 100644 index 0000000..127f727 --- /dev/null +++ b/src/NetTopologySuite.Features/IFeature.cs @@ -0,0 +1,25 @@ +using NetTopologySuite.Geometries; + +namespace NetTopologySuite.Features +{ + /// + /// Contains a and a description of its metadata. + /// + public interface IFeature + { + /// + /// Gets or sets the of this feature. + /// + Geometry Geometry { get; set; } + + /// + /// Gets or sets an that describes the bounds of this feature. + /// + Envelope BoundingBox { get; set; } + + /// + /// Gets or sets a representation of this feature's metadata, tagged by user-defined strings. + /// + IAttributesTable Attributes { get; set; } + } +} diff --git a/src/NetTopologySuite.Features/InternalExtensions.cs b/src/NetTopologySuite.Features/InternalExtensions.cs new file mode 100644 index 0000000..4377e54 --- /dev/null +++ b/src/NetTopologySuite.Features/InternalExtensions.cs @@ -0,0 +1,32 @@ +using System.Runtime.Serialization; + +using NetTopologySuite.Geometries; + +namespace NetTopologySuite.Features +{ + internal static class InternalExtensions + { + public static Envelope GetBoundingBox(this SerializationInfo info) + { + return info.GetBoolean("has_bbox") + ? new Envelope(info.GetDouble("bbox_x1"), info.GetDouble("bbox_x2"), info.GetDouble("bbox_y1"), info.GetDouble("bbox_y2")) + : null; + } + + public static void AddBoundingBox(this SerializationInfo info, Envelope boundingBox) + { + if (boundingBox is null) + { + info.AddValue("has_bbox", false); + } + else + { + info.AddValue("has_bbox", true); + info.AddValue("bbox_x1", boundingBox.MinX); + info.AddValue("bbox_x2", boundingBox.MaxX); + info.AddValue("bbox_y1", boundingBox.MinY); + info.AddValue("bbox_y2", boundingBox.MaxY); + } + } + } +} diff --git a/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj b/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj new file mode 100644 index 0000000..87572bc --- /dev/null +++ b/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj @@ -0,0 +1,30 @@ + + + + + netstandard2.0 + true + 659,168,1587 + + + + NetTopologySuite.Features + NTS - Topology Suite - Features + NetTopologySuite - Team + NetTopologySuite - Team + BSD-3-Clause + true + + A feature is a combination of spatial object and attribute data. + For this package attribute data is stored in AttributeTable objects. + These are combined with IGeometry objects to form a Feature. + A FeatureCollection is a collection of features. + + NTS;Topology;OGC;SFS + + + + + + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000..598b768 --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,16 @@ + + + + + + + false + + + + + + + + + diff --git a/test/NetTopologySuite.Features.Test/AttributesTableTest.cs b/test/NetTopologySuite.Features.Test/AttributesTableTest.cs new file mode 100644 index 0000000..f616af5 --- /dev/null +++ b/test/NetTopologySuite.Features.Test/AttributesTableTest.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; + +using NUnit.Framework; + +namespace NetTopologySuite.Features.Test +{ + [TestFixture] + public sealed class AttributesTableTests + { + private bool _savedAddAttributeWithIndexer; + + [SetUp] + public void SetUp() => _savedAddAttributeWithIndexer = AttributesTable.AddAttributeWithIndexer; + + [TearDown] + public void TearDown() => AttributesTable.AddAttributeWithIndexer = _savedAddAttributeWithIndexer; + + [Test] + public void TestBasicReadAndWriteOperations() + { + var expected = new Dictionary(); + var actual = new AttributesTable(); + + // test everything after a serialize + deserialize round-trip + ExpectedAndActual.RoundTrip(ref expected, ref actual); + + expected.Add("hello", "hi"); + actual.Add("hello", "hi"); + + AssertEqual(expected, actual); + + AttributesTable.AddAttributeWithIndexer = false; + Assert.That(() => actual["oh"] = 321, Throws.ArgumentException); + + AssertEqual(expected, actual); + + AttributesTable.AddAttributeWithIndexer = true; + expected["oh"] = 321; + Assert.That(() => actual["oh"] = 321, Throws.Nothing); + + AssertEqual(expected, actual); + + AssertEqual(expected, actual); + + expected.Remove("hello"); + actual.DeleteAttribute("hello"); + + AssertEqual(expected, actual); + + Assert.That(() => actual.DeleteAttribute("hello"), Throws.ArgumentException); + + AssertEqual(expected, actual); + + expected.Add("hello", new object()); + actual.Add("hello", expected["hello"]); + + AssertEqual(expected, actual); + + expected["hello"] = Guid.NewGuid(); + actual["hello"] = expected["hello"]; + + AssertEqual(expected, actual); + + Assert.That(() => actual.Add("hello", "oh, hi there"), Throws.ArgumentException); + + AssertEqual(expected, actual); + + Assert.That(() => actual["a key that shouldn't exist"], Throws.ArgumentException); + Assert.That(() => actual.GetType("a key that shouldn't exist"), Throws.InstanceOf()); + + AssertEqual(expected, actual); + } + + [Test] + public void TestMergeWith_PreferThis() + { + var table1 = new AttributesTable + { + { "1", "a" }, + { "2", "b" }, + { "3", "c" }, + }; + + var table2 = new AttributesTable + { + { "2", "x" }, + { "3", "y" }, + { "4", "z" }, + }; + + table1.MergeWith(table2, preferThis: true); + + var expected = new Dictionary + { + { "1", "a" }, + { "2", "b" }, + { "3", "c" }, + { "4", "z" }, + }; + + AssertEqual(expected, table1); + } + + [Test] + public void TestMergeWith_DoNotPreferThis() + { + var table1 = new AttributesTable + { + { "1", "a" }, + { "2", "b" }, + { "3", "c" }, + }; + + var table2 = new AttributesTable + { + { "2", "x" }, + { "3", "y" }, + { "4", "z" }, + }; + + table1.MergeWith(table2, preferThis: false); + + var expected = new Dictionary + { + { "1", "a" }, + { "2", "x" }, + { "3", "y" }, + { "4", "z" }, + }; + + AssertEqual(expected, table1); + } + + private static void AssertEqual(Dictionary expected, AttributesTable actual) + { + // test everything after a serialize + deserialize round-trip + ExpectedAndActual.RoundTrip(ref expected, ref actual); + + Assert.That(actual.Count, Is.EqualTo(expected.Count)); + Assert.That(actual, Is.EquivalentTo(expected)); + + Assert.That(actual.GetNames().Count, Is.EqualTo(expected.Keys.Count)); + Assert.That(actual.GetNames(), Is.EquivalentTo(expected.Keys)); + + Assert.That(actual.GetValues().Count, Is.EqualTo(expected.Values.Count)); + Assert.That(actual.GetValues(), Is.EquivalentTo(expected.Values)); + + foreach ((string key, object value) in expected) + { + Assert.That(actual.Exists(key)); + Assert.That(actual[key], Is.EqualTo(value)); + + object retrieved = actual.GetOptionalValue(key); + Assert.That(retrieved, Is.EqualTo(value)); + + Assert.That(actual.GetType(key), Is.EqualTo(value?.GetType() ?? typeof(object))); + } + } + + [Serializable] + private sealed class ExpectedAndActual + { + private readonly Dictionary _expected; + + private readonly AttributesTable _actual; + + private ExpectedAndActual(Dictionary expected, AttributesTable actual) => + (_expected, _actual) = (expected, actual); + + public static void RoundTrip(ref Dictionary expected, ref AttributesTable actual) + { + using (var ms = new MemoryStream()) + { + new BinaryFormatter().Serialize(ms, new ExpectedAndActual(expected, actual)); + ms.Position = 0; + var deserialized = (ExpectedAndActual)new BinaryFormatter().Deserialize(ms); + expected = deserialized._expected; + actual = deserialized._actual; + } + } + } + } +} diff --git a/test/NetTopologySuite.Features.Test/FeatureCollectionTest.cs b/test/NetTopologySuite.Features.Test/FeatureCollectionTest.cs new file mode 100644 index 0000000..3afc6b5 --- /dev/null +++ b/test/NetTopologySuite.Features.Test/FeatureCollectionTest.cs @@ -0,0 +1,105 @@ +using System.IO; +using System.Runtime.Serialization.Formatters.Binary; + +using NetTopologySuite.Geometries; + +using NUnit.Framework; + +namespace NetTopologySuite.Features.Test +{ + /// + /// A test fixture for the class + /// + public sealed class FeatureCollectionTest + { + private bool _savedComputeWhenMissing; + + [SetUp] + public void SetUp() => _savedComputeWhenMissing = Feature.ComputeBoundingBoxWhenItIsMissing; + + [TearDown] + public void TearDown() => Feature.ComputeBoundingBoxWhenItIsMissing = _savedComputeWhenMissing; + + [Test] + public void SimpleTest() + { + IFeature[] features = { CreateFeature(0), CreateFeature(1), null, CreateFeature(2), CreateFeature(3) }; + + var featureCollection = new FeatureCollection(); + foreach (var f in features) + { + featureCollection.Add(f); + } + + Assert.That(featureCollection, Is.EqualTo(features)); + } + + [Test] + public void BoundingBoxTest() + { + var featureCollection = new FeatureCollection(); + for (int i = 0; i < 4; i++) + { + featureCollection.Add(null); + featureCollection.Add(CreateFeature(i)); + featureCollection.Add(null); + } + + Feature.ComputeBoundingBoxWhenItIsMissing = false; + Assert.That(featureCollection.BoundingBox, Is.Null); + + Feature.ComputeBoundingBoxWhenItIsMissing = true; + Assert.That(featureCollection.BoundingBox, Is.EqualTo(new Envelope(0, 3, 0, 3))); + + Feature.ComputeBoundingBoxWhenItIsMissing = false; + Assert.That(featureCollection.BoundingBox, Is.EqualTo(new Envelope(0, 3, 0, 3))); + } + + [Test] + public void SerializationTest() + { + var featureCollection = new FeatureCollection(); + for (int i = 0; i < 4; i++) + { + featureCollection.Add(null); + featureCollection.Add(CreateFeature(i)); + featureCollection.Add(null); + } + + featureCollection.BoundingBox = new Envelope(2, 4, 8, 16); + + FeatureCollection deserialized; + using (var ms = new MemoryStream()) + { + var formatter = new BinaryFormatter(); + formatter.Serialize(ms, featureCollection); + + ms.Position = 0; + deserialized = (FeatureCollection)formatter.Deserialize(ms); + } + + // ensure that nulls we wrote out stay null when reading them in. + Feature.ComputeBoundingBoxWhenItIsMissing = false; + + for (int i = 0; i < featureCollection.Count; i++) + { + var expected = featureCollection[i]; + var actual = deserialized[i]; + + Assert.That(actual?.Geometry, Is.EqualTo(expected?.Geometry)); + Assert.That(actual?.Attributes, Is.EqualTo(expected?.Attributes)); + Assert.That(actual?.BoundingBox, Is.EqualTo(expected?.BoundingBox)); + } + + Assert.That(deserialized.BoundingBox, Is.EqualTo(new Envelope(2, 4, 8, 16))); + } + + private static IFeature CreateFeature(int i) + { + var geom = GeometryFactory.Default.CreatePoint(new Coordinate(i, i)); + var attributes = new AttributesTable { { $"test.{i}", i} }; + var bbox = i % 2 == 0 ? geom.EnvelopeInternal : null; + return new Feature(geom, attributes) { BoundingBox = bbox }; + } + } +} diff --git a/test/NetTopologySuite.Features.Test/FeatureTest.cs b/test/NetTopologySuite.Features.Test/FeatureTest.cs new file mode 100644 index 0000000..8ff4a7e --- /dev/null +++ b/test/NetTopologySuite.Features.Test/FeatureTest.cs @@ -0,0 +1,50 @@ +using NetTopologySuite.Geometries; + +using NUnit.Framework; + +namespace NetTopologySuite.Features.Test +{ + /// + /// A test fixture for the class + /// + public sealed class FeatureTest + { + private bool _savedComputeWhenMissing; + + [SetUp] + public void SetUp() => _savedComputeWhenMissing = Feature.ComputeBoundingBoxWhenItIsMissing; + + [TearDown] + public void TearDown() => Feature.ComputeBoundingBoxWhenItIsMissing = _savedComputeWhenMissing; + + [Test] + public void SimpleTest() + { + var geom = GeometryFactory.Default.CreatePoint(new Coordinate(1, 1)); + var attributes = new AttributesTable { { "test.1", new object() } }; + var feature = new Feature(geom, attributes); + + Assert.That(feature.Geometry, Is.EqualTo(geom)); + Assert.That(feature.Attributes, Is.EqualTo(attributes)); + } + + [Test] + public void BoundingBoxTest() + { + var c = new Coordinate(1, 1); + var feature = new Feature + { + Geometry = GeometryFactory.Default.CreatePoint(c), + }; + + Feature.ComputeBoundingBoxWhenItIsMissing = false; + Assert.That(feature.BoundingBox, Is.Null); + + Feature.ComputeBoundingBoxWhenItIsMissing = true; + Assert.That(feature.BoundingBox, Is.EqualTo(new Envelope(c))); + + Feature.ComputeBoundingBoxWhenItIsMissing = false; + Assert.That(feature.BoundingBox, Is.EqualTo(new Envelope(c))); + } + } +} diff --git a/test/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj b/test/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj new file mode 100644 index 0000000..336223f --- /dev/null +++ b/test/NetTopologySuite.Features.Test/NetTopologySuite.Features.Test.csproj @@ -0,0 +1,11 @@ + + + + netcoreapp2.2 + + + + + + + From ee118bd7ec495f2d728a6ac6035f64fe70a74ccc Mon Sep 17 00:00:00 2001 From: Joe Amenta Date: Fri, 23 Aug 2019 07:52:08 -0400 Subject: [PATCH 2/5] Allow Feature.Attributes to be null again. --- src/NetTopologySuite.Features/Feature.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/NetTopologySuite.Features/Feature.cs b/src/NetTopologySuite.Features/Feature.cs index 3305502..861c8fa 100644 --- a/src/NetTopologySuite.Features/Feature.cs +++ b/src/NetTopologySuite.Features/Feature.cs @@ -13,14 +13,12 @@ public sealed class Feature : IFeature, ISerializable { private Envelope _boundingBox; - private IAttributesTable _attributes; - /// /// Initializes a new instance of the class. /// public Feature() { - _attributes = new AttributesTable(); + Attributes = new AttributesTable(); } /// @@ -31,7 +29,7 @@ public Feature() public Feature(Geometry geometry, IAttributesTable attributes) { Geometry = geometry; - _attributes = attributes ?? throw new ArgumentNullException(nameof(attributes)); + Attributes = attributes; } private Feature(SerializationInfo info, StreamingContext context) @@ -51,11 +49,7 @@ private Feature(SerializationInfo info, StreamingContext context) public Geometry Geometry { get; set; } /// - public IAttributesTable Attributes - { - get => _attributes; - set => _attributes = value ?? throw new ArgumentNullException(nameof(value)); - } + public IAttributesTable Attributes { get; set; } /// public Envelope BoundingBox From 980ac8177f3573aee7806c03b6a3daf4ac5205ad Mon Sep 17 00:00:00 2001 From: Joe Amenta Date: Fri, 23 Aug 2019 08:18:57 -0400 Subject: [PATCH 3/5] Initialize Attributes null instead of empty. --- src/NetTopologySuite.Features/Feature.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NetTopologySuite.Features/Feature.cs b/src/NetTopologySuite.Features/Feature.cs index 861c8fa..5c7b3db 100644 --- a/src/NetTopologySuite.Features/Feature.cs +++ b/src/NetTopologySuite.Features/Feature.cs @@ -18,7 +18,6 @@ public sealed class Feature : IFeature, ISerializable /// public Feature() { - Attributes = new AttributesTable(); } /// From 44d93dfa8a4b43d33f6447c805440ca1df1f3ee9 Mon Sep 17 00:00:00 2001 From: Joe Amenta Date: Sun, 25 Aug 2019 16:50:56 -0400 Subject: [PATCH 4/5] Don't set InformationalVersion This was just supposed to be for NTS proper. --- src/Directory.Build.props | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index d1163fe..6aa410b 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -76,7 +76,6 @@ $(NtsMajorVersion).0.0.0 $(NtsMajorVersion).$(NtsMinorVersion).$(NtsPatchVersion).$(NtsBuildNumber) - $(NtsMajorVersion).$(NtsMinorVersion).$(NtsPatchVersion) (compatible with JTS $(JTSCompatibilityLevel)) NetTopologySuite - Team From 99744440d745aa0c6a430a6a77a09999f5d5c682 Mon Sep 17 00:00:00 2001 From: Joe Amenta Date: Mon, 26 Aug 2019 09:09:02 -0400 Subject: [PATCH 5/5] Update to the final NTS version. --- .travis.yml | 4 ++-- .../NetTopologySuite.Features.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4bfd0e9..70a1bce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,5 +31,5 @@ deploy: env: global: - - secure: LAI6KJjHA1usZL9Vm3BhLH2JpaukKFXe6OkWM9ahldsDbAqkScWfVIrBtQ0h0SteSpXTXTQDY35pFEuo3MUBmYcJo8NbgDd2f0u078lU6YFfQiHQnPqA8E1m6l+tCy8MTBHM2zePMYYOsyx4k0kOxZIjYK0RwhfmfDsG5QUjXYcABLK11z76vAl4ULIfYfvEnDF7hXbTOM+7XYS72Ve6q5LsNmS1kDGN1n6z8q6Phjac2254WTpUtSTv4u2wNnHYHIc7h7C3OBB6b7y5+pj6WEM2+r5ojs+Gq7QajK9VHNyYHRkUsCzbQKkSPrgskt10kKml3tcmdTCJshUq9nAE27qiCFc6OQO9iMtTh1m2ueZpeflyIhleGmMk12WHuqj1GmYH/8IQw75KzzezcyjuG19OJsL4QAT5FLMAdDfvckUgjY4+0bxPVI3hnWGnrvnrJA0aWXi9s7r+kT6SxI1MvZph7RqDlxC9/Mjt6lrzjMXvBJSf3vAyOGISF1bTOi+/bj586j7V0uagEYSy5tnj5+j/2wsbYcrb+5veVqYl0inPRYbrAAfaPnBux7ZJ/ZP7XggLnUVV0ZkSrqn1NLfEH6nZ30JCVbP9KX4Ztz00sIuHirqq5rhudHOSxL27+RNSX2RosnWDDMcNew6tRhOlSGZ1uZEekypnhvTK+0Ijzso= - - secure: gIlRSvxCO2AzEqiAzGVdowdkqyrlPw0BovjkyFC4HxRsvx7uc9RORv9lCRGR7ni7Z54QbG0DeLXK4PDxPAD6DlZpR8/2NsCLl1JSswRwQYddGsS1HBGTvUJE08RGlwdPYxhAUkz4jargs3EJnTq4TnqEkAzpYaLBSv4om2Q6VsoEe8Uat2iSoK0+NJD9EG++T0Szx2VsgF0M6ILIpYi0ICEqyK0Jb83ZW/78W5na4IN0ZnIOGoG0qeD5wMoOxq8OmnlSnKNJmsZI8LFEvMZu/QGb8YXz2aim+k0UE9kGa1sE/qweSyPtJuTIhUXqvefMZLfDzGIZVz1htvRRzcOQ1Cbh97T853UZiUHZgy+y5qFtuPxzXAt7eCvfTcjJjRDdXWRw7+NxyceEtQ1u4YSZ9yQLvwUyzhZukZXdclQ74k6GK2Wbohrt4lEADvnzm/PlCCYklv8b7TyKZdVRTILsFJ7eA3zZ8sXCbF8q2TG4BADJRkWxH+S/RdSeBkoiSlW43faFxUVHcC7yjBJshKbdBrQzncZG+7EFgUtw1hufXlwiSpWK0B01gYrsgYYPKYCbGidOJAMRjybyVYA8XfTPraeO7rw0b872jmGAv9TSVXvg+AwMGlnpOC+6n7Q+BL6qU/Q5Hnzi3YMg357qe2BgLJUGXwza/tEnJEeHbqXViZk= + - secure: wTmAdCS9uZJ6fMoX8zTD34cHpjtPyR+5PIFNEWboFPqak9z+5ZjiyAM6U3G8iQmu9qBq7pG8QA6t8MaU23XVYpGuGPByGNtm9bQBCnUcVlY+vXCB0xOrO06azA2hK3ZlQ2kzXFInI14KDc2SBC7R7B5cz5ysyTDLf6megQGU9ZtO6IqhI7OE8u67CgzuX/dzuBvXFER8ki/rfTR26m8CjyLKai5yMPApyl01EHIDBQmgf7fpw88+n1y3k8eWR6u+lGRVHcqGl+7/vdogZx6rsxG+UO6NX+9+IrLW6zSJWIJfLsEA98TNcWudeZ+IimPY9yV1+CU49v0Wv6Ow6TzpdHx4KQFr5SLIgCxbGVYC1N1JrHZ8Ln/YuqVwR3VmJ/Y+drigBYS9Gmbh3vhYyqrch183wVpCuJ58VajnmXnRDOo0o7hSFzO2JCEyL3oX8XG+03CRWTkjRu50p3wbllYQ1praTLengYPqWC7DDBHfcDyreLzKGxHEZBJbOuQio86Vx/55rTmILbnE3MV43gFQEU+7zArFifoGsEfyxU+Adhr6cnO4+IMWbdMXdAfNjmFX41kXX0UpNT2idcVH3WxEKrGuP1BPE0KGubL8QFsAxnY3JwDIEUDWvI0TDbVa9cgNLc3Z1Z3r8XwDArMyArjeXxmn/fJLJ7GUosDUUv0S8hI= + - secure: wDf+H4BS8n2mS876d3z+vv2s7wxSAr0UbO47qamCPVZQhAcgTXvfyjvClcwp7fYoC2zYJC4Qut/mdyDlPhnNWOAUPx+nVv/l5fPMaKEv+zAWO2PmWsMlKW0nSGQ8EMxinRxfmmmLPxlyh3pHVmcgjo1C+QMB1+rEyEhfIRoPm23Q7dC27VEXEwIeiFEvo3taTGSMs5h9siTwAOoPIfcHffCMSF9UaECsWiRj4CVz0uSon8veT9EIwNe9X1XprFf1zaBLG8FCz1BsksHH9JIqaimch6AN4lVd2Jyl7vs2+4WRzmFKwXqWIgnQDZPQVv6OujVwnBt6hQg5mc9Po/UbxnaGv79hGpnlhKa/TjnD7be2qpMhPHzXdS0aQIORjrD+PdIisxJFvya1scDGU/Pv3CET/ubtpiDsJTGHeIQmvbAILunWxji4HoukTWZGzTHGBENIVGi31O8vx8gROLPtS+3iKy4FCV6EW/mmP1k0e0kueFLHW/HmNOklUr+gWlimNZ1OhBFxrfXe0JlTD/cNijeJmJXlloSfDdoNmFDvzUst8v0qQ59nuQoR5llEggIBx8OpK7qXBMmhPWtgkiQ06H0BoKPewZxjHTVmdjyT4C2ZGPHJMAbeuZ0LebM4+beELrjFQ9f4V6J+D3P0dlTa8rmwgI3pFb0Ky6jwJEeOWy8= diff --git a/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj b/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj index 87572bc..ac457c9 100644 --- a/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj +++ b/src/NetTopologySuite.Features/NetTopologySuite.Features.csproj @@ -24,7 +24,7 @@ - +