From 4403c6c28f94fc58b56d1cc68964384d36a2902d Mon Sep 17 00:00:00 2001 From: Vernon R Schierding III Date: Tue, 28 Jan 2020 15:54:32 -0600 Subject: [PATCH] Performance Enhancements (#6) * Rebuilt the XCode project as a Package * Removed most protocols in favor of public struct objects * Increased performance all around * Added an option to pass in pre-validated GeoJson which is parsed without validation. This will have a a significant performance boost with the side effect of the application crashing if the GeoJson was not validated. The older parse methods still validate but should only need to be run once when pulling in new data and thereafter can be considered validated. * Large performance boost for Geohash coding and neighbors * Significant API changes * TimberSwift is no longer a dependency in favor of now passing back invalid geo json errors. --- .gitignore | 7 +- .swift-version | 2 +- Cartfile | 1 - Cartfile.resolved | 1 - .../GeospatialSwiftTests_Info.plist | 25 + .../GeospatialSwift_Info.plist | 25 + GeospatialSwift.xcodeproj/project.pbxproj | 4251 ++++++----------- .../contents.xcworkspacedata | 2 +- .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcschemes/GeospatialSwift iOS.xcscheme | 100 - .../xcschemes/GeospatialSwift macOS.xcscheme | 100 - .../xcschemes/GeospatialSwift tvOS.xcscheme | 100 - ...cheme => GeospatialSwift-Package.xcscheme} | 39 +- .../xcschemes/xcschememanagement.plist | 12 - Package.resolved | 16 - Package.swift | 8 +- README.md | 40 +- Scripts/install-tools.sh | 62 + Scripts/parrot.sh | 10 + Scripts/swiftlint.sh | 8 + .../API/Calculator/GeodesicCalculator.swift | 161 +- .../GeospatialSwift/API/GeoJson/GeoJson.swift | 36 +- .../API/GeoJson/GeodesicBearing.swift | 4 + .../API/GeoJson/GeodesicBoundingBox.swift | 124 +- .../API/GeoJson/GeodesicLine.swift | 26 +- .../API/GeoJson/GeodesicLineSegment.swift | 26 +- .../API/GeoJson/GeodesicPoint.swift | 14 +- .../API/GeoJson/GeodesicPolygon.swift | 24 +- .../API/GeoJson/Object/Feature.swift | 107 +- .../GeoJson/Object/FeatureCollection.swift | 84 +- .../GeoJson/Object/GeometryCollection.swift | 66 +- .../API/GeoJson/Object/LineString.swift | 123 +- .../API/GeoJson/Object/LinearRing.swift | 23 + .../API/GeoJson/Object/MultiLineString.swift | 94 +- .../API/GeoJson/Object/MultiPoint.swift | 91 +- .../API/GeoJson/Object/MultiPolygon.swift | 98 +- .../API/GeoJson/Object/Point.swift | 72 +- .../API/GeoJson/Object/Polygon.swift | 184 +- .../Protocol/GeoJsonClosedGeometry.swift | 4 +- .../Protocol/GeoJsonCoordinatesGeometry.swift | 12 +- .../Protocol/GeoJsonLinearGeometry.swift | 2 + .../Object/Protocol/GeoJsonObject.swift | 110 +- .../Object/Protocol/GeoJsonObjectType.swift | 16 +- .../API/Geohash/GeohashBox.swift | 32 +- .../API/Geohash/GeohashCoder.swift | 234 +- Sources/GeospatialSwift/API/Geospatial.swift | 28 +- .../GeospatialSwift/Extensions/Array.swift | 11 +- .../GeospatialSwift/Extensions/Bundle.swift | 8 +- .../Extensions/FloatingPoint.swift | 4 +- .../GeospatialSwift/Extensions/Result.swift | 24 + .../Parser/GeoJsonParser.swift | 204 +- .../Parser/InvalidGeoJson.swift | 15 + .../GeospatialSwift/Parser/WktParser.swift | 34 +- Sources/GeospatialSwift/Timber/Timber.swift | 6 - Sources/Info tvOS.plist | 2 +- Sources/Info.plist | 2 +- .../Data/GeoTestHelper.swift | 47 +- .../GeospatialSwiftTests/Data/MockData.swift | 52 +- .../Calculator/MockGeodesicCalculator.swift | 263 - .../GeoJson/Box/MockGeoJsonBoundingBox.swift | 125 - .../GeoJson/Box/MockGeoJsonGeohashBox.swift | 19 - .../Mock/API/GeoJson/MockGeoJson.swift | 91 - .../GeoJson/MockGeoJsonClosedGeometry.swift | 27 - .../MockGeoJsonCoordinatesGeometry.swift | 35 - .../API/GeoJson/MockGeoJsonGeometry.swift | 4 - .../GeoJson/MockGeoJsonLinearGeometry.swift | 11 - .../Mock/API/GeoJson/MockGeoJsonObject.swift | 56 - .../GeoJson/Object/MockGeoJsonFeature.swift | 41 - .../Object/MockGeoJsonFeatureCollection.swift | 11 - .../MockGeoJsonGeometryCollection.swift | 4 - .../Object/MockGeoJsonLineString.swift | 33 - .../Object/MockGeoJsonMultiLineString.swift | 15 - .../Object/MockGeoJsonMultiPoint.swift | 9 - .../Object/MockGeoJsonMultiPolygon.swift | 15 - .../API/GeoJson/Object/MockGeoJsonPoint.swift | 81 - .../GeoJson/Object/MockGeoJsonPolygon.swift | 36 - .../Mock/API/Geohash/MockGeohashCoder.swift | 51 - .../GeoJsonParsingPerformanceTests.swift | 2 +- .../Calculator/GeodesicCalculatorTests.swift | 56 +- .../Test/API/GeoJson/BoundingBoxTests.swift | 72 +- .../GeoJson/GeodesicLineSegmentTests.swift | 4 +- .../Object/FeatureCollectionTests.swift | 8 +- .../API/GeoJson/Object/FeatureTests.swift | 6 +- .../Object/GeometryCollectionTests.swift | 26 +- .../API/GeoJson/Object/LineStringTests.swift | 6 +- .../GeoJson/Object/MultiLineStringTests.swift | 22 +- .../API/GeoJson/Object/MultiPointTests.swift | 6 +- .../GeoJson/Object/MultiPolygonTests.swift | 14 +- .../Test/API/GeoJson/Object/PointTests.swift | 10 +- .../API/GeoJson/Object/PolygonTests.swift | 48 +- .../Test/API/Geohash/GeohashBoxTests.swift | 82 - .../Test/API/Geohash/GeohashCoderTests.swift | 204 +- .../Test/Extensions/Equatable.swift | 24 +- .../Test/Parser/GeoJsonParserTests.swift | 636 ++- .../Test/Parser/WktParserTests.swift | 6 +- 95 files changed, 3446 insertions(+), 5734 deletions(-) delete mode 100644 Cartfile delete mode 100644 Cartfile.resolved create mode 100644 GeospatialSwift.xcodeproj/GeospatialSwiftTests_Info.plist create mode 100644 GeospatialSwift.xcodeproj/GeospatialSwift_Info.plist create mode 100644 GeospatialSwift.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift iOS.xcscheme delete mode 100644 GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift macOS.xcscheme delete mode 100644 GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift tvOS.xcscheme rename GeospatialSwift.xcodeproj/xcshareddata/xcschemes/{GeospatialSwift watchOS.xcscheme => GeospatialSwift-Package.xcscheme} (63%) delete mode 100644 GeospatialSwift.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist delete mode 100644 Package.resolved create mode 100755 Scripts/install-tools.sh create mode 100755 Scripts/parrot.sh create mode 100755 Scripts/swiftlint.sh create mode 100644 Sources/GeospatialSwift/API/GeoJson/GeodesicBearing.swift create mode 100644 Sources/GeospatialSwift/API/GeoJson/Object/LinearRing.swift create mode 100644 Sources/GeospatialSwift/Extensions/Result.swift create mode 100644 Sources/GeospatialSwift/Parser/InvalidGeoJson.swift delete mode 100644 Sources/GeospatialSwift/Timber/Timber.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/Calculator/MockGeodesicCalculator.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonBoundingBox.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonGeohashBox.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJson.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonClosedGeometry.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonCoordinatesGeometry.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonGeometry.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonLinearGeometry.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonObject.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeature.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeatureCollection.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonGeometryCollection.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonLineString.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiLineString.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPoint.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPolygon.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPoint.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPolygon.swift delete mode 100644 Tests/GeospatialSwiftTests/Mock/API/Geohash/MockGeohashCoder.swift delete mode 100644 Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashBoxTests.swift diff --git a/.gitignore b/.gitignore index fbfbc33..01a6e16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,13 @@ # Mac OS X .DS_Store -# Xcode - ## Build generated build/ DerivedData +## Tools +Tools/ + ## Various settings *.pbxuser !default.pbxuser @@ -36,6 +37,6 @@ playground.xcworkspace .build/ # Carthage -Carthage +Carthage/Build .gitbackup diff --git a/.swift-version b/.swift-version index 7d5c902..61fcc87 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.1 +5.1.2 diff --git a/Cartfile b/Cartfile deleted file mode 100644 index 42e3e2d..0000000 --- a/Cartfile +++ /dev/null @@ -1 +0,0 @@ -github "MonsantoCo/TimberSwift" ~> 0.2.0 diff --git a/Cartfile.resolved b/Cartfile.resolved deleted file mode 100644 index 488dc18..0000000 --- a/Cartfile.resolved +++ /dev/null @@ -1 +0,0 @@ -github "MonsantoCo/TimberSwift" "0.2.0" diff --git a/GeospatialSwift.xcodeproj/GeospatialSwiftTests_Info.plist b/GeospatialSwift.xcodeproj/GeospatialSwiftTests_Info.plist new file mode 100644 index 0000000..7c23420 --- /dev/null +++ b/GeospatialSwift.xcodeproj/GeospatialSwiftTests_Info.plist @@ -0,0 +1,25 @@ + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/GeospatialSwift.xcodeproj/GeospatialSwift_Info.plist b/GeospatialSwift.xcodeproj/GeospatialSwift_Info.plist new file mode 100644 index 0000000..57ada9f --- /dev/null +++ b/GeospatialSwift.xcodeproj/GeospatialSwift_Info.plist @@ -0,0 +1,25 @@ + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/GeospatialSwift.xcodeproj/project.pbxproj b/GeospatialSwift.xcodeproj/project.pbxproj index f4e0af4..3506d1e 100644 --- a/GeospatialSwift.xcodeproj/project.pbxproj +++ b/GeospatialSwift.xcodeproj/project.pbxproj @@ -1,2898 +1,1359 @@ // !$*UTF8*$! { - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1E4BDD4A2121C59A008DC2BC /* GeodesicLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4BDD492121C59A008DC2BC /* GeodesicLine.swift */; }; - 1E4BDD4B2121C59A008DC2BC /* GeodesicLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4BDD492121C59A008DC2BC /* GeodesicLine.swift */; }; - 1E4BDD4C2121C59A008DC2BC /* GeodesicLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4BDD492121C59A008DC2BC /* GeodesicLine.swift */; }; - 1E4BDD4D2121C59A008DC2BC /* GeodesicLine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E4BDD492121C59A008DC2BC /* GeodesicLine.swift */; }; - 1E53D4D620AB5CC40006F1E1 /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4D520AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E53D4D720AB5CC70006F1E1 /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4C820AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E53D4D820AB5CCB0006F1E1 /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4CB20AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E53D4D920AB5CCF0006F1E1 /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4D020AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E53D4DC20AB5D370006F1E1 /* Timber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4DB20AB5D370006F1E1 /* Timber.swift */; }; - 1E53D4DD20AB5D370006F1E1 /* Timber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4DB20AB5D370006F1E1 /* Timber.swift */; }; - 1E53D4DE20AB5D370006F1E1 /* Timber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4DB20AB5D370006F1E1 /* Timber.swift */; }; - 1E53D4DF20AB5D370006F1E1 /* Timber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4DB20AB5D370006F1E1 /* Timber.swift */; }; - 1E53D4E120AB5DF30006F1E1 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4E020AB5DF30006F1E1 /* Bundle.swift */; }; - 1E53D4E220AB5DF30006F1E1 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4E020AB5DF30006F1E1 /* Bundle.swift */; }; - 1E53D4E320AB5DF30006F1E1 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4E020AB5DF30006F1E1 /* Bundle.swift */; }; - 1E53D4E420AB5DF30006F1E1 /* Bundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E53D4E020AB5DF30006F1E1 /* Bundle.swift */; }; - 1E53D4E820AB64390006F1E1 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E520AB64390006F1E1 /* Package.resolved */; }; - 1E53D4E920AB64390006F1E1 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E520AB64390006F1E1 /* Package.resolved */; }; - 1E53D4EA20AB64390006F1E1 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E520AB64390006F1E1 /* Package.resolved */; }; - 1E53D4EB20AB64390006F1E1 /* Package.resolved in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E520AB64390006F1E1 /* Package.resolved */; }; - 1E53D4EC20AB64390006F1E1 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E620AB64390006F1E1 /* .swiftlint.yml */; }; - 1E53D4ED20AB64390006F1E1 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E620AB64390006F1E1 /* .swiftlint.yml */; }; - 1E53D4EE20AB64390006F1E1 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E620AB64390006F1E1 /* .swiftlint.yml */; }; - 1E53D4EF20AB64390006F1E1 /* .swiftlint.yml in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E620AB64390006F1E1 /* .swiftlint.yml */; }; - 1E53D4F020AB64390006F1E1 /* .swift-version in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E720AB64390006F1E1 /* .swift-version */; }; - 1E53D4F120AB64390006F1E1 /* .swift-version in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E720AB64390006F1E1 /* .swift-version */; }; - 1E53D4F220AB64390006F1E1 /* .swift-version in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E720AB64390006F1E1 /* .swift-version */; }; - 1E53D4F320AB64390006F1E1 /* .swift-version in Resources */ = {isa = PBXBuildFile; fileRef = 1E53D4E720AB64390006F1E1 /* .swift-version */; }; - 1E54975520AB683000FE50EC /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4D520AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E54975720AB683500FE50EC /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4CB20AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E54976220AB6DEC00FE50EC /* TimberSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E53D4C820AB5CB00006F1E1 /* TimberSwift.framework */; }; - 1E6CC19E20A09AD20041DBA4 /* MockGeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E6CC19C20A09AA40041DBA4 /* MockGeoJsonClosedGeometry.swift */; }; - 1E6CC19F20A09AD20041DBA4 /* MockGeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E6CC19C20A09AA40041DBA4 /* MockGeoJsonClosedGeometry.swift */; }; - 1E6CC1A020A09AD20041DBA4 /* MockGeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E6CC19C20A09AA40041DBA4 /* MockGeoJsonClosedGeometry.swift */; }; - 1E7A6CD0209797ED0063F01F /* Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E7A6CCF209797ED0063F01F /* Equatable.swift */; }; - 1E7A6CD1209797ED0063F01F /* Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E7A6CCF209797ED0063F01F /* Equatable.swift */; }; - 1E7A6CD2209797ED0063F01F /* Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E7A6CCF209797ED0063F01F /* Equatable.swift */; }; - 1E7CB7212093A91400ECC023 /* GeoJsonTestJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7899209394DE0097A986 /* GeoJsonTestJson.swift */; }; - 1E7CB7222093A91400ECC023 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789A209394DE0097A986 /* MockData.swift */; }; - 1E7CB7232093A91400ECC023 /* WktTestJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789B209394DE0097A986 /* WktTestJson.swift */; }; - 1E7CB7242093A91400ECC023 /* GeoTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789C209394DE0097A986 /* GeoTestHelper.swift */; }; - 1E7CB7282093A91400ECC023 /* MockGeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7893209394DE0097A986 /* MockGeohashCoder.swift */; }; - 1E7CB7292093A91400ECC023 /* MockGeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7884209394DE0097A986 /* MockGeoJson.swift */; }; - 1E7CB72A2093A91400ECC023 /* MockGeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7887209394DE0097A986 /* MockGeoJsonCoordinatesGeometry.swift */; }; - 1E7CB72D2093A91400ECC023 /* MockGeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7886209394DE0097A986 /* MockGeoJsonObject.swift */; }; - 1E7CB72E2093A91400ECC023 /* MockGeoJsonGeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7881209394DE0097A986 /* MockGeoJsonGeohashBox.swift */; }; - 1E7CB72F2093A91400ECC023 /* MockGeoJsonBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7882209394DE0097A986 /* MockGeoJsonBoundingBox.swift */; }; - 1E7CB7302093A91400ECC023 /* MockGeoJsonGeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7889209394DE0097A986 /* MockGeoJsonGeometryCollection.swift */; }; - 1E7CB7312093A91400ECC023 /* MockGeoJsonFeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788A209394DE0097A986 /* MockGeoJsonFeatureCollection.swift */; }; - 1E7CB7322093A91400ECC023 /* MockGeoJsonPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788B209394DE0097A986 /* MockGeoJsonPoint.swift */; }; - 1E7CB7332093A91400ECC023 /* MockGeoJsonMultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788C209394DE0097A986 /* MockGeoJsonMultiLineString.swift */; }; - 1E7CB7342093A91400ECC023 /* MockGeoJsonFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788D209394DE0097A986 /* MockGeoJsonFeature.swift */; }; - 1E7CB7352093A91400ECC023 /* MockGeoJsonPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788E209394DE0097A986 /* MockGeoJsonPolygon.swift */; }; - 1E7CB7362093A91400ECC023 /* MockGeoJsonMultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788F209394DE0097A986 /* MockGeoJsonMultiPoint.swift */; }; - 1E7CB7372093A91400ECC023 /* MockGeoJsonLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7890209394DE0097A986 /* MockGeoJsonLineString.swift */; }; - 1E7CB7382093A91400ECC023 /* MockGeoJsonMultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7891209394DE0097A986 /* MockGeoJsonMultiPolygon.swift */; }; - 1E7CB7392093A91400ECC023 /* GeoJsonParsingPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7897209394DE0097A986 /* GeoJsonParsingPerformanceTests.swift */; }; - 1E7CB73A2093A91400ECC023 /* GeoJsonParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7866209394DE0097A986 /* GeoJsonParserTests.swift */; }; - 1E7CB73B2093A91400ECC023 /* WktParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7867209394DE0097A986 /* WktParserTests.swift */; }; - 1E7CB73C2093A91400ECC023 /* Assertions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7869209394DE0097A986 /* Assertions.swift */; }; - 1E7CB73D2093A91400ECC023 /* BoundingBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786C209394DE0097A986 /* BoundingBoxTests.swift */; }; - 1E7CB73E2093A91400ECC023 /* PolygonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786E209394DE0097A986 /* PolygonTests.swift */; }; - 1E7CB73F2093A91400ECC023 /* FeatureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786F209394DE0097A986 /* FeatureTests.swift */; }; - 1E7CB7402093A91400ECC023 /* FeatureCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7870209394DE0097A986 /* FeatureCollectionTests.swift */; }; - 1E7CB7412093A91400ECC023 /* GeometryCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7871209394DE0097A986 /* GeometryCollectionTests.swift */; }; - 1E7CB7422093A91500ECC023 /* LineStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7872209394DE0097A986 /* LineStringTests.swift */; }; - 1E7CB7432093A91500ECC023 /* MultiPolygonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7873209394DE0097A986 /* MultiPolygonTests.swift */; }; - 1E7CB7442093A91500ECC023 /* MultiPointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7874209394DE0097A986 /* MultiPointTests.swift */; }; - 1E7CB7452093A91500ECC023 /* MultiLineStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7875209394DE0097A986 /* MultiLineStringTests.swift */; }; - 1E7CB7462093A91500ECC023 /* PointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7876209394DE0097A986 /* PointTests.swift */; }; - 1E7CB7472093A91500ECC023 /* GeohashCoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7878209394DE0097A986 /* GeohashCoderTests.swift */; }; - 1E7CB7482093A91500ECC023 /* GeohashBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7879209394DE0097A986 /* GeohashBoxTests.swift */; }; - 1E7CB7492093A91600ECC023 /* GeoJsonTestJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7899209394DE0097A986 /* GeoJsonTestJson.swift */; }; - 1E7CB74A2093A91600ECC023 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789A209394DE0097A986 /* MockData.swift */; }; - 1E7CB74B2093A91600ECC023 /* WktTestJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789B209394DE0097A986 /* WktTestJson.swift */; }; - 1E7CB74C2093A91600ECC023 /* GeoTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789C209394DE0097A986 /* GeoTestHelper.swift */; }; - 1E7CB7502093A91600ECC023 /* MockGeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7893209394DE0097A986 /* MockGeohashCoder.swift */; }; - 1E7CB7512093A91600ECC023 /* MockGeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7884209394DE0097A986 /* MockGeoJson.swift */; }; - 1E7CB7522093A91600ECC023 /* MockGeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7887209394DE0097A986 /* MockGeoJsonCoordinatesGeometry.swift */; }; - 1E7CB7552093A91600ECC023 /* MockGeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7886209394DE0097A986 /* MockGeoJsonObject.swift */; }; - 1E7CB7562093A91600ECC023 /* MockGeoJsonGeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7881209394DE0097A986 /* MockGeoJsonGeohashBox.swift */; }; - 1E7CB7572093A91600ECC023 /* MockGeoJsonBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7882209394DE0097A986 /* MockGeoJsonBoundingBox.swift */; }; - 1E7CB7582093A91600ECC023 /* MockGeoJsonGeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7889209394DE0097A986 /* MockGeoJsonGeometryCollection.swift */; }; - 1E7CB7592093A91600ECC023 /* MockGeoJsonFeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788A209394DE0097A986 /* MockGeoJsonFeatureCollection.swift */; }; - 1E7CB75A2093A91600ECC023 /* MockGeoJsonPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788B209394DE0097A986 /* MockGeoJsonPoint.swift */; }; - 1E7CB75B2093A91600ECC023 /* MockGeoJsonMultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788C209394DE0097A986 /* MockGeoJsonMultiLineString.swift */; }; - 1E7CB75C2093A91600ECC023 /* MockGeoJsonFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788D209394DE0097A986 /* MockGeoJsonFeature.swift */; }; - 1E7CB75D2093A91600ECC023 /* MockGeoJsonPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788E209394DE0097A986 /* MockGeoJsonPolygon.swift */; }; - 1E7CB75E2093A91600ECC023 /* MockGeoJsonMultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788F209394DE0097A986 /* MockGeoJsonMultiPoint.swift */; }; - 1E7CB75F2093A91600ECC023 /* MockGeoJsonLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7890209394DE0097A986 /* MockGeoJsonLineString.swift */; }; - 1E7CB7602093A91600ECC023 /* MockGeoJsonMultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7891209394DE0097A986 /* MockGeoJsonMultiPolygon.swift */; }; - 1E7CB7612093A91600ECC023 /* GeoJsonParsingPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7897209394DE0097A986 /* GeoJsonParsingPerformanceTests.swift */; }; - 1E7CB7622093A91600ECC023 /* GeoJsonParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7866209394DE0097A986 /* GeoJsonParserTests.swift */; }; - 1E7CB7632093A91600ECC023 /* WktParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7867209394DE0097A986 /* WktParserTests.swift */; }; - 1E7CB7642093A91600ECC023 /* Assertions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7869209394DE0097A986 /* Assertions.swift */; }; - 1E7CB7652093A91600ECC023 /* BoundingBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786C209394DE0097A986 /* BoundingBoxTests.swift */; }; - 1E7CB7662093A91600ECC023 /* PolygonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786E209394DE0097A986 /* PolygonTests.swift */; }; - 1E7CB7672093A91600ECC023 /* FeatureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786F209394DE0097A986 /* FeatureTests.swift */; }; - 1E7CB7682093A91600ECC023 /* FeatureCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7870209394DE0097A986 /* FeatureCollectionTests.swift */; }; - 1E7CB7692093A91600ECC023 /* GeometryCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7871209394DE0097A986 /* GeometryCollectionTests.swift */; }; - 1E7CB76A2093A91600ECC023 /* LineStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7872209394DE0097A986 /* LineStringTests.swift */; }; - 1E7CB76B2093A91600ECC023 /* MultiPolygonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7873209394DE0097A986 /* MultiPolygonTests.swift */; }; - 1E7CB76C2093A91600ECC023 /* MultiPointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7874209394DE0097A986 /* MultiPointTests.swift */; }; - 1E7CB76D2093A91600ECC023 /* MultiLineStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7875209394DE0097A986 /* MultiLineStringTests.swift */; }; - 1E7CB76E2093A91600ECC023 /* PointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7876209394DE0097A986 /* PointTests.swift */; }; - 1E7CB76F2093A91600ECC023 /* GeohashCoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7878209394DE0097A986 /* GeohashCoderTests.swift */; }; - 1E7CB7702093A91600ECC023 /* GeohashBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7879209394DE0097A986 /* GeohashBoxTests.swift */; }; - 1E7CB7712093A91700ECC023 /* GeoJsonTestJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7899209394DE0097A986 /* GeoJsonTestJson.swift */; }; - 1E7CB7722093A91700ECC023 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789A209394DE0097A986 /* MockData.swift */; }; - 1E7CB7732093A91700ECC023 /* WktTestJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789B209394DE0097A986 /* WktTestJson.swift */; }; - 1E7CB7742093A91700ECC023 /* GeoTestHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B789C209394DE0097A986 /* GeoTestHelper.swift */; }; - 1E7CB7782093A91700ECC023 /* MockGeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7893209394DE0097A986 /* MockGeohashCoder.swift */; }; - 1E7CB7792093A91700ECC023 /* MockGeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7884209394DE0097A986 /* MockGeoJson.swift */; }; - 1E7CB77A2093A91700ECC023 /* MockGeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7887209394DE0097A986 /* MockGeoJsonCoordinatesGeometry.swift */; }; - 1E7CB77D2093A91700ECC023 /* MockGeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7886209394DE0097A986 /* MockGeoJsonObject.swift */; }; - 1E7CB77E2093A91700ECC023 /* MockGeoJsonGeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7881209394DE0097A986 /* MockGeoJsonGeohashBox.swift */; }; - 1E7CB77F2093A91700ECC023 /* MockGeoJsonBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7882209394DE0097A986 /* MockGeoJsonBoundingBox.swift */; }; - 1E7CB7802093A91700ECC023 /* MockGeoJsonGeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7889209394DE0097A986 /* MockGeoJsonGeometryCollection.swift */; }; - 1E7CB7812093A91700ECC023 /* MockGeoJsonFeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788A209394DE0097A986 /* MockGeoJsonFeatureCollection.swift */; }; - 1E7CB7822093A91700ECC023 /* MockGeoJsonPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788B209394DE0097A986 /* MockGeoJsonPoint.swift */; }; - 1E7CB7832093A91700ECC023 /* MockGeoJsonMultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788C209394DE0097A986 /* MockGeoJsonMultiLineString.swift */; }; - 1E7CB7842093A91700ECC023 /* MockGeoJsonFeature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788D209394DE0097A986 /* MockGeoJsonFeature.swift */; }; - 1E7CB7852093A91700ECC023 /* MockGeoJsonPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788E209394DE0097A986 /* MockGeoJsonPolygon.swift */; }; - 1E7CB7862093A91700ECC023 /* MockGeoJsonMultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B788F209394DE0097A986 /* MockGeoJsonMultiPoint.swift */; }; - 1E7CB7872093A91700ECC023 /* MockGeoJsonLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7890209394DE0097A986 /* MockGeoJsonLineString.swift */; }; - 1E7CB7882093A91700ECC023 /* MockGeoJsonMultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7891209394DE0097A986 /* MockGeoJsonMultiPolygon.swift */; }; - 1E7CB7892093A91700ECC023 /* GeoJsonParsingPerformanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7897209394DE0097A986 /* GeoJsonParsingPerformanceTests.swift */; }; - 1E7CB78A2093A91700ECC023 /* GeoJsonParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7866209394DE0097A986 /* GeoJsonParserTests.swift */; }; - 1E7CB78B2093A91700ECC023 /* WktParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7867209394DE0097A986 /* WktParserTests.swift */; }; - 1E7CB78C2093A91700ECC023 /* Assertions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7869209394DE0097A986 /* Assertions.swift */; }; - 1E7CB78D2093A91700ECC023 /* BoundingBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786C209394DE0097A986 /* BoundingBoxTests.swift */; }; - 1E7CB78E2093A91700ECC023 /* PolygonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786E209394DE0097A986 /* PolygonTests.swift */; }; - 1E7CB78F2093A91700ECC023 /* FeatureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B786F209394DE0097A986 /* FeatureTests.swift */; }; - 1E7CB7902093A91700ECC023 /* FeatureCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7870209394DE0097A986 /* FeatureCollectionTests.swift */; }; - 1E7CB7912093A91700ECC023 /* GeometryCollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7871209394DE0097A986 /* GeometryCollectionTests.swift */; }; - 1E7CB7922093A91700ECC023 /* LineStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7872209394DE0097A986 /* LineStringTests.swift */; }; - 1E7CB7932093A91700ECC023 /* MultiPolygonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7873209394DE0097A986 /* MultiPolygonTests.swift */; }; - 1E7CB7942093A91700ECC023 /* MultiPointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7874209394DE0097A986 /* MultiPointTests.swift */; }; - 1E7CB7952093A91700ECC023 /* MultiLineStringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7875209394DE0097A986 /* MultiLineStringTests.swift */; }; - 1E7CB7962093A91700ECC023 /* PointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7876209394DE0097A986 /* PointTests.swift */; }; - 1E7CB7972093A91700ECC023 /* GeohashCoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7878209394DE0097A986 /* GeohashCoderTests.swift */; }; - 1E7CB7982093A91700ECC023 /* GeohashBoxTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7879209394DE0097A986 /* GeohashBoxTests.swift */; }; - 1E8BF420211DE20D00A247BF /* GeodesicPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8BF41F211DE20D00A247BF /* GeodesicPolygon.swift */; }; - 1E8BF421211DE22000A247BF /* GeodesicPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8BF41F211DE20D00A247BF /* GeodesicPolygon.swift */; }; - 1E8BF422211DE22100A247BF /* GeodesicPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8BF41F211DE20D00A247BF /* GeodesicPolygon.swift */; }; - 1E8BF423211DE22200A247BF /* GeodesicPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8BF41F211DE20D00A247BF /* GeodesicPolygon.swift */; }; - 1E9091282093A3EE00DAEF11 /* Geospatial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7846209394D20097A986 /* Geospatial.swift */; }; - 1E9091292093A3EE00DAEF11 /* GeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7844209394D20097A986 /* GeohashBox.swift */; }; - 1E90912A2093A3EE00DAEF11 /* GeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7845209394D20097A986 /* GeohashCoder.swift */; }; - 1E90912B2093A3EE00DAEF11 /* GeodesicBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7834209394D20097A986 /* GeodesicBoundingBox.swift */; }; - 1E90912C2093A3EE00DAEF11 /* GeodesicPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7841209394D20097A986 /* GeodesicPoint.swift */; }; - 1E90912D2093A3EE00DAEF11 /* GeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7840209394D20097A986 /* GeoJson.swift */; }; - 1E90912E2093A3EE00DAEF11 /* GeoJsonDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7835209394D20097A986 /* GeoJsonDictionary.swift */; }; - 1E90912F2093A3EE00DAEF11 /* Feature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7837209394D20097A986 /* Feature.swift */; }; - 1E9091302093A3EE00DAEF11 /* FeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7838209394D20097A986 /* FeatureCollection.swift */; }; - 1E9091312093A3EE00DAEF11 /* Point.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7839209394D20097A986 /* Point.swift */; }; - 1E9091322093A3EE00DAEF11 /* MultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783A209394D20097A986 /* MultiPoint.swift */; }; - 1E9091332093A3EE00DAEF11 /* GeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783B209394D20097A986 /* GeometryCollection.swift */; }; - 1E9091342093A3EE00DAEF11 /* LineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783C209394D20097A986 /* LineString.swift */; }; - 1E9091352093A3EE00DAEF11 /* Polygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783D209394D20097A986 /* Polygon.swift */; }; - 1E9091362093A3EE00DAEF11 /* MultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783E209394D20097A986 /* MultiLineString.swift */; }; - 1E9091372093A3EE00DAEF11 /* MultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783F209394D20097A986 /* MultiPolygon.swift */; }; - 1E9091382093A3EE00DAEF11 /* GeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7827209394D20097A986 /* GeodesicCalculator.swift */; }; - 1E90913A2093A3EE00DAEF11 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782C209394D20097A986 /* Array.swift */; }; - 1E90913C2093A3EE00DAEF11 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782E209394D20097A986 /* FloatingPoint.swift */; }; - 1E90913D2093A3EE00DAEF11 /* WktParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7829209394D20097A986 /* WktParser.swift */; }; - 1E90913E2093A3EE00DAEF11 /* GeoJsonParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782A209394D20097A986 /* GeoJsonParser.swift */; }; - 1E9091402093A3EF00DAEF11 /* Geospatial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7846209394D20097A986 /* Geospatial.swift */; }; - 1E9091412093A3EF00DAEF11 /* GeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7844209394D20097A986 /* GeohashBox.swift */; }; - 1E9091422093A3EF00DAEF11 /* GeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7845209394D20097A986 /* GeohashCoder.swift */; }; - 1E9091432093A3EF00DAEF11 /* GeodesicBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7834209394D20097A986 /* GeodesicBoundingBox.swift */; }; - 1E9091442093A3EF00DAEF11 /* GeodesicPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7841209394D20097A986 /* GeodesicPoint.swift */; }; - 1E9091452093A3EF00DAEF11 /* GeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7840209394D20097A986 /* GeoJson.swift */; }; - 1E9091462093A3EF00DAEF11 /* GeoJsonDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7835209394D20097A986 /* GeoJsonDictionary.swift */; }; - 1E9091472093A3EF00DAEF11 /* Feature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7837209394D20097A986 /* Feature.swift */; }; - 1E9091482093A3EF00DAEF11 /* FeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7838209394D20097A986 /* FeatureCollection.swift */; }; - 1E9091492093A3EF00DAEF11 /* Point.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7839209394D20097A986 /* Point.swift */; }; - 1E90914A2093A3EF00DAEF11 /* MultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783A209394D20097A986 /* MultiPoint.swift */; }; - 1E90914B2093A3EF00DAEF11 /* GeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783B209394D20097A986 /* GeometryCollection.swift */; }; - 1E90914C2093A3EF00DAEF11 /* LineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783C209394D20097A986 /* LineString.swift */; }; - 1E90914D2093A3EF00DAEF11 /* Polygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783D209394D20097A986 /* Polygon.swift */; }; - 1E90914E2093A3EF00DAEF11 /* MultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783E209394D20097A986 /* MultiLineString.swift */; }; - 1E90914F2093A3EF00DAEF11 /* MultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783F209394D20097A986 /* MultiPolygon.swift */; }; - 1E9091502093A3EF00DAEF11 /* GeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7827209394D20097A986 /* GeodesicCalculator.swift */; }; - 1E9091522093A3EF00DAEF11 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782C209394D20097A986 /* Array.swift */; }; - 1E9091542093A3EF00DAEF11 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782E209394D20097A986 /* FloatingPoint.swift */; }; - 1E9091552093A3EF00DAEF11 /* WktParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7829209394D20097A986 /* WktParser.swift */; }; - 1E9091562093A3EF00DAEF11 /* GeoJsonParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782A209394D20097A986 /* GeoJsonParser.swift */; }; - 1E9091582093A3EF00DAEF11 /* Geospatial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7846209394D20097A986 /* Geospatial.swift */; }; - 1E9091592093A3EF00DAEF11 /* GeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7844209394D20097A986 /* GeohashBox.swift */; }; - 1E90915A2093A3EF00DAEF11 /* GeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7845209394D20097A986 /* GeohashCoder.swift */; }; - 1E90915B2093A3EF00DAEF11 /* GeodesicBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7834209394D20097A986 /* GeodesicBoundingBox.swift */; }; - 1E90915C2093A3EF00DAEF11 /* GeodesicPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7841209394D20097A986 /* GeodesicPoint.swift */; }; - 1E90915D2093A3EF00DAEF11 /* GeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7840209394D20097A986 /* GeoJson.swift */; }; - 1E90915E2093A3EF00DAEF11 /* GeoJsonDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7835209394D20097A986 /* GeoJsonDictionary.swift */; }; - 1E90915F2093A3EF00DAEF11 /* Feature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7837209394D20097A986 /* Feature.swift */; }; - 1E9091602093A3EF00DAEF11 /* FeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7838209394D20097A986 /* FeatureCollection.swift */; }; - 1E9091612093A3EF00DAEF11 /* Point.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7839209394D20097A986 /* Point.swift */; }; - 1E9091622093A3EF00DAEF11 /* MultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783A209394D20097A986 /* MultiPoint.swift */; }; - 1E9091632093A3EF00DAEF11 /* GeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783B209394D20097A986 /* GeometryCollection.swift */; }; - 1E9091642093A3EF00DAEF11 /* LineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783C209394D20097A986 /* LineString.swift */; }; - 1E9091652093A3EF00DAEF11 /* Polygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783D209394D20097A986 /* Polygon.swift */; }; - 1E9091662093A3EF00DAEF11 /* MultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783E209394D20097A986 /* MultiLineString.swift */; }; - 1E9091672093A3EF00DAEF11 /* MultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783F209394D20097A986 /* MultiPolygon.swift */; }; - 1E9091682093A3EF00DAEF11 /* GeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7827209394D20097A986 /* GeodesicCalculator.swift */; }; - 1E90916A2093A3EF00DAEF11 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782C209394D20097A986 /* Array.swift */; }; - 1E90916C2093A3EF00DAEF11 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782E209394D20097A986 /* FloatingPoint.swift */; }; - 1E90916D2093A3EF00DAEF11 /* WktParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7829209394D20097A986 /* WktParser.swift */; }; - 1E90916E2093A3EF00DAEF11 /* GeoJsonParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782A209394D20097A986 /* GeoJsonParser.swift */; }; - 1E9091702093A3F000DAEF11 /* Geospatial.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7846209394D20097A986 /* Geospatial.swift */; }; - 1E9091712093A3F000DAEF11 /* GeohashBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7844209394D20097A986 /* GeohashBox.swift */; }; - 1E9091722093A3F000DAEF11 /* GeohashCoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7845209394D20097A986 /* GeohashCoder.swift */; }; - 1E9091732093A3F000DAEF11 /* GeodesicBoundingBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7834209394D20097A986 /* GeodesicBoundingBox.swift */; }; - 1E9091742093A3F000DAEF11 /* GeodesicPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7841209394D20097A986 /* GeodesicPoint.swift */; }; - 1E9091752093A3F000DAEF11 /* GeoJson.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7840209394D20097A986 /* GeoJson.swift */; }; - 1E9091762093A3F000DAEF11 /* GeoJsonDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7835209394D20097A986 /* GeoJsonDictionary.swift */; }; - 1E9091772093A3F000DAEF11 /* Feature.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7837209394D20097A986 /* Feature.swift */; }; - 1E9091782093A3F000DAEF11 /* FeatureCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7838209394D20097A986 /* FeatureCollection.swift */; }; - 1E9091792093A3F000DAEF11 /* Point.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7839209394D20097A986 /* Point.swift */; }; - 1E90917A2093A3F000DAEF11 /* MultiPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783A209394D20097A986 /* MultiPoint.swift */; }; - 1E90917B2093A3F000DAEF11 /* GeometryCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783B209394D20097A986 /* GeometryCollection.swift */; }; - 1E90917C2093A3F000DAEF11 /* LineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783C209394D20097A986 /* LineString.swift */; }; - 1E90917D2093A3F000DAEF11 /* Polygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783D209394D20097A986 /* Polygon.swift */; }; - 1E90917E2093A3F000DAEF11 /* MultiLineString.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783E209394D20097A986 /* MultiLineString.swift */; }; - 1E90917F2093A3F000DAEF11 /* MultiPolygon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B783F209394D20097A986 /* MultiPolygon.swift */; }; - 1E9091802093A3F000DAEF11 /* GeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7827209394D20097A986 /* GeodesicCalculator.swift */; }; - 1E9091822093A3F000DAEF11 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782C209394D20097A986 /* Array.swift */; }; - 1E9091842093A3F000DAEF11 /* FloatingPoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782E209394D20097A986 /* FloatingPoint.swift */; }; - 1E9091852093A3F000DAEF11 /* WktParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B7829209394D20097A986 /* WktParser.swift */; }; - 1E9091862093A3F000DAEF11 /* GeoJsonParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E8B782A209394D20097A986 /* GeoJsonParser.swift */; }; - 1E92ABA720EC113D00EF4A4E /* GeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA620EC113D00EF4A4E /* GeoJsonObject.swift */; }; - 1E92ABAA20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA920ED938D00EF4A4E /* GeoJsonGeometry.swift */; }; - 1E92ABAB20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA920ED938D00EF4A4E /* GeoJsonGeometry.swift */; }; - 1E92ABAC20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA920ED938D00EF4A4E /* GeoJsonGeometry.swift */; }; - 1E92ABAD20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA920ED938D00EF4A4E /* GeoJsonGeometry.swift */; }; - 1E92ABAE20ED939200EF4A4E /* GeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA620EC113D00EF4A4E /* GeoJsonObject.swift */; }; - 1E92ABAF20ED939300EF4A4E /* GeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA620EC113D00EF4A4E /* GeoJsonObject.swift */; }; - 1E92ABB020ED939400EF4A4E /* GeoJsonObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABA620EC113D00EF4A4E /* GeoJsonObject.swift */; }; - 1E92ABB220ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABB120ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift */; }; - 1E92ABB320ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABB120ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift */; }; - 1E92ABB420ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABB120ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift */; }; - 1E92ABB520ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABB120ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift */; }; - 1E92ABC120ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC020ED948E00EF4A4E /* GeoJsonClosedGeometry.swift */; }; - 1E92ABC220ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC020ED948E00EF4A4E /* GeoJsonClosedGeometry.swift */; }; - 1E92ABC320ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC020ED948E00EF4A4E /* GeoJsonClosedGeometry.swift */; }; - 1E92ABC420ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC020ED948E00EF4A4E /* GeoJsonClosedGeometry.swift */; }; - 1E92ABC620ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC520ED94B200EF4A4E /* GeoJsonObjectType.swift */; }; - 1E92ABC720ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC520ED94B200EF4A4E /* GeoJsonObjectType.swift */; }; - 1E92ABC820ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC520ED94B200EF4A4E /* GeoJsonObjectType.swift */; }; - 1E92ABC920ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABC520ED94B200EF4A4E /* GeoJsonObjectType.swift */; }; - 1E92ABCB20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCA20ED955800EF4A4E /* GeoJsonLinearGeometry.swift */; }; - 1E92ABCC20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCA20ED955800EF4A4E /* GeoJsonLinearGeometry.swift */; }; - 1E92ABCD20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCA20ED955800EF4A4E /* GeoJsonLinearGeometry.swift */; }; - 1E92ABCE20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCA20ED955800EF4A4E /* GeoJsonLinearGeometry.swift */; }; - 1E92ABD020EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCF20EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift */; }; - 1E92ABD120EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCF20EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift */; }; - 1E92ABD220EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABCF20EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift */; }; - 1E92ABD420EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABD320EDC7AA00EF4A4E /* GeodesicLineSegment.swift */; }; - 1E92ABD520EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABD320EDC7AA00EF4A4E /* GeodesicLineSegment.swift */; }; - 1E92ABD620EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABD320EDC7AA00EF4A4E /* GeodesicLineSegment.swift */; }; - 1E92ABD720EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E92ABD320EDC7AA00EF4A4E /* GeodesicLineSegment.swift */; }; - 1E9A9BA420EE8B51003F381B /* GeodesicLineSegmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A9BA320EE8B51003F381B /* GeodesicLineSegmentTests.swift */; }; - 1E9A9BA520EE8B51003F381B /* GeodesicLineSegmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A9BA320EE8B51003F381B /* GeodesicLineSegmentTests.swift */; }; - 1E9A9BA620EE8B51003F381B /* GeodesicLineSegmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A9BA320EE8B51003F381B /* GeodesicLineSegmentTests.swift */; }; - 1E9A9BD520EEF5E5003F381B /* MockGeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A9BD420EEF5E4003F381B /* MockGeodesicCalculator.swift */; }; - 1E9A9BD620EEF5E5003F381B /* MockGeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A9BD420EEF5E4003F381B /* MockGeodesicCalculator.swift */; }; - 1E9A9BD720EEF5E5003F381B /* MockGeodesicCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E9A9BD420EEF5E4003F381B /* MockGeodesicCalculator.swift */; }; - 1EE89F1321147C890039554D /* GeodesicCalculatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EE89F1221147C890039554D /* GeodesicCalculatorTests.swift */; }; - 1EE89F1421147C890039554D /* GeodesicCalculatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EE89F1221147C890039554D /* GeodesicCalculatorTests.swift */; }; - 1EE89F1521147C890039554D /* GeodesicCalculatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EE89F1221147C890039554D /* GeodesicCalculatorTests.swift */; }; - 1EFFA4D820FD10770017D8C1 /* MockGeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFFA4D720FD10760017D8C1 /* MockGeoJsonGeometry.swift */; }; - 1EFFA4D920FD10770017D8C1 /* MockGeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFFA4D720FD10760017D8C1 /* MockGeoJsonGeometry.swift */; }; - 1EFFA4DA20FD10770017D8C1 /* MockGeoJsonGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFFA4D720FD10760017D8C1 /* MockGeoJsonGeometry.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 1E9090BA20939EA400DAEF11 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E9090AF20939EA300DAEF11; - remoteInfo = GeospatialSwift; - }; - 1E9090EC20939F2800DAEF11 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E9090E120939F2700DAEF11; - remoteInfo = "GeospatialSwift iOS"; - }; - 1E90910820939F5C00DAEF11 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = OBJ_1 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E9090FD20939F5C00DAEF11; - remoteInfo = "GeospatialSwift tvOS"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1E4BDD492121C59A008DC2BC /* GeodesicLine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeodesicLine.swift; sourceTree = ""; }; - 1E53D4A420AB5BD80006F1E1 /* Cartfile.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile.resolved; sourceTree = ""; }; - 1E53D4A520AB5BD90006F1E1 /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; - 1E53D4C820AB5CB00006F1E1 /* TimberSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TimberSwift.framework; sourceTree = ""; }; - 1E53D4CB20AB5CB00006F1E1 /* TimberSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TimberSwift.framework; sourceTree = ""; }; - 1E53D4D020AB5CB00006F1E1 /* TimberSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TimberSwift.framework; sourceTree = ""; }; - 1E53D4D520AB5CB00006F1E1 /* TimberSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TimberSwift.framework; sourceTree = ""; }; - 1E53D4DB20AB5D370006F1E1 /* Timber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timber.swift; sourceTree = ""; }; - 1E53D4E020AB5DF30006F1E1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; - 1E53D4E520AB64390006F1E1 /* Package.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Package.resolved; sourceTree = SOURCE_ROOT; }; - 1E53D4E620AB64390006F1E1 /* .swiftlint.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = .swiftlint.yml; sourceTree = SOURCE_ROOT; }; - 1E53D4E720AB64390006F1E1 /* .swift-version */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ".swift-version"; sourceTree = SOURCE_ROOT; }; - 1E6CC19C20A09AA40041DBA4 /* MockGeoJsonClosedGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockGeoJsonClosedGeometry.swift; sourceTree = ""; }; - 1E7A053F2093999100A003CD /* MAINTAINERS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MAINTAINERS; sourceTree = ""; }; - 1E7A05402093999100A003CD /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 1E7A05412093999200A003CD /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 1E7A05422093999200A003CD /* CONTRIBUTING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = ""; }; - 1E7A6CCF209797ED0063F01F /* Equatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Equatable.swift; sourceTree = ""; }; - 1E8B7827209394D20097A986 /* GeodesicCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeodesicCalculator.swift; sourceTree = ""; }; - 1E8B7829209394D20097A986 /* WktParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WktParser.swift; sourceTree = ""; }; - 1E8B782A209394D20097A986 /* GeoJsonParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJsonParser.swift; sourceTree = ""; }; - 1E8B782C209394D20097A986 /* Array.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = ""; }; - 1E8B782E209394D20097A986 /* FloatingPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingPoint.swift; sourceTree = ""; }; - 1E8B782F209394D20097A986 /* GeospatialSwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GeospatialSwift.h; sourceTree = ""; }; - 1E8B7834209394D20097A986 /* GeodesicBoundingBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeodesicBoundingBox.swift; sourceTree = ""; }; - 1E8B7835209394D20097A986 /* GeoJsonDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJsonDictionary.swift; sourceTree = ""; }; - 1E8B7837209394D20097A986 /* Feature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Feature.swift; sourceTree = ""; }; - 1E8B7838209394D20097A986 /* FeatureCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeatureCollection.swift; sourceTree = ""; }; - 1E8B7839209394D20097A986 /* Point.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Point.swift; sourceTree = ""; }; - 1E8B783A209394D20097A986 /* MultiPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiPoint.swift; sourceTree = ""; }; - 1E8B783B209394D20097A986 /* GeometryCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeometryCollection.swift; sourceTree = ""; }; - 1E8B783C209394D20097A986 /* LineString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineString.swift; sourceTree = ""; }; - 1E8B783D209394D20097A986 /* Polygon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Polygon.swift; sourceTree = ""; }; - 1E8B783E209394D20097A986 /* MultiLineString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiLineString.swift; sourceTree = ""; }; - 1E8B783F209394D20097A986 /* MultiPolygon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiPolygon.swift; sourceTree = ""; }; - 1E8B7840209394D20097A986 /* GeoJson.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJson.swift; sourceTree = ""; }; - 1E8B7841209394D20097A986 /* GeodesicPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeodesicPoint.swift; sourceTree = ""; }; - 1E8B7844209394D20097A986 /* GeohashBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeohashBox.swift; sourceTree = ""; }; - 1E8B7845209394D20097A986 /* GeohashCoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeohashCoder.swift; sourceTree = ""; }; - 1E8B7846209394D20097A986 /* Geospatial.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Geospatial.swift; sourceTree = ""; }; - 1E8B7847209394D20097A986 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1E8B7866209394DE0097A986 /* GeoJsonParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJsonParserTests.swift; sourceTree = ""; }; - 1E8B7867209394DE0097A986 /* WktParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WktParserTests.swift; sourceTree = ""; }; - 1E8B7869209394DE0097A986 /* Assertions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Assertions.swift; sourceTree = ""; }; - 1E8B786C209394DE0097A986 /* BoundingBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoundingBoxTests.swift; sourceTree = ""; }; - 1E8B786E209394DE0097A986 /* PolygonTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PolygonTests.swift; sourceTree = ""; }; - 1E8B786F209394DE0097A986 /* FeatureTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeatureTests.swift; sourceTree = ""; }; - 1E8B7870209394DE0097A986 /* FeatureCollectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeatureCollectionTests.swift; sourceTree = ""; }; - 1E8B7871209394DE0097A986 /* GeometryCollectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeometryCollectionTests.swift; sourceTree = ""; }; - 1E8B7872209394DE0097A986 /* LineStringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LineStringTests.swift; sourceTree = ""; }; - 1E8B7873209394DE0097A986 /* MultiPolygonTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiPolygonTests.swift; sourceTree = ""; }; - 1E8B7874209394DE0097A986 /* MultiPointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiPointTests.swift; sourceTree = ""; }; - 1E8B7875209394DE0097A986 /* MultiLineStringTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiLineStringTests.swift; sourceTree = ""; }; - 1E8B7876209394DE0097A986 /* PointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PointTests.swift; sourceTree = ""; }; - 1E8B7878209394DE0097A986 /* GeohashCoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeohashCoderTests.swift; sourceTree = ""; }; - 1E8B7879209394DE0097A986 /* GeohashBoxTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeohashBoxTests.swift; sourceTree = ""; }; - 1E8B7881209394DE0097A986 /* MockGeoJsonGeohashBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonGeohashBox.swift; sourceTree = ""; }; - 1E8B7882209394DE0097A986 /* MockGeoJsonBoundingBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonBoundingBox.swift; sourceTree = ""; }; - 1E8B7884209394DE0097A986 /* MockGeoJson.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJson.swift; sourceTree = ""; }; - 1E8B7886209394DE0097A986 /* MockGeoJsonObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonObject.swift; sourceTree = ""; }; - 1E8B7887209394DE0097A986 /* MockGeoJsonCoordinatesGeometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonCoordinatesGeometry.swift; sourceTree = ""; }; - 1E8B7889209394DE0097A986 /* MockGeoJsonGeometryCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonGeometryCollection.swift; sourceTree = ""; }; - 1E8B788A209394DE0097A986 /* MockGeoJsonFeatureCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonFeatureCollection.swift; sourceTree = ""; }; - 1E8B788B209394DE0097A986 /* MockGeoJsonPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonPoint.swift; sourceTree = ""; }; - 1E8B788C209394DE0097A986 /* MockGeoJsonMultiLineString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonMultiLineString.swift; sourceTree = ""; }; - 1E8B788D209394DE0097A986 /* MockGeoJsonFeature.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonFeature.swift; sourceTree = ""; }; - 1E8B788E209394DE0097A986 /* MockGeoJsonPolygon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonPolygon.swift; sourceTree = ""; }; - 1E8B788F209394DE0097A986 /* MockGeoJsonMultiPoint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonMultiPoint.swift; sourceTree = ""; }; - 1E8B7890209394DE0097A986 /* MockGeoJsonLineString.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonLineString.swift; sourceTree = ""; }; - 1E8B7891209394DE0097A986 /* MockGeoJsonMultiPolygon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonMultiPolygon.swift; sourceTree = ""; }; - 1E8B7893209394DE0097A986 /* MockGeohashCoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeohashCoder.swift; sourceTree = ""; }; - 1E8B7897209394DE0097A986 /* GeoJsonParsingPerformanceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJsonParsingPerformanceTests.swift; sourceTree = ""; }; - 1E8B7899209394DE0097A986 /* GeoJsonTestJson.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoJsonTestJson.swift; sourceTree = ""; }; - 1E8B789A209394DE0097A986 /* MockData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockData.swift; sourceTree = ""; }; - 1E8B789B209394DE0097A986 /* WktTestJson.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WktTestJson.swift; sourceTree = ""; }; - 1E8B789C209394DE0097A986 /* GeoTestHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeoTestHelper.swift; sourceTree = ""; }; - 1E8B789E209394DE0097A986 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1E8BF41F211DE20D00A247BF /* GeodesicPolygon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeodesicPolygon.swift; sourceTree = ""; }; - 1E9090B020939EA300DAEF11 /* GeospatialSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GeospatialSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E9090B820939EA400DAEF11 /* GeospatialSwift macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "GeospatialSwift macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E9090E220939F2700DAEF11 /* GeospatialSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GeospatialSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E9090EA20939F2700DAEF11 /* GeospatialSwift iOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "GeospatialSwift iOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E9090FE20939F5C00DAEF11 /* GeospatialSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GeospatialSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E90910620939F5C00DAEF11 /* GeospatialSwift tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "GeospatialSwift tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E90911A20939F6900DAEF11 /* GeospatialSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GeospatialSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E9091262093A1E500DAEF11 /* Info tvOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info tvOS.plist"; sourceTree = ""; }; - 1E92ABA620EC113D00EF4A4E /* GeoJsonObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonObject.swift; sourceTree = ""; }; - 1E92ABA920ED938D00EF4A4E /* GeoJsonGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonGeometry.swift; sourceTree = ""; }; - 1E92ABB120ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonCoordinatesGeometry.swift; sourceTree = ""; }; - 1E92ABC020ED948E00EF4A4E /* GeoJsonClosedGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonClosedGeometry.swift; sourceTree = ""; }; - 1E92ABC520ED94B200EF4A4E /* GeoJsonObjectType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonObjectType.swift; sourceTree = ""; }; - 1E92ABCA20ED955800EF4A4E /* GeoJsonLinearGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoJsonLinearGeometry.swift; sourceTree = ""; }; - 1E92ABCF20EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockGeoJsonLinearGeometry.swift; sourceTree = ""; }; - 1E92ABD320EDC7AA00EF4A4E /* GeodesicLineSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeodesicLineSegment.swift; sourceTree = ""; }; - 1E9A9BA320EE8B51003F381B /* GeodesicLineSegmentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeodesicLineSegmentTests.swift; sourceTree = ""; }; - 1E9A9BD420EEF5E4003F381B /* MockGeodesicCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeodesicCalculator.swift; sourceTree = ""; }; - 1EE89F1221147C890039554D /* GeodesicCalculatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeodesicCalculatorTests.swift; sourceTree = ""; }; - 1EFFA4D720FD10760017D8C1 /* MockGeoJsonGeometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockGeoJsonGeometry.swift; sourceTree = ""; }; - OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1E9090AC20939EA300DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4D720AB5CC70006F1E1 /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090B520939EA400DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E54976220AB6DEC00FE50EC /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090DE20939F2700DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4D620AB5CC40006F1E1 /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090E720939F2700DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E54975520AB683000FE50EC /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090FA20939F5C00DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4D820AB5CCB0006F1E1 /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90910320939F5C00DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E54975720AB683500FE50EC /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90911620939F6900DAEF11 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4D920AB5CCF0006F1E1 /* TimberSwift.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 1E53D4C620AB5CB00006F1E1 /* Mac */ = { - isa = PBXGroup; - children = ( - 1E53D4C820AB5CB00006F1E1 /* TimberSwift.framework */, - ); - name = Mac; - path = Carthage/Build/Mac; - sourceTree = ""; - }; - 1E53D4C920AB5CB00006F1E1 /* tvOS */ = { - isa = PBXGroup; - children = ( - 1E53D4CB20AB5CB00006F1E1 /* TimberSwift.framework */, - ); - name = tvOS; - path = Carthage/Build/tvOS; - sourceTree = ""; - }; - 1E53D4CD20AB5CB00006F1E1 /* watchOS */ = { - isa = PBXGroup; - children = ( - 1E53D4D020AB5CB00006F1E1 /* TimberSwift.framework */, - ); - name = watchOS; - path = Carthage/Build/watchOS; - sourceTree = ""; - }; - 1E53D4D120AB5CB00006F1E1 /* iOS */ = { - isa = PBXGroup; - children = ( - 1E53D4D520AB5CB00006F1E1 /* TimberSwift.framework */, - ); - name = iOS; - path = Carthage/Build/iOS; - sourceTree = ""; - }; - 1E53D4DA20AB5CFE0006F1E1 /* Timber */ = { - isa = PBXGroup; - children = ( - 1E53D4DB20AB5D370006F1E1 /* Timber.swift */, - ); - path = Timber; - sourceTree = ""; - }; - 1E57A3042093B523009F9B8D /* GeospatialSwift */ = { - isa = PBXGroup; - children = ( - 1E8B7832209394D20097A986 /* API */, - 1E8B7828209394D20097A986 /* Parser */, - 1E53D4DA20AB5CFE0006F1E1 /* Timber */, - 1E8B782B209394D20097A986 /* Extensions */, - ); - path = GeospatialSwift; - sourceTree = ""; - }; - 1E57A3052093B537009F9B8D /* GeospatialSwiftTests */ = { - isa = PBXGroup; - children = ( - 1E8B7898209394DE0097A986 /* Data */, - 1E8B787A209394DE0097A986 /* Mock */, - 1E8B7896209394DE0097A986 /* Performance */, - 1E8B7864209394DE0097A986 /* Test */, - ); - path = GeospatialSwiftTests; - sourceTree = ""; - }; - 1E6C083D20AB56B8001788C3 /* XCode Dependencies */ = { - isa = PBXGroup; - children = ( - 1E53D4A520AB5BD90006F1E1 /* Cartfile */, - 1E53D4A420AB5BD80006F1E1 /* Cartfile.resolved */, - 1E53D4E620AB64390006F1E1 /* .swiftlint.yml */, - 1E53D4D120AB5CB00006F1E1 /* iOS */, - 1E53D4C620AB5CB00006F1E1 /* Mac */, - 1E53D4C920AB5CB00006F1E1 /* tvOS */, - 1E53D4CD20AB5CB00006F1E1 /* watchOS */, - ); - name = "XCode Dependencies"; - sourceTree = ""; - }; - 1E7A053E2093992700A003CD /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 1E8B789E209394DE0097A986 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 1E7A05482093999C00A003CD /* Dependencies */ = { - isa = PBXGroup; - children = ( - OBJ_6 /* Package.swift */, - 1E53D4E520AB64390006F1E1 /* Package.resolved */, - 1E53D4E720AB64390006F1E1 /* .swift-version */, - ); - name = Dependencies; - sourceTree = ""; - }; - 1E7A0549209399E800A003CD /* Documentation */ = { - isa = PBXGroup; - children = ( - 1E7A05422093999200A003CD /* CONTRIBUTING.md */, - 1E7A05402093999100A003CD /* LICENSE */, - 1E7A053F2093999100A003CD /* MAINTAINERS */, - 1E7A05412093999200A003CD /* README.md */, - ); - name = Documentation; - sourceTree = ""; - }; - 1E8B7825209394D20097A986 /* Sources */ = { - isa = PBXGroup; - children = ( - 1E57A3042093B523009F9B8D /* GeospatialSwift */, - 1E8B78E7209398FD0097A986 /* Supporting Files */, - ); - path = Sources; - sourceTree = ""; - }; - 1E8B7826209394D20097A986 /* Calculator */ = { - isa = PBXGroup; - children = ( - 1E8B7827209394D20097A986 /* GeodesicCalculator.swift */, - ); - path = Calculator; - sourceTree = ""; - }; - 1E8B7828209394D20097A986 /* Parser */ = { - isa = PBXGroup; - children = ( - 1E8B7829209394D20097A986 /* WktParser.swift */, - 1E8B782A209394D20097A986 /* GeoJsonParser.swift */, - ); - path = Parser; - sourceTree = ""; - }; - 1E8B782B209394D20097A986 /* Extensions */ = { - isa = PBXGroup; - children = ( - 1E8B782C209394D20097A986 /* Array.swift */, - 1E53D4E020AB5DF30006F1E1 /* Bundle.swift */, - 1E8B782E209394D20097A986 /* FloatingPoint.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - 1E8B7832209394D20097A986 /* API */ = { - isa = PBXGroup; - children = ( - 1E8B7846209394D20097A986 /* Geospatial.swift */, - 1E8B7826209394D20097A986 /* Calculator */, - 1E8B7843209394D20097A986 /* Geohash */, - 1E8B7833209394D20097A986 /* GeoJson */, - ); - path = API; - sourceTree = ""; - }; - 1E8B7833209394D20097A986 /* GeoJson */ = { - isa = PBXGroup; - children = ( - 1E8B7840209394D20097A986 /* GeoJson.swift */, - 1E8B7835209394D20097A986 /* GeoJsonDictionary.swift */, - 1E8B7841209394D20097A986 /* GeodesicPoint.swift */, - 1E92ABD320EDC7AA00EF4A4E /* GeodesicLineSegment.swift */, - 1E4BDD492121C59A008DC2BC /* GeodesicLine.swift */, - 1E8BF41F211DE20D00A247BF /* GeodesicPolygon.swift */, - 1E8B7834209394D20097A986 /* GeodesicBoundingBox.swift */, - 1E8B7836209394D20097A986 /* Object */, - ); - path = GeoJson; - sourceTree = ""; - }; - 1E8B7836209394D20097A986 /* Object */ = { - isa = PBXGroup; - children = ( - 1E92ABA820ED935600EF4A4E /* Protocol */, - 1E8B7839209394D20097A986 /* Point.swift */, - 1E8B783A209394D20097A986 /* MultiPoint.swift */, - 1E8B783C209394D20097A986 /* LineString.swift */, - 1E8B783E209394D20097A986 /* MultiLineString.swift */, - 1E8B783D209394D20097A986 /* Polygon.swift */, - 1E8B783F209394D20097A986 /* MultiPolygon.swift */, - 1E8B783B209394D20097A986 /* GeometryCollection.swift */, - 1E8B7837209394D20097A986 /* Feature.swift */, - 1E8B7838209394D20097A986 /* FeatureCollection.swift */, - ); - path = Object; - sourceTree = ""; - }; - 1E8B7843209394D20097A986 /* Geohash */ = { - isa = PBXGroup; - children = ( - 1E8B7844209394D20097A986 /* GeohashBox.swift */, - 1E8B7845209394D20097A986 /* GeohashCoder.swift */, - ); - path = Geohash; - sourceTree = ""; - }; - 1E8B7862209394DE0097A986 /* Tests */ = { - isa = PBXGroup; - children = ( - 1E57A3052093B537009F9B8D /* GeospatialSwiftTests */, - 1E7A053E2093992700A003CD /* Supporting Files */, - ); - path = Tests; - sourceTree = ""; - }; - 1E8B7864209394DE0097A986 /* Test */ = { - isa = PBXGroup; - children = ( - 1E8B786A209394DE0097A986 /* API */, - 1E8B7865209394DE0097A986 /* Parser */, - 1E8B7868209394DE0097A986 /* Extensions */, - ); - path = Test; - sourceTree = ""; - }; - 1E8B7865209394DE0097A986 /* Parser */ = { - isa = PBXGroup; - children = ( - 1E8B7866209394DE0097A986 /* GeoJsonParserTests.swift */, - 1E8B7867209394DE0097A986 /* WktParserTests.swift */, - ); - path = Parser; - sourceTree = ""; - }; - 1E8B7868209394DE0097A986 /* Extensions */ = { - isa = PBXGroup; - children = ( - 1E8B7869209394DE0097A986 /* Assertions.swift */, - 1E7A6CCF209797ED0063F01F /* Equatable.swift */, - ); - path = Extensions; - sourceTree = ""; - }; - 1E8B786A209394DE0097A986 /* API */ = { - isa = PBXGroup; - children = ( - 1EE89F1621147C930039554D /* Calculator */, - 1E8B786B209394DE0097A986 /* GeoJson */, - 1E8B7877209394DE0097A986 /* Geohash */, - ); - path = API; - sourceTree = ""; - }; - 1E8B786B209394DE0097A986 /* GeoJson */ = { - isa = PBXGroup; - children = ( - 1E9A9BA320EE8B51003F381B /* GeodesicLineSegmentTests.swift */, - 1E8B786C209394DE0097A986 /* BoundingBoxTests.swift */, - 1E8B786D209394DE0097A986 /* Object */, - ); - path = GeoJson; - sourceTree = ""; - }; - 1E8B786D209394DE0097A986 /* Object */ = { - isa = PBXGroup; - children = ( - 1E8B7876209394DE0097A986 /* PointTests.swift */, - 1E8B7874209394DE0097A986 /* MultiPointTests.swift */, - 1E8B7872209394DE0097A986 /* LineStringTests.swift */, - 1E8B7875209394DE0097A986 /* MultiLineStringTests.swift */, - 1E8B786E209394DE0097A986 /* PolygonTests.swift */, - 1E8B7873209394DE0097A986 /* MultiPolygonTests.swift */, - 1E8B7871209394DE0097A986 /* GeometryCollectionTests.swift */, - 1E8B786F209394DE0097A986 /* FeatureTests.swift */, - 1E8B7870209394DE0097A986 /* FeatureCollectionTests.swift */, - ); - path = Object; - sourceTree = ""; - }; - 1E8B7877209394DE0097A986 /* Geohash */ = { - isa = PBXGroup; - children = ( - 1E8B7878209394DE0097A986 /* GeohashCoderTests.swift */, - 1E8B7879209394DE0097A986 /* GeohashBoxTests.swift */, - ); - path = Geohash; - sourceTree = ""; - }; - 1E8B787A209394DE0097A986 /* Mock */ = { - isa = PBXGroup; - children = ( - 1E8B787E209394DE0097A986 /* API */, - ); - path = Mock; - sourceTree = ""; - }; - 1E8B787E209394DE0097A986 /* API */ = { - isa = PBXGroup; - children = ( - 1E9A9BD320EEF5D7003F381B /* Calculator */, - 1E8B7892209394DE0097A986 /* Geohash */, - 1E8B787F209394DE0097A986 /* GeoJson */, - ); - path = API; - sourceTree = ""; - }; - 1E8B787F209394DE0097A986 /* GeoJson */ = { - isa = PBXGroup; - children = ( - 1E8B7884209394DE0097A986 /* MockGeoJson.swift */, - 1E8B7886209394DE0097A986 /* MockGeoJsonObject.swift */, - 1EFFA4D720FD10760017D8C1 /* MockGeoJsonGeometry.swift */, - 1E8B7887209394DE0097A986 /* MockGeoJsonCoordinatesGeometry.swift */, - 1E6CC19C20A09AA40041DBA4 /* MockGeoJsonClosedGeometry.swift */, - 1E92ABCF20EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift */, - 1E8B7880209394DE0097A986 /* Box */, - 1E8B7888209394DE0097A986 /* Object */, - ); - path = GeoJson; - sourceTree = ""; - }; - 1E8B7880209394DE0097A986 /* Box */ = { - isa = PBXGroup; - children = ( - 1E8B7882209394DE0097A986 /* MockGeoJsonBoundingBox.swift */, - 1E8B7881209394DE0097A986 /* MockGeoJsonGeohashBox.swift */, - ); - path = Box; - sourceTree = ""; - }; - 1E8B7888209394DE0097A986 /* Object */ = { - isa = PBXGroup; - children = ( - 1E8B788B209394DE0097A986 /* MockGeoJsonPoint.swift */, - 1E8B788F209394DE0097A986 /* MockGeoJsonMultiPoint.swift */, - 1E8B7890209394DE0097A986 /* MockGeoJsonLineString.swift */, - 1E8B788C209394DE0097A986 /* MockGeoJsonMultiLineString.swift */, - 1E8B788E209394DE0097A986 /* MockGeoJsonPolygon.swift */, - 1E8B7891209394DE0097A986 /* MockGeoJsonMultiPolygon.swift */, - 1E8B7889209394DE0097A986 /* MockGeoJsonGeometryCollection.swift */, - 1E8B788D209394DE0097A986 /* MockGeoJsonFeature.swift */, - 1E8B788A209394DE0097A986 /* MockGeoJsonFeatureCollection.swift */, - ); - path = Object; - sourceTree = ""; - }; - 1E8B7892209394DE0097A986 /* Geohash */ = { - isa = PBXGroup; - children = ( - 1E8B7893209394DE0097A986 /* MockGeohashCoder.swift */, - ); - path = Geohash; - sourceTree = ""; - }; - 1E8B7896209394DE0097A986 /* Performance */ = { - isa = PBXGroup; - children = ( - 1E8B7897209394DE0097A986 /* GeoJsonParsingPerformanceTests.swift */, - ); - path = Performance; - sourceTree = ""; - }; - 1E8B7898209394DE0097A986 /* Data */ = { - isa = PBXGroup; - children = ( - 1E8B7899209394DE0097A986 /* GeoJsonTestJson.swift */, - 1E8B789A209394DE0097A986 /* MockData.swift */, - 1E8B789B209394DE0097A986 /* WktTestJson.swift */, - 1E8B789C209394DE0097A986 /* GeoTestHelper.swift */, - ); - path = Data; - sourceTree = ""; - }; - 1E8B78E7209398FD0097A986 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 1E8B782F209394D20097A986 /* GeospatialSwift.h */, - 1E8B7847209394D20097A986 /* Info.plist */, - 1E9091262093A1E500DAEF11 /* Info tvOS.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 1E92ABA820ED935600EF4A4E /* Protocol */ = { - isa = PBXGroup; - children = ( - 1E92ABA620EC113D00EF4A4E /* GeoJsonObject.swift */, - 1E92ABC520ED94B200EF4A4E /* GeoJsonObjectType.swift */, - 1E92ABA920ED938D00EF4A4E /* GeoJsonGeometry.swift */, - 1E92ABB120ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift */, - 1E92ABC020ED948E00EF4A4E /* GeoJsonClosedGeometry.swift */, - 1E92ABCA20ED955800EF4A4E /* GeoJsonLinearGeometry.swift */, - ); - path = Protocol; - sourceTree = ""; - }; - 1E9A9BD320EEF5D7003F381B /* Calculator */ = { - isa = PBXGroup; - children = ( - 1E9A9BD420EEF5E4003F381B /* MockGeodesicCalculator.swift */, - ); - path = Calculator; - sourceTree = ""; - }; - 1EE89F1621147C930039554D /* Calculator */ = { - isa = PBXGroup; - children = ( - 1EE89F1221147C890039554D /* GeodesicCalculatorTests.swift */, - ); - path = Calculator; - sourceTree = ""; - }; - OBJ_123 /* Products */ = { - isa = PBXGroup; - children = ( - 1E9090B020939EA300DAEF11 /* GeospatialSwift.framework */, - 1E9090B820939EA400DAEF11 /* GeospatialSwift macOS Tests.xctest */, - 1E9090E220939F2700DAEF11 /* GeospatialSwift.framework */, - 1E9090EA20939F2700DAEF11 /* GeospatialSwift iOS Tests.xctest */, - 1E9090FE20939F5C00DAEF11 /* GeospatialSwift.framework */, - 1E90910620939F5C00DAEF11 /* GeospatialSwift tvOSTests.xctest */, - 1E90911A20939F6900DAEF11 /* GeospatialSwift.framework */, - ); - name = Products; - path = ..; - sourceTree = BUILT_PRODUCTS_DIR; - }; - OBJ_5 = { - isa = PBXGroup; - children = ( - 1E8B7825209394D20097A986 /* Sources */, - 1E8B7862209394DE0097A986 /* Tests */, - 1E7A0549209399E800A003CD /* Documentation */, - 1E7A05482093999C00A003CD /* Dependencies */, - 1E6C083D20AB56B8001788C3 /* XCode Dependencies */, - OBJ_123 /* Products */, - ); - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 1E9090AD20939EA300DAEF11 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090DF20939F2700DAEF11 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090FB20939F5C00DAEF11 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90911720939F6900DAEF11 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 1E9090AF20939EA300DAEF11 /* GeospatialSwift macOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E9090C120939EA400DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift macOS" */; - buildPhases = ( - 1E160A8220F788B300C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */, - 1E9090AB20939EA300DAEF11 /* Sources */, - 1E9090AC20939EA300DAEF11 /* Frameworks */, - 1E9090AD20939EA300DAEF11 /* Headers */, - 1E9090AE20939EA300DAEF11 /* Resources */, - 1E8BCB422093BBB30091DA81 /* Run Script - Swift Lint */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "GeospatialSwift macOS"; - productName = GeospatialSwift; - productReference = 1E9090B020939EA300DAEF11 /* GeospatialSwift.framework */; - productType = "com.apple.product-type.framework"; - }; - 1E9090B720939EA400DAEF11 /* GeospatialSwift macOS Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E9090C420939EA400DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift macOS Tests" */; - buildPhases = ( - 1E9090B420939EA400DAEF11 /* Sources */, - 1E9090B520939EA400DAEF11 /* Frameworks */, - 1E9090B620939EA400DAEF11 /* Resources */, - 1E54975E20AB6A7D00FE50EC /* Run Script - Carthage Copy */, - ); - buildRules = ( - ); - dependencies = ( - 1E9090BB20939EA400DAEF11 /* PBXTargetDependency */, - ); - name = "GeospatialSwift macOS Tests"; - productName = GeospatialSwiftTests; - productReference = 1E9090B820939EA400DAEF11 /* GeospatialSwift macOS Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 1E9090E120939F2700DAEF11 /* GeospatialSwift iOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E9090F320939F2800DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift iOS" */; - buildPhases = ( - 1E160A8320F788C200C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */, - 1E9090DD20939F2700DAEF11 /* Sources */, - 1E9090DE20939F2700DAEF11 /* Frameworks */, - 1E9090DF20939F2700DAEF11 /* Headers */, - 1E9090E020939F2700DAEF11 /* Resources */, - 1E8BCB432093BBC70091DA81 /* Run Script - Swift Lint */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "GeospatialSwift iOS"; - productName = "GeospatialSwift iOS"; - productReference = 1E9090E220939F2700DAEF11 /* GeospatialSwift.framework */; - productType = "com.apple.product-type.framework"; - }; - 1E9090E920939F2700DAEF11 /* GeospatialSwift iOS Tests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E9090F620939F2800DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift iOS Tests" */; - buildPhases = ( - 1E9090E620939F2700DAEF11 /* Sources */, - 1E9090E720939F2700DAEF11 /* Frameworks */, - 1E9090E820939F2700DAEF11 /* Resources */, - 1E54975F20AB6AF500FE50EC /* Run Script - Carthage Copy */, - ); - buildRules = ( - ); - dependencies = ( - 1E9090ED20939F2800DAEF11 /* PBXTargetDependency */, - ); - name = "GeospatialSwift iOS Tests"; - productName = "GeospatialSwift iOSTests"; - productReference = 1E9090EA20939F2700DAEF11 /* GeospatialSwift iOS Tests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 1E9090FD20939F5C00DAEF11 /* GeospatialSwift tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E90910F20939F5C00DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift tvOS" */; - buildPhases = ( - 1E160A8420F788CA00C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */, - 1E9090F920939F5C00DAEF11 /* Sources */, - 1E9090FA20939F5C00DAEF11 /* Frameworks */, - 1E9090FB20939F5C00DAEF11 /* Headers */, - 1E9090FC20939F5C00DAEF11 /* Resources */, - 1E8BCB442093BBCD0091DA81 /* Run Script - Swift Lint */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "GeospatialSwift tvOS"; - productName = "GeospatialSwift tvOS"; - productReference = 1E9090FE20939F5C00DAEF11 /* GeospatialSwift.framework */; - productType = "com.apple.product-type.framework"; - }; - 1E90910520939F5C00DAEF11 /* GeospatialSwift tvOSTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E90911220939F5C00DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift tvOSTests" */; - buildPhases = ( - 1E90910220939F5C00DAEF11 /* Sources */, - 1E90910320939F5C00DAEF11 /* Frameworks */, - 1E90910420939F5C00DAEF11 /* Resources */, - 1E54976120AB6AFC00FE50EC /* Run Script - Carthage Copy */, - ); - buildRules = ( - ); - dependencies = ( - 1E90910920939F5C00DAEF11 /* PBXTargetDependency */, - ); - name = "GeospatialSwift tvOSTests"; - productName = "GeospatialSwift tvOSTests"; - productReference = 1E90910620939F5C00DAEF11 /* GeospatialSwift tvOSTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 1E90911920939F6900DAEF11 /* GeospatialSwift watchOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E90911F20939F6900DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift watchOS" */; - buildPhases = ( - 1E160A8520F788D300C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */, - 1E90911520939F6900DAEF11 /* Sources */, - 1E90911620939F6900DAEF11 /* Frameworks */, - 1E90911720939F6900DAEF11 /* Headers */, - 1E90911820939F6900DAEF11 /* Resources */, - 1E8BCB452093BBD20091DA81 /* Run Script - Swift Lint */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "GeospatialSwift watchOS"; - productName = "GeospatialSwift watchOS"; - productReference = 1E90911A20939F6900DAEF11 /* GeospatialSwift.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - OBJ_1 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 1020; - TargetAttributes = { - 1E9090AF20939EA300DAEF11 = { - CreatedOnToolsVersion = 9.3; - LastSwiftMigration = 1020; - ProvisioningStyle = Manual; - }; - 1E9090B720939EA400DAEF11 = { - CreatedOnToolsVersion = 9.3; - DevelopmentTeam = 557EJSX593; - LastSwiftMigration = 1020; - ProvisioningStyle = Automatic; - }; - 1E9090E120939F2700DAEF11 = { - CreatedOnToolsVersion = 9.3; - LastSwiftMigration = 1020; - ProvisioningStyle = Manual; - }; - 1E9090E920939F2700DAEF11 = { - CreatedOnToolsVersion = 9.3; - DevelopmentTeam = 557EJSX593; - LastSwiftMigration = 1020; - ProvisioningStyle = Automatic; - }; - 1E9090FD20939F5C00DAEF11 = { - CreatedOnToolsVersion = 9.3; - LastSwiftMigration = 1020; - ProvisioningStyle = Manual; - }; - 1E90910520939F5C00DAEF11 = { - CreatedOnToolsVersion = 9.3; - DevelopmentTeam = 557EJSX593; - LastSwiftMigration = 1020; - ProvisioningStyle = Automatic; - }; - 1E90911920939F6900DAEF11 = { - CreatedOnToolsVersion = 9.3; - LastSwiftMigration = 1020; - ProvisioningStyle = Manual; - }; - }; - }; - buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "GeospatialSwift" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = OBJ_5; - productRefGroup = OBJ_123 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 1E9090AF20939EA300DAEF11 /* GeospatialSwift macOS */, - 1E9090B720939EA400DAEF11 /* GeospatialSwift macOS Tests */, - 1E9090E120939F2700DAEF11 /* GeospatialSwift iOS */, - 1E9090E920939F2700DAEF11 /* GeospatialSwift iOS Tests */, - 1E9090FD20939F5C00DAEF11 /* GeospatialSwift tvOS */, - 1E90910520939F5C00DAEF11 /* GeospatialSwift tvOSTests */, - 1E90911920939F6900DAEF11 /* GeospatialSwift watchOS */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 1E9090AE20939EA300DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4EC20AB64390006F1E1 /* .swiftlint.yml in Resources */, - 1E53D4F020AB64390006F1E1 /* .swift-version in Resources */, - 1E53D4E820AB64390006F1E1 /* Package.resolved in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090B620939EA400DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090E020939F2700DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4ED20AB64390006F1E1 /* .swiftlint.yml in Resources */, - 1E53D4F120AB64390006F1E1 /* .swift-version in Resources */, - 1E53D4E920AB64390006F1E1 /* Package.resolved in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090E820939F2700DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090FC20939F5C00DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4EE20AB64390006F1E1 /* .swiftlint.yml in Resources */, - 1E53D4F220AB64390006F1E1 /* .swift-version in Resources */, - 1E53D4EA20AB64390006F1E1 /* Package.resolved in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90910420939F5C00DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90911820939F6900DAEF11 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4EF20AB64390006F1E1 /* .swiftlint.yml in Resources */, - 1E53D4F320AB64390006F1E1 /* .swift-version in Resources */, - 1E53D4EB20AB64390006F1E1 /* Package.resolved in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 1E160A8220F788B300C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Raise error and warning flags for \"TODO:\", \"SOMEDAY:\", and \"QUESTION:\" in code"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "SOMEDAY=\"SOMEDAY:\"\nTODO=\"TODO:\"\nQUESTION=\"QUESTION:\"\nfind \"${PROJECT_DIR}/Sources\" \"${PROJECT_DIR}/Tests\" \\( -name \"*.swift\" \\) -print0 | xargs -0 egrep --with-filename --line-number --only-matching \"($SOMEDAY).*\\$|($TODO).*\\$|($QUESTION).*\\$\" | perl -p -e \"s/($TODO)/ warning: \\$1/\" | perl -p -e \"s/($SOMEDAY)/ warning: \\$1/\" | perl -p -e \"s/($QUESTION)/ warning: \\$1/\"\n"; - }; - 1E160A8320F788C200C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Raise error and warning flags for \"TODO:\", \"SOMEDAY:\", and \"QUESTION:\" in code"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "SOMEDAY=\"SOMEDAY:\"\nTODO=\"TODO:\"\nQUESTION=\"QUESTION:\"\nfind \"${PROJECT_DIR}/Sources\" \"${PROJECT_DIR}/Tests\" \\( -name \"*.swift\" \\) -print0 | xargs -0 egrep --with-filename --line-number --only-matching \"($SOMEDAY).*\\$|($TODO).*\\$|($QUESTION).*\\$\" | perl -p -e \"s/($TODO)/ warning: \\$1/\" | perl -p -e \"s/($SOMEDAY)/ warning: \\$1/\" | perl -p -e \"s/($QUESTION)/ warning: \\$1/\"\n"; - }; - 1E160A8420F788CA00C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Raise error and warning flags for \"TODO:\", \"SOMEDAY:\", and \"QUESTION:\" in code"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "SOMEDAY=\"SOMEDAY:\"\nTODO=\"TODO:\"\nQUESTION=\"QUESTION:\"\nfind \"${PROJECT_DIR}/Sources\" \"${PROJECT_DIR}/Tests\" \\( -name \"*.swift\" \\) -print0 | xargs -0 egrep --with-filename --line-number --only-matching \"($SOMEDAY).*\\$|($TODO).*\\$|($QUESTION).*\\$\" | perl -p -e \"s/($TODO)/ warning: \\$1/\" | perl -p -e \"s/($SOMEDAY)/ warning: \\$1/\" | perl -p -e \"s/($QUESTION)/ warning: \\$1/\"\n"; - }; - 1E160A8520F788D300C556D0 /* Run Script - Raise error and warning flags for "TODO:", "SOMEDAY:", and "QUESTION:" in code */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Raise error and warning flags for \"TODO:\", \"SOMEDAY:\", and \"QUESTION:\" in code"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "SOMEDAY=\"SOMEDAY:\"\nTODO=\"TODO:\"\nQUESTION=\"QUESTION:\"\nfind \"${PROJECT_DIR}/Sources\" \"${PROJECT_DIR}/Tests\" \\( -name \"*.swift\" \\) -print0 | xargs -0 egrep --with-filename --line-number --only-matching \"($SOMEDAY).*\\$|($TODO).*\\$|($QUESTION).*\\$\" | perl -p -e \"s/($TODO)/ warning: \\$1/\" | perl -p -e \"s/($SOMEDAY)/ warning: \\$1/\" | perl -p -e \"s/($QUESTION)/ warning: \\$1/\"\n"; - }; - 1E54975E20AB6A7D00FE50EC /* Run Script - Carthage Copy */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/Carthage/Build/Mac/TimberSwift.framework", - ); - name = "Run Script - Carthage Copy"; - outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/TimberSwift.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks"; - }; - 1E54975F20AB6AF500FE50EC /* Run Script - Carthage Copy */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/Carthage/Build/iOS/TimberSwift.framework", - ); - name = "Run Script - Carthage Copy"; - outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/TimberSwift.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks"; - }; - 1E54976120AB6AFC00FE50EC /* Run Script - Carthage Copy */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/Carthage/Build/tvOS/TimberSwift.framework", - ); - name = "Run Script - Carthage Copy"; - outputPaths = ( - "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/TimberSwift.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/carthage copy-frameworks"; - }; - 1E8BCB422093BBB30091DA81 /* Run Script - Swift Lint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Swift Lint"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; - }; - 1E8BCB432093BBC70091DA81 /* Run Script - Swift Lint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Swift Lint"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; - }; - 1E8BCB442093BBCD0091DA81 /* Run Script - Swift Lint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Swift Lint"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; - }; - 1E8BCB452093BBD20091DA81 /* Run Script - Swift Lint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script - Swift Lint"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if which swiftlint >/dev/null; then\nswiftlint\nelse\necho \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1E9090AB20939EA300DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4E120AB5DF30006F1E1 /* Bundle.swift in Sources */, - 1E90913E2093A3EE00DAEF11 /* GeoJsonParser.swift in Sources */, - 1E90913A2093A3EE00DAEF11 /* Array.swift in Sources */, - 1E90913C2093A3EE00DAEF11 /* FloatingPoint.swift in Sources */, - 1E90912D2093A3EE00DAEF11 /* GeoJson.swift in Sources */, - 1E92ABD420EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */, - 1E90913D2093A3EE00DAEF11 /* WktParser.swift in Sources */, - 1E90912B2093A3EE00DAEF11 /* GeodesicBoundingBox.swift in Sources */, - 1E8BF420211DE20D00A247BF /* GeodesicPolygon.swift in Sources */, - 1E9091282093A3EE00DAEF11 /* Geospatial.swift in Sources */, - 1E90912A2093A3EE00DAEF11 /* GeohashCoder.swift in Sources */, - 1E9091322093A3EE00DAEF11 /* MultiPoint.swift in Sources */, - 1E92ABA720EC113D00EF4A4E /* GeoJsonObject.swift in Sources */, - 1E53D4DC20AB5D370006F1E1 /* Timber.swift in Sources */, - 1E92ABCB20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */, - 1E90912C2093A3EE00DAEF11 /* GeodesicPoint.swift in Sources */, - 1E9091382093A3EE00DAEF11 /* GeodesicCalculator.swift in Sources */, - 1E9091332093A3EE00DAEF11 /* GeometryCollection.swift in Sources */, - 1E9091292093A3EE00DAEF11 /* GeohashBox.swift in Sources */, - 1E92ABC120ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */, - 1E9091342093A3EE00DAEF11 /* LineString.swift in Sources */, - 1E9091302093A3EE00DAEF11 /* FeatureCollection.swift in Sources */, - 1E92ABAA20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */, - 1E9091362093A3EE00DAEF11 /* MultiLineString.swift in Sources */, - 1E4BDD4A2121C59A008DC2BC /* GeodesicLine.swift in Sources */, - 1E9091312093A3EE00DAEF11 /* Point.swift in Sources */, - 1E9091352093A3EE00DAEF11 /* Polygon.swift in Sources */, - 1E90912F2093A3EE00DAEF11 /* Feature.swift in Sources */, - 1E92ABC620ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */, - 1E92ABB220ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */, - 1E9091372093A3EE00DAEF11 /* MultiPolygon.swift in Sources */, - 1E90912E2093A3EE00DAEF11 /* GeoJsonDictionary.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090B420939EA400DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E7CB73B2093A91400ECC023 /* WktParserTests.swift in Sources */, - 1EFFA4D820FD10770017D8C1 /* MockGeoJsonGeometry.swift in Sources */, - 1EE89F1321147C890039554D /* GeodesicCalculatorTests.swift in Sources */, - 1E7CB7402093A91400ECC023 /* FeatureCollectionTests.swift in Sources */, - 1E7CB7482093A91500ECC023 /* GeohashBoxTests.swift in Sources */, - 1E7CB7372093A91400ECC023 /* MockGeoJsonLineString.swift in Sources */, - 1E7CB7452093A91500ECC023 /* MultiLineStringTests.swift in Sources */, - 1E92ABD020EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift in Sources */, - 1E6CC1A020A09AD20041DBA4 /* MockGeoJsonClosedGeometry.swift in Sources */, - 1E7CB7212093A91400ECC023 /* GeoJsonTestJson.swift in Sources */, - 1E7CB72E2093A91400ECC023 /* MockGeoJsonGeohashBox.swift in Sources */, - 1E9A9BD520EEF5E5003F381B /* MockGeodesicCalculator.swift in Sources */, - 1E7CB7412093A91400ECC023 /* GeometryCollectionTests.swift in Sources */, - 1E7CB7432093A91500ECC023 /* MultiPolygonTests.swift in Sources */, - 1E7CB7462093A91500ECC023 /* PointTests.swift in Sources */, - 1E7CB7322093A91400ECC023 /* MockGeoJsonPoint.swift in Sources */, - 1E7CB7242093A91400ECC023 /* GeoTestHelper.swift in Sources */, - 1E7CB7422093A91500ECC023 /* LineStringTests.swift in Sources */, - 1E7CB7352093A91400ECC023 /* MockGeoJsonPolygon.swift in Sources */, - 1E7CB7382093A91400ECC023 /* MockGeoJsonMultiPolygon.swift in Sources */, - 1E7CB7232093A91400ECC023 /* WktTestJson.swift in Sources */, - 1E7CB72F2093A91400ECC023 /* MockGeoJsonBoundingBox.swift in Sources */, - 1E7CB7332093A91400ECC023 /* MockGeoJsonMultiLineString.swift in Sources */, - 1E7CB73A2093A91400ECC023 /* GeoJsonParserTests.swift in Sources */, - 1E7CB7222093A91400ECC023 /* MockData.swift in Sources */, - 1E7CB73D2093A91400ECC023 /* BoundingBoxTests.swift in Sources */, - 1E7CB73E2093A91400ECC023 /* PolygonTests.swift in Sources */, - 1E7CB72A2093A91400ECC023 /* MockGeoJsonCoordinatesGeometry.swift in Sources */, - 1E9A9BA420EE8B51003F381B /* GeodesicLineSegmentTests.swift in Sources */, - 1E7CB7472093A91500ECC023 /* GeohashCoderTests.swift in Sources */, - 1E7CB73C2093A91400ECC023 /* Assertions.swift in Sources */, - 1E7CB73F2093A91400ECC023 /* FeatureTests.swift in Sources */, - 1E7CB7292093A91400ECC023 /* MockGeoJson.swift in Sources */, - 1E7CB7442093A91500ECC023 /* MultiPointTests.swift in Sources */, - 1E7CB7312093A91400ECC023 /* MockGeoJsonFeatureCollection.swift in Sources */, - 1E7CB7392093A91400ECC023 /* GeoJsonParsingPerformanceTests.swift in Sources */, - 1E7CB7302093A91400ECC023 /* MockGeoJsonGeometryCollection.swift in Sources */, - 1E7CB72D2093A91400ECC023 /* MockGeoJsonObject.swift in Sources */, - 1E7CB7342093A91400ECC023 /* MockGeoJsonFeature.swift in Sources */, - 1E7CB7362093A91400ECC023 /* MockGeoJsonMultiPoint.swift in Sources */, - 1E7A6CD0209797ED0063F01F /* Equatable.swift in Sources */, - 1E7CB7282093A91400ECC023 /* MockGeohashCoder.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090DD20939F2700DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4E220AB5DF30006F1E1 /* Bundle.swift in Sources */, - 1E9091562093A3EF00DAEF11 /* GeoJsonParser.swift in Sources */, - 1E9091522093A3EF00DAEF11 /* Array.swift in Sources */, - 1E9091542093A3EF00DAEF11 /* FloatingPoint.swift in Sources */, - 1E9091452093A3EF00DAEF11 /* GeoJson.swift in Sources */, - 1E92ABD520EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */, - 1E9091552093A3EF00DAEF11 /* WktParser.swift in Sources */, - 1E9091432093A3EF00DAEF11 /* GeodesicBoundingBox.swift in Sources */, - 1E9091402093A3EF00DAEF11 /* Geospatial.swift in Sources */, - 1E9091422093A3EF00DAEF11 /* GeohashCoder.swift in Sources */, - 1E90914A2093A3EF00DAEF11 /* MultiPoint.swift in Sources */, - 1E53D4DD20AB5D370006F1E1 /* Timber.swift in Sources */, - 1E9091442093A3EF00DAEF11 /* GeodesicPoint.swift in Sources */, - 1E92ABCC20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */, - 1E9091502093A3EF00DAEF11 /* GeodesicCalculator.swift in Sources */, - 1E90914B2093A3EF00DAEF11 /* GeometryCollection.swift in Sources */, - 1E92ABAE20ED939200EF4A4E /* GeoJsonObject.swift in Sources */, - 1E9091412093A3EF00DAEF11 /* GeohashBox.swift in Sources */, - 1E92ABC220ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */, - 1E90914C2093A3EF00DAEF11 /* LineString.swift in Sources */, - 1E9091482093A3EF00DAEF11 /* FeatureCollection.swift in Sources */, - 1E92ABAB20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */, - 1E90914E2093A3EF00DAEF11 /* MultiLineString.swift in Sources */, - 1E9091492093A3EF00DAEF11 /* Point.swift in Sources */, - 1E4BDD4B2121C59A008DC2BC /* GeodesicLine.swift in Sources */, - 1E8BF421211DE22000A247BF /* GeodesicPolygon.swift in Sources */, - 1E90914D2093A3EF00DAEF11 /* Polygon.swift in Sources */, - 1E9091472093A3EF00DAEF11 /* Feature.swift in Sources */, - 1E92ABC720ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */, - 1E92ABB320ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */, - 1E90914F2093A3EF00DAEF11 /* MultiPolygon.swift in Sources */, - 1E9091462093A3EF00DAEF11 /* GeoJsonDictionary.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090E620939F2700DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E7CB7632093A91600ECC023 /* WktParserTests.swift in Sources */, - 1EFFA4D920FD10770017D8C1 /* MockGeoJsonGeometry.swift in Sources */, - 1EE89F1421147C890039554D /* GeodesicCalculatorTests.swift in Sources */, - 1E7CB7682093A91600ECC023 /* FeatureCollectionTests.swift in Sources */, - 1E7CB7702093A91600ECC023 /* GeohashBoxTests.swift in Sources */, - 1E7CB75F2093A91600ECC023 /* MockGeoJsonLineString.swift in Sources */, - 1E7CB76D2093A91600ECC023 /* MultiLineStringTests.swift in Sources */, - 1E92ABD120EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift in Sources */, - 1E6CC19F20A09AD20041DBA4 /* MockGeoJsonClosedGeometry.swift in Sources */, - 1E7CB7492093A91600ECC023 /* GeoJsonTestJson.swift in Sources */, - 1E7CB7562093A91600ECC023 /* MockGeoJsonGeohashBox.swift in Sources */, - 1E9A9BD620EEF5E5003F381B /* MockGeodesicCalculator.swift in Sources */, - 1E7CB7692093A91600ECC023 /* GeometryCollectionTests.swift in Sources */, - 1E7CB76B2093A91600ECC023 /* MultiPolygonTests.swift in Sources */, - 1E7CB76E2093A91600ECC023 /* PointTests.swift in Sources */, - 1E7CB75A2093A91600ECC023 /* MockGeoJsonPoint.swift in Sources */, - 1E7CB74C2093A91600ECC023 /* GeoTestHelper.swift in Sources */, - 1E7CB76A2093A91600ECC023 /* LineStringTests.swift in Sources */, - 1E7CB75D2093A91600ECC023 /* MockGeoJsonPolygon.swift in Sources */, - 1E7CB7602093A91600ECC023 /* MockGeoJsonMultiPolygon.swift in Sources */, - 1E7CB74B2093A91600ECC023 /* WktTestJson.swift in Sources */, - 1E7CB7572093A91600ECC023 /* MockGeoJsonBoundingBox.swift in Sources */, - 1E7CB75B2093A91600ECC023 /* MockGeoJsonMultiLineString.swift in Sources */, - 1E7CB7622093A91600ECC023 /* GeoJsonParserTests.swift in Sources */, - 1E7CB74A2093A91600ECC023 /* MockData.swift in Sources */, - 1E7CB7652093A91600ECC023 /* BoundingBoxTests.swift in Sources */, - 1E7CB7662093A91600ECC023 /* PolygonTests.swift in Sources */, - 1E7CB7522093A91600ECC023 /* MockGeoJsonCoordinatesGeometry.swift in Sources */, - 1E9A9BA520EE8B51003F381B /* GeodesicLineSegmentTests.swift in Sources */, - 1E7CB76F2093A91600ECC023 /* GeohashCoderTests.swift in Sources */, - 1E7CB7642093A91600ECC023 /* Assertions.swift in Sources */, - 1E7CB7672093A91600ECC023 /* FeatureTests.swift in Sources */, - 1E7CB7512093A91600ECC023 /* MockGeoJson.swift in Sources */, - 1E7CB76C2093A91600ECC023 /* MultiPointTests.swift in Sources */, - 1E7CB7592093A91600ECC023 /* MockGeoJsonFeatureCollection.swift in Sources */, - 1E7CB7612093A91600ECC023 /* GeoJsonParsingPerformanceTests.swift in Sources */, - 1E7CB7582093A91600ECC023 /* MockGeoJsonGeometryCollection.swift in Sources */, - 1E7CB7552093A91600ECC023 /* MockGeoJsonObject.swift in Sources */, - 1E7CB75C2093A91600ECC023 /* MockGeoJsonFeature.swift in Sources */, - 1E7CB75E2093A91600ECC023 /* MockGeoJsonMultiPoint.swift in Sources */, - 1E7A6CD1209797ED0063F01F /* Equatable.swift in Sources */, - 1E7CB7502093A91600ECC023 /* MockGeohashCoder.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E9090F920939F5C00DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4E320AB5DF30006F1E1 /* Bundle.swift in Sources */, - 1E90916E2093A3EF00DAEF11 /* GeoJsonParser.swift in Sources */, - 1E90916A2093A3EF00DAEF11 /* Array.swift in Sources */, - 1E90916C2093A3EF00DAEF11 /* FloatingPoint.swift in Sources */, - 1E90915D2093A3EF00DAEF11 /* GeoJson.swift in Sources */, - 1E92ABD620EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */, - 1E90916D2093A3EF00DAEF11 /* WktParser.swift in Sources */, - 1E90915B2093A3EF00DAEF11 /* GeodesicBoundingBox.swift in Sources */, - 1E9091582093A3EF00DAEF11 /* Geospatial.swift in Sources */, - 1E90915A2093A3EF00DAEF11 /* GeohashCoder.swift in Sources */, - 1E9091622093A3EF00DAEF11 /* MultiPoint.swift in Sources */, - 1E53D4DE20AB5D370006F1E1 /* Timber.swift in Sources */, - 1E90915C2093A3EF00DAEF11 /* GeodesicPoint.swift in Sources */, - 1E92ABCD20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */, - 1E9091682093A3EF00DAEF11 /* GeodesicCalculator.swift in Sources */, - 1E9091632093A3EF00DAEF11 /* GeometryCollection.swift in Sources */, - 1E92ABAF20ED939300EF4A4E /* GeoJsonObject.swift in Sources */, - 1E9091592093A3EF00DAEF11 /* GeohashBox.swift in Sources */, - 1E92ABC320ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */, - 1E9091642093A3EF00DAEF11 /* LineString.swift in Sources */, - 1E9091602093A3EF00DAEF11 /* FeatureCollection.swift in Sources */, - 1E92ABAC20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */, - 1E9091662093A3EF00DAEF11 /* MultiLineString.swift in Sources */, - 1E9091612093A3EF00DAEF11 /* Point.swift in Sources */, - 1E4BDD4C2121C59A008DC2BC /* GeodesicLine.swift in Sources */, - 1E8BF422211DE22100A247BF /* GeodesicPolygon.swift in Sources */, - 1E9091652093A3EF00DAEF11 /* Polygon.swift in Sources */, - 1E90915F2093A3EF00DAEF11 /* Feature.swift in Sources */, - 1E92ABC820ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */, - 1E92ABB420ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */, - 1E9091672093A3EF00DAEF11 /* MultiPolygon.swift in Sources */, - 1E90915E2093A3EF00DAEF11 /* GeoJsonDictionary.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90910220939F5C00DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E7CB78B2093A91700ECC023 /* WktParserTests.swift in Sources */, - 1EFFA4DA20FD10770017D8C1 /* MockGeoJsonGeometry.swift in Sources */, - 1EE89F1521147C890039554D /* GeodesicCalculatorTests.swift in Sources */, - 1E7CB7902093A91700ECC023 /* FeatureCollectionTests.swift in Sources */, - 1E7CB7982093A91700ECC023 /* GeohashBoxTests.swift in Sources */, - 1E7CB7872093A91700ECC023 /* MockGeoJsonLineString.swift in Sources */, - 1E7CB7952093A91700ECC023 /* MultiLineStringTests.swift in Sources */, - 1E92ABD220EDA69700EF4A4E /* MockGeoJsonLinearGeometry.swift in Sources */, - 1E6CC19E20A09AD20041DBA4 /* MockGeoJsonClosedGeometry.swift in Sources */, - 1E7CB7712093A91700ECC023 /* GeoJsonTestJson.swift in Sources */, - 1E7CB77E2093A91700ECC023 /* MockGeoJsonGeohashBox.swift in Sources */, - 1E9A9BD720EEF5E5003F381B /* MockGeodesicCalculator.swift in Sources */, - 1E7CB7912093A91700ECC023 /* GeometryCollectionTests.swift in Sources */, - 1E7CB7932093A91700ECC023 /* MultiPolygonTests.swift in Sources */, - 1E7CB7962093A91700ECC023 /* PointTests.swift in Sources */, - 1E7CB7822093A91700ECC023 /* MockGeoJsonPoint.swift in Sources */, - 1E7CB7742093A91700ECC023 /* GeoTestHelper.swift in Sources */, - 1E7CB7922093A91700ECC023 /* LineStringTests.swift in Sources */, - 1E7CB7852093A91700ECC023 /* MockGeoJsonPolygon.swift in Sources */, - 1E7CB7882093A91700ECC023 /* MockGeoJsonMultiPolygon.swift in Sources */, - 1E7CB7732093A91700ECC023 /* WktTestJson.swift in Sources */, - 1E7CB77F2093A91700ECC023 /* MockGeoJsonBoundingBox.swift in Sources */, - 1E7CB7832093A91700ECC023 /* MockGeoJsonMultiLineString.swift in Sources */, - 1E7CB78A2093A91700ECC023 /* GeoJsonParserTests.swift in Sources */, - 1E7CB7722093A91700ECC023 /* MockData.swift in Sources */, - 1E7CB78D2093A91700ECC023 /* BoundingBoxTests.swift in Sources */, - 1E7CB78E2093A91700ECC023 /* PolygonTests.swift in Sources */, - 1E7CB77A2093A91700ECC023 /* MockGeoJsonCoordinatesGeometry.swift in Sources */, - 1E9A9BA620EE8B51003F381B /* GeodesicLineSegmentTests.swift in Sources */, - 1E7CB7972093A91700ECC023 /* GeohashCoderTests.swift in Sources */, - 1E7CB78C2093A91700ECC023 /* Assertions.swift in Sources */, - 1E7CB78F2093A91700ECC023 /* FeatureTests.swift in Sources */, - 1E7CB7792093A91700ECC023 /* MockGeoJson.swift in Sources */, - 1E7CB7942093A91700ECC023 /* MultiPointTests.swift in Sources */, - 1E7CB7812093A91700ECC023 /* MockGeoJsonFeatureCollection.swift in Sources */, - 1E7CB7892093A91700ECC023 /* GeoJsonParsingPerformanceTests.swift in Sources */, - 1E7CB7802093A91700ECC023 /* MockGeoJsonGeometryCollection.swift in Sources */, - 1E7CB77D2093A91700ECC023 /* MockGeoJsonObject.swift in Sources */, - 1E7CB7842093A91700ECC023 /* MockGeoJsonFeature.swift in Sources */, - 1E7CB7862093A91700ECC023 /* MockGeoJsonMultiPoint.swift in Sources */, - 1E7A6CD2209797ED0063F01F /* Equatable.swift in Sources */, - 1E7CB7782093A91700ECC023 /* MockGeohashCoder.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E90911520939F6900DAEF11 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E53D4E420AB5DF30006F1E1 /* Bundle.swift in Sources */, - 1E9091862093A3F000DAEF11 /* GeoJsonParser.swift in Sources */, - 1E9091822093A3F000DAEF11 /* Array.swift in Sources */, - 1E9091842093A3F000DAEF11 /* FloatingPoint.swift in Sources */, - 1E9091752093A3F000DAEF11 /* GeoJson.swift in Sources */, - 1E92ABD720EDC7AA00EF4A4E /* GeodesicLineSegment.swift in Sources */, - 1E9091852093A3F000DAEF11 /* WktParser.swift in Sources */, - 1E9091732093A3F000DAEF11 /* GeodesicBoundingBox.swift in Sources */, - 1E9091702093A3F000DAEF11 /* Geospatial.swift in Sources */, - 1E9091722093A3F000DAEF11 /* GeohashCoder.swift in Sources */, - 1E90917A2093A3F000DAEF11 /* MultiPoint.swift in Sources */, - 1E53D4DF20AB5D370006F1E1 /* Timber.swift in Sources */, - 1E9091742093A3F000DAEF11 /* GeodesicPoint.swift in Sources */, - 1E92ABCE20ED955800EF4A4E /* GeoJsonLinearGeometry.swift in Sources */, - 1E9091802093A3F000DAEF11 /* GeodesicCalculator.swift in Sources */, - 1E90917B2093A3F000DAEF11 /* GeometryCollection.swift in Sources */, - 1E92ABB020ED939400EF4A4E /* GeoJsonObject.swift in Sources */, - 1E9091712093A3F000DAEF11 /* GeohashBox.swift in Sources */, - 1E92ABC420ED948E00EF4A4E /* GeoJsonClosedGeometry.swift in Sources */, - 1E90917C2093A3F000DAEF11 /* LineString.swift in Sources */, - 1E9091782093A3F000DAEF11 /* FeatureCollection.swift in Sources */, - 1E92ABAD20ED938D00EF4A4E /* GeoJsonGeometry.swift in Sources */, - 1E90917E2093A3F000DAEF11 /* MultiLineString.swift in Sources */, - 1E9091792093A3F000DAEF11 /* Point.swift in Sources */, - 1E4BDD4D2121C59A008DC2BC /* GeodesicLine.swift in Sources */, - 1E8BF423211DE22200A247BF /* GeodesicPolygon.swift in Sources */, - 1E90917D2093A3F000DAEF11 /* Polygon.swift in Sources */, - 1E9091772093A3F000DAEF11 /* Feature.swift in Sources */, - 1E92ABC920ED94B200EF4A4E /* GeoJsonObjectType.swift in Sources */, - 1E92ABB520ED93B400EF4A4E /* GeoJsonCoordinatesGeometry.swift in Sources */, - 1E90917F2093A3F000DAEF11 /* MultiPolygon.swift in Sources */, - 1E9091762093A3F000DAEF11 /* GeoJsonDictionary.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 1E9090BB20939EA400DAEF11 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E9090AF20939EA300DAEF11 /* GeospatialSwift macOS */; - targetProxy = 1E9090BA20939EA400DAEF11 /* PBXContainerItemProxy */; - }; - 1E9090ED20939F2800DAEF11 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E9090E120939F2700DAEF11 /* GeospatialSwift iOS */; - targetProxy = 1E9090EC20939F2800DAEF11 /* PBXContainerItemProxy */; - }; - 1E90910920939F5C00DAEF11 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E9090FD20939F5C00DAEF11 /* GeospatialSwift tvOS */; - targetProxy = 1E90910820939F5C00DAEF11 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 1E9090C220939EA400DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - FRAMEWORK_VERSION = A; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Sources/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = macosx; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 10.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Debug; - }; - 1E9090C320939EA400DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - FRAMEWORK_VERSION = A; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Sources/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = macosx; - SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 10.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Release; - }; - 1E9090C520939EA400DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 557EJSX593; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - "$(PROJECT_DIR)/Carthage/Build/iOS", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwiftTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - }; - name = Debug; - }; - 1E9090C620939EA400DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "Mac Developer"; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = 557EJSX593; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - "$(PROJECT_DIR)/Carthage/Build/iOS", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwiftTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - }; - name = Release; - }; - 1E9090F420939F2800DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Sources/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TVOS_DEPLOYMENT_TARGET = 10.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Debug; - }; - 1E9090F520939F2800DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Sources/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TVOS_DEPLOYMENT_TARGET = 10.0; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Release; - }; - 1E9090F720939F2800DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 557EJSX593; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - "$(PROJECT_DIR)/Carthage/Build/Mac", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.monsanto.GeospatialSwift-iOSTests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 1E9090F820939F2800DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = 557EJSX593; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/iOS", - "$(PROJECT_DIR)/Carthage/Build/Mac", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 11.3; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "com.monsanto.GeospatialSwift-iOSTests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 1E90911020939F5C00DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "Sources/Info tvOS.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 10.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Debug; - }; - 1E90911120939F5C00DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "Sources/Info tvOS.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "appletvsimulator appletvos"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 10.0; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Release; - }; - 1E90911320939F5C00DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 557EJSX593; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - "$(PROJECT_DIR)/Carthage/Build/iOS", - "$(PROJECT_DIR)/Carthage/Build/Mac", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = "com.monsanto.GeospatialSwift-tvOSTests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 11.3; - }; - name = Debug; - }; - 1E90911420939F5C00DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_STYLE = Automatic; - COPY_PHASE_STRIP = NO; - DEVELOPMENT_TEAM = 557EJSX593; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/tvOS", - "$(PROJECT_DIR)/Carthage/Build/iOS", - "$(PROJECT_DIR)/Carthage/Build/Mac", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Tests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = "com.monsanto.GeospatialSwift-tvOSTests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 11.3; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 1E90912020939F6900DAEF11 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Sources/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = watchos; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "watchsimulator watchos"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 4; - TVOS_DEPLOYMENT_TARGET = 10.0; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Debug; - }; - 1E90912120939F6900DAEF11 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - APPLICATION_EXTENSION_API_ONLY = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = ""; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/watchOS", - ); - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = Sources/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.13; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_BUNDLE_IDENTIFIER = com.monsanto.GeospatialSwift; - PRODUCT_NAME = GeospatialSwift; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = watchos; - SKIP_INSTALL = YES; - SUPPORTED_PLATFORMS = "watchsimulator watchos"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 4; - TVOS_DEPLOYMENT_TARGET = 10.0; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - WATCHOS_DEPLOYMENT_TARGET = 3.0; - }; - name = Release; - }; - OBJ_3 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_NS_ASSERTIONS = YES; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - ONLY_ACTIVE_ARCH = YES; - OTHER_SWIFT_FLAGS = "-DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - USE_HEADERMAP = NO; - }; - name = Debug; - }; - OBJ_4 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COMBINE_HIDPI_IMAGES = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = s; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.10; - OTHER_SWIFT_FLAGS = "-DXcode"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = macosx; - SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - USE_HEADERMAP = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1E9090C120939EA400DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift macOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E9090C220939EA400DAEF11 /* Debug */, - 1E9090C320939EA400DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E9090C420939EA400DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift macOS Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E9090C520939EA400DAEF11 /* Debug */, - 1E9090C620939EA400DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E9090F320939F2800DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift iOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E9090F420939F2800DAEF11 /* Debug */, - 1E9090F520939F2800DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E9090F620939F2800DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift iOS Tests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E9090F720939F2800DAEF11 /* Debug */, - 1E9090F820939F2800DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E90910F20939F5C00DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E90911020939F5C00DAEF11 /* Debug */, - 1E90911120939F5C00DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E90911220939F5C00DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift tvOSTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E90911320939F5C00DAEF11 /* Debug */, - 1E90911420939F5C00DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E90911F20939F6900DAEF11 /* Build configuration list for PBXNativeTarget "GeospatialSwift watchOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E90912020939F6900DAEF11 /* Debug */, - 1E90912120939F6900DAEF11 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - OBJ_2 /* Build configuration list for PBXProject "GeospatialSwift" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - OBJ_3 /* Debug */, - OBJ_4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = OBJ_1 /* Project object */; + archiveVersion = "1"; + objectVersion = "46"; + objects = { + "GeospatialSwift::GeospatialSwift" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_96"; + buildPhases = ( + "OBJ_99", + "OBJ_135" + ); + dependencies = ( + ); + name = "GeospatialSwift"; + productName = "GeospatialSwift"; + productReference = "GeospatialSwift::GeospatialSwift::Product"; + productType = "com.apple.product-type.framework"; + }; + "GeospatialSwift::GeospatialSwift::Product" = { + isa = "PBXFileReference"; + path = "GeospatialSwift.framework"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "GeospatialSwift::GeospatialSwiftPackageTests::ProductTarget" = { + isa = "PBXAggregateTarget"; + buildConfigurationList = "OBJ_143"; + buildPhases = ( + ); + dependencies = ( + "OBJ_146" + ); + name = "GeospatialSwiftPackageTests"; + productName = "GeospatialSwiftPackageTests"; + }; + "GeospatialSwift::GeospatialSwiftTests" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_148"; + buildPhases = ( + "OBJ_151", + "OBJ_174" + ); + dependencies = ( + "OBJ_176" + ); + name = "GeospatialSwiftTests"; + productName = "GeospatialSwiftTests"; + productReference = "GeospatialSwift::GeospatialSwiftTests::Product"; + productType = "com.apple.product-type.bundle.unit-test"; + }; + "GeospatialSwift::GeospatialSwiftTests::Product" = { + isa = "PBXFileReference"; + path = "GeospatialSwiftTests.xctest"; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "GeospatialSwift::SwiftPMPackageDescription" = { + isa = "PBXNativeTarget"; + buildConfigurationList = "OBJ_137"; + buildPhases = ( + "OBJ_140" + ); + dependencies = ( + ); + name = "GeospatialSwiftPackageDescription"; + productName = "GeospatialSwiftPackageDescription"; + productType = "com.apple.product-type.framework"; + }; + "OBJ_1" = { + isa = "PBXProject"; + attributes = { + LastSwiftMigration = "9999"; + LastUpgradeCheck = "9999"; + }; + buildConfigurationList = "OBJ_2"; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = "en"; + hasScannedForEncodings = "0"; + knownRegions = ( + "en" + ); + mainGroup = "OBJ_5"; + productRefGroup = "OBJ_86"; + projectDirPath = "."; + targets = ( + "GeospatialSwift::GeospatialSwift", + "GeospatialSwift::SwiftPMPackageDescription", + "GeospatialSwift::GeospatialSwiftPackageTests::ProductTarget", + "GeospatialSwift::GeospatialSwiftTests" + ); + }; + "OBJ_10" = { + isa = "PBXGroup"; + children = ( + "OBJ_11" + ); + name = "Calculator"; + path = "Calculator"; + sourceTree = ""; + }; + "OBJ_100" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_11"; + }; + "OBJ_101" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_13"; + }; + "OBJ_102" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_14"; + }; + "OBJ_103" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_15"; + }; + "OBJ_104" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_16"; + }; + "OBJ_105" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_17"; + }; + "OBJ_106" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_18"; + }; + "OBJ_107" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_19"; + }; + "OBJ_108" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_20"; + }; + "OBJ_109" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_22"; + }; + "OBJ_11" = { + isa = "PBXFileReference"; + path = "GeodesicCalculator.swift"; + sourceTree = ""; + }; + "OBJ_110" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_23"; + }; + "OBJ_111" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_24"; + }; + "OBJ_112" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_25"; + }; + "OBJ_113" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_26"; + }; + "OBJ_114" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_27"; + }; + "OBJ_115" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_28"; + }; + "OBJ_116" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_29"; + }; + "OBJ_117" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_30"; + }; + "OBJ_118" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_31"; + }; + "OBJ_119" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_33"; + }; + "OBJ_12" = { + isa = "PBXGroup"; + children = ( + "OBJ_13", + "OBJ_14", + "OBJ_15", + "OBJ_16", + "OBJ_17", + "OBJ_18", + "OBJ_19", + "OBJ_20", + "OBJ_21" + ); + name = "GeoJson"; + path = "GeoJson"; + sourceTree = ""; + }; + "OBJ_120" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_34"; + }; + "OBJ_121" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_35"; + }; + "OBJ_122" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_36"; + }; + "OBJ_123" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_37"; + }; + "OBJ_124" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_38"; + }; + "OBJ_125" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_40"; + }; + "OBJ_126" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_41"; + }; + "OBJ_127" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_42"; + }; + "OBJ_128" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_44"; + }; + "OBJ_129" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_45"; + }; + "OBJ_13" = { + isa = "PBXFileReference"; + path = "GeoJson.swift"; + sourceTree = ""; + }; + "OBJ_130" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_46"; + }; + "OBJ_131" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_47"; + }; + "OBJ_132" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_49"; + }; + "OBJ_133" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_50"; + }; + "OBJ_134" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_51"; + }; + "OBJ_135" = { + isa = "PBXFrameworksBuildPhase"; + files = ( + ); + }; + "OBJ_137" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_138", + "OBJ_139" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_138" = { + isa = "XCBuildConfiguration"; + buildSettings = { + LD = "/usr/bin/true"; + OTHER_SWIFT_FLAGS = ( + "-swift-version", + "5", + "-I", + "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2", + "-target", + "x86_64-apple-macosx10.10", + "-sdk", + "/Applications/Xcode-11.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", + "-package-description-version", + "5.1" + ); + SWIFT_VERSION = "5.0"; + }; + name = "Debug"; + }; + "OBJ_139" = { + isa = "XCBuildConfiguration"; + buildSettings = { + LD = "/usr/bin/true"; + OTHER_SWIFT_FLAGS = ( + "-swift-version", + "5", + "-I", + "$(TOOLCHAIN_DIR)/usr/lib/swift/pm/4_2", + "-target", + "x86_64-apple-macosx10.10", + "-sdk", + "/Applications/Xcode-11.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk", + "-package-description-version", + "5.1" + ); + SWIFT_VERSION = "5.0"; + }; + name = "Release"; + }; + "OBJ_14" = { + isa = "PBXFileReference"; + path = "GeoJsonDictionary.swift"; + sourceTree = ""; + }; + "OBJ_140" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_141" + ); + }; + "OBJ_141" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_6"; + }; + "OBJ_143" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_144", + "OBJ_145" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_144" = { + isa = "XCBuildConfiguration"; + buildSettings = { + }; + name = "Debug"; + }; + "OBJ_145" = { + isa = "XCBuildConfiguration"; + buildSettings = { + }; + name = "Release"; + }; + "OBJ_146" = { + isa = "PBXTargetDependency"; + target = "GeospatialSwift::GeospatialSwiftTests"; + }; + "OBJ_148" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_149", + "OBJ_150" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_149" = { + isa = "XCBuildConfiguration"; + buildSettings = { + CLANG_ENABLE_MODULES = "YES"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)" + ); + INFOPLIST_FILE = "GeospatialSwift.xcodeproj/GeospatialSwiftTests_Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = "8.0"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@loader_path/../Frameworks", + "@loader_path/Frameworks" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "5.0"; + TARGET_NAME = "GeospatialSwiftTests"; + TVOS_DEPLOYMENT_TARGET = "9.0"; + WATCHOS_DEPLOYMENT_TARGET = "2.0"; + }; + name = "Debug"; + }; + "OBJ_15" = { + isa = "PBXFileReference"; + path = "GeodesicBearing.swift"; + sourceTree = ""; + }; + "OBJ_150" = { + isa = "XCBuildConfiguration"; + buildSettings = { + CLANG_ENABLE_MODULES = "YES"; + EMBEDDED_CONTENT_CONTAINS_SWIFT = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)" + ); + INFOPLIST_FILE = "GeospatialSwift.xcodeproj/GeospatialSwiftTests_Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = "8.0"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@loader_path/../Frameworks", + "@loader_path/Frameworks" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "5.0"; + TARGET_NAME = "GeospatialSwiftTests"; + TVOS_DEPLOYMENT_TARGET = "9.0"; + WATCHOS_DEPLOYMENT_TARGET = "2.0"; + }; + name = "Release"; + }; + "OBJ_151" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_152", + "OBJ_153", + "OBJ_154", + "OBJ_155", + "OBJ_156", + "OBJ_157", + "OBJ_158", + "OBJ_159", + "OBJ_160", + "OBJ_161", + "OBJ_162", + "OBJ_163", + "OBJ_164", + "OBJ_165", + "OBJ_166", + "OBJ_167", + "OBJ_168", + "OBJ_169", + "OBJ_170", + "OBJ_171", + "OBJ_172", + "OBJ_173" + ); + }; + "OBJ_152" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_55"; + }; + "OBJ_153" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_56"; + }; + "OBJ_154" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_57"; + }; + "OBJ_155" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_58"; + }; + "OBJ_156" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_60"; + }; + "OBJ_157" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_64"; + }; + "OBJ_158" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_66"; + }; + "OBJ_159" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_67"; + }; + "OBJ_16" = { + isa = "PBXFileReference"; + path = "GeodesicBoundingBox.swift"; + sourceTree = ""; + }; + "OBJ_160" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_69"; + }; + "OBJ_161" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_70"; + }; + "OBJ_162" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_71"; + }; + "OBJ_163" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_72"; + }; + "OBJ_164" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_73"; + }; + "OBJ_165" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_74"; + }; + "OBJ_166" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_75"; + }; + "OBJ_167" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_76"; + }; + "OBJ_168" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_77"; + }; + "OBJ_169" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_79"; + }; + "OBJ_17" = { + isa = "PBXFileReference"; + path = "GeodesicLine.swift"; + sourceTree = ""; + }; + "OBJ_170" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_81"; + }; + "OBJ_171" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_82"; + }; + "OBJ_172" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_84"; + }; + "OBJ_173" = { + isa = "PBXBuildFile"; + fileRef = "OBJ_85"; + }; + "OBJ_174" = { + isa = "PBXFrameworksBuildPhase"; + files = ( + "OBJ_175" + ); + }; + "OBJ_175" = { + isa = "PBXBuildFile"; + fileRef = "GeospatialSwift::GeospatialSwift::Product"; + }; + "OBJ_176" = { + isa = "PBXTargetDependency"; + target = "GeospatialSwift::GeospatialSwift"; + }; + "OBJ_18" = { + isa = "PBXFileReference"; + path = "GeodesicLineSegment.swift"; + sourceTree = ""; + }; + "OBJ_19" = { + isa = "PBXFileReference"; + path = "GeodesicPoint.swift"; + sourceTree = ""; + }; + "OBJ_2" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_3", + "OBJ_4" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_20" = { + isa = "PBXFileReference"; + path = "GeodesicPolygon.swift"; + sourceTree = ""; + }; + "OBJ_21" = { + isa = "PBXGroup"; + children = ( + "OBJ_22", + "OBJ_23", + "OBJ_24", + "OBJ_25", + "OBJ_26", + "OBJ_27", + "OBJ_28", + "OBJ_29", + "OBJ_30", + "OBJ_31", + "OBJ_32" + ); + name = "Object"; + path = "Object"; + sourceTree = ""; + }; + "OBJ_22" = { + isa = "PBXFileReference"; + path = "Feature.swift"; + sourceTree = ""; + }; + "OBJ_23" = { + isa = "PBXFileReference"; + path = "FeatureCollection.swift"; + sourceTree = ""; + }; + "OBJ_24" = { + isa = "PBXFileReference"; + path = "GeometryCollection.swift"; + sourceTree = ""; + }; + "OBJ_25" = { + isa = "PBXFileReference"; + path = "LineString.swift"; + sourceTree = ""; + }; + "OBJ_26" = { + isa = "PBXFileReference"; + path = "LinearRing.swift"; + sourceTree = ""; + }; + "OBJ_27" = { + isa = "PBXFileReference"; + path = "MultiLineString.swift"; + sourceTree = ""; + }; + "OBJ_28" = { + isa = "PBXFileReference"; + path = "MultiPoint.swift"; + sourceTree = ""; + }; + "OBJ_29" = { + isa = "PBXFileReference"; + path = "MultiPolygon.swift"; + sourceTree = ""; + }; + "OBJ_3" = { + isa = "XCBuildConfiguration"; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = "YES"; + COMBINE_HIDPI_IMAGES = "YES"; + COPY_PHASE_STRIP = "NO"; + DEBUG_INFORMATION_FORMAT = "dwarf"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = "YES"; + GCC_OPTIMIZATION_LEVEL = "0"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE=1", + "DEBUG=1" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + ONLY_ACTIVE_ARCH = "YES"; + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + "-DXcode" + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = "macosx"; + SUPPORTED_PLATFORMS = ( + "macosx", + "iphoneos", + "iphonesimulator", + "appletvos", + "appletvsimulator", + "watchos", + "watchsimulator" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG" + ); + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + USE_HEADERMAP = "NO"; + }; + name = "Debug"; + }; + "OBJ_30" = { + isa = "PBXFileReference"; + path = "Point.swift"; + sourceTree = ""; + }; + "OBJ_31" = { + isa = "PBXFileReference"; + path = "Polygon.swift"; + sourceTree = ""; + }; + "OBJ_32" = { + isa = "PBXGroup"; + children = ( + "OBJ_33", + "OBJ_34", + "OBJ_35", + "OBJ_36", + "OBJ_37", + "OBJ_38" + ); + name = "Protocol"; + path = "Protocol"; + sourceTree = ""; + }; + "OBJ_33" = { + isa = "PBXFileReference"; + path = "GeoJsonClosedGeometry.swift"; + sourceTree = ""; + }; + "OBJ_34" = { + isa = "PBXFileReference"; + path = "GeoJsonCoordinatesGeometry.swift"; + sourceTree = ""; + }; + "OBJ_35" = { + isa = "PBXFileReference"; + path = "GeoJsonGeometry.swift"; + sourceTree = ""; + }; + "OBJ_36" = { + isa = "PBXFileReference"; + path = "GeoJsonLinearGeometry.swift"; + sourceTree = ""; + }; + "OBJ_37" = { + isa = "PBXFileReference"; + path = "GeoJsonObject.swift"; + sourceTree = ""; + }; + "OBJ_38" = { + isa = "PBXFileReference"; + path = "GeoJsonObjectType.swift"; + sourceTree = ""; + }; + "OBJ_39" = { + isa = "PBXGroup"; + children = ( + "OBJ_40", + "OBJ_41" + ); + name = "Geohash"; + path = "Geohash"; + sourceTree = ""; + }; + "OBJ_4" = { + isa = "XCBuildConfiguration"; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = "YES"; + COMBINE_HIDPI_IMAGES = "YES"; + COPY_PHASE_STRIP = "YES"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_OPTIMIZATION_LEVEL = "s"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE=1" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_SWIFT_FLAGS = ( + "$(inherited)", + "-DXcode" + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = "macosx"; + SUPPORTED_PLATFORMS = ( + "macosx", + "iphoneos", + "iphonesimulator", + "appletvos", + "appletvsimulator", + "watchos", + "watchsimulator" + ); + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)", + "SWIFT_PACKAGE" + ); + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + USE_HEADERMAP = "NO"; + }; + name = "Release"; + }; + "OBJ_40" = { + isa = "PBXFileReference"; + path = "GeohashBox.swift"; + sourceTree = ""; + }; + "OBJ_41" = { + isa = "PBXFileReference"; + path = "GeohashCoder.swift"; + sourceTree = ""; + }; + "OBJ_42" = { + isa = "PBXFileReference"; + path = "Geospatial.swift"; + sourceTree = ""; + }; + "OBJ_43" = { + isa = "PBXGroup"; + children = ( + "OBJ_44", + "OBJ_45", + "OBJ_46", + "OBJ_47" + ); + name = "Extensions"; + path = "Extensions"; + sourceTree = ""; + }; + "OBJ_44" = { + isa = "PBXFileReference"; + path = "Array.swift"; + sourceTree = ""; + }; + "OBJ_45" = { + isa = "PBXFileReference"; + path = "Bundle.swift"; + sourceTree = ""; + }; + "OBJ_46" = { + isa = "PBXFileReference"; + path = "FloatingPoint.swift"; + sourceTree = ""; + }; + "OBJ_47" = { + isa = "PBXFileReference"; + path = "Result.swift"; + sourceTree = ""; + }; + "OBJ_48" = { + isa = "PBXGroup"; + children = ( + "OBJ_49", + "OBJ_50", + "OBJ_51" + ); + name = "Parser"; + path = "Parser"; + sourceTree = ""; + }; + "OBJ_49" = { + isa = "PBXFileReference"; + path = "GeoJsonParser.swift"; + sourceTree = ""; + }; + "OBJ_5" = { + isa = "PBXGroup"; + children = ( + "OBJ_6", + "OBJ_7", + "OBJ_52", + "OBJ_86", + "OBJ_89", + "OBJ_90", + "OBJ_91", + "OBJ_92", + "OBJ_93", + "OBJ_94" + ); + path = ""; + sourceTree = ""; + }; + "OBJ_50" = { + isa = "PBXFileReference"; + path = "InvalidGeoJson.swift"; + sourceTree = ""; + }; + "OBJ_51" = { + isa = "PBXFileReference"; + path = "WktParser.swift"; + sourceTree = ""; + }; + "OBJ_52" = { + isa = "PBXGroup"; + children = ( + "OBJ_53" + ); + name = "Tests"; + path = ""; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_53" = { + isa = "PBXGroup"; + children = ( + "OBJ_54", + "OBJ_59", + "OBJ_61" + ); + name = "GeospatialSwiftTests"; + path = "Tests/GeospatialSwiftTests"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_54" = { + isa = "PBXGroup"; + children = ( + "OBJ_55", + "OBJ_56", + "OBJ_57", + "OBJ_58" + ); + name = "Data"; + path = "Data"; + sourceTree = ""; + }; + "OBJ_55" = { + isa = "PBXFileReference"; + path = "GeoJsonTestJson.swift"; + sourceTree = ""; + }; + "OBJ_56" = { + isa = "PBXFileReference"; + path = "GeoTestHelper.swift"; + sourceTree = ""; + }; + "OBJ_57" = { + isa = "PBXFileReference"; + path = "MockData.swift"; + sourceTree = ""; + }; + "OBJ_58" = { + isa = "PBXFileReference"; + path = "WktTestJson.swift"; + sourceTree = ""; + }; + "OBJ_59" = { + isa = "PBXGroup"; + children = ( + "OBJ_60" + ); + name = "Performance"; + path = "Performance"; + sourceTree = ""; + }; + "OBJ_6" = { + isa = "PBXFileReference"; + explicitFileType = "sourcecode.swift"; + path = "Package.swift"; + sourceTree = ""; + }; + "OBJ_60" = { + isa = "PBXFileReference"; + path = "GeoJsonParsingPerformanceTests.swift"; + sourceTree = ""; + }; + "OBJ_61" = { + isa = "PBXGroup"; + children = ( + "OBJ_62", + "OBJ_80", + "OBJ_83" + ); + name = "Test"; + path = "Test"; + sourceTree = ""; + }; + "OBJ_62" = { + isa = "PBXGroup"; + children = ( + "OBJ_63", + "OBJ_65", + "OBJ_78" + ); + name = "API"; + path = "API"; + sourceTree = ""; + }; + "OBJ_63" = { + isa = "PBXGroup"; + children = ( + "OBJ_64" + ); + name = "Calculator"; + path = "Calculator"; + sourceTree = ""; + }; + "OBJ_64" = { + isa = "PBXFileReference"; + path = "GeodesicCalculatorTests.swift"; + sourceTree = ""; + }; + "OBJ_65" = { + isa = "PBXGroup"; + children = ( + "OBJ_66", + "OBJ_67", + "OBJ_68" + ); + name = "GeoJson"; + path = "GeoJson"; + sourceTree = ""; + }; + "OBJ_66" = { + isa = "PBXFileReference"; + path = "BoundingBoxTests.swift"; + sourceTree = ""; + }; + "OBJ_67" = { + isa = "PBXFileReference"; + path = "GeodesicLineSegmentTests.swift"; + sourceTree = ""; + }; + "OBJ_68" = { + isa = "PBXGroup"; + children = ( + "OBJ_69", + "OBJ_70", + "OBJ_71", + "OBJ_72", + "OBJ_73", + "OBJ_74", + "OBJ_75", + "OBJ_76", + "OBJ_77" + ); + name = "Object"; + path = "Object"; + sourceTree = ""; + }; + "OBJ_69" = { + isa = "PBXFileReference"; + path = "FeatureCollectionTests.swift"; + sourceTree = ""; + }; + "OBJ_7" = { + isa = "PBXGroup"; + children = ( + "OBJ_8" + ); + name = "Sources"; + path = ""; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_70" = { + isa = "PBXFileReference"; + path = "FeatureTests.swift"; + sourceTree = ""; + }; + "OBJ_71" = { + isa = "PBXFileReference"; + path = "GeometryCollectionTests.swift"; + sourceTree = ""; + }; + "OBJ_72" = { + isa = "PBXFileReference"; + path = "LineStringTests.swift"; + sourceTree = ""; + }; + "OBJ_73" = { + isa = "PBXFileReference"; + path = "MultiLineStringTests.swift"; + sourceTree = ""; + }; + "OBJ_74" = { + isa = "PBXFileReference"; + path = "MultiPointTests.swift"; + sourceTree = ""; + }; + "OBJ_75" = { + isa = "PBXFileReference"; + path = "MultiPolygonTests.swift"; + sourceTree = ""; + }; + "OBJ_76" = { + isa = "PBXFileReference"; + path = "PointTests.swift"; + sourceTree = ""; + }; + "OBJ_77" = { + isa = "PBXFileReference"; + path = "PolygonTests.swift"; + sourceTree = ""; + }; + "OBJ_78" = { + isa = "PBXGroup"; + children = ( + "OBJ_79" + ); + name = "Geohash"; + path = "Geohash"; + sourceTree = ""; + }; + "OBJ_79" = { + isa = "PBXFileReference"; + path = "GeohashCoderTests.swift"; + sourceTree = ""; + }; + "OBJ_8" = { + isa = "PBXGroup"; + children = ( + "OBJ_9", + "OBJ_43", + "OBJ_48" + ); + name = "GeospatialSwift"; + path = "Sources/GeospatialSwift"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_80" = { + isa = "PBXGroup"; + children = ( + "OBJ_81", + "OBJ_82" + ); + name = "Extensions"; + path = "Extensions"; + sourceTree = ""; + }; + "OBJ_81" = { + isa = "PBXFileReference"; + path = "Assertions.swift"; + sourceTree = ""; + }; + "OBJ_82" = { + isa = "PBXFileReference"; + path = "Equatable.swift"; + sourceTree = ""; + }; + "OBJ_83" = { + isa = "PBXGroup"; + children = ( + "OBJ_84", + "OBJ_85" + ); + name = "Parser"; + path = "Parser"; + sourceTree = ""; + }; + "OBJ_84" = { + isa = "PBXFileReference"; + path = "GeoJsonParserTests.swift"; + sourceTree = ""; + }; + "OBJ_85" = { + isa = "PBXFileReference"; + path = "WktParserTests.swift"; + sourceTree = ""; + }; + "OBJ_86" = { + isa = "PBXGroup"; + children = ( + "GeospatialSwift::GeospatialSwiftTests::Product", + "GeospatialSwift::GeospatialSwift::Product" + ); + name = "Products"; + path = ""; + sourceTree = "BUILT_PRODUCTS_DIR"; + }; + "OBJ_89" = { + isa = "PBXFileReference"; + path = "Tools"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_9" = { + isa = "PBXGroup"; + children = ( + "OBJ_10", + "OBJ_12", + "OBJ_39", + "OBJ_42" + ); + name = "API"; + path = "API"; + sourceTree = ""; + }; + "OBJ_90" = { + isa = "PBXFileReference"; + path = "Scripts"; + sourceTree = "SOURCE_ROOT"; + }; + "OBJ_91" = { + isa = "PBXFileReference"; + path = "LICENSE"; + sourceTree = ""; + }; + "OBJ_92" = { + isa = "PBXFileReference"; + path = "MAINTAINERS"; + sourceTree = ""; + }; + "OBJ_93" = { + isa = "PBXFileReference"; + path = "README.md"; + sourceTree = ""; + }; + "OBJ_94" = { + isa = "PBXFileReference"; + path = "CONTRIBUTING.md"; + sourceTree = ""; + }; + "OBJ_96" = { + isa = "XCConfigurationList"; + buildConfigurations = ( + "OBJ_97", + "OBJ_98" + ); + defaultConfigurationIsVisible = "0"; + defaultConfigurationName = "Release"; + }; + "OBJ_97" = { + isa = "XCBuildConfiguration"; + buildSettings = { + ENABLE_TESTABILITY = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)" + ); + INFOPLIST_FILE = "GeospatialSwift.xcodeproj/GeospatialSwift_Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = "8.0"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)" + ); + PRODUCT_BUNDLE_IDENTIFIER = "GeospatialSwift"; + PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = "YES"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "5.0"; + TARGET_NAME = "GeospatialSwift"; + TVOS_DEPLOYMENT_TARGET = "9.0"; + WATCHOS_DEPLOYMENT_TARGET = "2.0"; + }; + name = "Debug"; + }; + "OBJ_98" = { + isa = "XCBuildConfiguration"; + buildSettings = { + ENABLE_TESTABILITY = "YES"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PLATFORM_DIR)/Developer/Library/Frameworks" + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)" + ); + INFOPLIST_FILE = "GeospatialSwift.xcodeproj/GeospatialSwift_Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = "8.0"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx" + ); + MACOSX_DEPLOYMENT_TARGET = "10.10"; + OTHER_CFLAGS = ( + "$(inherited)" + ); + OTHER_LDFLAGS = ( + "$(inherited)" + ); + OTHER_SWIFT_FLAGS = ( + "$(inherited)" + ); + PRODUCT_BUNDLE_IDENTIFIER = "GeospatialSwift"; + PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = "YES"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = ( + "$(inherited)" + ); + SWIFT_VERSION = "5.0"; + TARGET_NAME = "GeospatialSwift"; + TVOS_DEPLOYMENT_TARGET = "9.0"; + WATCHOS_DEPLOYMENT_TARGET = "2.0"; + }; + name = "Release"; + }; + "OBJ_99" = { + isa = "PBXSourcesBuildPhase"; + files = ( + "OBJ_100", + "OBJ_101", + "OBJ_102", + "OBJ_103", + "OBJ_104", + "OBJ_105", + "OBJ_106", + "OBJ_107", + "OBJ_108", + "OBJ_109", + "OBJ_110", + "OBJ_111", + "OBJ_112", + "OBJ_113", + "OBJ_114", + "OBJ_115", + "OBJ_116", + "OBJ_117", + "OBJ_118", + "OBJ_119", + "OBJ_120", + "OBJ_121", + "OBJ_122", + "OBJ_123", + "OBJ_124", + "OBJ_125", + "OBJ_126", + "OBJ_127", + "OBJ_128", + "OBJ_129", + "OBJ_130", + "OBJ_131", + "OBJ_132", + "OBJ_133", + "OBJ_134" + ); + }; + }; + rootObject = "OBJ_1"; } diff --git a/GeospatialSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/GeospatialSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 919434a..fe1aa71 100644 --- a/GeospatialSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/GeospatialSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,4 @@ - + \ No newline at end of file diff --git a/GeospatialSwift.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/GeospatialSwift.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..a72dc2b --- /dev/null +++ b/GeospatialSwift.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + \ No newline at end of file diff --git a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift iOS.xcscheme b/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift iOS.xcscheme deleted file mode 100644 index 8fdc27f..0000000 --- a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift iOS.xcscheme +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift macOS.xcscheme b/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift macOS.xcscheme deleted file mode 100644 index bb8d02a..0000000 --- a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift macOS.xcscheme +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift tvOS.xcscheme b/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift tvOS.xcscheme deleted file mode 100644 index e3fc71d..0000000 --- a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift tvOS.xcscheme +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift watchOS.xcscheme b/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift-Package.xcscheme similarity index 63% rename from GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift watchOS.xcscheme rename to GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift-Package.xcscheme index 598f054..3822232 100644 --- a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift watchOS.xcscheme +++ b/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/GeospatialSwift-Package.xcscheme @@ -1,6 +1,6 @@ @@ -26,12 +26,19 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - codeCoverageEnabled = "YES" shouldUseLaunchSchemeArgsEnv = "YES"> + + + + - - - - - - - - - - - - diff --git a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist b/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist deleted file mode 100644 index cd135df..0000000 --- a/GeospatialSwift.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,12 +0,0 @@ - - - - SchemeUserState - - GeospatialSwift-Package.xcscheme - - - SuppressBuildableAutocreation - - - diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index 6a6cb20..0000000 --- a/Package.resolved +++ /dev/null @@ -1,16 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "TimberSwift", - "repositoryURL": "https://github.com/MonsantoCo/TimberSwift.git", - "state": { - "branch": null, - "revision": "88840001b43aa2587bcbc714104977c24ddfc54f", - "version": "0.1.0" - } - } - ] - }, - "version": 1 -} diff --git a/Package.swift b/Package.swift index 2351f58..55d66e6 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:4.1 +// swift-tools-version:5.1 import PackageDescription @@ -10,13 +10,11 @@ let package = Package( targets: ["GeospatialSwift"] ) ], - dependencies: [ - .package(url: "https://github.com/MonsantoCo/TimberSwift.git", .upToNextMajor(from: "0.1.0")) - ], + dependencies: [], targets: [ .target( name: "GeospatialSwift", - dependencies: ["TimberSwift"] + dependencies: [] ), .testTarget( name: "GeospatialSwiftTests", diff --git a/README.md b/README.md index 558a412..d51b887 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # GeospatialSwift [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) -[![Swift 5](https://img.shields.io/badge/Swift-5-orange.svg?style=flat)](https://developer.apple.com/swift/) +[![Swift 5.1](https://img.shields.io/badge/Swift-5.1-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Platforms](https://img.shields.io/badge/Platforms-macOS%20%7C%20Linux%20%7C%20iOS%20%7C%20tvOS%20%7C%20watchOS-green.svg?style=flat)](https://swift.org/package-manager/) What is GeospatialSwift? @@ -19,11 +19,11 @@ A GeoJsonObject can be transformed to a bounding box. ### Carthage -```github "MonsantoCo/GeospatialSwift" ~> 0.1.0``` +```github "MonsantoCo/GeospatialSwift" ~> 1.0.0``` ### Package Manager -```.package(url: "git@github.com:MonsantoCo/GeospatialSwift.git", from: "0.1.0")``` +```.package(url: "git@github.com:MonsantoCo/GeospatialSwift.git", from: "1.0.0")``` ## Geospatial @@ -44,11 +44,10 @@ Geospatial.geoJson * Minimum distance to a given point (Optional error distance) * Contains a given point (Optional error distance) -* Bounding box -* GeoJson as a Dictionary -* Points array which make up the geometry -* GeodesicPoint with SimplePoint implementation -* GeodesicLineSegment with midpoint and bearing functions +* Bounding box for any shape +* GeoJson returned as a Dictionary +* Coordinates array for the associated geometry +* Line segments with midpoint and bearing functions * Point * Normalize @@ -70,10 +69,9 @@ Geospatial.geoJson Geospatial.geohash -* Find the geohash of any coordinate -* Find the center coordinate of any geohash -* Find all 9 neighboring geohash given a coordinate -* Create a bounding box (GeohashBox) from a geohash +* Create a geohash from a coordinate or bounding box +* Get geohash neighbors (8) +* Create a bounding box for a geohash ### WKT - Not Fully Supported @@ -83,3 +81,21 @@ Geospatial.parse(wkt: String) -> GeoJsonObject * POINT, LINESTRING, MULTILINESTRING, POLYGON, MULTPOLYGON. * This is currently only intended to parse a very simple WKT string +### Running GeospatialSwift in XCode +- Bootstrap Example: `rm -rf *.xcodeproj || rm -rf .build || swift package resolve && swift package generate-xcodeproj && open *.xcodeproj` +- In the Target `GeospatialSwift`, select the tab `Signing & Capabilities` and check the box `Automatically manage signing` +- In the scheme menu, select `Edit Scheme...`, select the `Test` item on the left, select the tab `Options`, and check the box `Gather coverage for "all targets"` +- In the target `GeospatialSwiftTests` select the tab `Build Phases` and add a `Run Script Phase` with the body `$PROJECT_DIR/Scripts/parrot.sh` and move the item to the top of the Buld Phases just below `Dependencies`. +- In the target `GeospatialSwift` select the tab `Build Phases` and add a `Run Script Phase` with the body `$PROJECT_DIR/Scripts/swiftlint.sh`. + +## Extending GeospatialSwift in XCode + +#### Option 1: Run with the current XCode project as is + +#### Option 2: Rebuild it using `generate-xcodeproj` + +- Setup: Package Manager Example: `rm -rf *.xcodeproj || rm -rf .build || swift package resolve && swift package generate-xcodeproj && open *.xcodeproj` +- Building: In the Target `GeospatialSwift`, select the tab `Signing & Capabilities` and check the box `Automatically manage signing` +- Code Coverage: In the scheme menu, select `Edit Scheme...`, select the `Test` item on the left, select the tab `Options`, and check the box `Gather coverage for "all targets"` +- Mocking: In the target `GeospatialSwiftTests` select the tab `Build Phases` and add a `Run Script Phase` with the body `$PROJECT_DIR/Scripts/parrot.sh` and move the item to the top of the Buld Phases just below `Dependencies`. +- Linting: In the target `GeospatialSwift` select the tab `Build Phases` and add a `Run Script Phase` with the body `$PROJECT_DIR/Scripts/swiftlint.sh`. diff --git a/Scripts/install-tools.sh b/Scripts/install-tools.sh new file mode 100755 index 0000000..7a580ac --- /dev/null +++ b/Scripts/install-tools.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +### Installation script for Parrot ### + +PROJECT_NAME=$(basename $PWD) + +# Directories +PROJECT_DIR=$(xcodebuild -project $PROJECT_NAME.xcodeproj -showBuildSettings | grep PROJECT_DIR | sed -e 's/PROJECT_DIR = //' | sed -e 's/ //g') +TMP_DIR="$PROJECT_DIR/.tmp" # Temp directory to be used during installation +TOOLS_DIR="$PROJECT_DIR/Tools" + +# Githib repos +PARROT_REPO="https://github.com/MonsantoCo/Parrot.git" + +# Parrot files +PARROT_XCODEPROJ_FILE="$TMP_DIR/Parrot.xcodeproj" +PARROT_PBX_FILE="$TMP_DIR/Parrot.xcodeproj/project.pbxproj" +PARROT_RELEASE_BINARY="$TMP_DIR/build/Release/Parrot" + +# Development team necessary for code-signing +DEVELOPMENT_TEAM=$(xcodebuild -project $PROJECT_NAME.xcodeproj -showBuildSettings | grep DEVELOPMENT_TEAM | sed -e 's/DEVELOPMENT_TEAM = //' | sed -e 's/ //g') + +# Script clean up +function cleanupAndExit { + rm -rf "$TMP_DIR" + exit $1 +} + +# Handle ctrl^C +trap "cleanupAndExit 1" SIGINT + +# Setup directories +function createDirectories { + mkdir -p "$TOOLS_DIR" + chflags hidden "$TOOLS_DIR" + mkdir -p "$TMP_DIR" +} + +function installParrot { + echo "Starting Parrot installation..." + + # Clone Parrot into the TMP_DIR + echo "Fetching Parrot from the latest master branch...\n" + git clone --single-branch --branch master "$PARROT_REPO" "$TMP_DIR" || cleanupAndExit 1 + + # Add the signing profile + sed -i '' "s/DEVELOPMENT_TEAM = \"\";/DEVELOPMENT_TEAM = \"$DEVELOPMENT_TEAM\";/g" "$PARROT_PBX_FILE" + + # Build the Parrot Xcode project and then copy the binary to the bin directory + echo "\nBuilding Parrot..." + xcodebuild -project $PARROT_XCODEPROJ_FILE -quiet || cleanupAndExit 1 + + # Copy binary to TOOLS_DIR + cp "$PARROT_RELEASE_BINARY" "$TOOLS_DIR" + + echo "Parrot build complete. Binary located at $TOOLS_DIR/Parrot" +} + +# Program flow +createDirectories +installParrot +cleanupAndExit 0 diff --git a/Scripts/parrot.sh b/Scripts/parrot.sh new file mode 100755 index 0000000..349a5e3 --- /dev/null +++ b/Scripts/parrot.sh @@ -0,0 +1,10 @@ +PARROT=$PROJECT_DIR/Tools/Parrot +SOURCE=$PROJECT_DIR/Sources +TESTS=$PROJECT_DIR/Tests + +if [ -f "$PARROT" ]; then +echo "💚 Running Parrot - SQUAAWWWKKKK 💚" +$PARROT $SOURCE $TESTS || exit 0 +else +echo "warning: ⚠️ ./Scripts/install-tools.sh to enable Parrot" +fi diff --git a/Scripts/swiftlint.sh b/Scripts/swiftlint.sh new file mode 100755 index 0000000..c8bc779 --- /dev/null +++ b/Scripts/swiftlint.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +if which swiftlint >/dev/null; then +swiftlint +#echo "⚠️ warning: SwiftLint turned off" +else +echo "⚠️ warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" +fi diff --git a/Sources/GeospatialSwift/API/Calculator/GeodesicCalculator.swift b/Sources/GeospatialSwift/API/Calculator/GeodesicCalculator.swift index b0300e4..533124a 100644 --- a/Sources/GeospatialSwift/API/Calculator/GeodesicCalculator.swift +++ b/Sources/GeospatialSwift/API/Calculator/GeodesicCalculator.swift @@ -1,70 +1,22 @@ import Foundation +// SOMEDAY: Overlaps / Contains(Fully)? (Line to Line, Line in Multi/Polygon, Polygon in Multi/Polygon) +// func contains(_ lineSegment: GeodesicLineSegment, in polygon: GeodesicPolygon, tolerance: Double) -> Bool +// SOMEDAY: Split Lines +// func canSplit(_ polygon: GeodesicPolygon, from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Bool +// func split(_ polygon: GeodesicPolygon, from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> (GeodesicPolygon, GeodesicPolygon) + // SOMEDAY: Altitude is not considered. Perhaps there should be 3D calculations as well. // SOMEDAY: Break this up into pieces. // swiftlint:disable file_length -public protocol GeodesicCalculatorProtocol { - func area(of polygon: GeodesicPolygon) -> Double - func length(of line: GeodesicLine) -> Double - - func centroid(polygon: GeodesicPolygon) -> GeodesicPoint - func destinationPoint(origin: GeodesicPoint, bearing: Double, distance: Double) -> GeodesicPoint - - func haversineDistance(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double - func lawOfCosinesDistance(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double - - func distance(from point: GeodesicPoint, to otherPoint: GeodesicPoint, tolerance: Double) -> Double - func distance(from point: GeodesicPoint, to lineSegment: GeodesicLineSegment, tolerance: Double) -> Double - func distance(from lineSegment: GeodesicLineSegment, to otherLineSegment: GeodesicLineSegment, tolerance: Double) -> Double - func distance(from point: GeodesicPoint, to line: GeodesicLine, tolerance: Double) -> Double - func distance(from point: GeodesicPoint, to polygon: GeodesicPolygon, tolerance: Double) -> Double - func edgeDistance(from point: GeodesicPoint, to polygon: GeodesicPolygon, tolerance: Double) -> Double - - func equals(_ points: [GeodesicPoint], tolerance: Double) -> Bool - func equalsIndices(_ points: [GeodesicPoint], tolerance: Double) -> [Int] - - func hasIntersection(_ lineSegment: GeodesicLineSegment, with otherLineSegment: GeodesicLineSegment, tolerance: Double) -> Bool - func hasIntersection(_ lineSegment: GeodesicLineSegment, with polygon: GeodesicPolygon, tolerance: Double) -> Bool - func hasIntersection(_ line: GeodesicLine, tolerance: Double) -> Bool - func hasIntersection(_ polygon: GeodesicPolygon, tolerance: Double) -> Bool - - func intersection(of lineSegment: GeodesicLineSegment, with otherLineSegment: GeodesicLineSegment) -> GeodesicPoint? - func intersectionIndices(from line: GeodesicLine, tolerance: Double) -> [Int] - func intersectionIndices(from polygon: GeodesicPolygon, tolerance: Double) -> [[[Int]]] - - func contains(_ point: GeodesicPoint, in lineSegment: GeodesicLineSegment, tolerance: Double) -> Bool - func contains(_ point: GeodesicPoint, in line: GeodesicLine, tolerance: Double) -> Bool - func contains(_ point: GeodesicPoint, in polygon: GeodesicPolygon, tolerance: Double) -> Bool - - // SOMEDAY: Overlaps / Contains(Fully)? (Line to Line, Line in Multi/Polygon, Polygon in Multi/Polygon) - // func contains(_ lineSegment: GeodesicLineSegment, in polygon: GeodesicPolygon, tolerance: Double) -> Bool - // SOMEDAY: Split Lines - // func canSplit(_ polygon: GeodesicPolygon, from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Bool - // func split(_ polygon: GeodesicPolygon, from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> (GeodesicPolygon, GeodesicPolygon) - - func midpoint(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> GeodesicPoint - - func initialBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double - func averageBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double - func finalBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double - - func normalize(longitude: Double) -> Double - func normalize(latitude: Double) -> Double - func normalize(_ point: GeodesicPoint) -> GeodesicPoint - func normalizePositive(longitude: Double) -> Double - func normalizePositive(latitude: Double) -> Double - func normalizePositive(_ point: GeodesicPoint) -> GeodesicPoint -} -internal let Calculator = GeodesicCalculator.shared +internal let Calculator = GeodesicCalculator() /** All calculation input and output is based in meters. Geospatial input and output is expected in longitude/latitude and degrees. */ -public struct GeodesicCalculator: GeodesicCalculatorProtocol { - internal static let shared: GeodesicCalculatorProtocol = GeodesicCalculator() - - private init() { } +public struct GeodesicCalculator { + fileprivate init() { } // Guess at the radius of the earth based on latitude private let earthRadiusEquator: Double = 6378137 @@ -106,26 +58,18 @@ public struct GeodesicCalculator: GeodesicCalculatorProtocol { return atan2(sin(Δλ) * cos(φ2), cos(φ1) * sin(φ2) - sin(φ1) * cos(φ2) * cos(Δλ)).radiansToDegrees } - public func initialBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - return (bearing(from: point, to: otherPoint) + 360).truncatingRemainder(dividingBy: 360) - } + public func initialBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { (bearing(from: point, to: otherPoint) + 360).truncatingRemainder(dividingBy: 360) } - public func averageBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - return initialBearing(from: midpoint(from: point, to: otherPoint), to: otherPoint) - } + public func averageBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { initialBearing(from: midpoint(from: point, to: otherPoint), to: otherPoint) } - public func finalBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - return (bearing(from: otherPoint, to: point) + 180).truncatingRemainder(dividingBy: 360) - } + public func finalBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { (bearing(from: otherPoint, to: point) + 180).truncatingRemainder(dividingBy: 360) } } // MARK: Measurement Functions // SOMEDAY: Area calculations are not geodesic? extension GeodesicCalculator { - public func length(of line: GeodesicLine) -> Double { - return line.segments.reduce(0.0) { $0 + distance(from: $1.point, to: $1.otherPoint, tolerance: 0) } - } + public func length(of line: GeodesicLine) -> Double { line.segments.reduce(0.0) { $0 + distance(from: $1.point, to: $1.otherPoint, tolerance: 0) } } public func area(of polygon: GeodesicPolygon) -> Double { let earthRadius = self.earthRadius(latitudeAverage: centroid(polygon: polygon).latitude) @@ -134,9 +78,7 @@ extension GeodesicCalculator { guard polygon.negativeRings.count > 0 else { return mainRingArea } - return mainRingArea - polygon.negativeRings.map { $0.points }.reduce(0.0) { - return $0 + area(of: $1, earthRadius: earthRadius) - } + return mainRingArea - polygon.negativeRings.map { $0.points }.reduce(0.0) { $0 + area(of: $1, earthRadius: earthRadius) } } private func area(of linearRingPoints: [GeodesicPoint], earthRadius: Double) -> Double { @@ -161,13 +103,9 @@ extension GeodesicCalculator { // MARK: Normalize Functions extension GeodesicCalculator { - public func normalize(longitude: Double) -> Double { - return normalizeCoordinate(value: longitude, shift: 360.0) - } + public func normalize(longitude: Double) -> Double { normalizeCoordinate(value: longitude, shift: 360.0) } - public func normalize(latitude: Double) -> Double { - return normalizeCoordinate(value: latitude, shift: 180.0) - } + public func normalize(latitude: Double) -> Double { normalizeCoordinate(value: latitude, shift: 180.0) } public func normalizePositive(longitude: Double) -> Double { let normalizedLongitude = normalize(longitude: longitude) @@ -181,13 +119,9 @@ extension GeodesicCalculator { return normalizedLatitude < 0 ? normalizedLatitude + 180 : normalizedLatitude } - public func normalize(_ point: GeodesicPoint) -> GeodesicPoint { - return SimplePoint(longitude: normalize(longitude: point.longitude), latitude: normalize(latitude: point.latitude), altitude: point.altitude) - } + public func normalize(_ point: GeodesicPoint) -> GeodesicPoint { SimplePoint(longitude: normalize(longitude: point.longitude), latitude: normalize(latitude: point.latitude), altitude: point.altitude) } - public func normalizePositive(_ point: GeodesicPoint) -> GeodesicPoint { - return SimplePoint(longitude: normalizePositive(longitude: point.longitude), latitude: normalizePositive(latitude: point.latitude), altitude: point.altitude) - } + public func normalizePositive(_ point: GeodesicPoint) -> GeodesicPoint { SimplePoint(longitude: normalizePositive(longitude: point.longitude), latitude: normalizePositive(latitude: point.latitude), altitude: point.altitude) } // A normalized value (longitude or latitude) is greater than the minimum and less than or equal to the maximum yet geospatially equal to the original. private func normalizeCoordinate(value: Double, shift: Double) -> Double { @@ -201,13 +135,11 @@ extension GeodesicCalculator { extension GeodesicCalculator { // The default distance formula - public func distance(from point: GeodesicPoint, to otherPoint: GeodesicPoint, tolerance: Double) -> Double { - return max(haversineDistance(from: point, to: otherPoint) - tolerance, 0.0) - } + public func distance(from point: GeodesicPoint, to otherPoint: GeodesicPoint, tolerance: Double) -> Double { max(haversineDistance(from: point, to: otherPoint) - tolerance, 0.0) } public func distance(from point: GeodesicPoint, to lineSegment: GeodesicLineSegment, tolerance: Double) -> Double { let distance1 = distancePartialResult(from: point, to: lineSegment) - let reverseSegment = LineSegment(point: lineSegment.otherPoint, otherPoint: lineSegment.point) + let reverseSegment = GeodesicLineSegment(point: lineSegment.otherPoint, otherPoint: lineSegment.point) let distance2 = distancePartialResult(from: point, to: reverseSegment) return max(min(distance1, distance2) - tolerance, 0.0) @@ -244,9 +176,7 @@ extension GeodesicCalculator { return edgeDistance(from: point, to: polygon, tolerance: tolerance) } - public func edgeDistance(from point: GeodesicPoint, to polygon: GeodesicPolygon, tolerance: Double) -> Double { - return polygon.linearRings.map { distance(from: point, to: $0, tolerance: tolerance) }.min()! - } + public func edgeDistance(from point: GeodesicPoint, to polygon: GeodesicPolygon, tolerance: Double) -> Double { polygon.linearRings.map { distance(from: point, to: $0, tolerance: tolerance) }.min()! } // Law Of Cosines is not accurate under 0.5 meters. public func lawOfCosinesDistance(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { @@ -284,6 +214,14 @@ extension GeodesicCalculator { return angularDistance * earthRadius } + // SOMEDAY: It was suggested this could be almost twice as fast - Run tests! Protect asin from NaN +// func haversineOptimized(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { +// let p = 0.017453292519943295 // Math.PI / 180 +// let a = 0.5 - (cos((otherPoint.latitude - point.latitude) * p) / 2) + (cos(point.latitude * p) * cos(otherPoint.latitude * p) * (1 - cos((otherPoint.longitude - point.longitude) * p)) / 2) +// +// return 12742 * asin(sqrt(a)) // 2 * R; R = 6371 km +// } + // SOMEDAY: It would be nice to understand this better as there seems to be too much to calling this twice but twice produces the correct result. private func distancePartialResult(from point: GeodesicPoint, to lineSegment: GeodesicLineSegment) -> Double { let earthRadius = self.earthRadius(latitudeAverage: midpoint(from: lineSegment.point, to: lineSegment.otherPoint).latitude) @@ -319,17 +257,11 @@ extension GeodesicCalculator { // MARK: Contains extension GeodesicCalculator { - public func contains(_ point: GeodesicPoint, in otherPoint: GeodesicPoint, tolerance: Double) -> Bool { - return distance(from: point, to: otherPoint, tolerance: tolerance) == 0 - } + public func contains(_ point: GeodesicPoint, in otherPoint: GeodesicPoint, tolerance: Double) -> Bool { distance(from: point, to: otherPoint, tolerance: tolerance) == 0 } - public func contains(_ point: GeodesicPoint, in lineSegment: GeodesicLineSegment, tolerance: Double) -> Bool { - return distance(from: point, to: lineSegment, tolerance: tolerance) == 0 - } + public func contains(_ point: GeodesicPoint, in lineSegment: GeodesicLineSegment, tolerance: Double) -> Bool { distance(from: point, to: lineSegment, tolerance: tolerance) == 0 } - public func contains(_ point: GeodesicPoint, in line: GeodesicLine, tolerance: Double) -> Bool { - return distance(from: point, to: line, tolerance: tolerance) == 0 - } + public func contains(_ point: GeodesicPoint, in line: GeodesicLine, tolerance: Double) -> Bool { distance(from: point, to: line, tolerance: tolerance) == 0 } public func contains(_ point: GeodesicPoint, in polygon: GeodesicPolygon, tolerance: Double) -> Bool { // Must at least be within the bounding box. @@ -340,9 +272,7 @@ extension GeodesicCalculator { let mainRingContains = contains(point: point, vertices: polygon.mainRing.points) // Skip running hole contains calculations if mainRingContains is false - let holeContains: () -> (Bool) = { - return polygon.negativeRings.map { $0.points }.first { self.contains(point: point, vertices: $0) } != nil - } + let holeContains: () -> (Bool) = { polygon.negativeRings.map { $0.points }.first { self.contains(point: point, vertices: $0) } != nil } let baseContains = mainRingContains && !holeContains() @@ -387,9 +317,7 @@ extension GeodesicCalculator { } } - public func hasIntersection(_ lineSegment: GeodesicLineSegment, with otherLineSegment: GeodesicLineSegment, tolerance: Double) -> Bool { - return distance(from: lineSegment, to: otherLineSegment, tolerance: tolerance) == 0 - } + public func hasIntersection(_ lineSegment: GeodesicLineSegment, with otherLineSegment: GeodesicLineSegment, tolerance: Double) -> Bool { distance(from: lineSegment, to: otherLineSegment, tolerance: tolerance) == 0 } // SOMEDAY: Consider holes public func hasIntersection(_ lineSegment: GeodesicLineSegment, with polygon: GeodesicPolygon, tolerance: Double) -> Bool { @@ -406,18 +334,14 @@ extension GeodesicCalculator { guard currentLineIndex < nextLineIndex else { return false } // If next line continues from previous ensure no overlapping - if currentLineIndex == nextLineIndex - 1 && currentLineSegment.otherPoint == nextLineSegment.point { - return contains(nextLineSegment.otherPoint, in: currentLineSegment, tolerance: tolerance) - } + if currentLineIndex == nextLineIndex - 1 && currentLineSegment.otherPoint == nextLineSegment.point { return contains(nextLineSegment.otherPoint, in: currentLineSegment, tolerance: tolerance) } return hasIntersection(currentLineSegment, with: nextLineSegment, tolerance: tolerance) } } } - public func hasIntersection(_ polygon: GeodesicPolygon, tolerance: Double) -> Bool { - return polygon.linearRings.contains { hasIntersection($0, tolerance: tolerance) } - } + public func hasIntersection(_ polygon: GeodesicPolygon, tolerance: Double) -> Bool { polygon.linearRings.contains { hasIntersection($0, tolerance: tolerance) } } public func equalsIndices(_ points: [GeodesicPoint], tolerance: Double) -> [Int] { return points.enumerated().filter { currentIndex, currentPoint in @@ -436,9 +360,7 @@ extension GeodesicCalculator { guard currentLineIndex < nextLineIndex else { return false } // If next line continues from previous ensure no overlapping - if currentLineIndex == nextLineIndex - 1 && currentLineSegment.otherPoint == nextLineSegment.point { - return contains(nextLineSegment.otherPoint, in: currentLineSegment, tolerance: tolerance) - } + if currentLineIndex == nextLineIndex - 1 && currentLineSegment.otherPoint == nextLineSegment.point { return contains(nextLineSegment.otherPoint, in: currentLineSegment, tolerance: tolerance) } return hasIntersection(currentLineSegment, with: nextLineSegment, tolerance: tolerance) } @@ -471,17 +393,12 @@ extension GeodesicCalculator { let numerator1 = (longitudeDeltaSegment2 * latitudeSegmentsOffset) - (latitudeDeltaSegment2 * longitudeSegmentsOffset) let numerator2 = (longitudeDeltaSegment1 * latitudeSegmentsOffset) - (latitudeDeltaSegment1 * longitudeSegmentsOffset) - guard denominator != 0 && (numerator1 != 0 || numerator2 != 0) else { - Log.debug("denominator: \(denominator), numerator1: \(numerator1), numerator2: \(numerator2)") - return nil - } + guard denominator != 0 && (numerator1 != 0 || numerator2 != 0) else { return nil } let result1 = numerator1 / denominator let result2 = numerator2 / denominator - guard case 0...1 = result1, case 0...1 = result2 else { - return nil - } + guard case 0...1 = result1, case 0...1 = result2 else { return nil } let resultLongitude = lineSegment.point.longitude + (result1 * longitudeDeltaSegment1) let resultLatitude = lineSegment.point.latitude + (result1 * latitudeDeltaSegment1) diff --git a/Sources/GeospatialSwift/API/GeoJson/GeoJson.swift b/Sources/GeospatialSwift/API/GeoJson/GeoJson.swift index 8525366..a86e6b7 100644 --- a/Sources/GeospatialSwift/API/GeoJson/GeoJson.swift +++ b/Sources/GeospatialSwift/API/GeoJson/GeoJson.swift @@ -1,22 +1,8 @@ -public protocol GeoJsonProtocol { - func parse(geoJson: GeoJsonDictionary) -> GeoJsonObject? - - // GeoJsonObject Factory methods - func featureCollection(features: [GeoJsonFeature]) -> GeoJsonFeatureCollection? - func feature(geometry: GeoJsonGeometry?, id: Any?, properties: GeoJsonDictionary?) -> GeoJsonFeature? - func geometryCollection(geometries: [GeoJsonGeometry]?) -> GeoJsonGeometryCollection - func multiPolygon(polygons: [GeoJsonPolygon]) -> GeoJsonMultiPolygon? - func polygon(linearRings: [GeoJsonLineString]) -> GeoJsonPolygon? - func multiLineString(lineStrings: [GeoJsonLineString]) -> GeoJsonMultiLineString? - func lineString(points: [GeoJsonPoint]) -> GeoJsonLineString? - func multiPoint(points: [GeoJsonPoint]) -> GeoJsonMultiPoint? - func point(longitude: Double, latitude: Double, altitude: Double?) -> GeoJsonPoint - func point(longitude: Double, latitude: Double) -> GeoJsonPoint -} - -public struct GeoJson: GeoJsonProtocol { +public struct GeoJson { internal static let parser = GeoJsonParser() + internal static func coordinates(geoJson: GeoJsonDictionary) -> [Any]? { geoJson["coordinates"] as? [Any] } + /** Parses a GeoJsonDictionary into a GeoJsonObject. @@ -24,7 +10,17 @@ public struct GeoJson: GeoJsonProtocol { - returns: A successfully parsed GeoJsonObject or nil if the specification was not correct */ - public func parse(geoJson: GeoJsonDictionary) -> GeoJsonObject? { - return GeoJson.parser.geoJsonObject(from: geoJson) - } + public func parseObject(fromGeoJson geoJson: GeoJsonDictionary) -> Result { GeoJson.parser.geoJsonObject(fromGeoJson: geoJson) } + public func parseCoordinatesGeometry(fromGeoJson geoJson: GeoJsonDictionary) -> Result { GeoJson.parser.geoJsonCoordinatesGeometry(fromGeoJson: geoJson) } + + /** + Parses a validated GeoJsonDictionary into a GeoJsonObject. + Assumes validated GeoJson for performance and will crash if invalid! + + - geoJson: An JSON dictionary conforming to the GeoJson current spcification. + + - returns: A GeoJsonObject or nil if the specification was not correct + */ + public func parseObject(fromValidatedGeoJson geoJson: GeoJsonDictionary) -> GeoJsonObject { GeoJson.parser.geoJsonObject(fromValidatedGeoJson: geoJson) } + public func parseCoordinatesGeometry(fromValidatedGeoJson geoJson: GeoJsonDictionary) -> GeoJsonCoordinatesGeometry { GeoJson.parser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) } } diff --git a/Sources/GeospatialSwift/API/GeoJson/GeodesicBearing.swift b/Sources/GeospatialSwift/API/GeoJson/GeodesicBearing.swift new file mode 100644 index 0000000..9e65cce --- /dev/null +++ b/Sources/GeospatialSwift/API/GeoJson/GeodesicBearing.swift @@ -0,0 +1,4 @@ +public struct GeodesicBearing { + public let bearing: Double + public let back: Double +} diff --git a/Sources/GeospatialSwift/API/GeoJson/GeodesicBoundingBox.swift b/Sources/GeospatialSwift/API/GeoJson/GeodesicBoundingBox.swift index 760d92b..79aad3f 100644 --- a/Sources/GeospatialSwift/API/GeoJson/GeodesicBoundingBox.swift +++ b/Sources/GeospatialSwift/API/GeoJson/GeodesicBoundingBox.swift @@ -1,109 +1,60 @@ -// SOMEDAY: The concept of minimums and maximums is not right. Crossing the Antimeridian will do odd things. Fix all things BoundingCoordinates and BoundingBox. - -public typealias BoundingCoordinates = (minLongitude: Double, minLatitude: Double, maxLongitude: Double, maxLatitude: Double) - -public protocol GeodesicBoundingBox: CustomStringConvertible { - var minLongitude: Double { get } - var minLatitude: Double { get } - var maxLongitude: Double { get } - var maxLatitude: Double { get } - - var longitudeDelta: Double { get } - var latitudeDelta: Double { get } - - var points: [GeodesicPoint] { get } - var centroid: GeodesicPoint { get } - var boundingCoordinates: BoundingCoordinates { get } - var segments: [GeodesicLineSegment] { get } - var box: GeodesicPolygon { get } - - func best(_ boundingBoxes: [GeodesicBoundingBox]) -> GeodesicBoundingBox - func validBoundingBox(minimumAdjustment: Double) -> GeodesicBoundingBox - func insetBoundingBox(topPercent: Double, leftPercent: Double, bottomPercent: Double, rightPercent: Double) -> GeodesicBoundingBox - func contains(point: GeodesicPoint, tolerance: Double) -> Bool - func overlaps(boundingBox: GeodesicBoundingBox, tolerance: Double) -> Bool -} - -extension GeodesicBoundingBox { - public func insetBoundingBox(percent: Double) -> GeodesicBoundingBox { - return insetBoundingBox(widthPercent: percent, heightPercent: percent) - } - - public func insetBoundingBox(widthPercent: Double, heightPercent: Double) -> GeodesicBoundingBox { - return insetBoundingBox(topPercent: heightPercent, leftPercent: widthPercent, bottomPercent: heightPercent, rightPercent: widthPercent) - } -} +// TODO: "The concept of minimums and maximums is not right. Crossing the Antimeridian will do odd things. Fix all things BoundingCoordinates and BoundingBox. /** A bounding box intended to exactly fit a GeoJsonObject. Also known as a "Minimum Bounding Box", "Bounding Envelope". */ -public class BoundingBox: GeodesicBoundingBox { - public var description: String { - return "BoundingBox: (\n\tminLongitude: \(minLongitude),\n\tminLatitude: \(minLatitude),\n\tmaxLongitude: \(maxLongitude),\n\tmaxLatitude: \(maxLatitude),\n\tcentroid: \(centroid)\n)" - } - - public let points: [GeodesicPoint] +public struct GeodesicBoundingBox { + public var points: [GeodesicPoint] { [SimplePoint(longitude: minLongitude, latitude: minLatitude), SimplePoint(longitude: minLongitude, latitude: maxLatitude), SimplePoint(longitude: maxLongitude, latitude: maxLatitude), SimplePoint(longitude: maxLongitude, latitude: minLatitude)] } - public let centroid: GeodesicPoint - - public var boundingCoordinates: BoundingCoordinates { return (minLongitude: minLongitude, minLatitude: minLatitude, maxLongitude: maxLongitude, maxLatitude: maxLatitude) } + public var centroid: GeodesicPoint { SimplePoint(longitude: maxLongitude - (longitudeDelta / 2), latitude: maxLatitude - (latitudeDelta / 2)) } public let minLongitude: Double public let minLatitude: Double public let maxLongitude: Double public let maxLatitude: Double - public let longitudeDelta: Double - public let latitudeDelta: Double + public var longitudeDelta: Double { maxLongitude - minLongitude } + public var latitudeDelta: Double { maxLatitude - minLatitude } - public var segments: [GeodesicLineSegment] { - return [LineSegment(point: points[0], otherPoint: points[1]), LineSegment(point: points[1], otherPoint: points[2]), LineSegment(point: points[2], otherPoint: points[3]), LineSegment(point: points[3], otherPoint: points[0])] - } + public var segments: [GeodesicLineSegment] { [.init(point: points[0], otherPoint: points[1]), .init(point: points[1], otherPoint: points[2]), .init(point: points[2], otherPoint: points[3]), .init(point: points[3], otherPoint: points[0])] } - public var box: GeodesicPolygon { return SimplePolygon(mainRing: SimpleLine(segments: segments)!)! } + public var box: GeodesicPolygon { SimplePolygon(mainRing: SimpleLine(segments: segments)!)! } - public init(boundingCoordinates: BoundingCoordinates) { - minLongitude = boundingCoordinates.minLongitude - minLatitude = boundingCoordinates.minLatitude - maxLongitude = boundingCoordinates.maxLongitude - maxLatitude = boundingCoordinates.maxLatitude - - points = [SimplePoint(longitude: minLongitude, latitude: minLatitude), SimplePoint(longitude: minLongitude, latitude: maxLatitude), SimplePoint(longitude: maxLongitude, latitude: maxLatitude), SimplePoint(longitude: maxLongitude, latitude: minLatitude)] - - longitudeDelta = maxLongitude - minLongitude - latitudeDelta = maxLatitude - minLatitude - - centroid = SimplePoint(longitude: maxLongitude - (longitudeDelta / 2), latitude: maxLatitude - (latitudeDelta / 2)) + public init(minLongitude: Double, minLatitude: Double, maxLongitude: Double, maxLatitude: Double) { + self.minLongitude = minLongitude + self.minLatitude = minLatitude + self.maxLongitude = maxLongitude + self.maxLatitude = maxLatitude } + public func contains(point: GeodesicPoint) -> Bool { contains(point: point, tolerance: 0) } public func contains(point: GeodesicPoint, tolerance: Double) -> Bool { - // SOMEDAY: Lose this logic? -// let minPoint = points[0] -// let maxPoint = points[2] -// let maxLatitude = tolerance != 0 ? Calculator.destinationPoint(origin: maxPoint, bearing: 0, distance: tolerance).latitude : maxPoint.latitude -// let maxLongitude = tolerance != 0 ? Calculator.destinationPoint(origin: maxPoint, bearing: 90, distance: tolerance).longitude : maxPoint.longitude -// let minLatitude = tolerance != 0 ? Calculator.destinationPoint(origin: minPoint, bearing: 180, distance: tolerance).latitude : minPoint.latitude -// let minLongitude = tolerance != 0 ? Calculator.destinationPoint(origin: minPoint, bearing: 270, distance: tolerance).longitude : minPoint.longitude -// -// guard maxLatitude >= minLatitude && maxLongitude >= minLongitude else { return false } -// -// return point.latitude >= minLatitude && -// point.latitude <= maxLatitude && -// point.longitude >= minLongitude && -// point.longitude <= maxLongitude + guard tolerance != 0 else { + return point.latitude >= minLatitude && + point.latitude <= maxLatitude && + point.longitude >= minLongitude && + point.longitude <= maxLongitude + } + return Calculator.contains(point, in: box, tolerance: tolerance) } + public func overlaps(boundingBox: GeodesicBoundingBox) -> Bool { overlaps(boundingBox: boundingBox, tolerance: 0) } public func overlaps(boundingBox: GeodesicBoundingBox, tolerance: Double) -> Bool { - return points.contains { boundingBox.contains(point: $0, tolerance: tolerance) } || boundingBox.points.contains { contains(point: $0, tolerance: tolerance) } + guard tolerance != 0 else { + return minLongitude <= boundingBox.maxLongitude && boundingBox.minLongitude <= maxLongitude && minLatitude <= boundingBox.maxLatitude && boundingBox.minLatitude <= maxLatitude + } + + return minLongitude + tolerance <= boundingBox.maxLongitude && + boundingBox.minLongitude + tolerance <= maxLongitude && + minLatitude + tolerance <= boundingBox.maxLatitude && + boundingBox.minLatitude + tolerance <= maxLatitude } // SOMEDAY: This should follow the rule "5.2. The Antimeridian" in the GeoJson spec. public func best(_ boundingBoxes: [GeodesicBoundingBox]) -> GeodesicBoundingBox { return boundingBoxes.reduce(self) { - let boundingCoordinates = (minLongitude: min($0.minLongitude, $1.minLongitude), minLatitude: min($0.minLatitude, $1.minLatitude), maxLongitude: max($0.maxLongitude, $1.maxLongitude), maxLatitude: max($0.maxLatitude, $1.maxLatitude)) - - return BoundingBox(boundingCoordinates: boundingCoordinates) + return GeodesicBoundingBox(minLongitude: min($0.minLongitude, $1.minLongitude), minLatitude: min($0.minLatitude, $1.minLatitude), maxLongitude: max($0.maxLongitude, $1.maxLongitude), maxLatitude: max($0.maxLatitude, $1.maxLatitude)) } } @@ -111,19 +62,18 @@ public class BoundingBox: GeodesicBoundingBox { let longitudeAdjustment = minLongitude == maxLongitude ? minimumAdjustment : 0 let latitudeAdjustment = minLatitude == maxLatitude ? minimumAdjustment : 0 - let boundingCoordinates = (minLongitude: minLongitude - longitudeAdjustment, minLatitude: minLatitude - latitudeAdjustment, maxLongitude: maxLongitude + longitudeAdjustment, maxLatitude: maxLatitude + latitudeAdjustment) - - return BoundingBox(boundingCoordinates: boundingCoordinates) + return GeodesicBoundingBox(minLongitude: minLongitude - longitudeAdjustment, minLatitude: minLatitude - latitudeAdjustment, maxLongitude: maxLongitude + longitudeAdjustment, maxLatitude: maxLatitude + latitudeAdjustment) } public func insetBoundingBox(topPercent: Double, leftPercent: Double, bottomPercent: Double, rightPercent: Double) -> GeodesicBoundingBox { - let boundingCoordinates = (minLongitude: minLongitude - (longitudeDelta * leftPercent), minLatitude: minLatitude - (longitudeDelta * bottomPercent), maxLongitude: maxLongitude + (longitudeDelta * rightPercent), maxLatitude: maxLatitude + (longitudeDelta * topPercent)) - - return BoundingBox(boundingCoordinates: boundingCoordinates) + return GeodesicBoundingBox(minLongitude: minLongitude - (longitudeDelta * leftPercent), minLatitude: minLatitude - (longitudeDelta * bottomPercent), maxLongitude: maxLongitude + (longitudeDelta * rightPercent), maxLatitude: maxLatitude + (longitudeDelta * topPercent)) } + public func insetBoundingBox(percent: Double) -> GeodesicBoundingBox { insetBoundingBox(widthPercent: percent, heightPercent: percent) } + public func insetBoundingBox(widthPercent: Double, heightPercent: Double) -> GeodesicBoundingBox { insetBoundingBox(topPercent: heightPercent, leftPercent: widthPercent, bottomPercent: heightPercent, rightPercent: widthPercent) } + } -public extension BoundingBox { +public extension GeodesicBoundingBox { static func best(_ boundingBoxes: [GeodesicBoundingBox]) -> GeodesicBoundingBox? { guard let firstBoundingBox = boundingBoxes.first else { return nil } diff --git a/Sources/GeospatialSwift/API/GeoJson/GeodesicLine.swift b/Sources/GeospatialSwift/API/GeoJson/GeodesicLine.swift index 316ef0f..fea53c4 100644 --- a/Sources/GeospatialSwift/API/GeoJson/GeodesicLine.swift +++ b/Sources/GeospatialSwift/API/GeoJson/GeodesicLine.swift @@ -7,22 +7,21 @@ public protocol GeodesicLine { public struct SimpleLine: GeodesicLine { public let points: [GeodesicPoint] - public let segments: [GeodesicLineSegment] - public var boundingBox: GeodesicBoundingBox { - return BoundingBox.best(points.map { BoundingBox(boundingCoordinates: (minLongitude: $0.longitude, minLatitude: $0.latitude, maxLongitude: $0.longitude, maxLatitude: $0.latitude)) })! + public var segments: [GeodesicLineSegment] { + points.enumerated().compactMap { (offset, point) in + if points.count == offset + 1 { return nil } + + return .init(point: point, otherPoint: points[offset + 1]) + } } + public var boundingBox: GeodesicBoundingBox { .best(points.map { .init(minLongitude: $0.longitude, minLatitude: $0.latitude, maxLongitude: $0.longitude, maxLatitude: $0.latitude) })! } + public init?(points: [GeodesicPoint]) { guard points.count >= 2 else { return nil } self.points = points - - segments = points.enumerated().compactMap { (offset, point) in - if points.count == offset + 1 { return nil } - - return LineSegment(point: point, otherPoint: points[offset + 1]) - } } init?(segments: [GeodesicLineSegment]) { @@ -33,6 +32,13 @@ public struct SimpleLine: GeodesicLine { } self.points = segments.map { $0.point } + [segments.last!.otherPoint] - self.segments = segments } } + +public func == (lhs: GeodesicLine, rhs: GeodesicLine) -> Bool { + guard lhs.points.count == rhs.points.count else { return false } + + for (index, point) in lhs.points.enumerated() where !(rhs.points[index] == point) { return false } + + return true +} diff --git a/Sources/GeospatialSwift/API/GeoJson/GeodesicLineSegment.swift b/Sources/GeospatialSwift/API/GeoJson/GeodesicLineSegment.swift index f5be12f..da5c699 100644 --- a/Sources/GeospatialSwift/API/GeoJson/GeodesicLineSegment.swift +++ b/Sources/GeospatialSwift/API/GeoJson/GeodesicLineSegment.swift @@ -1,35 +1,25 @@ -public protocol GeodesicLineSegment { - var point: GeodesicPoint { get } - var otherPoint: GeodesicPoint { get } - - var midpoint: GeodesicPoint { get } - var initialBearing: (bearing: Double, back: Double) { get } - var averageBearing: (bearing: Double, back: Double) { get } - var finalBearing: (bearing: Double, back: Double) { get } -} - -internal struct LineSegment: GeodesicLineSegment { +public struct GeodesicLineSegment { public let point: GeodesicPoint public let otherPoint: GeodesicPoint - public var midpoint: GeodesicPoint { return Calculator.midpoint(from: point, to: otherPoint) } + public var midpoint: GeodesicPoint { Calculator.midpoint(from: point, to: otherPoint) } - public var initialBearing: (bearing: Double, back: Double) { + public var initialBearing: GeodesicBearing { let bearing = Calculator.initialBearing(from: point, to: otherPoint) let back = bearing > 180 ? bearing - 180 : bearing + 180 - return (bearing, back) + return .init(bearing: bearing, back: back) } - public var averageBearing: (bearing: Double, back: Double) { + public var averageBearing: GeodesicBearing { let bearing = Calculator.averageBearing(from: point, to: otherPoint) let back = bearing > 180 ? bearing - 180 : bearing + 180 - return (bearing, back) + return .init(bearing: bearing, back: back) } - public var finalBearing: (bearing: Double, back: Double) { + public var finalBearing: GeodesicBearing { let bearing = Calculator.finalBearing(from: point, to: otherPoint) let back = bearing > 180 ? bearing - 180 : bearing + 180 - return (bearing, back) + return .init(bearing: bearing, back: back) } } diff --git a/Sources/GeospatialSwift/API/GeoJson/GeodesicPoint.swift b/Sources/GeospatialSwift/API/GeoJson/GeodesicPoint.swift index 534b7fa..9c3b2b3 100644 --- a/Sources/GeospatialSwift/API/GeoJson/GeodesicPoint.swift +++ b/Sources/GeospatialSwift/API/GeoJson/GeodesicPoint.swift @@ -1,9 +1,14 @@ -public protocol GeodesicPoint: CustomStringConvertible { +public protocol GeodesicPoint { var longitude: Double { get } var latitude: Double { get } var altitude: Double? { get } } +public extension GeodesicPoint { + var degreesToRadians: GeodesicPoint { SimplePoint(longitude: longitude.degreesToRadians, latitude: latitude.degreesToRadians, altitude: altitude) } + var radiansToDegrees: GeodesicPoint { SimplePoint(longitude: longitude.radiansToDegrees, latitude: latitude.radiansToDegrees, altitude: altitude) } +} + public struct SimplePoint: GeodesicPoint { public let longitude: Double public let latitude: Double @@ -14,13 +19,6 @@ public struct SimplePoint: GeodesicPoint { self.latitude = latitude self.altitude = altitude } - - public var description: String { return "SimplePoint: (longitude: \(longitude), latitude: \(latitude)\(altitude != nil ? ", altitude: \(altitude!.description)" : ""))" } -} - -public extension GeodesicPoint { - var degreesToRadians: GeodesicPoint { return SimplePoint(longitude: longitude.degreesToRadians, latitude: latitude.degreesToRadians, altitude: altitude) } - var radiansToDegrees: GeodesicPoint { return SimplePoint(longitude: longitude.radiansToDegrees, latitude: latitude.radiansToDegrees, altitude: altitude) } } public func == (lhs: GeodesicPoint, rhs: GeodesicPoint) -> Bool { diff --git a/Sources/GeospatialSwift/API/GeoJson/GeodesicPolygon.swift b/Sources/GeospatialSwift/API/GeoJson/GeodesicPolygon.swift index c3bdaa9..550adbe 100644 --- a/Sources/GeospatialSwift/API/GeoJson/GeodesicPolygon.swift +++ b/Sources/GeospatialSwift/API/GeoJson/GeodesicPolygon.swift @@ -1,21 +1,23 @@ -public protocol GeodesicPolygon: CustomStringConvertible { +public protocol GeodesicPolygon { var points: [GeodesicPoint] { get } var mainRing: GeodesicLine { get } var negativeRings: [GeodesicLine] { get } var linearRings: [GeodesicLine] { get } var boundingBox: GeodesicBoundingBox { get } + + var centroid: GeodesicPoint { get } } public struct SimplePolygon: GeodesicPolygon { - public var points: [GeodesicPoint] { return linearRings.flatMap { $0.points } } - public var linearRings: [GeodesicLine] { return [mainRing] + negativeRings } + public var points: [GeodesicPoint] { linearRings.flatMap { $0.points } } + public var linearRings: [GeodesicLine] { [mainRing] + negativeRings } public let mainRing: GeodesicLine public let negativeRings: [GeodesicLine] - public var boundingBox: GeodesicBoundingBox { - return BoundingBox.best(linearRings.map { $0.boundingBox })! - } + public var boundingBox: GeodesicBoundingBox { .best(linearRings.map { $0.boundingBox })! } + + public var centroid: GeodesicPoint { Calculator.centroid(polygon: self) } public init?(mainRing: GeodesicLine, negativeRings: [GeodesicLine] = []) { for linearRingSegments in ([mainRing.segments] + negativeRings.map { $0.segments }) { @@ -27,6 +29,14 @@ public struct SimplePolygon: GeodesicPolygon { self.mainRing = mainRing self.negativeRings = negativeRings } +} + +public func == (lhs: GeodesicPolygon, rhs: GeodesicPolygon) -> Bool { + guard lhs.negativeRings.count == rhs.negativeRings.count else { return false } + + guard lhs.mainRing == rhs.mainRing else { return false } + + for linearRing in lhs.negativeRings where !(rhs.negativeRings).contains { $0 == linearRing } { return false } - public var description: String { return "SimplePolygon: MainRing: (\(mainRing.segments.map { $0.point })" } + return true } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Feature.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Feature.swift index d65b84e..4b4ec9a 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Feature.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Feature.swift @@ -1,82 +1,85 @@ -import Foundation - -public protocol GeoJsonFeature: GeoJsonObject { - var geometry: GeoJsonGeometry? { get } - var id: Any? { get } - var idAsString: String? { get } - var properties: GeoJsonDictionary? { get } -} +import class Foundation.NSNull extension GeoJson { /** - Creates a GeoJsonFeature + Creates a Feature */ - public func feature(geometry: GeoJsonGeometry?, id: Any?, properties: GeoJsonDictionary?) -> GeoJsonFeature? { - return Feature(geometry: geometry, id: id, properties: properties) + public func feature(geometry: GeoJsonGeometry?, id: Any?, properties: GeoJsonDictionary?) -> Result { + guard id == nil || id is NSNull || id is String || id is Double || id is Int else { return .failure(.init(reason: "Id must be of type null, String, Double, or Int")) } + + return .success(Feature(geometry: geometry, id: id, properties: properties)) } - public struct Feature: GeoJsonFeature { + public struct Feature: GeoJsonObject { public let type: GeoJsonObjectType = .feature - public var geoJson: GeoJsonDictionary { - var geoJson: GeoJsonDictionary = ["type": type.name, "geometry": geometry?.geoJson ?? NSNull(), "properties": properties ?? NSNull()] - if let id = id { geoJson["id"] = id } - return geoJson - } - - public var id: Any? { return idString ?? idDouble ?? idInt } - public var idAsString: String? { return idString ?? idDouble?.description ?? idInt?.description } - - public var description: String { - return """ - Feature: \( - """ - (\n\(geometry != nil ? "Geometry - \(geometry!)" : "null") - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } public let geometry: GeoJsonGeometry? public let properties: GeoJsonDictionary? - public let objectGeometries: [GeoJsonGeometry]? - public let objectBoundingBox: GeodesicBoundingBox? - internal let idString: String? internal let idDouble: Double? internal let idInt: Int? - internal init?(geoJsonDictionary: GeoJsonDictionary) { - let id = geoJsonDictionary["id"] as? String ?? (geoJsonDictionary["id"] as? Double)?.description ?? (geoJsonDictionary["id"] as? Int)?.description - - let properties = geoJsonDictionary["properties"] as? GeoJsonDictionary - - if geoJsonDictionary["geometry"] is NSNull { self.init(geometry: nil, id: id, properties: properties); return } - - guard let geometryJson = geoJsonDictionary["geometry"] as? GeoJsonDictionary else { Log.warning("A valid Feature must have a \"geometry\" key: String : \(geoJsonDictionary)"); return nil } + internal init(geoJson: GeoJsonDictionary) { + let id: Any? = geoJson["id"] + let geometryJson = geoJson["geometry"] as? GeoJsonDictionary + let propertiesJson = geoJson["properties"] as? GeoJsonDictionary - guard let geometry = parser.geoJsonObject(from: geometryJson) as? GeoJsonGeometry else { Log.warning("Feature must contain a valid geometry"); return nil } - - self.init(geometry: geometry, id: id, properties: properties) + // swiftlint:disable:next force_cast + geometry = geometryJson.flatMap { parser.geoJsonGeometry(fromValidatedGeoJson: $0) } + idString = id as? String + idDouble = id as? Double + idInt = id as? Int + properties = propertiesJson } - fileprivate init?(geometry: GeoJsonGeometry?, id: Any?, properties: GeoJsonDictionary?) { - guard id == nil || id is String || id is Double || id is Int else { return nil } - + fileprivate init(geometry: GeoJsonGeometry?, id: Any?, properties: GeoJsonDictionary?) { self.geometry = geometry self.idString = id as? String self.idDouble = id as? Double self.idInt = id as? Int self.properties = properties + } + } +} + +extension GeoJson.Feature { + public var geoJson: GeoJsonDictionary { + var geoJson: GeoJsonDictionary = ["type": type.name, "geometry": geometry?.geoJson ?? NSNull(), "properties": properties ?? NSNull()] + if let id = id { geoJson["id"] = id } + return geoJson + } + + public var id: Any? { idString ?? idDouble ?? idInt } + public var idAsString: String? { idString ?? idDouble?.description ?? idInt?.description } + + public var objectGeometries: [GeoJsonGeometry] { geometry.flatMap { [$0] } ?? [] } + public var objectBoundingBox: GeodesicBoundingBox? { geometry?.objectBoundingBox } + + public func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { geometry?.objectDistance(to: point, tolerance: tolerance) } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { geometry?.contains(point, tolerance: tolerance) ?? false } +} + +extension GeoJson.Feature { + internal static func validate(geoJson: GeoJsonDictionary) -> InvalidGeoJson? { + func validateGeometry() -> InvalidGeoJson? { + guard let geometryJson = geoJson["geometry"] else { return .init(reason: "A valid Feature must have a \"geometry\" key") } - objectGeometries = geometry != nil ? [geometry!] : nil + // No geometry value is valid + if geometryJson is NSNull { return nil } - objectBoundingBox = geometry?.objectBoundingBox + guard let geometryGeoJson = geometryJson as? GeoJsonDictionary else { return .init(reason: "Not a valid feature geometry") } + + return GeoJson.parser.validateGeoJsonGeometry(geoJson: geometryGeoJson).flatMap { .init(reason: "Invalid Geometry in Feature") + $0 } } - public func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { return geometry?.objectDistance(to: point, tolerance: tolerance) } + func validateId() -> InvalidGeoJson? { + guard let id = geoJson["id"] else { return nil } + + return (id is NSNull || id is String || id is Double || id is Int) ? nil : .init(reason: "Id must be of type NSNull, String, Double, or Int") + } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { return geometry?.contains(point, tolerance: tolerance) ?? false } + return validateGeometry() + validateId() } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/FeatureCollection.swift b/Sources/GeospatialSwift/API/GeoJson/Object/FeatureCollection.swift index a21e6a0..38f6c0a 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/FeatureCollection.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/FeatureCollection.swift @@ -1,67 +1,51 @@ -public protocol GeoJsonFeatureCollection: GeoJsonObject { - var features: [GeoJsonFeature] { get } -} - extension GeoJson { /** - Creates a GeoJsonFeatureCollection + Creates a FeatureCollection */ - public func featureCollection(features: [GeoJsonFeature]) -> GeoJsonFeatureCollection? { - return FeatureCollection(features: features) + public func featureCollection(features: [Feature]) -> Result { + guard features.count >= 1 else { return .failure(.init(reason: "A valid FeatureCollection must have at least one feature")) } + + return .success(FeatureCollection(features: features)) } - public struct FeatureCollection: GeoJsonFeatureCollection { + public struct FeatureCollection: GeoJsonObject { public let type: GeoJsonObjectType = .featureCollection - public var geoJson: GeoJsonDictionary { return ["type": type.name, "features": features.map { $0.geoJson } ] } - - public var description: String { - return """ - FeatureCollection: \( - """ - (\n\(features.enumerated().map { "Line \($0) - \($1)" }.joined(separator: ",\n")) - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - - public let features: [GeoJsonFeature] - public let objectGeometries: [GeoJsonGeometry]? - public let objectBoundingBox: GeodesicBoundingBox? + public let features: [Feature] - internal init?(geoJsonDictionary: GeoJsonDictionary) { - guard let featuresJson = geoJsonDictionary["features"] as? [GeoJsonDictionary] else { Log.warning("A valid FeatureCollection must have a \"features\" key: String : \(geoJsonDictionary)"); return nil } + internal init(geoJson: GeoJsonDictionary) { + // swiftlint:disable:next force_cast + let featuresJson = geoJson["features"] as! [GeoJsonDictionary] - var features = [GeoJsonFeature]() - for featureJson in featuresJson { - if let feature = Feature(geoJsonDictionary: featureJson) { - features.append(feature) - } else { - Log.warning("Invalid Feature in FeatureCollection") - return nil - } - } - - self.init(features: features) + features = featuresJson.map { Feature(geoJson: $0) } } - fileprivate init?(features: [GeoJsonFeature]) { - guard features.count >= 1 else { Log.warning("A valid FeatureCollection must have at least one feature."); return nil } - + fileprivate init(features: [Feature]) { self.features = features - - let geometries = features.compactMap { $0.objectGeometries }.flatMap { $0 } - - self.objectGeometries = geometries.count > 0 ? geometries : nil - - objectBoundingBox = BoundingBox.best(geometries.compactMap { $0.objectBoundingBox }) } + } +} + +extension GeoJson.FeatureCollection { + public var geoJson: GeoJsonDictionary { ["type": type.name, "features": features.map { $0.geoJson } ] } + + public var objectGeometries: [GeoJsonGeometry] { features.compactMap { $0.objectGeometries }.flatMap { $0 } } + + public var objectBoundingBox: GeodesicBoundingBox? { .best(objectGeometries.compactMap { $0.objectBoundingBox }) } + + public func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { features.compactMap { $0.objectDistance(to: point, tolerance: tolerance) }.min() } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { features.first { $0.contains(point, tolerance: tolerance) } != nil } +} + +extension GeoJson.FeatureCollection { + internal static func validate(geoJson: GeoJsonDictionary) -> InvalidGeoJson? { + guard let featuresJson = geoJson["features"] as? [GeoJsonDictionary] else { return .init(reason: "A valid FeatureCollection must have a \"features\" key") } - public func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { - return features.compactMap { $0.objectDistance(to: point, tolerance: tolerance) }.min() - } + guard featuresJson.count >= 1 else { return .init(reason: "A valid FeatureCollection must have at least one feature") } + + let validateFeatures = featuresJson.reduce(nil) { $0 + GeoJson.parser.validateGeoJsonObject(geoJson: $1, validTypes: [.feature]) } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { return features.first { $0.contains(point, tolerance: tolerance) } != nil } + return validateFeatures.flatMap { .init(reason: "Invalid Feature(s) in FeatureCollection") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/GeometryCollection.swift b/Sources/GeospatialSwift/API/GeoJson/Object/GeometryCollection.swift index f272c28..5cd1e8c 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/GeometryCollection.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/GeometryCollection.swift @@ -1,54 +1,48 @@ -public protocol GeoJsonGeometryCollection: GeoJsonGeometry { } +import class Foundation.NSNull extension GeoJson { /** - Creates a GeoJsonGeometryCollection + Creates a GeometryCollection */ - public func geometryCollection(geometries: [GeoJsonGeometry]?) -> GeoJsonGeometryCollection { - return GeometryCollection(geometries: geometries) - } + public func geometryCollection(geometries: [GeoJsonGeometry]) -> GeometryCollection { GeometryCollection(geometries: geometries) } - public struct GeometryCollection: GeoJsonGeometryCollection { + public struct GeometryCollection: GeoJsonGeometry { public let type: GeoJsonObjectType = .geometryCollection - public var geoJson: GeoJsonDictionary { return ["type": type.name, "geometries": objectGeometries?.map { $0.geoJson } ?? [] ] } - - public var description: String { - return """ - GeometryCollection: \( - """ - (\n\(objectGeometries != nil ? objectGeometries!.enumerated().map { "Line \($0) - \($1)" }.joined(separator: ",\n") : "null") - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - public let objectGeometries: [GeoJsonGeometry]? - public let objectBoundingBox: GeodesicBoundingBox? + public let objectGeometries: [GeoJsonGeometry] - internal init?(geoJsonDictionary: GeoJsonDictionary) { - guard let geometriesJson = geoJsonDictionary["geometries"] as? [GeoJsonDictionary] else { Log.warning("A valid GeometryCollection must have a \"geometries\" key: String : \(geoJsonDictionary)"); return nil } - - var geometries = [GeoJsonGeometry]() - for geometryJson in geometriesJson { - guard let geometry = parser.geoJsonObject(from: geometryJson) as? GeoJsonGeometry else { Log.warning("Invalid Geometry for GeometryCollection"); return nil } - - geometries.append(geometry) - } + internal init(geoJson: GeoJsonDictionary) { + // swiftlint:disable:next force_cast + let geometriesJson = geoJson["geometries"] as! [GeoJsonDictionary] - self.init(geometries: geometries) + // swiftlint:disable:next force_cast + self.objectGeometries = geometriesJson.map { parser.geoJsonObject(fromValidatedGeoJson: $0) as! GeoJsonGeometry } } - fileprivate init(geometries: [GeoJsonGeometry]?) { + fileprivate init(geometries: [GeoJsonGeometry]) { self.objectGeometries = geometries - - objectBoundingBox = BoundingBox.best(geometries?.compactMap { $0.objectBoundingBox } ?? []) } + } +} + +extension GeoJson.GeometryCollection { + public var geoJson: GeoJsonDictionary { ["type": type.name, "geometries": objectGeometries.map { $0.geoJson } ] } + + public var objectBoundingBox: GeodesicBoundingBox? { .best(objectGeometries.compactMap { $0.objectBoundingBox }) } + + public func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { objectGeometries.compactMap { $0.objectDistance(to: point, tolerance: tolerance) }.min() } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { objectGeometries.first { $0.contains(point, tolerance: tolerance) } != nil } +} + +extension GeoJson.GeometryCollection { + internal static func validate(geoJson: GeoJsonDictionary) -> InvalidGeoJson? { + guard let geometriesGeoJson = geoJson["geometries"] as? [GeoJsonDictionary] else { return .init(reason: "A valid GeometryCollection must have a \"geometries\" key") } - public func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { - return objectGeometries?.compactMap { $0.objectDistance(to: point, tolerance: tolerance) }.min() + let validateGeometries: InvalidGeoJson? = geometriesGeoJson.reduce(nil) { result, geometryGeoJson in + return result + GeoJson.parser.validateGeoJsonGeometry(geoJson: geometryGeoJson) } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { return objectGeometries?.first { $0.contains(point, tolerance: tolerance) } != nil } + return validateGeometries.flatMap { .init(reason: "Invalid Geometry(s) in GeometryCollection") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/LineString.swift b/Sources/GeospatialSwift/API/GeoJson/Object/LineString.swift index 45c5fa3..cf39dd5 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/LineString.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/LineString.swift @@ -1,96 +1,63 @@ -public enum LineStringInvalidReason { - case duplicates(indices: [Int]) - case selfIntersects(segmentIndices: [Int]) -} - -public protocol GeoJsonLineString: GeoJsonLinearGeometry, GeodesicLine { - var geoJsonPoints: [GeoJsonPoint] { get } - - func invalidReasons(tolerance: Double) -> [LineStringInvalidReason] -} - extension GeoJson { /** - Creates a GeoJsonLineString + Creates a LineString */ - public func lineString(points: [GeoJsonPoint]) -> GeoJsonLineString? { - return LineString(points: points) + public func lineString(points: [Point]) -> Result { + guard points.count >= 2 else { return .failure(.init(reason: "A valid LineString must have at least two Points")) } + + return .success(LineString(points: points)) } - public struct LineString: GeoJsonLineString { + public struct LineString: GeoJsonLinearGeometry, GeodesicLine { public let type: GeoJsonObjectType = .lineString - public var geoJsonCoordinates: [Any] { return geoJsonPoints.map { $0.geoJsonCoordinates } } - - public var description: String { - return """ - LineString: \( - """ - (\n\(points.enumerated().map { "\($0 + 1) - \($1)" }.joined(separator: ",\n")) - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - - public let points: [GeodesicPoint] - public let geoJsonPoints: [GeoJsonPoint] - public var boundingBox: GeodesicBoundingBox { - return BoundingBox.best(geoJsonPoints.compactMap { $0.boundingBox })! - } - - public var length: Double { - return Calculator.length(of: self) - } + private let geoJsonPoints: [Point] - public let segments: [GeodesicLineSegment] - - internal init?(coordinatesJson: [Any]) { - guard let pointsJson = coordinatesJson as? [[Any]] else { Log.warning("A valid LineString must have valid coordinates"); return nil } - - var points = [GeoJsonPoint]() - for pointJson in pointsJson { - if let point = Point(coordinatesJson: pointJson) { - points.append(point) - } else { - Log.warning("Invalid Point in LineString"); return nil - } - } + internal init(coordinatesJson: [Any]) { + // swiftlint:disable:next force_cast + let pointsJson = coordinatesJson as! [[Any]] - self.init(points: points) + geoJsonPoints = pointsJson.map { Point(coordinatesJson: $0) } } - fileprivate init?(points: [GeoJsonPoint]) { - guard points.count >= 2 else { Log.warning("A valid LineString must have at least two Points"); return nil } - - self.points = points - self.geoJsonPoints = points + fileprivate init(points: [Point]) { + geoJsonPoints = points + } + } +} + +extension GeoJson.LineString { + public var points: [GeodesicPoint] { geoJsonPoints } + + public var lines: [GeodesicLine] { [self] } + + public var segments: [GeodesicLineSegment] { + points.enumerated().compactMap { (offset, point) in + if points.count == offset + 1 { return nil } - segments = points.enumerated().compactMap { (offset, point) in - if points.count == offset + 1 { return nil } - - return LineSegment(point: point, otherPoint: points[offset + 1]) - } + return .init(point: point, otherPoint: points[offset + 1]) } + } + + public var geoJsonCoordinates: [Any] { geoJsonPoints.map { $0.geoJsonCoordinates } } + + public var boundingBox: GeodesicBoundingBox { .best(geoJsonPoints.compactMap { $0.boundingBox })! } + + public var length: Double { Calculator.length(of: self) } + + public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { Calculator.distance(from: point, to: self, tolerance: tolerance) } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { Calculator.contains(point, in: self, tolerance: tolerance) } +} + +extension GeoJson.LineString { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard let pointsCoordinatesJson = coordinatesJson as? [[Any]] else { return .init(reason: "A valid LineString must have valid coordinates") } - public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { - return Calculator.distance(from: point, to: self, tolerance: tolerance) - } + guard pointsCoordinatesJson.count >= 2 else { return .init(reason: "A valid LineString must have at least two Points") } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { - return Calculator.contains(point, in: self, tolerance: tolerance) - } + let validatePoints = pointsCoordinatesJson.reduce(nil) { $0 + GeoJson.Point.validate(coordinatesJson: $1) } - public func invalidReasons(tolerance: Double) -> [LineStringInvalidReason] { - let duplicateIndices = Calculator.equalsIndices(points, tolerance: tolerance) - - guard duplicateIndices.isEmpty else { return [.duplicates(indices: duplicateIndices)] } - - let selfIntersectsIndices = Calculator.intersectionIndices(from: self, tolerance: tolerance) - - guard selfIntersectsIndices.isEmpty else { return [.selfIntersects(segmentIndices: selfIntersectsIndices)] } - - return [] - } + return validatePoints.flatMap { .init(reason: "Invalid Point(s) in LineString") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/LinearRing.swift b/Sources/GeospatialSwift/API/GeoJson/Object/LinearRing.swift new file mode 100644 index 0000000..7b652bb --- /dev/null +++ b/Sources/GeospatialSwift/API/GeoJson/Object/LinearRing.swift @@ -0,0 +1,23 @@ +extension GeoJson { + internal struct LinearRing { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard let pointsCoordinatesJson = coordinatesJson as? [[Double]] else { return .init(reason: "A valid LinearRing must have valid coordinates") } + + guard pointsCoordinatesJson.first! == pointsCoordinatesJson.last! else { return .init(reason: "A valid LinearRing must have the first and last points equal") } + + guard pointsCoordinatesJson.count >= 4 else { return .init(reason: "A valid LinearRing must have at least 4 points") } + + let validatePoints = pointsCoordinatesJson.reduce(nil) { $0 + Point.validate(coordinatesJson: $1) } + + return validatePoints.flatMap { .init(reason: "Invalid Point in LinearRing") + $0 } + } + + internal static func validate(linearRing: LineString) -> InvalidGeoJson? { + guard linearRing.points.first! == linearRing.points.last! else { return .init(reason: "A valid LinearRing must have the first and last points equal") } + + guard linearRing.points.count >= 4 else { return .init(reason: "A valid LinearRing must have at least 4 points")} + + return nil + } + } +} diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/MultiLineString.swift b/Sources/GeospatialSwift/API/GeoJson/Object/MultiLineString.swift index 03db528..226b929 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/MultiLineString.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/MultiLineString.swift @@ -1,73 +1,55 @@ -public protocol GeoJsonMultiLineString: GeoJsonLinearGeometry { - var lineStrings: [GeoJsonLineString] { get } - - func invalidReasons(tolerance: Double) -> [[LineStringInvalidReason]] -} - extension GeoJson { /** - Creates a GeoJsonMultiLineString + Creates a MultiLineString */ - public func multiLineString(lineStrings: [GeoJsonLineString]) -> GeoJsonMultiLineString? { - return MultiLineString(lineStrings: lineStrings) + public func multiLineString(lineStrings: [LineString]) -> Result { + guard lineStrings.count >= 1 else { return .failure(.init(reason: "A valid MultiLineString must have at least one LineString")) } + + return .success(MultiLineString(lineStrings: lineStrings)) } - public struct MultiLineString: GeoJsonMultiLineString { + public struct MultiLineString: GeoJsonLinearGeometry { public let type: GeoJsonObjectType = .multiLineString - public var geoJsonCoordinates: [Any] { return lineStrings.map { $0.geoJsonCoordinates } } - public var description: String { - return """ - MultiLineString: \( - """ - (\n\(lineStrings.enumerated().map { "Line \($0) - \($1)" }.joined(separator: ",\n")) - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - - public let lineStrings: [GeoJsonLineString] + private let geoJsonLineStrings: [LineString] - public var points: [GeodesicPoint] { - return lineStrings.flatMap { $0.points } - } - - public var boundingBox: GeodesicBoundingBox { - return BoundingBox.best(lineStrings.map { $0.boundingBox })! - } - - public var length: Double { - return lineStrings.reduce(0) { $0 + $1.length } - } - - internal init?(coordinatesJson: [Any]) { - guard let lineStringsJson = coordinatesJson as? [[Any]] else { Log.warning("A valid MultiLineString must have valid coordinates"); return nil } - - var lineStrings = [GeoJsonLineString]() - for lineStringJson in lineStringsJson { - if let lineString = LineString(coordinatesJson: lineStringJson) { - lineStrings.append(lineString) - } else { - Log.warning("Invalid LineString in MultiLineString"); return nil - } - } + internal init(coordinatesJson: [Any]) { + // swiftlint:disable:next force_cast + let lineStringsJson = coordinatesJson as! [[Any]] - self.init(lineStrings: lineStrings) + geoJsonLineStrings = lineStringsJson.map { LineString(coordinatesJson: $0) } } - fileprivate init?(lineStrings: [GeoJsonLineString]) { - guard lineStrings.count >= 1 else { Log.warning("A valid MultiLineString must have at least one LineString"); return nil } - - self.lineStrings = lineStrings + fileprivate init(lineStrings: [LineString]) { + geoJsonLineStrings = lineStrings } + } +} + +extension GeoJson.MultiLineString { + public var lines: [GeodesicLine] { geoJsonLineStrings } + + public var geoJsonCoordinates: [Any] { geoJsonLineStrings.map { $0.geoJsonCoordinates } } + + public var points: [GeodesicPoint] { lines.flatMap { $0.points } } + + public var boundingBox: GeodesicBoundingBox { .best(lines.map { $0.boundingBox })! } + + public var length: Double { geoJsonLineStrings.reduce(0) { $0 + $1.length } } + + public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { geoJsonLineStrings.map { $0.distance(to: point, tolerance: tolerance) }.min()! } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { geoJsonLineStrings.first { $0.contains(point, tolerance: tolerance) } != nil } +} + +extension GeoJson.MultiLineString { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard let lineStringsCoordinatesJson = coordinatesJson as? [[Any]] else { return .init(reason: "A valid MultiLineString must have valid coordinates") } - public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { return lineStrings.map { $0.distance(to: point, tolerance: tolerance) }.min()! } + guard lineStringsCoordinatesJson.count >= 1 else { return .init(reason: "A valid MultiLineString must have at least one LineString") } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { return lineStrings.first { $0.contains(point, tolerance: tolerance) } != nil } + let validateLineStrings = lineStringsCoordinatesJson.reduce(nil) { $0 + GeoJson.LineString.validate(coordinatesJson: $1) } - public func invalidReasons(tolerance: Double) -> [[LineStringInvalidReason]] { - return lineStrings.map { $0.invalidReasons(tolerance: tolerance) } - } + return validateLineStrings.flatMap { .init(reason: "Invalid LineString(s) in MultiLineString") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/MultiPoint.swift b/Sources/GeospatialSwift/API/GeoJson/Object/MultiPoint.swift index 7e3c0c1..c752ab2 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/MultiPoint.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/MultiPoint.swift @@ -1,74 +1,51 @@ -public enum MultipointInvalidReason { - case duplicates(indices: [Int]) -} - -public protocol GeoJsonMultiPoint: GeoJsonCoordinatesGeometry { - var geoJsonPoints: [GeoJsonPoint] { get } - - func invalidReasons(tolerance: Double) -> [MultipointInvalidReason] -} - extension GeoJson { /** - Creates a GeoJsonMultiPoint + Creates a MultiPoint */ - public func multiPoint(points: [GeoJsonPoint]) -> GeoJsonMultiPoint? { - return MultiPoint(points: points) + public func multiPoint(points: [Point]) -> Result { + guard points.count >= 1 else { return .failure(.init(reason: "A valid MultiPoint must have at least one Point")) } + + return .success(MultiPoint(points: points)) } - public struct MultiPoint: GeoJsonMultiPoint { - public var type: GeoJsonObjectType { return .multiPoint } - public var geoJsonCoordinates: [Any] { return geoJsonPoints.map { $0.geoJsonCoordinates } } + public struct MultiPoint: GeoJsonCoordinatesGeometry { + public let type: GeoJsonObjectType = .multiPoint - public var description: String { - return """ - MultiPoint: \( - """ - (\n\(points.enumerated().map { "\($0 + 1) - \($1)" }.joined(separator: ",\n")) - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - - public var points: [GeodesicPoint] { return geoJsonPoints } - public let geoJsonPoints: [GeoJsonPoint] - - public var boundingBox: GeodesicBoundingBox { - return BoundingBox.best(geoJsonPoints.compactMap { $0.boundingBox })! - } + private let geoJsonPoints: [Point] - internal init?(coordinatesJson: [Any]) { - guard let pointsJson = coordinatesJson as? [[Any]] else { Log.warning("A valid MultiPoint must have valid coordinates"); return nil } - - var points = [GeoJsonPoint]() - for pointJson in pointsJson { - if let point = Point(coordinatesJson: pointJson) { - points.append(point) - } else { - Log.warning("Invalid Point in MultiPoint"); return nil - } - } + internal init(coordinatesJson: [Any]) { + // swiftlint:disable:next force_cast + let pointsJson = coordinatesJson as! [[Any]] - self.init(points: points) + geoJsonPoints = pointsJson.map { Point(coordinatesJson: $0) } } - fileprivate init?(points: [GeoJsonPoint]) { - guard points.count >= 1 else { Log.warning("A valid MultiPoint must have at least one Point"); return nil } - + fileprivate init(points: [Point]) { geoJsonPoints = points } + } +} + +extension GeoJson.MultiPoint { + public var points: [GeodesicPoint] { geoJsonPoints } + + public var geoJsonCoordinates: [Any] { geoJsonPoints.map { $0.geoJsonCoordinates } } + + public var boundingBox: GeodesicBoundingBox { .best(geoJsonPoints.compactMap { $0.boundingBox })! } + + public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { geoJsonPoints.map { $0.distance(to: point, tolerance: tolerance) }.min()! } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { geoJsonPoints.first { $0.contains(point, tolerance: tolerance) } != nil } +} + +extension GeoJson.MultiPoint { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard let pointsCoordinatesJson = coordinatesJson as? [[Any]] else { return .init(reason: "A valid MultiPoint must have valid coordinates") } - public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { return geoJsonPoints.map { $0.distance(to: point, tolerance: tolerance) }.min()! } + guard pointsCoordinatesJson.count >= 1 else { return .init(reason: "A valid MultiPoint must have at least one Point") } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { return geoJsonPoints.first { $0.contains(point, tolerance: tolerance) } != nil } + let validatePoints = pointsCoordinatesJson.reduce(nil) { $0 + GeoJson.Point.validate(coordinatesJson: $1) } - public func invalidReasons(tolerance: Double) -> [MultipointInvalidReason] { - let duplicateIndices = Calculator.equalsIndices(points, tolerance: tolerance) - - guard duplicateIndices.isEmpty else { return [.duplicates(indices: duplicateIndices)] } - - return [] - } + return validatePoints.flatMap { .init(reason: "Invalid Point(s) in MultiPoint") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/MultiPolygon.swift b/Sources/GeospatialSwift/API/GeoJson/Object/MultiPolygon.swift index fb8e7df..13f8441 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/MultiPolygon.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/MultiPolygon.swift @@ -1,75 +1,61 @@ -public protocol GeoJsonMultiPolygon: GeoJsonClosedGeometry { - var polygons: [GeoJsonPolygon] { get } - - func invalidReasons(tolerance: Double) -> [[PolygonInvalidReason]] -} - extension GeoJson { /** - Creates a GeoJsonMultiPolygon + Creates a MultiPolygon */ - public func multiPolygon(polygons: [GeoJsonPolygon]) -> GeoJsonMultiPolygon? { - return MultiPolygon(polygons: polygons) + public func multiPolygon(polygons: [Polygon]) -> Result { + guard polygons.count >= 1 else { return .failure(.init(reason: "A valid MultiPolygon must have at least one Polygon")) } + + return .success(MultiPolygon(polygons: polygons)) } - public struct MultiPolygon: GeoJsonMultiPolygon { + public struct MultiPolygon: GeoJsonClosedGeometry { public let type: GeoJsonObjectType = .multiPolygon - public var geoJsonCoordinates: [Any] { return polygons.map { $0.geoJsonCoordinates } } - - public var description: String { - return """ - MultiPolygon: \( - """ - (\n\(polygons.enumerated().map { "Line \($0) - \($1)" }.joined(separator: ",\n")) - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - - public let polygons: [GeoJsonPolygon] - public var points: [GeodesicPoint] { return polygons.flatMap { $0.points } } + public let geoJsonPolygons: [Polygon] - public var boundingBox: GeodesicBoundingBox { return BoundingBox.best(polygons.map { $0.boundingBox })! } - - public var hasHole: Bool { return polygons.contains { $0.hasHole } } - - public var area: Double { return polygons.reduce(0) { $0 + $1.area } } - - internal init?(coordinatesJson: [Any]) { - guard let multiPolygonJson = coordinatesJson as? [[Any]] else { Log.warning("A valid MultiPolygon must have valid coordinates"); return nil } - - var polygons = [GeoJsonPolygon]() - for polygonJson in multiPolygonJson { - if let polygon = Polygon(coordinatesJson: polygonJson) { - polygons.append(polygon) - } else { - Log.warning("Invalid Polygon in MultiPolygon"); return nil - } - } + internal init(coordinatesJson: [Any]) { + // swiftlint:disable:next force_cast + let multiPolygonJson = coordinatesJson as! [[Any]] - self.init(polygons: polygons) + geoJsonPolygons = multiPolygonJson.map { Polygon(coordinatesJson: $0) } } // SOMEDAY: More strict additions: // Multipolygon where two polygons intersect - validate that two polygons are merged as well - fileprivate init?(polygons: [GeoJsonPolygon]) { - guard polygons.count >= 1 else { Log.warning("A valid MultiPolygon must have at least one Polygon"); return nil } - - self.polygons = polygons - } - - public func edgeDistance(to point: GeodesicPoint, tolerance: Double) -> Double { - return polygons.map { $0.edgeDistance(to: point, tolerance: tolerance) }.min()! + fileprivate init(polygons: [Polygon]) { + geoJsonPolygons = polygons } + } +} + +extension GeoJson.MultiPolygon { + public var polygons: [GeodesicPolygon] { geoJsonPolygons } + + public var geoJsonCoordinates: [Any] { geoJsonPolygons.map { $0.geoJsonCoordinates } } + + public var points: [GeodesicPoint] { polygons.flatMap { $0.points } } + + public var boundingBox: GeodesicBoundingBox { .best(polygons.map { $0.boundingBox })! } + + public var hasHole: Bool { geoJsonPolygons.contains { $0.hasHole } } + + public var area: Double { geoJsonPolygons.reduce(0) { $0 + $1.area } } + + public func edgeDistance(to point: GeodesicPoint, tolerance: Double) -> Double { geoJsonPolygons.map { $0.edgeDistance(to: point, tolerance: tolerance) }.min()! } + + public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { geoJsonPolygons.map { $0.distance(to: point, tolerance: tolerance) }.min()! } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { geoJsonPolygons.first { $0.contains(point, tolerance: tolerance) } != nil } +} + +extension GeoJson.MultiPolygon { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard let multiPolygonCoordinatesJson = coordinatesJson as? [[Any]] else { return .init(reason: "A valid MultiPolygon must have valid coordinates") } - public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { return polygons.map { $0.distance(to: point, tolerance: tolerance) }.min()! } + guard multiPolygonCoordinatesJson.count >= 1 else { return .init(reason: "A valid FeatureCollection must have at least one feature") } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { return polygons.first { $0.contains(point, tolerance: tolerance) } != nil } + let validatePolygons = multiPolygonCoordinatesJson.reduce(nil) { $0 + GeoJson.Polygon.validate(coordinatesJson: $1) } - public func invalidReasons(tolerance: Double) -> [[PolygonInvalidReason]] { - return polygons.map { $0.invalidReasons(tolerance: tolerance) } - } + return validatePolygons.flatMap { .init(reason: "Invalid Polygon(s) in MultiPolygon") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Point.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Point.swift index 237164a..aa8b912 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Point.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Point.swift @@ -1,36 +1,18 @@ -import Foundation - -public protocol GeoJsonPoint: GeodesicPoint, GeoJsonCoordinatesGeometry { - var normalize: GeodesicPoint { get } - var normalizePostitive: GeodesicPoint { get } -} +import class Foundation.NSNumber extension GeoJson { /** - Creates a GeoJsonPoint without altitiude + Creates a Point without altitiude */ - public func point(longitude: Double, latitude: Double) -> GeoJsonPoint { - return Point(longitude: longitude, latitude: latitude) - } + public func point(longitude: Double, latitude: Double) -> Point { Point(longitude: longitude, latitude: latitude) } /** - Creates a GeoJsonPoint + Creates a Point */ - public func point(longitude: Double, latitude: Double, altitude: Double?) -> GeoJsonPoint { - return Point(longitude: longitude, latitude: latitude, altitude: altitude) - } + public func point(longitude: Double, latitude: Double, altitude: Double?) -> Point { Point(longitude: longitude, latitude: latitude, altitude: altitude) } - public struct Point: GeoJsonPoint { - public var type: GeoJsonObjectType { return .point } - - public var geoJsonCoordinates: [Any] { return altitude != nil ? [longitude, latitude, altitude!] : [longitude, latitude] } - - public var normalize: GeodesicPoint { return Calculator.normalize(self) } - public var normalizePostitive: GeodesicPoint { return Calculator.normalizePositive(self) } - - public var description: String { return "Point: (longitude: \(longitude), latitude: \(latitude)\(altitude != nil ? ", altitude: \(altitude!.description)" : ""))" } - - public var points: [GeodesicPoint] { return [self] } + public struct Point: GeodesicPoint, GeoJsonCoordinatesGeometry { + public let type: GeoJsonObjectType = .point public let longitude: Double public let latitude: Double @@ -38,12 +20,9 @@ extension GeoJson { // SOMEDAY: Maybe a new type for altitude, Point3D? public var altitude: Double? - public var boundingBox: GeodesicBoundingBox { - return BoundingBox(boundingCoordinates: (minLongitude: longitude, minLatitude: latitude, maxLongitude: longitude, maxLatitude: latitude)) - } - - internal init?(coordinatesJson: [Any]) { - guard let pointJson = (coordinatesJson as? [NSNumber])?.map({ $0.doubleValue }), pointJson.count >= 2 else { Log.warning("A valid Point must have at least a longitude and latitude"); return nil } + internal init(coordinatesJson: [Any]) { + // swiftlint:disable:next force_cast + let pointJson = (coordinatesJson as! [NSNumber]).map { $0.doubleValue } self.init(longitude: pointJson[0], latitude: pointJson[1], altitude: pointJson.count >= 3 ? pointJson[2] : nil) } @@ -53,14 +32,29 @@ extension GeoJson { self.latitude = latitude self.altitude = altitude } + } +} + +extension GeoJson.Point { + public var geoJsonCoordinates: [Any] { altitude != nil ? [longitude, latitude, altitude!] : [longitude, latitude] } + + public var normalize: GeodesicPoint { Calculator.normalize(self) } + public var normalizePostitive: GeodesicPoint { Calculator.normalizePositive(self) } + + public var points: [GeodesicPoint] { [self] } + + public var boundingBox: GeodesicBoundingBox { .init(minLongitude: longitude, minLatitude: latitude, maxLongitude: longitude, maxLatitude: latitude) } + + // SOMEDAY: Consider Altitude? What to do if altitude is nil in some cases? + public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { Calculator.distance(from: self, to: point, tolerance: tolerance) } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { Calculator.distance(from: self, to: point, tolerance: tolerance) == 0 } +} + +extension GeoJson.Point { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard (coordinatesJson as? [NSNumber])?.map({ $0.doubleValue }).count ?? 0 >= 2 else { return .init(reason: "A valid Point must have at least a longitude and latitude") } - // SOMEDAY: Consider Altitude? What to do if altitude is nil in some cases? - public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { - return Calculator.distance(from: self, to: point, tolerance: tolerance) - } - - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { - return Calculator.distance(from: self, to: point, tolerance: tolerance) == 0 - } + return nil } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Polygon.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Polygon.swift index f25d596..3d02936 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Polygon.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Polygon.swift @@ -1,134 +1,86 @@ -public enum PolygonInvalidReason { - case duplicates(indices: [Int]) - case selfIntersects(ringIndices: [[[Int]]]) - case holeOutside(ringIndices: [Int]) - case ringInvalidReasons(_: [[LineStringInvalidReason]]) -} - -public protocol GeoJsonPolygon: GeoJsonClosedGeometry, GeodesicPolygon { - var geoJsonLinearRings: [GeoJsonLineString] { get } - var geoJsonMainRing: GeoJsonLineString { get } - var geoJsonNegativeRings: [GeoJsonLineString] { get } - var centroid: GeodesicPoint { get } - - func invalidReasons(tolerance: Double) -> [PolygonInvalidReason] -} - -// SOMEDAY: Create Polygon by mainRing and negativeRings instead of [LinearRings] which does not imply a main ring needs to exist to be valid. extension GeoJson { /** - Creates a GeoJsonPolygon + Creates a Polygon */ - public func polygon(linearRings: [GeoJsonLineString]) -> GeoJsonPolygon? { - return Polygon(linearRings: linearRings) + public func polygon(mainRing: LineString, negativeRings: [LineString]) -> Result { + if let invalidGeoJson = LinearRing.validate(linearRing: mainRing) + negativeRings.reduce(nil, { $0 + LinearRing.validate(linearRing: $1) }) { return .failure(invalidGeoJson) } + + return .success(Polygon(mainRing: mainRing, negativeRings: negativeRings)) } - public struct Polygon: GeoJsonPolygon { + public struct Polygon: GeoJsonClosedGeometry, GeodesicPolygon { public let type: GeoJsonObjectType = .polygon - public var geoJsonCoordinates: [Any] { return geoJsonLinearRings.map { $0.geoJsonCoordinates } } - - public var description: String { - return """ - Polygon: \( - """ - //\nMain Ring: \(mainRing) - (\n\(negativeRings.enumerated().map { "\("Negative Ring \($0 + 1)") - \($1)" }.joined(separator: ",\n")) - """ - .replacingOccurrences(of: "\n", with: "\n\t") - )\n) - """ - } - - public let geoJsonLinearRings: [GeoJsonLineString] - public let geoJsonMainRing: GeoJsonLineString - public let geoJsonNegativeRings: [GeoJsonLineString] - - public var linearRings: [GeodesicLine] { return geoJsonLinearRings } - public var mainRing: GeodesicLine { return geoJsonMainRing } - public var negativeRings: [GeodesicLine] { return geoJsonNegativeRings } - - public var points: [GeodesicPoint] { return linearRings.flatMap { $0.points } } - - public var boundingBox: GeodesicBoundingBox { return BoundingBox.best(geoJsonLinearRings.map { $0.boundingBox })! } - - public var centroid: GeodesicPoint { return Calculator.centroid(polygon: self) } - public var hasHole: Bool { return negativeRings.count > 0 } + private let geoJsonMainRing: LineString + private let geoJsonNegativeRings: [LineString] - public var area: Double { return Calculator.area(of: self) } - - internal init?(coordinatesJson: [Any]) { - guard let linearRingsJson = coordinatesJson as? [[Any]] else { Log.warning("A valid Polygon must have valid coordinates"); return nil } - - var linearRings = [GeoJsonLineString]() - for linearRingJson in linearRingsJson { - if let linearRing = LineString(coordinatesJson: linearRingJson) { - linearRings.append(linearRing) - } else { - Log.warning("Invalid linear ring (LineString) in Polygon"); return nil - } - } - - self.init(linearRings: linearRings) - } - - fileprivate init?(linearRings: [GeoJsonLineString]) { - guard linearRings.count >= 1 else { Log.warning("A valid Polygon must have at least one LinearRing"); return nil } - - for linearRing in linearRings { - guard linearRing.points.first! == linearRing.points.last! else { Log.warning("A valid Polygon LinearRing must have the first and last points equal"); return nil } - - guard linearRing.points.count >= 4 else { Log.warning("A valid Polygon LinearRing must have at least 4 points"); return nil } - } + internal init(coordinatesJson: [Any]) { + // swiftlint:disable:next force_cast + let linearRingsJson = coordinatesJson as! [[Any]] - geoJsonLinearRings = linearRings - geoJsonMainRing = linearRings.first! - geoJsonNegativeRings = linearRings.tail ?? [] + geoJsonMainRing = LineString(coordinatesJson: linearRingsJson.first!) + geoJsonNegativeRings = linearRingsJson.dropFirst().map { LineString(coordinatesJson: $0) } } - public func edgeDistance(to point: GeodesicPoint, tolerance: Double) -> Double { - return Calculator.edgeDistance(from: point, to: self, tolerance: tolerance) + fileprivate init(mainRing: LineString, negativeRings: [LineString]) { + geoJsonMainRing = mainRing + geoJsonNegativeRings = negativeRings } + } +} + +extension GeoJson.Polygon { + public var mainRing: GeodesicLine { geoJsonMainRing } + public var negativeRings: [GeodesicLine] { geoJsonNegativeRings } + public var linearRings: [GeodesicLine] { geoJsonLinearRings } + + private var geoJsonLinearRings: [GeoJson.LineString] { [geoJsonMainRing] + geoJsonNegativeRings } + + public var geoJsonCoordinates: [Any] { geoJsonLinearRings.map { $0.geoJsonCoordinates } } + + public var points: [GeodesicPoint] { linearRings.flatMap { $0.points } } + + public var boundingBox: GeodesicBoundingBox { .best(linearRings.map { $0.boundingBox })! } + + public var centroid: GeodesicPoint { Calculator.centroid(polygon: self) } + + public var polygons: [GeodesicPolygon] { [self] } + + public var hasHole: Bool { negativeRings.count > 0 } + + public var area: Double { Calculator.area(of: self) } + + public func edgeDistance(to point: GeodesicPoint, tolerance: Double) -> Double { Calculator.edgeDistance(from: point, to: self, tolerance: tolerance) } + + public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { Calculator.distance(from: point, to: self, tolerance: tolerance) } + + public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { + // Must at least be within the bounding box. + guard mainRing.boundingBox.contains(point: point, tolerance: tolerance) else { return false } - public func distance(to point: GeodesicPoint, tolerance: Double) -> Double { - return Calculator.distance(from: point, to: self, tolerance: tolerance) - } + return Calculator.contains(point, in: self, tolerance: tolerance) + } + + // SOMEDAY: See this helpful link for validations: https://github.com/mapbox/mapnik-vector-tile/issues/153 + + // Checking winding order is valid + // Triangle that reprojection to tile coordinates will cause winding order reversed + // Polygon that will be reprojected into tile coordinates as a line + // Polygon with "spike" + // Polygon with hole that has a "spike" + // Polygon where area threshold removes geometry AFTER clipping + // Polygon with reversed winding order + // Polygon with hole where hole has invalid winding order +} + +extension GeoJson.Polygon { + internal static func validate(coordinatesJson: [Any]) -> InvalidGeoJson? { + guard let linearRingsCoordinatesJson = coordinatesJson as? [[Any]] else { return .init(reason: "A valid Polygon must have valid coordinates") } - public func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { - // Must at least be within the bounding box. - guard geoJsonMainRing.boundingBox.contains(point: point, tolerance: tolerance) else { return false } - - return Calculator.contains(point, in: self, tolerance: tolerance) - } + guard linearRingsCoordinatesJson.count >= 1 else { return .init(reason: "A valid Polygon must have at least one LinearRing") } - // SOMEDAY: See this helpful link for validations: https://github.com/mapbox/mapnik-vector-tile/issues/153 + let validateLinearRings = linearRingsCoordinatesJson.reduce(nil) { $0 + GeoJson.LinearRing.validate(coordinatesJson: $1) } - // Checking winding order is valid - // Triangle that reprojection to tile coordinates will cause winding order reversed - // Polygon that will be reprojected into tile coordinates as a line - // Polygon with "spike" - // Polygon with hole that has a "spike" - // Polygon where area threshold removes geometry AFTER clipping - // Polygon with reversed winding order - // Polygon with hole where hole has invalid winding order - public func invalidReasons(tolerance: Double) -> [PolygonInvalidReason] { - let ringInvalidReasons = geoJsonLinearRings.compactMap { $0.invalidReasons(tolerance: tolerance) } - - guard ringInvalidReasons.isEmpty else { return [.ringInvalidReasons(ringInvalidReasons)] } - - let duplicateIndices = Calculator.equalsIndices(points, tolerance: tolerance) - - guard duplicateIndices.isEmpty else { return [.duplicates(indices: duplicateIndices)] } - - let selfIntersectsIndices = Calculator.intersectionIndices(from: self, tolerance: tolerance) - - guard selfIntersectsIndices.isEmpty else { return [.selfIntersects(ringIndices: selfIntersectsIndices)] } - - let holeOutsideIndices = negativeRings.enumerated().filter { _, negativeRing in negativeRing.points.contains { !Calculator.contains($0, in: mainRing, tolerance: tolerance) } }.map { $0.offset } - - guard holeOutsideIndices.isEmpty else { return [.holeOutside(ringIndices: holeOutsideIndices)] } - - return [] - } + return validateLinearRings.flatMap { .init(reason: "Invalid LinearRing(s) in Polygon") + $0 } } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonClosedGeometry.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonClosedGeometry.swift index 5967422..a3ecb05 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonClosedGeometry.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonClosedGeometry.swift @@ -2,6 +2,8 @@ A GeoJsonClosedGeometry is a geometry made of polygons */ public protocol GeoJsonClosedGeometry: GeoJsonCoordinatesGeometry { + var polygons: [GeodesicPolygon] { get } + var hasHole: Bool { get } var area: Double { get } @@ -10,5 +12,5 @@ public protocol GeoJsonClosedGeometry: GeoJsonCoordinatesGeometry { } public extension GeoJsonClosedGeometry { - func edgeDistance(to point: GeodesicPoint) -> Double { return edgeDistance(to: point, tolerance: 0) } + func edgeDistance(to point: GeodesicPoint) -> Double { edgeDistance(to: point, tolerance: 0) } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonCoordinatesGeometry.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonCoordinatesGeometry.swift index 9ff361a..2091478 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonCoordinatesGeometry.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonCoordinatesGeometry.swift @@ -14,15 +14,15 @@ public protocol GeoJsonCoordinatesGeometry: GeoJsonGeometry { } public extension GeoJsonCoordinatesGeometry { - var objectGeometries: [GeoJsonGeometry]? { return geometries } + var objectGeometries: [GeoJsonGeometry] { geometries } - var objectBoundingBox: GeodesicBoundingBox? { return boundingBox } + var objectBoundingBox: GeodesicBoundingBox? { boundingBox } - var geoJson: GeoJsonDictionary { return ["type": type.name, "coordinates": geoJsonCoordinates] } + var geoJson: GeoJsonDictionary { ["type": type.name, "coordinates": geoJsonCoordinates] } - var geometries: [GeoJsonGeometry] { return [self] } + var geometries: [GeoJsonGeometry] { [self] } - func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { return distance(to: point, tolerance: tolerance) } + func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { distance(to: point, tolerance: tolerance) } - func distance(to point: GeodesicPoint) -> Double { return distance(to: point, tolerance: 0) } + func distance(to point: GeodesicPoint) -> Double { distance(to: point, tolerance: 0) } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonLinearGeometry.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonLinearGeometry.swift index 0a037d0..bf02a3e 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonLinearGeometry.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonLinearGeometry.swift @@ -2,5 +2,7 @@ A GeoJsonLinearGeometry is a geometry made of lines */ public protocol GeoJsonLinearGeometry: GeoJsonCoordinatesGeometry { + var lines: [GeodesicLine] { get } + var length: Double { get } } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObject.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObject.swift index 3252590..b0e8dff 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObject.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObject.swift @@ -5,51 +5,43 @@ import Foundation Does not support projected coordinates, only geographic */ -public protocol GeoJsonObject: CustomStringConvertible { +public protocol GeoJsonObject { + // SOMEDAY: does not yet handle optional "bbox" or "crs" members + var type: GeoJsonObjectType { get } - var objectGeometries: [GeoJsonGeometry]? { get } + var objectGeometries: [GeoJsonGeometry] { get } var objectBoundingBox: GeodesicBoundingBox? { get } var geoJson: GeoJsonDictionary { get } - // SOMEDAY: Could this be expanded to more than point? func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? - // SOMEDAY: Could this be expanded to more than point? func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool // SOMEDAY: More fun! //func overlaps(geoJsonObject: GeoJsonObject, tolerance: Double) -> Bool - - func invalidReasons(tolerance: Double) -> [GeoJsonInvalidReason] } extension GeoJsonObject { - public func contains(_ point: GeodesicPoint) -> Bool { return contains(point, tolerance: 0) } + public func contains(_ point: GeodesicPoint) -> Bool { contains(point, tolerance: 0) } - public func objectDistance(to point: GeodesicPoint) -> Double? { return objectDistance(to: point, tolerance: 0) } + public func objectDistance(to point: GeodesicPoint) -> Double? { objectDistance(to: point, tolerance: 0) } } extension GeoJsonObject { - public var isSimpleGeometry: Bool { - return [.point, .lineString, .polygon].contains(type) - } + public var isSimpleGeometry: Bool { [.point, .lineString, .polygon].contains(type) } // Trust geoJson serialization - public var geoJsonData: Data { - // swiftlint:disable:next force_try - return try! JSONSerialization.data(withJSONObject: geoJson, options: []) - } + // swiftlint:disable:next force_try + public var geoJsonData: Data { try! JSONSerialization.data(withJSONObject: geoJson, options: []) } // Trust geoJson encoding - public var geoJsonString: String { - return String(data: geoJsonData, encoding: .utf8)! - } + public var geoJsonString: String { String(data: geoJsonData, encoding: .utf8)! } public var coordinatesGeometries: [GeoJsonCoordinatesGeometry] { - return (objectGeometries ?? []).flatMap { objectGeometry -> [GeoJsonCoordinatesGeometry] in + objectGeometries.flatMap { objectGeometry -> [GeoJsonCoordinatesGeometry] in if let geometry = objectGeometry as? GeoJsonCoordinatesGeometry { return [geometry] } return objectGeometry.coordinatesGeometries @@ -57,7 +49,7 @@ extension GeoJsonObject { } public var linearGeometries: [GeoJsonLinearGeometry] { - return (objectGeometries ?? []).flatMap { objectGeometry -> [GeoJsonLinearGeometry] in + objectGeometries.flatMap { objectGeometry -> [GeoJsonLinearGeometry] in if let geometry = objectGeometry as? GeoJsonLinearGeometry { return [geometry] } if objectGeometry is GeoJsonCoordinatesGeometry { return [] } @@ -67,7 +59,7 @@ extension GeoJsonObject { } public var closedGeometries: [GeoJsonClosedGeometry] { - return (objectGeometries ?? []).flatMap { objectGeometry -> [GeoJsonClosedGeometry] in + objectGeometries.flatMap { objectGeometry -> [GeoJsonClosedGeometry] in if let geometry = objectGeometry as? GeoJsonClosedGeometry { return [geometry] } if objectGeometry is GeoJsonCoordinatesGeometry { return [] } @@ -77,48 +69,6 @@ extension GeoJsonObject { } } -public enum GeoJsonInvalidReason { - case multipointInvalidReasons(_: [MultipointInvalidReason]) - case lineStringInvalidReasons(_: [LineStringInvalidReason]) - case multiLineStringInvalidReasons(_: [[LineStringInvalidReason]]) - case polygonInvalidReasons(_: [PolygonInvalidReason]) - case multiPolygonInvalidReasons(_: [[PolygonInvalidReason]]) -} - -extension GeoJsonObject { - // swiftlint:disable:next cyclomatic_complexity - public func invalidReasons(tolerance: Double) -> [GeoJsonInvalidReason] { - guard let objectGeometries = objectGeometries else { return [] } - - let invalidReasons = objectGeometries.compactMap { object -> [GeoJsonInvalidReason] in - switch object { - case _ as GeoJsonPoint: - return [] - case let object as GeoJsonMultiPoint: - return [.multipointInvalidReasons(object.invalidReasons(tolerance: tolerance))] - case let object as GeoJsonLineString: - return [.lineStringInvalidReasons(object.invalidReasons(tolerance: tolerance))] - case let object as GeoJsonMultiLineString: - return [.multiLineStringInvalidReasons(object.invalidReasons(tolerance: tolerance))] - case let object as GeoJsonPolygon: - return [.polygonInvalidReasons(object.invalidReasons(tolerance: tolerance))] - case let object as GeoJsonMultiPolygon: - return [.multiPolygonInvalidReasons(object.invalidReasons(tolerance: tolerance))] - case let object as GeoJsonGeometryCollection: - return object.invalidReasons(tolerance: tolerance) - case let object as GeoJsonFeature: - return object.invalidReasons(tolerance: tolerance) - case let object as GeoJsonFeatureCollection: - return object.invalidReasons(tolerance: tolerance) - default: - return [] - } - } - - return invalidReasons.flatMap { $0 } - } -} - // swiftlint:disable:next cyclomatic_complexity public func == (lhs: GeoJsonObject?, rhs: GeoJsonObject?) -> Bool { guard lhs != nil || rhs != nil else { return type(of: lhs) == type(of: rhs) } @@ -127,53 +77,45 @@ public func == (lhs: GeoJsonObject?, rhs: GeoJsonObject?) -> Bool { switch type { case .featureCollection: - guard let lhs = lhs as? GeoJsonFeatureCollection, let rhs = rhs as? GeoJsonFeatureCollection, lhs.features.count == rhs.features.count else { return false } + guard let lhs = lhs as? GeoJson.FeatureCollection, let rhs = rhs as? GeoJson.FeatureCollection, lhs.features.count == rhs.features.count else { return false } for feature in lhs.features where !rhs.features.contains { $0 == feature } { return false } return true case .feature: - guard let lhs = lhs as? GeoJsonFeature, let rhs = rhs as? GeoJsonFeature else { return false } + guard let lhs = lhs as? GeoJson.Feature, let rhs = rhs as? GeoJson.Feature else { return false } return lhs.geometry == rhs.geometry && lhs.idAsString == rhs.idAsString && lhs.properties == rhs.properties case .geometryCollection: - guard let lhs = lhs as? GeoJsonGeometryCollection, let rhs = rhs as? GeoJsonGeometryCollection else { return false } + guard let lhs = lhs as? GeoJson.GeometryCollection, let rhs = rhs as? GeoJson.GeometryCollection else { return false } - if lhs.objectGeometries == nil && rhs.objectGeometries == nil { return true } + guard lhs.objectGeometries.count == rhs.objectGeometries.count else { return false } - guard let lhsGeometries = lhs.objectGeometries, let rhsGeometries = rhs.objectGeometries, lhsGeometries.count == rhsGeometries.count else { return false } - - for geometry in lhsGeometries where !rhsGeometries.contains { $0 == geometry } { return false } + for geometry in lhs.objectGeometries where !rhs.objectGeometries.contains { $0 == geometry } { return false } return true case .multiPolygon: - guard let lhs = lhs as? GeoJsonMultiPolygon, let rhs = rhs as? GeoJsonMultiPolygon, lhs.polygons.count == rhs.polygons.count else { return false } + guard let lhs = lhs as? GeoJson.MultiPolygon, let rhs = rhs as? GeoJson.MultiPolygon, lhs.polygons.count == rhs.polygons.count else { return false } for polygon in lhs.polygons where !rhs.polygons.contains { $0 == polygon } { return false } return true case .polygon: - guard let lhs = lhs as? GeoJsonPolygon, let rhs = rhs as? GeoJsonPolygon, lhs.negativeRings.count == rhs.negativeRings.count else { return false } - - guard lhs.geoJsonMainRing == rhs.geoJsonMainRing else { return false } - - for linearRing in lhs.geoJsonNegativeRings where !(rhs.geoJsonNegativeRings).contains { $0 == linearRing } { return false } + guard let lhs = lhs as? GeodesicPolygon, let rhs = rhs as? GeodesicPolygon else { return false } - return true + return lhs == rhs case .multiLineString: - guard let lhs = lhs as? GeoJsonMultiLineString, let rhs = rhs as? GeoJsonMultiLineString, lhs.lineStrings.count == rhs.lineStrings.count else { return false } + guard let lhs = lhs as? GeoJson.MultiLineString, let rhs = rhs as? GeoJson.MultiLineString, lhs.lines.count == rhs.lines.count else { return false } - for lineString in lhs.lineStrings where !rhs.lineStrings.contains { $0 == lineString } { return false } + for line in lhs.lines where !rhs.lines.contains { $0 == line } { return false } return true case .lineString: - guard let lhs = lhs as? GeoJsonLineString, let rhs = rhs as? GeoJsonLineString, lhs.points.count == rhs.points.count else { return false } - - for (index, point) in lhs.points.enumerated() where !(rhs.points[index] == point) { return false } + guard let lhs = lhs as? GeodesicLine, let rhs = rhs as? GeodesicLine else { return false } - return true + return lhs == rhs case .multiPoint: - guard let lhs = lhs as? GeoJsonMultiPoint, let rhs = rhs as? GeoJsonMultiPoint, lhs.points.count == rhs.points.count else { return false } + guard let lhs = lhs as? GeoJson.MultiPoint, let rhs = rhs as? GeoJson.MultiPoint, lhs.points.count == rhs.points.count else { return false } for point in lhs.points where !rhs.points.contains { $0 == point } { return false } diff --git a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObjectType.swift b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObjectType.swift index f5d4c06..d15d3d6 100644 --- a/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObjectType.swift +++ b/Sources/GeospatialSwift/API/GeoJson/Object/Protocol/GeoJsonObjectType.swift @@ -9,9 +9,23 @@ public enum GeoJsonObjectType: String, Codable { case feature = "Feature" case featureCollection = "FeatureCollection" - public var name: String { return rawValue } + public var name: String { rawValue } public init?(name: String) { self.init(rawValue: name) } + + public var isCoordinatesGeometry: Bool { + switch self { + case .point, .multiPoint, .lineString, .multiLineString, .polygon, .multiPolygon: return true + case .geometryCollection, .feature, .featureCollection: return false + } + } + + public var isGeometry: Bool { + switch self { + case .point, .multiPoint, .lineString, .multiLineString, .polygon, .multiPolygon, .geometryCollection: return true + case .feature, .featureCollection: return false + } + } } diff --git a/Sources/GeospatialSwift/API/Geohash/GeohashBox.swift b/Sources/GeospatialSwift/API/Geohash/GeohashBox.swift index 4bca409..60d27ef 100644 --- a/Sources/GeospatialSwift/API/Geohash/GeohashBox.swift +++ b/Sources/GeospatialSwift/API/Geohash/GeohashBox.swift @@ -1,36 +1,8 @@ -public protocol GeoJsonGeohashBox: GeodesicBoundingBox { - var geohash: String { get } - - func geohashNeighbor(direction: GeohashCompassPoint, precision: Int) -> GeoJsonGeohashBox -} - public enum GeohashCompassPoint { case north, south, east, west } -internal final class GeohashBox: BoundingBox, GeoJsonGeohashBox { - private let geohashCoder: GeohashCoderProtocol - +public struct GeohashBox { + public let boundingBox: GeodesicBoundingBox public let geohash: String - - init(boundingCoordinates: BoundingCoordinates, geohashCoder: GeohashCoderProtocol, geohash: String) { - self.geohashCoder = geohashCoder - - self.geohash = geohash - - super.init(boundingCoordinates: boundingCoordinates) - } - - public func geohashNeighbor(direction: GeohashCompassPoint, precision: Int) -> GeoJsonGeohashBox { - let point: GeodesicPoint = { - switch direction { - case .north: return SimplePoint(longitude: centroid.longitude, latitude: centroid.latitude + latitudeDelta) - case .south: return SimplePoint(longitude: centroid.longitude, latitude: centroid.latitude - latitudeDelta) - case .east: return SimplePoint(longitude: centroid.longitude + longitudeDelta, latitude: centroid.latitude) - case .west: return SimplePoint(longitude: centroid.longitude - longitudeDelta, latitude: centroid.latitude) - } - }() - - return geohashCoder.geohashBox(for: point, precision: precision) - } } diff --git a/Sources/GeospatialSwift/API/Geohash/GeohashCoder.swift b/Sources/GeospatialSwift/API/Geohash/GeohashCoder.swift index 761360c..800e316 100644 --- a/Sources/GeospatialSwift/API/Geohash/GeohashCoder.swift +++ b/Sources/GeospatialSwift/API/Geohash/GeohashCoder.swift @@ -1,18 +1,13 @@ -public protocol GeohashCoderProtocol { - func geohash(for point: GeodesicPoint, precision: Int) -> String - - func geohashBox(for point: GeodesicPoint, precision: Int) -> GeoJsonGeohashBox - - func geohashBox(geohash: String) -> GeoJsonGeohashBox? - - func geohashes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [String] - - func geohashBoxes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [GeoJsonGeohashBox] +public struct GeohashCoder { + /** + Validate a geohash created outside the framework before passing to another GeohashCoder function to avoid crashing + + - geohash: The string to validate + + - returns: true if valid + */ + public func validate(geohash: String) -> Bool { geohash.count > 0 && geohash.count <= 22 && !geohash.contains { !decimalToBase32Characters.contains($0) } } - func geohashWithNeighbors(for point: GeodesicPoint, precision: Int) -> [String] -} - -public struct GeohashCoder: GeohashCoderProtocol { /** Returns a geohash associated to the coordinate @@ -21,98 +16,109 @@ public struct GeohashCoder: GeohashCoderProtocol { - returns: A geohash */ - public func geohash(for point: GeodesicPoint, precision: Int) -> String { - return transform(point: point, precision: precision).geohash - } + public func geohash(for point: GeodesicPoint, precision: Int) -> String { geohashBox(point: point, precision: precision).geohash } + + /** + Returns an array of geohashes associated to the boundingbox + + - boundingBox: The boundingBox used to create geohashes + - precision: How precise of a geohash to use + + - returns: An array of geohashes + */ + public func geohashes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [String] { geohashBoxes(boundingBox: boundingBox, precision: precision).map { $0.geohash } } /** Returns a geohashBox associated to the geohash + Assumes valid geohash for performance! - geohash: The geohash used to create geohashBox - returns: A geohashBox */ - public func geohashBox(geohash: String) -> GeoJsonGeohashBox? { - return transform(geohash: geohash) - } - public func geohashBox(for point: GeodesicPoint, precision: Int) -> GeoJsonGeohashBox { - return transform(point: point, precision: precision) - } + public func geohashBox(forGeohash geohash: String) -> GeohashBox { geohashBox(geohash: geohash) } /** - Returns an array of geohashes associated to the boundingbox + Returns a geohash box associated to the coordinate - - boundingBox: The boundingBox used to create geohashes + - point: The point used to create geohash - precision: How precise of a geohash to use - - returns: An array of geohashes + - returns: A geohash box */ - public func geohashes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [String] { - return transform(boundingBox: boundingBox, precision: precision).map { $0.geohash } - } - public func geohashBoxes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [GeoJsonGeohashBox] { - return transform(boundingBox: boundingBox, precision: precision) - } + public func geohashBox(for point: GeodesicPoint, precision: Int) -> GeohashBox { geohashBox(point: point, precision: precision) } /** - Returns a geohash with neighbors associated to the coordinate + Returns an array of geohash boxes associated to the boundingbox - - point: The point used to create geohash + - boundingBox: The boundingBox used to create geohashes - precision: How precise of a geohash to use + - returns: An array of geohash boxes + */ + public func geohashBoxes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [GeohashBox] { geohashBoxes(boundingBox: boundingBox, precision: precision) } + + /** + Returns a geohash with neighbors associated to the geohash + Assumes valid geohash for performance! + + - geohash: The geohash used to create the neighbor + - direction: The compass direction of the neighbor + - returns: A geohash */ - public func geohashWithNeighbors(for point: GeodesicPoint, precision: Int) -> [String] { - let geohashBox = transform(point: point, precision: precision) - var neighborGeohashBoxes = neighborGeohashes(geohashBox: geohashBox, precision: precision) - neighborGeohashBoxes.append(geohashBox) - return neighborGeohashBoxes.map { $0.geohash } - } + public func geohashNeighbor(forGeohash geohash: String, direction: GeohashCompassPoint) -> String { adjacent(geohash: geohash, direction: direction) } + + /** + Returns the geohash neighbors associated to the geohash excluding the geohash + Assumes valid geohash for performance! + + - geohash: The geohash used to compute neighbors + + - returns: Neighbor geohashes + */ + public func geohashNeighbors(forGeohash geohash: String) -> [String] { neighbors(geohash: geohash) } + + /** + Returns the geohash neighbors associated to the geohash including the geohash + Assumes valid geohash for performance! + + - geohash: The geohash used to compute neighbors + + - returns: The geohash with neighbor geohashes + */ + public func geohashWithNeighbors(forGeohash geohash: String) -> [String] { [geohash] + neighbors(geohash: geohash) } } // MARK: Private -private enum Parity { - case even, odd - - prefix static func ! (parity: Parity) -> Parity { - return parity == .even ? .odd : .even - } -} - -private let decimalToBase32Map = "0123456789bcdefghjkmnpqrstuvwxyz".map { $0 } +private let decimalToBase32Characters: [Character] = "0123456789bcdefghjkmnpqrstuvwxyz".map { $0 } private let base32BitflowInit: UInt8 = 0b10000 +private let neighborCodeByIndex1 = "p0r21436x8zb9dcf5h7kjnmqesgutwvy".enumerated().reduce(into: [Character: Int]()) { $0[$1.element] = $1.offset } +private let neighborCodeByIndex2 = "14365h7k9dcfesgujnmqp0r2twvyx8zb".enumerated().reduce(into: [Character: Int]()) { $0[$1.element] = $1.offset } +private let neighborCodeByIndex3 = "bc01fg45238967deuvhjyznpkmstqrwx".enumerated().reduce(into: [Character: Int]()) { $0[$1.element] = $1.offset } +private let neighborCodeByIndex4 = "238967debc01fg45kmstqrwxuvhjyznp".enumerated().reduce(into: [Character: Int]()) { $0[$1.element] = $1.offset } + +private let borderCodeSet1 = "prxz".reduce(into: Set()) { $0.insert($1) } +private let borderCodeSet2 = "028b".reduce(into: Set()) { $0.insert($1) } +private let borderCodeSet3 = "bcfguvyz".reduce(into: Set()) { $0.insert($1) } +private let borderCodeSet4 = "0145hjnp".reduce(into: Set()) { $0.insert($1) } + extension GeohashCoder { - private func neighborGeohashes(geohashBox: GeoJsonGeohashBox, precision: Int) -> [GeoJsonGeohashBox] { - let northGeohash = geohashBox.geohashNeighbor(direction: .north, precision: precision) - let eastGeohash = geohashBox.geohashNeighbor(direction: .east, precision: precision) - let southGeohash = geohashBox.geohashNeighbor(direction: .south, precision: precision) - let westGeohash = geohashBox.geohashNeighbor(direction: .west, precision: precision) - - let northWestGeohash = northGeohash.geohashNeighbor(direction: .west, precision: precision) - let northEastGeohash = northGeohash.geohashNeighbor(direction: .east, precision: precision) - let southEastGeohash = southGeohash.geohashNeighbor(direction: .east, precision: precision) - let southWestGeohash = southGeohash.geohashNeighbor(direction: .west, precision: precision) + private func geohashBox(point: GeodesicPoint, precision: Int) -> GeohashBox { + let point = Calculator.normalize(point) - // in clockwise order - return [northWestGeohash, northGeohash, northEastGeohash, eastGeohash, southEastGeohash, southGeohash, southWestGeohash, westGeohash] - } - - private func transform(point: GeodesicPoint, precision: Int) -> GeoJsonGeohashBox { var range = (longitude: (min: -180.0, max: 180.0), latitude: (min: -90.0, max: 90.0)) - var parity = Parity.even + var even = true var base32char = 0 var bit = base32BitflowInit var geohash = "" - let point = Calculator.normalize(point) - repeat { - switch parity { - case .even: + if even { let center = (range.longitude.min + range.longitude.max) / 2 if point.longitude >= center { base32char |= Int(bit) @@ -120,7 +126,7 @@ extension GeohashCoder { } else { range.longitude.max = center } - case .odd: + } else { let center = (range.latitude.min + range.latitude.max) / 2 if point.latitude >= center { base32char |= Int(bit) @@ -130,64 +136,61 @@ extension GeohashCoder { } } - parity = !parity + even = !even bit >>= 1 if bit == 0b00000 { - geohash += String(decimalToBase32Map[base32char]) + geohash += String(decimalToBase32Characters[base32char]) bit = base32BitflowInit base32char = 0 } } while geohash.count < precision - let boundingCoordinates = (minLongitude: range.longitude.min, minLatitude: range.latitude.min, maxLongitude: range.longitude.max, maxLatitude: range.latitude.max) - - return GeohashBox(boundingCoordinates: boundingCoordinates, geohashCoder: self, geohash: geohash) + return GeohashBox(boundingBox: .init(minLongitude: range.longitude.min, minLatitude: range.latitude.min, maxLongitude: range.longitude.max, maxLatitude: range.latitude.max), geohash: geohash) } - private func transform(boundingBox: GeodesicBoundingBox, precision: Int) -> [GeoJsonGeohashBox] { - var geohashBoxes = [GeoJsonGeohashBox]() + private func geohashBoxes(boundingBox: GeodesicBoundingBox, precision: Int) -> [GeohashBox] { + var geohashBoxes = [GeohashBox]() let point = SimplePoint(longitude: boundingBox.minLongitude, latitude: boundingBox.minLatitude) - var longitudeGeohashBox = transform(point: point, precision: precision) + var longitudeGeohashBox = geohashBox(point: point, precision: precision) repeat { geohashBoxes.append(longitudeGeohashBox) - var latitudeGeohashBox = longitudeGeohashBox.geohashNeighbor(direction: .north, precision: precision) + var latitudeGeohashBox = geohashBox(geohash: adjacent(geohash: longitudeGeohashBox.geohash, direction: .north)) - while latitudeGeohashBox.overlaps(boundingBox: boundingBox, tolerance: 0) { + while latitudeGeohashBox.boundingBox.overlaps(boundingBox: boundingBox) { geohashBoxes.append(latitudeGeohashBox) - latitudeGeohashBox = latitudeGeohashBox.geohashNeighbor(direction: .north, precision: precision) + latitudeGeohashBox = geohashBox(geohash: adjacent(geohash: latitudeGeohashBox.geohash, direction: .north)) } - longitudeGeohashBox = longitudeGeohashBox.geohashNeighbor(direction: .east, precision: precision) - } while longitudeGeohashBox.overlaps(boundingBox: boundingBox, tolerance: 0) + longitudeGeohashBox = geohashBox(geohash: adjacent(geohash: longitudeGeohashBox.geohash, direction: .east)) + } while longitudeGeohashBox.boundingBox.overlaps(boundingBox: boundingBox) return geohashBoxes } - private func transform(geohash: String) -> GeoJsonGeohashBox? { + private func geohashBox(geohash: String) -> GeohashBox { var range = (longitude: (min: -180.0, max: 180.0), latitude: (min: -90.0, max: 90.0)) - var parity = Parity.even + var even = true for character in geohash { - guard let bitmap = decimalToBase32Map.firstIndex(of: character) else { Log.warning("Invalid geohash: \(geohash)"); return nil } + let bitmap = decimalToBase32Characters.firstIndex(of: character)! var mask = Int(base32BitflowInit) while mask != 0 { - switch parity { - case .even: + if even { let center = (range.longitude.min + range.longitude.max) / 2 if bitmap & mask != 0 { range.longitude.min = center } else { range.longitude.max = center } - case .odd: + } else { let center = (range.latitude.min + range.latitude.max) / 2 if bitmap & mask != 0 { range.latitude.min = center @@ -196,13 +199,60 @@ extension GeohashCoder { } } - parity = !parity + even = !even mask >>= 1 } } - let boundingCoordinates = (minLongitude: range.longitude.min, minLatitude: range.latitude.min, maxLongitude: range.longitude.max, maxLatitude: range.latitude.max) + return GeohashBox(boundingBox: .init(minLongitude: range.longitude.min, minLatitude: range.latitude.min, maxLongitude: range.longitude.max, maxLatitude: range.latitude.max), geohash: geohash) + } + + private func neighbors(geohash: String) -> [String] { + let north = adjacent(geohash: geohash, direction: .north) + let east = adjacent(geohash: geohash, direction: .east) + let south = adjacent(geohash: geohash, direction: .south) + let west = adjacent(geohash: geohash, direction: .west) + let northEast = adjacent(geohash: north, direction: .east) + let southEast = adjacent(geohash: south, direction: .east) + let southWest = adjacent(geohash: south, direction: .west) + let northWest = adjacent(geohash: north, direction: .west) + + // in clockwise order + return [north, northEast, east, southEast, south, southWest, west, northWest] + } + + private func adjacent(geohash: String, direction: GeohashCompassPoint) -> String { + // last character of hash + let lastCharacter = geohash.last! + // hash without last character + var parent = geohash.dropLast().description - return GeohashBox(boundingCoordinates: boundingCoordinates, geohashCoder: self, geohash: geohash) + let even = geohash.count % 2 == 0 + + // check for edge-cases which don't share common prefix + if !parent.isEmpty, borderContains(direction: direction, even: even, character: lastCharacter) { + parent = adjacent(geohash: parent, direction: direction) + } + + // append letter for direction to parent + return parent + decimalToBase32Characters[neighborIndex(direction: direction, even: even, character: lastCharacter)].description + } + + private func neighborIndex(direction: GeohashCompassPoint, even: Bool, character: Character) -> Int { + switch direction { + case .north: return even ? neighborCodeByIndex1[character]! : neighborCodeByIndex3[character]! + case .south: return even ? neighborCodeByIndex2[character]! : neighborCodeByIndex4[character]! + case .east: return even ? neighborCodeByIndex3[character]! : neighborCodeByIndex1[character]! + case .west: return even ? neighborCodeByIndex4[character]! : neighborCodeByIndex2[character]! + } + } + + private func borderContains(direction: GeohashCompassPoint, even: Bool, character: Character) -> Bool { + switch direction { + case .north: return even ? borderCodeSet1.contains(character) : borderCodeSet3.contains(character) + case .south: return even ? borderCodeSet2.contains(character) : borderCodeSet4.contains(character) + case .east: return even ? borderCodeSet3.contains(character) : borderCodeSet1.contains(character) + case .west: return even ? borderCodeSet4.contains(character) : borderCodeSet2.contains(character) + } } } diff --git a/Sources/GeospatialSwift/API/Geospatial.swift b/Sources/GeospatialSwift/API/Geospatial.swift index a90e320..96c1678 100644 --- a/Sources/GeospatialSwift/API/Geospatial.swift +++ b/Sources/GeospatialSwift/API/Geospatial.swift @@ -1,37 +1,25 @@ -/** - A protocol provided for unit testing. - */ -public protocol GeospatialProtocol: class { - var geoJson: GeoJsonProtocol { get } - var geohash: GeohashCoderProtocol { get } - - var calculator: GeodesicCalculatorProtocol { get } - - func parse(wkt: String) -> GeoJsonObject? -} - /** A framework to parse GeoJson and create GeoJson by means of a GeoJsonObject. The GeoJson object has many helper methods including boundingBox, which eliminates the need to add a bbox parameter on the geoJson. */ -open class Geospatial: GeospatialProtocol { +open class Geospatial { /** Everything GeoJson. The base of all other functionality. */ - public let geoJson: GeoJsonProtocol + public let geoJson: GeoJson /** Everything Geohash */ - public let geohash: GeohashCoderProtocol + public let geohash: GeohashCoder /** Everything Geospatial Calculation */ - public let calculator: GeodesicCalculatorProtocol + public let calculator: GeodesicCalculator - internal let wktParser: WktParserProtocol + internal let wktParser: WktParser /** Initialize the interface using a configuration to describe how the interface should react to requests. @@ -41,7 +29,7 @@ open class Geospatial: GeospatialProtocol { geohash = GeohashCoder() - calculator = GeodesicCalculator.shared + calculator = Calculator wktParser = WktParser(geoJson: geoJson) } @@ -55,7 +43,5 @@ open class Geospatial: GeospatialProtocol { Experimental, untested, not fully written, and no plans to fully support in the future. */ - public func parse(wkt: String) -> GeoJsonObject? { - return wktParser.geoJsonObject(from: wkt) - } + public func parse(wkt: String) -> GeoJsonObject? { wktParser.geoJsonObject(from: wkt) } } diff --git a/Sources/GeospatialSwift/Extensions/Array.swift b/Sources/GeospatialSwift/Extensions/Array.swift index 4b785bb..c3f28bc 100644 --- a/Sources/GeospatialSwift/Extensions/Array.swift +++ b/Sources/GeospatialSwift/Extensions/Array.swift @@ -1,7 +1,10 @@ internal extension Array { - var tail: Array? { - let tail = Array(dropFirst()) - if tail.isEmpty { return nil } - return tail + private var nilIfEmpty: Array? { isEmpty ? nil : self } + + var tail: Array? { Array(dropFirst()).nilIfEmpty } + + @inlinable mutating func appendChainable(_ newElement: Element) -> Self { + append(newElement) + return self } } diff --git a/Sources/GeospatialSwift/Extensions/Bundle.swift b/Sources/GeospatialSwift/Extensions/Bundle.swift index f2b65ef..9b30517 100644 --- a/Sources/GeospatialSwift/Extensions/Bundle.swift +++ b/Sources/GeospatialSwift/Extensions/Bundle.swift @@ -3,7 +3,11 @@ import Foundation private class BundleClass {} internal extension Bundle { - static var source: Bundle { return Bundle(for: BundleClass.self) } + #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + static var source: Bundle { Bundle(for: BundleClass.self) } - static var sourceVersion: String { return source.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" } + static var sourceVersion: String { source.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" } + #else + static var sourceVersion: String { "0.2.0" } + #endif } diff --git a/Sources/GeospatialSwift/Extensions/FloatingPoint.swift b/Sources/GeospatialSwift/Extensions/FloatingPoint.swift index ea5353c..e225c61 100644 --- a/Sources/GeospatialSwift/Extensions/FloatingPoint.swift +++ b/Sources/GeospatialSwift/Extensions/FloatingPoint.swift @@ -1,4 +1,4 @@ internal extension FloatingPoint { - var degreesToRadians: Self { return self * .pi / 180 } - var radiansToDegrees: Self { return self * 180 / .pi } + var degreesToRadians: Self { self * .pi / 180 } + var radiansToDegrees: Self { self * 180 / .pi } } diff --git a/Sources/GeospatialSwift/Extensions/Result.swift b/Sources/GeospatialSwift/Extensions/Result.swift new file mode 100644 index 0000000..f851d0c --- /dev/null +++ b/Sources/GeospatialSwift/Extensions/Result.swift @@ -0,0 +1,24 @@ +extension Result { + var succeeded: Bool { + switch self { + case .success: return true + case .failure: return false + } + } + + var failed: Bool { !succeeded } + + var success: Success? { + switch self { + case .success(let success): return success + case .failure: return nil + } + } + + var failure: Failure? { + switch self { + case .success: return nil + case .failure(let failure): return failure + } + } +} diff --git a/Sources/GeospatialSwift/Parser/GeoJsonParser.swift b/Sources/GeospatialSwift/Parser/GeoJsonParser.swift index b0a731a..692e932 100644 --- a/Sources/GeospatialSwift/Parser/GeoJsonParser.swift +++ b/Sources/GeospatialSwift/Parser/GeoJsonParser.swift @@ -1,51 +1,171 @@ -internal protocol GeoJsonParserProtocol { - func geoJsonObject(from geoJson: GeoJsonDictionary) -> GeoJsonObject? +internal struct GeoJsonParser { + func validateGeoJsonObject(geoJson: GeoJsonDictionary, validTypes: [GeoJsonObjectType]? = nil) -> InvalidGeoJson? { + let typeResult = self.geoJsonObjectTypeResult(geoJson: geoJson) + + switch typeResult { + case .success(let type): + if let invalidGeoJson = validateGeoJsonObject(geoJson: geoJson, type: type) { return invalidGeoJson } + + guard validTypes.flatMap({ $0.contains(type) }) ?? true else { return .init(reason: "Type not allowed: \(type)") } + + return nil + case .failure(let invalidGeoJson): return invalidGeoJson + } + } + + func validateGeoJsonGeometry(geoJson: GeoJsonDictionary, validTypes: [GeoJsonObjectType]? = nil) -> InvalidGeoJson? { + let typeResult = self.geoJsonObjectTypeResult(geoJson: geoJson) + + switch typeResult { + case .success(let type): + if let invalidGeoJson = validateGeoJsonGeometry(geoJson: geoJson, type: type) { return invalidGeoJson } + + guard validTypes.flatMap({ $0.contains(type) }) ?? true else { return .init(reason: "Type not allowed: \(type)") } + + return nil + case .failure(let invalidGeoJson): return invalidGeoJson + } + } + + func validateGeoJsonCoordinatesGeometry(geoJson: GeoJsonDictionary, validTypes: [GeoJsonObjectType]? = nil) -> InvalidGeoJson? { + let typeResult = self.geoJsonObjectTypeResult(geoJson: geoJson) + + switch typeResult { + case .success(let type): + if let invalidGeoJson = validateGeoJsonCoordinatesGeometry(geoJson: geoJson, type: type) { return invalidGeoJson } + + guard validTypes.flatMap({ $0.contains(type) }) ?? true else { return .init(reason: "Type not allowed: \(type)") } + + return nil + case .failure(let invalidGeoJson): return invalidGeoJson + } + } + + func geoJsonObject(fromGeoJson geoJson: GeoJsonDictionary) -> Result { + let typeResult = self.geoJsonObjectTypeResult(geoJson: geoJson) + + switch typeResult { + case .success(let type): + if let invalidGeoJson = validateGeoJsonObject(geoJson: geoJson, type: type) { return .failure(invalidGeoJson) } + + return .success(geoJsonObject(validatedGeoJson: geoJson, type: type)) + case .failure(let invalidGeoJson): return .failure(invalidGeoJson) + } + } + + func geoJsonObject(fromValidatedGeoJson geoJson: GeoJsonDictionary) -> GeoJsonObject { + return geoJsonObject(validatedGeoJson: geoJson, type: geoJsonObjectTypeResult(geoJson: geoJson).success!) + } + + func geoJsonGeometry(fromGeoJson geoJson: GeoJsonDictionary) -> Result { + let typeResult = self.geoJsonObjectTypeResult(geoJson: geoJson) + + switch typeResult { + case .success(let type): + if let invalidGeoJson = validateGeoJsonGeometry(geoJson: geoJson, type: type) { return .failure(invalidGeoJson) } + + return .success(geoJsonGeometry(validatedGeoJson: geoJson, type: type)) + case .failure(let invalidGeoJson): return .failure(invalidGeoJson) + } + } + + func geoJsonGeometry(fromValidatedGeoJson geoJson: GeoJsonDictionary) -> GeoJsonGeometry { + return geoJsonGeometry(validatedGeoJson: geoJson, type: geoJsonObjectTypeResult(geoJson: geoJson).success!) + } + + func geoJsonCoordinatesGeometry(fromGeoJson geoJson: GeoJsonDictionary) -> Result { + let typeResult = self.geoJsonObjectTypeResult(geoJson: geoJson) + + switch typeResult { + case .success(let type): + if let invalidGeoJson = validateGeoJsonCoordinatesGeometry(geoJson: geoJson, type: type) { return .failure(invalidGeoJson) } + + return .success(geoJsonCoordinatesGeometry(validatedGeoJson: geoJson, type: type)) + case .failure(let invalidGeoJson): return .failure(invalidGeoJson) + } + } + + func geoJsonCoordinatesGeometry(fromValidatedGeoJson geoJson: GeoJsonDictionary) -> GeoJsonCoordinatesGeometry { + return geoJsonCoordinatesGeometry(validatedGeoJson: geoJson, type: geoJsonObjectTypeResult(geoJson: geoJson).success!) + } } -internal struct GeoJsonParser: GeoJsonParserProtocol { - // SOMEDAY: does not handle optional "bbox" or "crs" members - func geoJsonObject(from geoJsonDictionary: GeoJsonDictionary) -> GeoJsonObject? { - guard let type = geoJsonObjectType(geoJsonDictionary: geoJsonDictionary) else { return nil } +extension GeoJsonParser { + private func validateGeoJsonObject(geoJson: GeoJsonDictionary, type: GeoJsonObjectType) -> InvalidGeoJson? { + switch type { + case .feature: return GeoJson.Feature.validate(geoJson: geoJson) + case .featureCollection: return GeoJson.FeatureCollection.validate(geoJson: geoJson) + case .geometryCollection, .point, .multiPoint, .lineString, .multiLineString, .polygon, .multiPolygon: + return validateGeoJsonGeometry(geoJson: geoJson, type: type) + } + } + + private func validateGeoJsonGeometry(geoJson: GeoJsonDictionary, type: GeoJsonObjectType) -> InvalidGeoJson? { + switch type { + case .geometryCollection: return GeoJson.GeometryCollection.validate(geoJson: geoJson) + case .point, .multiPoint, .lineString, .multiLineString, .polygon, .multiPolygon: + return validateGeoJsonCoordinatesGeometry(geoJson: geoJson, type: type) + case .feature, .featureCollection: return .init(reason: "Not a GeoJsonGeometry") + } + } + + private func validateGeoJsonCoordinatesGeometry(geoJson: GeoJsonDictionary, type: GeoJsonObjectType) -> InvalidGeoJson? { + let coordinatesJson = self.coordinatesJson(geoJson: geoJson) + + switch coordinatesJson { + case .success(let coordinatesJson): + switch type { + case .point: return GeoJson.Point.validate(coordinatesJson: coordinatesJson) + case .multiPoint: return GeoJson.MultiPoint.validate(coordinatesJson: coordinatesJson) + case .lineString: return GeoJson.LineString.validate(coordinatesJson: coordinatesJson) + case .multiLineString: return GeoJson.MultiLineString.validate(coordinatesJson: coordinatesJson) + case .polygon: return GeoJson.Polygon.validate(coordinatesJson: coordinatesJson) + case .multiPolygon: return GeoJson.MultiPolygon.validate(coordinatesJson: coordinatesJson) + case .geometryCollection, .feature, .featureCollection: return .init(reason: "Not a GeoJsonCoordinatesGeometry") + } + case .failure(let invalidGeoJson): return invalidGeoJson + } + } + + private func geoJsonObjectTypeResult(geoJson: GeoJsonDictionary) -> Result { + guard let typeName = geoJson["type"] as? String else { return .failure(InvalidGeoJson(reason: "A valid geoJson must have a \"type\" key")) } + return GeoJsonObjectType(name: typeName).flatMap { .success($0) } ?? .failure(InvalidGeoJson(reason: "Invalid GeoJson Geometry type: \(typeName)")) + } + + private func geoJsonObject(validatedGeoJson geoJson: GeoJsonDictionary, type: GeoJsonObjectType) -> GeoJsonObject { switch type { - case .feature: - return GeoJson.Feature(geoJsonDictionary: geoJsonDictionary) - case .featureCollection: - return GeoJson.FeatureCollection(geoJsonDictionary: geoJsonDictionary) - default: return geometry(geoJsonDictionary: geoJsonDictionary, geoJsonObjectType: type) + case .feature: return GeoJson.Feature(geoJson: geoJson) + case .featureCollection: return GeoJson.FeatureCollection(geoJson: geoJson) + case .geometryCollection, .point, .multiPoint, .lineString, .multiLineString, .polygon, .multiPolygon: + return geoJsonGeometry(validatedGeoJson: geoJson, type: type) } } -} - -private extension GeoJsonParser { - private func geoJsonObjectType(geoJsonDictionary: GeoJsonDictionary) -> GeoJsonObjectType? { - guard let typeString = geoJsonDictionary["type"] as? String else { Log.warning("A valid geoJson must have a \"type\" key: String : \(geoJsonDictionary)"); return nil } - guard let type = GeoJsonObjectType(name: typeString) else { Log.warning("Invalid GeoJson Geometry type: \(typeString)"); return nil } - - return type - } - - private func geometry(geoJsonDictionary: GeoJsonDictionary, geoJsonObjectType: GeoJsonObjectType) -> GeoJsonGeometry? { - if geoJsonObjectType == .geometryCollection { return GeoJson.GeometryCollection(geoJsonDictionary: geoJsonDictionary) } - - guard let coordinates = geoJsonDictionary["coordinates"] as? [Any] else { Log.warning("A valid GeoJson Coordinates Geometry must have a valid \"coordinates\" array: String : \(geoJsonDictionary)"); return nil } - - switch geoJsonObjectType { - case .point: - return GeoJson.Point(coordinatesJson: coordinates) - case .multiPoint: - return GeoJson.MultiPoint(coordinatesJson: coordinates) - case .lineString: - return GeoJson.LineString(coordinatesJson: coordinates) - case .multiLineString: - return GeoJson.MultiLineString(coordinatesJson: coordinates) - case .polygon: - return GeoJson.Polygon(coordinatesJson: coordinates) - case .multiPolygon: - return GeoJson.MultiPolygon(coordinatesJson: coordinates) - default: - Log.warning("\(geoJsonObjectType.name) is not a valid Coordinates Geometry.") - return nil + + private func geoJsonGeometry(validatedGeoJson geoJson: GeoJsonDictionary, type: GeoJsonObjectType) -> GeoJsonGeometry { + switch type { + case .geometryCollection: return GeoJson.GeometryCollection(geoJson: geoJson) + case .point, .multiPoint, .lineString, .multiLineString, .polygon, .multiPolygon: + return geoJsonCoordinatesGeometry(validatedGeoJson: geoJson, type: type) + case .feature, .featureCollection: fatalError("Not a GeoJsonGeometry") } } + + private func geoJsonCoordinatesGeometry(validatedGeoJson geoJson: GeoJsonDictionary, type: GeoJsonObjectType) -> GeoJsonCoordinatesGeometry { + let coordinatesJson = self.coordinatesJson(geoJson: geoJson).success! + + switch type { + case .point: return GeoJson.Point(coordinatesJson: coordinatesJson) + case .multiPoint: return GeoJson.MultiPoint(coordinatesJson: coordinatesJson) + case .lineString: return GeoJson.LineString(coordinatesJson: coordinatesJson) + case .multiLineString: return GeoJson.MultiLineString(coordinatesJson: coordinatesJson) + case .polygon: return GeoJson.Polygon(coordinatesJson: coordinatesJson) + case .multiPolygon: return GeoJson.MultiPolygon(coordinatesJson: coordinatesJson) + case .geometryCollection, .feature, .featureCollection: fatalError("Not a GeoJsonCoordinatesGeometry") + } + } + + private func coordinatesJson(geoJson: GeoJsonDictionary) -> Result<[Any], InvalidGeoJson> { + (geoJson["coordinates"] as? [Any]).flatMap { .success($0) } ?? .failure(.init(reason: "A valid GeoJson Coordinates Geometry must have a valid \"coordinates\" array")) + } } diff --git a/Sources/GeospatialSwift/Parser/InvalidGeoJson.swift b/Sources/GeospatialSwift/Parser/InvalidGeoJson.swift new file mode 100644 index 0000000..0e7d0b5 --- /dev/null +++ b/Sources/GeospatialSwift/Parser/InvalidGeoJson.swift @@ -0,0 +1,15 @@ +public struct InvalidGeoJson: Error { + public let reasons: [String] +} + +internal extension InvalidGeoJson { + init (reason: String) { + reasons = [reason] + } +} + +internal func + (lhs: InvalidGeoJson?, rhs: InvalidGeoJson?) -> InvalidGeoJson? { + guard let lhs = lhs else { return rhs } + guard let rhs = rhs else { return lhs } + return .init(reasons: lhs.reasons + rhs.reasons) +} diff --git a/Sources/GeospatialSwift/Parser/WktParser.swift b/Sources/GeospatialSwift/Parser/WktParser.swift index 26cb2e1..259b161 100644 --- a/Sources/GeospatialSwift/Parser/WktParser.swift +++ b/Sources/GeospatialSwift/Parser/WktParser.swift @@ -1,16 +1,12 @@ import Foundation -internal protocol WktParserProtocol { - func geoJsonObject(from wkt: String) -> GeoJsonObject? -} - // SOMEDAY: Forced unwrapping leads to exceptions when WKT is invalid. -internal struct WktParser: WktParserProtocol { - let geoJson: GeoJsonProtocol +internal struct WktParser { + let geoJson: GeoJson func geoJsonObject(from wkt: String) -> GeoJsonObject? { - guard let startRange = wkt.range(of: "(") else { Log.warning("Malformed WKT: \(wkt)"); return nil } - guard let endRange = wkt.range(of: ")", options: .backwards) else { Log.warning("Malformed WKT: \(wkt)"); return nil } + guard let startRange = wkt.range(of: "(") else { return nil } + guard let endRange = wkt.range(of: ")", options: .backwards) else { return nil } let range = startRange.upperBound.. GeoJsonPoint { + private func parsePointString(_ data: String) throws -> GeoJson.Point { let formatter = NumberFormatter.formatterForCoordinates let coordinates = data.trimmingCharacters(in: CharacterSet(charactersIn: " ")).components(separatedBy: " ") @@ -63,20 +55,20 @@ internal struct WktParser: WktParserProtocol { return geoJson.point(longitude: longitude, latitude: latitude) } - private func parseLineString(_ data: String) throws -> GeoJsonLineString { + private func parseLineString(_ data: String) throws -> GeoJson.LineString { let points = try data.components(separatedBy: ",").map { try parsePointString($0) } - return geoJson.lineString(points: points)! + return geoJson.lineString(points: points).success! } - private func parsePolygonString(_ data: String) throws -> GeoJsonPolygon { - let linearRings: [GeoJsonLineString] = try data.wktTokens.map { wktLinearRing in + private func parsePolygonString(_ data: String) throws -> GeoJson.Polygon { + let linearRings: [GeoJson.LineString] = try data.wktTokens.map { wktLinearRing in let wktPoints = wktLinearRing.components(separatedBy: ",") - return geoJson.lineString(points: try wktPoints.map { try parsePointString($0) })! + return geoJson.lineString(points: try wktPoints.map { try parsePointString($0) }).success! } - return geoJson.polygon(linearRings: linearRings)! + return geoJson.polygon(mainRing: linearRings.first!, negativeRings: Array(linearRings.dropFirst())).success! } } diff --git a/Sources/GeospatialSwift/Timber/Timber.swift b/Sources/GeospatialSwift/Timber/Timber.swift deleted file mode 100644 index afb005c..0000000 --- a/Sources/GeospatialSwift/Timber/Timber.swift +++ /dev/null @@ -1,6 +0,0 @@ -import Foundation -import TimberSwift - -private let timber: TimberProtocol = Timber(source: Source(title: "Geospatial Swift", version: Bundle.sourceVersion, emoji: "🗺️")) - -internal let Log = timber.log diff --git a/Sources/Info tvOS.plist b/Sources/Info tvOS.plist index ffbb93f..070fd26 100644 --- a/Sources/Info tvOS.plist +++ b/Sources/Info tvOS.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.4.0 + $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/Sources/Info.plist b/Sources/Info.plist index fff2849..fcd3639 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.4.0 + $(MARKETING_VERSION) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/Tests/GeospatialSwiftTests/Data/GeoTestHelper.swift b/Tests/GeospatialSwiftTests/Data/GeoTestHelper.swift index acbc617..086945c 100644 --- a/Tests/GeospatialSwiftTests/Data/GeoTestHelper.swift +++ b/Tests/GeospatialSwiftTests/Data/GeoTestHelper.swift @@ -1,50 +1,27 @@ @testable import GeospatialSwift -// swiftlint:disable force_cast class GeoTestHelper { - static private let geoJson = GeoJson() + static private let geoJsonHandler = GeoJson() - static func parse(_ geoJsonDictionary: GeoJsonDictionary) -> GeoJsonObject { - return geoJson.parse(geoJson: geoJsonDictionary)! - } + static func parse(_ geoJson: GeoJsonDictionary) -> GeoJsonObject { geoJsonHandler.parseObject(fromValidatedGeoJson: geoJson) } - static func simplePoint(_ longitude: Double, _ latitude: Double, _ altitude: Double? = nil) -> SimplePoint { - return SimplePoint(longitude: longitude, latitude: latitude, altitude: altitude) - } + static func simplePoint(_ longitude: Double, _ latitude: Double, _ altitude: Double? = nil) -> SimplePoint { SimplePoint(longitude: longitude, latitude: latitude, altitude: altitude) } - static func point(_ longitude: Double, _ latitude: Double, _ altitude: Double? = nil) -> Point { - return geoJson.point(longitude: longitude, latitude: latitude, altitude: altitude) as! Point - } + static func point(_ longitude: Double, _ latitude: Double, _ altitude: Double? = nil) -> Point { geoJsonHandler.point(longitude: longitude, latitude: latitude, altitude: altitude) } - static func multiPoint(_ points: [GeoJsonPoint]) -> MultiPoint { - return geoJson.multiPoint(points: points) as! MultiPoint - } + static func multiPoint(_ points: [GeoJson.Point]) -> MultiPoint { geoJsonHandler.multiPoint(points: points).success! } - static func lineString(_ points: [GeoJsonPoint]) -> LineString { - return geoJson.lineString(points: points) as! LineString - } + static func lineString(_ points: [GeoJson.Point]) -> LineString { geoJsonHandler.lineString(points: points).success! } - static func multiLineString(_ lineStrings: [GeoJsonLineString]) -> MultiLineString { - return geoJson.multiLineString(lineStrings: lineStrings) as! MultiLineString - } + static func multiLineString(_ lineStrings: [GeoJson.LineString]) -> MultiLineString { geoJsonHandler.multiLineString(lineStrings: lineStrings).success! } - static func polygon(_ linearRings: [GeoJsonLineString]) -> Polygon { - return geoJson.polygon(linearRings: linearRings) as! Polygon - } + static func polygon(_ mainRing: GeoJson.LineString, _ negativeRings: [GeoJson.LineString] = []) -> Polygon { geoJsonHandler.polygon(mainRing: mainRing, negativeRings: negativeRings).success! } - static func multiPolygon(_ polygons: [GeoJsonPolygon]) -> MultiPolygon { - return geoJson.multiPolygon(polygons: polygons) as! MultiPolygon - } + static func multiPolygon(_ polygons: [GeoJson.Polygon]) -> MultiPolygon { geoJsonHandler.multiPolygon(polygons: polygons).success! } - static func geometryCollection(_ geometries: [GeoJsonGeometry]? = nil) -> GeometryCollection { - return geoJson.geometryCollection(geometries: geometries) as! GeometryCollection - } + static func geometryCollection(_ geometries: [GeoJsonGeometry]) -> GeometryCollection { geoJsonHandler.geometryCollection(geometries: geometries) } - static func feature(_ geometry: GeoJsonGeometry?, _ id: Any? = nil, _ properties: GeoJsonDictionary? = nil) -> Feature { - return geoJson.feature(geometry: geometry, id: id, properties: properties) as! Feature - } + static func feature(_ geometry: GeoJsonGeometry?, _ id: Any? = nil, _ properties: GeoJsonDictionary? = nil) -> Feature { geoJsonHandler.feature(geometry: geometry, id: id, properties: properties).success! } - static func featureCollection(_ features: [GeoJsonFeature]) -> FeatureCollection { - return geoJson.featureCollection(features: features) as! FeatureCollection - } + static func featureCollection(_ features: [GeoJson.Feature]) -> FeatureCollection { geoJsonHandler.featureCollection(features: features).success! } } diff --git a/Tests/GeospatialSwiftTests/Data/MockData.swift b/Tests/GeospatialSwiftTests/Data/MockData.swift index 0ec9ab0..a9bca26 100644 --- a/Tests/GeospatialSwiftTests/Data/MockData.swift +++ b/Tests/GeospatialSwiftTests/Data/MockData.swift @@ -6,38 +6,32 @@ import Foundation final class MockData { static let geoJson = GeoJson() - static let geoJsonTestData: [GeoJsonDictionary] = { return json(jsonString: geoJsonTestJson)["geoJsonObjects"] as! [GeoJsonDictionary] }() - static let wktTestData: [GeoJsonDictionary] = { return json(jsonString: wktTestJson)["wktObjects"] as! [GeoJsonDictionary] }() + static let geoJsonTestData: [GeoJsonDictionary] = { json(jsonString: geoJsonTestJson)["geoJsonObjects"] as! [GeoJsonDictionary] }() + static let wktTestData: [GeoJsonDictionary] = { json(jsonString: wktTestJson)["wktObjects"] as! [GeoJsonDictionary] }() - static func testGeoJson(_ name: String) -> GeoJsonDictionary { - return geoJsonTestData.first { ($0["name"] as! String) == name }!["geoJson"] as! GeoJsonDictionary - } + static func testGeoJson(_ name: String) -> GeoJsonDictionary { geoJsonTestData.first { ($0["name"] as! String) == name }!["geoJson"] as! GeoJsonDictionary } - static func testGeoJsonObject(geoJsonDataName: String) -> GeoJsonObject { - return geoJson.parse(geoJson: testGeoJson(geoJsonDataName))! - } + static func testGeoJsonObject(geoJsonDataName: String) -> GeoJsonObject { geoJson.parseObject(fromValidatedGeoJson: testGeoJson(geoJsonDataName)) } - static func testWkt(_ name: String) -> String { - return wktTestData.first { ($0["name"] as! String) == name }!["wkt"] as! String - } + static func testWkt(_ name: String) -> String { wktTestData.first { ($0["name"] as! String) == name }!["wkt"] as! String } - static let point: GeoJsonPoint = geoJson.point(longitude: 1, latitude: 2, altitude: 3) - static let points: [GeoJsonPoint] = linesPoints.first! - static let lineStrings: [GeoJsonLineString] = linesPoints.map { geoJson.lineString(points: $0)! } - static let linearRings: [GeoJsonLineString] = linearRingsList.first! - static let polygons: [GeoJsonPolygon] = linearRingsList.map { geoJson.polygon(linearRings: $0)! } + static let point: GeoJson.Point = geoJson.point(longitude: 1, latitude: 2, altitude: 3) + static let points: [GeoJson.Point] = linesPoints.first! + static let lineStrings: [GeoJson.LineString] = linesPoints.map { geoJson.lineString(points: $0).success! } + static let linearRings: [GeoJson.LineString] = linearRingsList.first! + static let polygons: [GeoJson.Polygon] = linearRingsList.map { geoJson.polygon(mainRing: $0.first!, negativeRings: Array($0.dropFirst())).success! } static let geometries: [GeoJsonGeometry] = [ MockData.point, - geoJson.multiPoint(points: MockData.points)!, - geoJson.lineString(points: MockData.points)!, - geoJson.multiLineString(lineStrings: MockData.lineStrings)!, - geoJson.polygon(linearRings: MockData.linearRings)!, - geoJson.multiPolygon(polygons: MockData.polygons)! + geoJson.multiPoint(points: MockData.points).success!, + geoJson.lineString(points: MockData.points).success!, + geoJson.multiLineString(lineStrings: MockData.lineStrings).success!, + geoJson.polygon(mainRing: MockData.linearRings.first!, negativeRings: Array(MockData.linearRings.dropFirst())).success!, + geoJson.multiPolygon(polygons: MockData.polygons).success! ] - static let features: [GeoJsonFeature] = [ - geoJson.feature(geometry: geoJson.point(longitude: 1, latitude: 2, altitude: 3), id: nil, properties: nil)!, - geoJson.feature(geometry: geoJson.lineString(points: MockData.points)!, id: nil, properties: nil)!, - geoJson.feature(geometry: geoJson.polygon(linearRings: MockData.linearRings)!, id: nil, properties: nil)! + static let features: [GeoJson.Feature] = [ + geoJson.feature(geometry: geoJson.point(longitude: 1, latitude: 2, altitude: 3), id: nil, properties: nil).success!, + geoJson.feature(geometry: geoJson.lineString(points: MockData.points).success!, id: nil, properties: nil).success!, + geoJson.feature(geometry: geoJson.polygon(mainRing: MockData.linearRings.first!, negativeRings: Array(MockData.linearRings.dropFirst())).success!, id: nil, properties: nil).success! ] static let pointsCoordinatesJson = [[1.0, 2.0, 3.0], [2.0, 2.0, 4.0], [2.0, 3.0, 5.0]] @@ -61,14 +55,14 @@ extension MockData { return jsonData as! GeoJsonDictionary } - private static let linesPoints: [[GeoJsonPoint]] = [ + private static let linesPoints: [[GeoJson.Point]] = [ [GeoTestHelper.point(1, 2, 3), GeoTestHelper.point(2, 2, 4), GeoTestHelper.point(2, 3, 5)], [GeoTestHelper.point(2, 3, 3), GeoTestHelper.point(3, 3, 4), GeoTestHelper.point(3, 4, 5), GeoTestHelper.point(4, 5, 6)] ] - private static let polygonPoints: [[GeoJsonPoint]] = polygonPointsList.first! + private static let polygonPoints: [[GeoJson.Point]] = polygonPointsList.first! - private static let polygonPointsList: [[[GeoJsonPoint]]] = [ + private static let polygonPointsList: [[[GeoJson.Point]]] = [ [ [GeoTestHelper.point(1, 2, 3), GeoTestHelper.point(2, 2, 4), GeoTestHelper.point(2, 3, 5), GeoTestHelper.point(1, 3, 4), GeoTestHelper.point(1, 2, 3)], [GeoTestHelper.point(2, 3, 3), GeoTestHelper.point(3, 3, 4), GeoTestHelper.point(3, 4, 5), GeoTestHelper.point(2, 4, 4), GeoTestHelper.point(2, 3, 3)] @@ -79,5 +73,5 @@ extension MockData { ] ] - private static let linearRingsList: [[GeoJsonLineString]] = polygonPointsList.map { $0.map { geoJson.lineString(points: $0)! } } + private static let linearRingsList: [[GeoJson.LineString]] = polygonPointsList.map { $0.map { geoJson.lineString(points: $0).success! } } } diff --git a/Tests/GeospatialSwiftTests/Mock/API/Calculator/MockGeodesicCalculator.swift b/Tests/GeospatialSwiftTests/Mock/API/Calculator/MockGeodesicCalculator.swift deleted file mode 100644 index 5621981..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/Calculator/MockGeodesicCalculator.swift +++ /dev/null @@ -1,263 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeodesicCalculator: GeodesicCalculatorProtocol { - private(set) var destinationPointCallCount = 0 - func destinationPoint(origin: GeodesicPoint, bearing: Double, distance: Double) -> GeodesicPoint { - destinationPointCallCount += 1 - - return origin - } - - private(set) var equalsCallCount = 0 - var equalsResult: Bool = false - func equals(_ points: [GeodesicPoint], tolerance: Double) -> Bool { - equalsCallCount += 1 - - return equalsResult - } - - private(set) var equalsIndicesCallCount = 0 - var equalsIndicesResult: [Int] = [] - func equalsIndices(_ points: [GeodesicPoint], tolerance: Double) -> [Int] { - equalsIndicesCallCount += 1 - - return equalsIndicesResult - } - - private(set) var hasIntersectionLineCallCount = 0 - var hasIntersectionLineResult: Bool = false - func hasIntersection(_ lineSegment1: GeodesicLineSegment, with lineSegment2: GeodesicLineSegment, tolerance: Double) -> Bool { - hasIntersectionLineCallCount += 1 - - return hasIntersectionLineResult - } - - private(set) var hasIntersectionPolygonCallCount = 0 - var hasIntersectionPolygonResult: Bool = false - func hasIntersection(_ lineSegment: GeodesicLineSegment, with polygon: GeodesicPolygon, tolerance: Double) -> Bool { - hasIntersectionPolygonCallCount += 1 - - return hasIntersectionPolygonResult - } - - private(set) var hasSelfIntersectionLineCallCount = 0 - var hasSelfIntersectionLineResult: Bool = false - func hasIntersection(_ line: GeodesicLine, tolerance: Double) -> Bool { - hasSelfIntersectionLineCallCount += 1 - - return hasSelfIntersectionLineResult - } - - private(set) var hasSelfIntersectionPolygonCallCount = 0 - var hasSelfIntersectionPolygonResult: Bool = false - func hasIntersection(_ polygon: GeodesicPolygon, tolerance: Double) -> Bool { - hasSelfIntersectionPolygonCallCount += 1 - - return hasSelfIntersectionPolygonResult - } - - private(set) var intersectionLineCallCount = 0 - var intersectionLineResult: GeodesicPoint? - func intersection(of lineSegment: GeodesicLineSegment, with otherLineSegment: GeodesicLineSegment) -> GeodesicPoint? { - intersectionLineCallCount += 1 - - return intersectionLineResult - } - - private(set) var intersectionIndicesLineCallCount = 0 - var intersectionIndicesLineResult: [Int] = [] - func intersectionIndices(from line: GeodesicLine, tolerance: Double) -> [Int] { - intersectionIndicesLineCallCount += 1 - - return intersectionIndicesLineResult - } - - private(set) var intersectionIndicesPolygonCallCount = 0 - var intersectionIndicesPolygonResult: [[[Int]]] = [] - func intersectionIndices(from polygon: GeodesicPolygon, tolerance: Double) -> [[[Int]]] { - intersectionIndicesPolygonCallCount += 1 - - return intersectionIndicesPolygonResult - } - - private(set) var lineLengthCallCount = 0 - var lineLengthResult: Double = 0 - func length(of line: GeodesicLine) -> Double { - lineLengthCallCount += 1 - - return lineLengthResult - } - - private(set) var polygonAreaCallCount = 0 - var polygonAreaResult: Double = 0 - func area(of polygon: GeodesicPolygon) -> Double { - polygonAreaCallCount += 1 - - return polygonAreaResult - } - - func centroid(polygon: GeodesicPolygon) -> GeodesicPoint { - return polygon.points.first! - } - - private(set) var distanceToPointCallCount = 0 - var distanceToPointResult: Double = 0 - func distance(from point: GeodesicPoint, to otherPoint: GeodesicPoint, tolerance: Double) -> Double { - distanceToPointCallCount += 1 - - return distanceToPointResult - } - - private(set) var distanceToLineCallCount = 0 - var distanceToLineResult: Double = 0 - func distance(from point: GeodesicPoint, to lineSegment: GeodesicLineSegment, tolerance: Double) -> Double { - distanceToLineCallCount += 1 - - return distanceToLineResult - } - - private(set) var distanceToLinesCallCount = 0 - var distanceToLinesResult: Double = 0 - func distance(from point: GeodesicPoint, to line: GeodesicLine, tolerance: Double) -> Double { - distanceToLinesCallCount += 1 - - return distanceToLinesResult - } - - private(set) var distanceToPolygonCallCount = 0 - var distanceToPolygoResult: Double = 0 - func distance(from point: GeodesicPoint, to polygon: GeodesicPolygon, tolerance: Double) -> Double { - distanceToPolygonCallCount += 1 - - return distanceToPolygoResult - } - - private(set) var edgeDistanceToPolygonCallCount = 0 - var edgeDistanceToPolygoResult: Double = 0 - func edgeDistance(from point: GeodesicPoint, to polygon: GeodesicPolygon, tolerance: Double) -> Double { - edgeDistanceToPolygonCallCount += 1 - - return edgeDistanceToPolygoResult - } - - private(set) var distanceFromLineToLineCallCount = 0 - var distanceFromLineToLineResult: Double = 0 - func distance(from lineSegment: GeodesicLineSegment, to otherLineSegment: GeodesicLineSegment, tolerance: Double) -> Double { - distanceFromLineToLineCallCount += 1 - - return distanceFromLineToLineResult - } - - private(set) var lawOfCosinesDistanceCallCount = 0 - var lawOfCosinesDistanceResult: Double = 0 - func lawOfCosinesDistance(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - lawOfCosinesDistanceCallCount += 1 - - return lawOfCosinesDistanceResult - } - - private(set) var haversineDistanceCallCount = 0 - var haversineDistanceResult: Double = 0 - func haversineDistance(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - haversineDistanceCallCount += 1 - - return haversineDistanceResult - } - - private(set) var containsLineCallCount = 0 - var containsLineResult: Bool = false - func contains(_ point: GeodesicPoint, in lineSegment: GeodesicLineSegment, tolerance: Double) -> Bool { - containsLineCallCount += 1 - - return containsLineResult - } - - private(set) var containsLinesCallCount = 0 - var containsLinesResult: Bool = false - func contains(_ point: GeodesicPoint, in line: GeodesicLine, tolerance: Double) -> Bool { - containsLinesCallCount += 1 - - return containsLinesResult - } - - private(set) var containsPolygonCallCount = 0 - var containsPolygonResult: Bool = false - func contains(_ point: GeodesicPoint, in polygon: GeodesicPolygon, tolerance: Double) -> Bool { - containsPolygonCallCount += 1 - - return containsPolygonResult - } - - private(set) var midpointCallCount = 0 - func midpoint(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> GeodesicPoint { - midpointCallCount += 1 - - return point - } - - private(set) var normalizeLongitudeCallCount = 0 - func normalize(longitude: Double) -> Double { - normalizeLongitudeCallCount += 1 - - return longitude - } - - private(set) var normalizeLatitudeCallCount = 0 - func normalize(latitude: Double) -> Double { - normalizeLatitudeCallCount += 1 - - return latitude - } - - private(set) var normalizeCallCount = 0 - func normalize(_ point: GeodesicPoint) -> GeodesicPoint { - normalizeCallCount += 1 - - return point - } - - private(set) var normalizePositiveLongitudeCallCount = 0 - func normalizePositive(longitude: Double) -> Double { - normalizePositiveLongitudeCallCount += 1 - - return longitude - } - - private(set) var normalizePositiveLatitudeCallCount = 0 - func normalizePositive(latitude: Double) -> Double { - normalizePositiveLatitudeCallCount += 1 - - return latitude - } - - private(set) var normalizePositiveCallCount = 0 - func normalizePositive(_ point: GeodesicPoint) -> GeodesicPoint { - normalizePositiveCallCount += 1 - - return point - } - - private(set) var initialBearingCallCount = 0 - var initialBearingResult: Double = 0 - func initialBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - initialBearingCallCount += 1 - - return initialBearingResult - } - - private(set) var averageBearingCallCount = 0 - var averageBearingResult: Double = 0 - func averageBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - averageBearingCallCount += 1 - - return averageBearingResult - } - - private(set) var finalBearingCallCount = 0 - var finalBearingResult: Double = 0 - func finalBearing(from point: GeodesicPoint, to otherPoint: GeodesicPoint) -> Double { - finalBearingCallCount += 1 - - return finalBearingResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonBoundingBox.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonBoundingBox.swift deleted file mode 100644 index a56cbc2..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonBoundingBox.swift +++ /dev/null @@ -1,125 +0,0 @@ -@testable import GeospatialSwift - -class MockGeoJsonBoundingBox: GeodesicBoundingBox { - var segments: [GeodesicLineSegment] = MockData.box.linearRings.flatMap { $0.segments } - - var box: GeodesicPolygon = MockData.box - - var description: String = "" - - private(set) var minLongitudeCallCount = 0 - var minLongitude: Double { - minLongitudeCallCount += 1 - - return boundingCoordinatesResult.minLongitude - } - - private(set) var minLatitudeCallCount = 0 - var minLatitude: Double { - minLatitudeCallCount += 1 - - return boundingCoordinatesResult.minLatitude - } - - private(set) var maxLongitudeCallCount = 0 - var maxLongitude: Double { - maxLongitudeCallCount += 1 - - return boundingCoordinatesResult.maxLongitude - } - - private(set) var maxLatitudeCallCount = 0 - var maxLatitude: Double { - maxLatitudeCallCount += 1 - - return boundingCoordinatesResult.maxLatitude - } - - private(set) var longitudeDeltaCallCount = 0 - var longitudeDeltaResult: Double = 0 - var longitudeDelta: Double { - longitudeDeltaCallCount += 1 - - return longitudeDeltaResult - } - - private(set) var latitudeDeltaCallCount = 0 - var latitudeDeltaResult: Double = 0 - var latitudeDelta: Double { - latitudeDeltaCallCount += 1 - - return latitudeDeltaResult - } - - private(set) var polygonCallCount = 0 - lazy var polygonResult: GeoJsonPolygon = MockGeoJsonPolygon() - var polygon: GeoJsonPolygon { - polygonCallCount += 1 - - return polygonResult - } - - private(set) var pointsCallCount = 0 - var pointsResult: [GeoJsonPoint] = [] - var points: [GeodesicPoint] { - pointsCallCount += 1 - - return pointsResult - } - - private(set) var centroidCallCount = 0 - lazy var centroidResult: GeoJsonPoint = MockGeoJsonPoint() - var centroid: GeodesicPoint { - centroidCallCount += 1 - - return centroidResult - } - - private(set) var bestCallCount = 0 - lazy var bestResult: GeodesicBoundingBox = MockGeoJsonBoundingBox() - func best(_ boundingBoxes: [GeodesicBoundingBox]) -> GeodesicBoundingBox { - bestCallCount += 1 - - return bestResult - } - - private(set) var validBoundingBoxCallCount = 0 - lazy var validBoundingBoxResult: GeodesicBoundingBox = MockGeoJsonBoundingBox() - func validBoundingBox(minimumAdjustment: Double) -> GeodesicBoundingBox { - validBoundingBoxCallCount += 1 - - return validBoundingBoxResult - } - - private(set) var insetBoundingBoxCallCount = 0 - lazy var insetBoundingBoxResult: GeodesicBoundingBox = MockGeoJsonBoundingBox() - func insetBoundingBox(topPercent: Double, leftPercent: Double, bottomPercent: Double, rightPercent: Double) -> GeodesicBoundingBox { - insetBoundingBoxCallCount += 1 - - return insetBoundingBoxResult - } - - private(set) var containsCallCount = 0 - var containsResult: Bool = false - func contains(point: GeodesicPoint, tolerance: Double) -> Bool { - containsCallCount += 1 - - return containsResult - } - - private(set) var overlapsCallCount = 0 - var overlapsResult: Bool = false - func overlaps(boundingBox: GeodesicBoundingBox, tolerance: Double) -> Bool { - overlapsCallCount += 1 - - return overlapsResult - } - - private(set) var boundingCoordinatesCallCount = 0 - var boundingCoordinatesResult: BoundingCoordinates = (0, 0, 0, 0) - var boundingCoordinates: BoundingCoordinates { - boundingCoordinatesCallCount += 1 - - return boundingCoordinatesResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonGeohashBox.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonGeohashBox.swift deleted file mode 100644 index cd82727..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Box/MockGeoJsonGeohashBox.swift +++ /dev/null @@ -1,19 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonGeohashBox: MockGeoJsonBoundingBox, GeoJsonGeohashBox { - private(set) var geohashCallCount = 0 - var geohashResult: String = "" - var geohash: String { - geohashCallCount += 1 - - return geohashResult - } - - private(set) var geohashNeighborCallCount = 0 - lazy var geohashNeighborResult: GeoJsonGeohashBox = MockGeoJsonGeohashBox() - func geohashNeighbor(direction: GeohashCompassPoint, precision: Int) -> GeoJsonGeohashBox { - geohashNeighborCallCount += 1 - - return geohashNeighborResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJson.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJson.swift deleted file mode 100644 index ff4885f..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJson.swift +++ /dev/null @@ -1,91 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJson: GeoJsonProtocol { - private(set) var parseCallCount = 0 - var parseResult: GeoJsonObject = MockGeoJsonPoint() - func parse(geoJson: GeoJsonDictionary) -> GeoJsonObject? { - parseCallCount += 1 - - return parseResult - } - - private(set) var featureCollectionCallCount = 0 - var featureCollectionResult: GeoJsonFeatureCollection = MockGeoJsonFeatureCollection() - func featureCollection(features: [GeoJsonFeature]) -> GeoJsonFeatureCollection? { - featureCollectionCallCount += 1 - - return featureCollectionResult - } - - private(set) var featureCallCount = 0 - var featureResult: GeoJsonFeature = MockGeoJsonFeature() - func feature(geometry: GeoJsonGeometry?, id: Any?, properties: GeoJsonDictionary?) -> GeoJsonFeature? { - featureCallCount += 1 - - return featureResult - } - - private(set) var geometryCollectionCallCount = 0 - var geometryCollectionResult: GeoJsonGeometryCollection = MockGeoJsonGeometryCollection() - func geometryCollection(geometries: [GeoJsonGeometry]?) -> GeoJsonGeometryCollection { - geometryCollectionCallCount += 1 - - return geometryCollectionResult - } - - private(set) var multiPolygonCallCount = 0 - var multiPolygonResult: GeoJsonMultiPolygon = MockGeoJsonMultiPolygon() - func multiPolygon(polygons: [GeoJsonPolygon]) -> GeoJsonMultiPolygon? { - multiPolygonCallCount += 1 - - return multiPolygonResult - } - - private(set) var polygonCallCount = 0 - var polygonResult: GeoJsonPolygon = MockGeoJsonPolygon() - func polygon(linearRings: [GeoJsonLineString]) -> GeoJsonPolygon? { - polygonCallCount += 1 - - return polygonResult - } - - private(set) var multiLineStringCallCount = 0 - var multiLineStringResult: GeoJsonMultiLineString = MockGeoJsonMultiLineString() - func multiLineString(lineStrings: [GeoJsonLineString]) -> GeoJsonMultiLineString? { - multiLineStringCallCount += 1 - - return multiLineStringResult - } - - private(set) var lineStringCallCount = 0 - var lineStringResult: GeoJsonLineString = MockGeoJsonLineString() - func lineString(points: [GeoJsonPoint]) -> GeoJsonLineString? { - lineStringCallCount += 1 - - return lineStringResult - } - - private(set) var multiPointCallCount = 0 - var multiPointResult: GeoJsonMultiPoint = MockGeoJsonMultiPoint() - func multiPoint(points: [GeoJsonPoint]) -> GeoJsonMultiPoint? { - multiPointCallCount += 1 - - return multiPointResult - } - - private(set) var pointAltitudeCallCount = 0 - var pointAltitudeResult: GeoJsonPoint = MockGeoJsonPoint() - func point(longitude: Double, latitude: Double, altitude: Double?) -> GeoJsonPoint { - pointAltitudeCallCount += 1 - - return pointAltitudeResult - } - - private(set) var pointCallCount = 0 - var pointResult: GeoJsonPoint = MockGeoJsonPoint() - func point(longitude: Double, latitude: Double) -> GeoJsonPoint { - pointCallCount += 1 - - return pointResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonClosedGeometry.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonClosedGeometry.swift deleted file mode 100644 index 0bfe683..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonClosedGeometry.swift +++ /dev/null @@ -1,27 +0,0 @@ -@testable import GeospatialSwift - -class MockGeoJsonClosedGeometry: MockGeoJsonCoordinatesGeometry, GeoJsonClosedGeometry { - private(set) var edgeDistanceCallCount = 0 - var edgeDistanceResult: Double = 0 - func edgeDistance(to point: GeodesicPoint, tolerance: Double) -> Double { - edgeDistanceCallCount += 1 - - return edgeDistanceResult - } - - private(set) var hasHoleCallCount = 0 - var hasHoleResult: Bool = false - var hasHole: Bool { - hasHoleCallCount += 1 - - return hasHoleResult - } - - private(set) var areaCallCount = 0 - var areaResult: Double = 0 - var area: Double { - areaCallCount += 1 - - return areaResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonCoordinatesGeometry.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonCoordinatesGeometry.swift deleted file mode 100644 index 59f85a5..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonCoordinatesGeometry.swift +++ /dev/null @@ -1,35 +0,0 @@ -@testable import GeospatialSwift - -class MockGeoJsonCoordinatesGeometry: MockGeoJsonGeometry, GeoJsonCoordinatesGeometry { - private(set) var geoJsonCoordinatesCallCount = 0 - var geoJsonCoordinatesResult: [Any] = [] - var geoJsonCoordinates: [Any] { - geoJsonCoordinatesCallCount += 1 - - return geoJsonCoordinatesResult - } - - private(set) var boundingBoxCallCount = 0 - lazy var boundingBoxResult: GeodesicBoundingBox = MockGeoJsonBoundingBox() - var boundingBox: GeodesicBoundingBox { - boundingBoxCallCount += 1 - - return boundingBoxResult - } - - private(set) var distanceCallCount = 0 - var distanceResult: Double = 0 - func distance(to point: GeodesicPoint, tolerance: Double) -> Double { - distanceCallCount += 1 - - return distanceResult - } - - private(set) var pointsCallCount = 0 - var pointsResult: [GeoJsonPoint] = [] - var points: [GeodesicPoint] { - pointsCallCount += 1 - - return pointsResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonGeometry.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonGeometry.swift deleted file mode 100644 index d62a1a3..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonGeometry.swift +++ /dev/null @@ -1,4 +0,0 @@ -@testable import GeospatialSwift - -class MockGeoJsonGeometry: MockGeoJsonObject, GeoJsonGeometry { -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonLinearGeometry.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonLinearGeometry.swift deleted file mode 100644 index 36b4c5b..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonLinearGeometry.swift +++ /dev/null @@ -1,11 +0,0 @@ -@testable import GeospatialSwift - -class MockGeoJsonLinearGeometry: MockGeoJsonCoordinatesGeometry, GeoJsonLinearGeometry { - private(set) var lengthCallCount = 0 - var lengthResult: Double = 0 - var length: Double { - lengthCallCount += 1 - - return lengthResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonObject.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonObject.swift deleted file mode 100644 index df4d2f6..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/MockGeoJsonObject.swift +++ /dev/null @@ -1,56 +0,0 @@ -@testable import GeospatialSwift - -class MockGeoJsonObject: GeoJsonObject { - private(set) var geoJsonObjectTypeCallCount = 0 - var geoJsonObjectTypeResult: GeoJsonObjectType = .point - - var description: String = "" - - var type: GeoJsonObjectType { - geoJsonObjectTypeCallCount += 1 - - return geoJsonObjectTypeResult - } - - private(set) var objectGeometriesCallCount = 0 - var objectGeometriesResult: [GeoJsonGeometry]? - var objectGeometries: [GeoJsonGeometry]? { - objectGeometriesCallCount += 1 - - return objectGeometriesResult - } - - private(set) var objectBoundingBoxCallCount = 0 - var objectBoundingBoxResult: GeodesicBoundingBox? - var objectBoundingBox: GeodesicBoundingBox? { - objectBoundingBoxCallCount += 1 - - return objectBoundingBoxResult - } - - private(set) var geoJsonCallCount = 0 - var geoJsonResult: GeoJsonDictionary = [:] - var geoJson: GeoJsonDictionary { - geoJsonCallCount += 1 - - return geoJsonResult - } - - private(set) var objectDistanceCallCount = 0 - var objectDistanceResult: Double? - func objectDistance(to point: GeodesicPoint, tolerance: Double) -> Double? { - objectDistanceCallCount += 1 - - return objectDistanceResult - } - - private(set) var containsCallCount = 0 - private(set) var containsToleranceCallCount = 0 - var containsResult: Bool = false - var containsToleranceResult: Bool = false - func contains(_ point: GeodesicPoint, tolerance: Double) -> Bool { - if tolerance > 0 { containsToleranceCallCount += 1 } else { containsCallCount += 1 } - - return tolerance > 0 ? containsToleranceResult : containsResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeature.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeature.swift deleted file mode 100644 index 006d309..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeature.swift +++ /dev/null @@ -1,41 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonFeature: MockGeoJsonObject, GeoJsonFeature { - override init() { - super.init() - - geoJsonObjectTypeResult = .feature - } - - private(set) var geometryCallCount: Int = 0 - var geometryResult: GeoJsonGeometry? = MockGeoJsonPolygon() - var geometry: GeoJsonGeometry? { - geometryCallCount += 1 - - return geometryResult - } - - private(set) var idCallCount: Int = 0 - var idResult: Any? - var id: Any? { - idCallCount += 1 - - return idResult - } - - private(set) var idAsStringCallCount: Int = 0 - var idAsStringResult: String? - var idAsString: String? { - idAsStringCallCount += 1 - - return idAsStringResult - } - - private(set) var propertiesCallCount: Int = 0 - var propertiesResult: GeoJsonDictionary? - var properties: GeoJsonDictionary? { - propertiesCallCount += 1 - - return propertiesResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeatureCollection.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeatureCollection.swift deleted file mode 100644 index 906998b..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonFeatureCollection.swift +++ /dev/null @@ -1,11 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonFeatureCollection: MockGeoJsonObject, GeoJsonFeatureCollection { - private(set) var featuresCallCount = 0 - var featuresResult: [GeoJsonFeature] = [] - var features: [GeoJsonFeature] { - featuresCallCount += 1 - - return featuresResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonGeometryCollection.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonGeometryCollection.swift deleted file mode 100644 index a43c54c..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonGeometryCollection.swift +++ /dev/null @@ -1,4 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonGeometryCollection: MockGeoJsonGeometry, GeoJsonGeometryCollection { -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonLineString.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonLineString.swift deleted file mode 100644 index 0635864..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonLineString.swift +++ /dev/null @@ -1,33 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonLineString: MockGeoJsonLinearGeometry, GeoJsonLineString { - var geoJsonPoints: [GeoJsonPoint] = [] - - func invalidReasons(tolerance: Double) -> [LineStringInvalidReason] { - return [] - } - - var invalidReason: LineStringInvalidReason? - - override init() { - super.init() - - geoJsonObjectTypeResult = .lineString - } - - private(set) var segmentsCallCount = 0 - var segmentsResult: [GeodesicLineSegment] = [] - var segments: [GeodesicLineSegment] { - segmentsCallCount += 1 - - return segmentsResult - } - - private(set) var bearingCallCount = 0 - var bearingResult: (average: Double, back: Double)? = (0, 0) - var bearing: (average: Double, back: Double)? { - bearingCallCount += 1 - - return bearingResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiLineString.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiLineString.swift deleted file mode 100644 index 5562871..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiLineString.swift +++ /dev/null @@ -1,15 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonMultiLineString: MockGeoJsonLinearGeometry, GeoJsonMultiLineString { - func invalidReasons(tolerance: Double) -> [[LineStringInvalidReason]] { - return [] - } - - private(set) var lineStringsCallCount = 0 - var lineStringsResult: [GeoJsonLineString] = [] - var lineStrings: [GeoJsonLineString] { - lineStringsCallCount += 1 - - return lineStringsResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPoint.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPoint.swift deleted file mode 100644 index 7938904..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPoint.swift +++ /dev/null @@ -1,9 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonMultiPoint: MockGeoJsonCoordinatesGeometry, GeoJsonMultiPoint { - var geoJsonPoints: [GeoJsonPoint] = [] - - func invalidReasons(tolerance: Double) -> [MultipointInvalidReason] { - return [] - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPolygon.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPolygon.swift deleted file mode 100644 index 49c3ba3..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonMultiPolygon.swift +++ /dev/null @@ -1,15 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonMultiPolygon: MockGeoJsonClosedGeometry, GeoJsonMultiPolygon { - func invalidReasons(tolerance: Double) -> [[PolygonInvalidReason]] { - return [] - } - - private(set) var polygonsCallCount = 0 - var polygonsResult: [GeoJsonPolygon] = [] - var polygons: [GeoJsonPolygon] { - polygonsCallCount += 1 - - return polygonsResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPoint.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPoint.swift deleted file mode 100644 index 3e3d33e..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPoint.swift +++ /dev/null @@ -1,81 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonPoint: MockGeoJsonCoordinatesGeometry, GeoJsonPoint { - override init() { - super.init() - - geoJsonObjectTypeResult = .point - } - - private(set) var longitudeCallCount: Int = 0 - var longitudeResult: Double = 0 - var longitude: Double { - longitudeCallCount += 1 - - return longitudeResult - } - - private(set) var latitudeCallCount: Int = 0 - var latitudeResult: Double = 0 - var latitude: Double { - latitudeCallCount += 1 - - return latitudeResult - } - - private(set) var altitudeCallCount: Int = 0 - var altitudeResult: Double? - var altitude: Double? { - altitudeCallCount += 1 - - return altitudeResult - } - - private(set) var normalizeCallCount: Int = 0 - var normalizeResult: GeodesicPoint = SimplePoint(longitude: 0, latitude: 0) - var normalize: GeodesicPoint { - normalizeCallCount += 1 - - return normalizeResult - } - - private(set) var normalizePostitiveCallCount: Int = 0 - var normalizePostitiveResult: GeodesicPoint = SimplePoint(longitude: 0, latitude: 0) - var normalizePostitive: GeodesicPoint { - normalizePostitiveCallCount += 1 - - return normalizePostitiveResult - } - - private(set) var initialBearingCallCount: Int = 0 - var initialBearingResult: Double = 0 - func initialBearing(to point: GeodesicPoint) -> Double { - initialBearingCallCount += 1 - - return initialBearingResult - } - - private(set) var averageBearingCallCount: Int = 0 - var averageBearingResult: Double = 0 - func averageBearing(to point: GeodesicPoint) -> Double { - averageBearingCallCount += 1 - - return averageBearingResult - } - - private(set) var finalBearingCallCount: Int = 0 - var finalBearingResult: Double = 0 - func finalBearing(to point: GeodesicPoint) -> Double { - finalBearingCallCount += 1 - - return finalBearingResult - } - - private(set) var midpointCallCount: Int = 0 - var midpointResult: GeodesicPoint = SimplePoint(longitude: 0, latitude: 0) - func midpoint(with point: GeodesicPoint) -> GeodesicPoint { - midpointCallCount += 1 - - return midpointResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPolygon.swift b/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPolygon.swift deleted file mode 100644 index 0bca39a..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/GeoJson/Object/MockGeoJsonPolygon.swift +++ /dev/null @@ -1,36 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeoJsonPolygon: MockGeoJsonClosedGeometry, GeoJsonPolygon { - var geoJsonLinearRings: [GeoJsonLineString] { return [geoJsonMainRing] + geoJsonNegativeRings } - var geoJsonMainRing: GeoJsonLineString = MockData.lineStrings.first! - var geoJsonNegativeRings: [GeoJsonLineString] = [] - - var mainRing: GeodesicLine { return geoJsonMainRing } - var negativeRings: [GeodesicLine] { return geoJsonNegativeRings } - - override init() { - super.init() - - geoJsonObjectTypeResult = .polygon - } - - func invalidReasons(tolerance: Double) -> [PolygonInvalidReason] { - return [] - } - - private(set) var linearRingsCallCount: Int = 0 - var linearRingsResult: [GeodesicLine] { return geoJsonLinearRings } - var linearRings: [GeodesicLine] { - linearRingsCallCount += 1 - - return linearRingsResult - } - - private(set) var centroidCallCount = 0 - var centroidResult: GeoJsonPoint = MockGeoJsonPoint() - var centroid: GeodesicPoint { - centroidCallCount += 1 - - return centroidResult - } -} diff --git a/Tests/GeospatialSwiftTests/Mock/API/Geohash/MockGeohashCoder.swift b/Tests/GeospatialSwiftTests/Mock/API/Geohash/MockGeohashCoder.swift deleted file mode 100644 index ab86ff0..0000000 --- a/Tests/GeospatialSwiftTests/Mock/API/Geohash/MockGeohashCoder.swift +++ /dev/null @@ -1,51 +0,0 @@ -@testable import GeospatialSwift - -final class MockGeohashCoder: GeohashCoderProtocol { - private(set) var geohashFromPointCallCount = 0 - var geohashFromPointResult: String = "" - func geohash(for point: GeodesicPoint, precision: Int) -> String { - geohashFromPointCallCount += 1 - - return geohashFromPointResult - } - - private(set) var geohashBoxFromPointCallCount = 0 - lazy var geohashBoxFromPointResult: GeoJsonGeohashBox = MockGeoJsonGeohashBox() - func geohashBox(for point: GeodesicPoint, precision: Int) -> GeoJsonGeohashBox { - geohashBoxFromPointCallCount += 1 - - return geohashBoxFromPointResult - } - - private(set) var geohashBoxFromGeohashCallCount = 0 - lazy var geohashBoxFromGeohashResult: GeoJsonGeohashBox = MockGeoJsonGeohashBox() - func geohashBox(geohash: String) -> GeoJsonGeohashBox? { - geohashBoxFromGeohashCallCount += 1 - - return geohashBoxFromGeohashResult - } - - private(set) var geohashesCallCount = 0 - var geohashesResult: [String] = [] - func geohashes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [String] { - geohashesCallCount += 1 - - return geohashesResult - } - - private(set) var geohashBoxesCallCount = 0 - var geohashBoxesResult: [GeoJsonGeohashBox] = [] - func geohashBoxes(for boundingBox: GeodesicBoundingBox, precision: Int) -> [GeoJsonGeohashBox] { - geohashBoxesCallCount += 1 - - return geohashBoxesResult - } - - private(set) var geohashWithNeighborsCallCount = 0 - var geohashWithNeighborsResult: [String] = [] - func geohashWithNeighbors(for point: GeodesicPoint, precision: Int) -> [String] { - geohashWithNeighborsCallCount += 1 - - return geohashWithNeighborsResult - } -} diff --git a/Tests/GeospatialSwiftTests/Performance/GeoJsonParsingPerformanceTests.swift b/Tests/GeospatialSwiftTests/Performance/GeoJsonParsingPerformanceTests.swift index 81a05e5..1a38183 100644 --- a/Tests/GeospatialSwiftTests/Performance/GeoJsonParsingPerformanceTests.swift +++ b/Tests/GeospatialSwiftTests/Performance/GeoJsonParsingPerformanceTests.swift @@ -14,7 +14,7 @@ final class GeoJsonParsingPerformanceTest: XCTestCase { measure { for _ in 0..<50 { for geoJson in geoJsons { - cacheForMemoryUsageInfo.append(geospatial.geoJson.parse(geoJson: geoJson)!) + cacheForMemoryUsageInfo.append(geospatial.geoJson.parseObject(fromValidatedGeoJson: geoJson)) } } } diff --git a/Tests/GeospatialSwiftTests/Test/API/Calculator/GeodesicCalculatorTests.swift b/Tests/GeospatialSwiftTests/Test/API/Calculator/GeodesicCalculatorTests.swift index a6cb1ac..c062a77 100644 --- a/Tests/GeospatialSwiftTests/Test/API/Calculator/GeodesicCalculatorTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/Calculator/GeodesicCalculatorTests.swift @@ -3,8 +3,6 @@ import XCTest @testable import GeospatialSwift class GeodesicCalculatorTests: XCTestCase { - private let geodesicCalculator = GeodesicCalculator.shared - override func setUp() { super.setUp() } @@ -12,9 +10,9 @@ class GeodesicCalculatorTests: XCTestCase { func testHasIntersection_SameLine() { let point = SimplePoint(longitude: 1, latitude: 2) let otherPoint = SimplePoint(longitude: 1.5, latitude: 2.5) - let lineSegment = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment = GeodesicLineSegment(point: point, otherPoint: otherPoint) - let intersects = geodesicCalculator.hasIntersection(lineSegment, with: lineSegment, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment, with: lineSegment, tolerance: 0) XCTAssertEqual(intersects, true) } @@ -22,13 +20,13 @@ class GeodesicCalculatorTests: XCTestCase { func testHasIntersection_Overlaps_InsideLine_NotEnoughTolerence() { var point = SimplePoint(longitude: 1, latitude: 2) var otherPoint = SimplePoint(longitude: 1.5, latitude: 2.5) - let lineSegment1 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment1 = GeodesicLineSegment(point: point, otherPoint: otherPoint) point = SimplePoint(longitude: 1.2, latitude: 2.2) otherPoint = SimplePoint(longitude: 1.7, latitude: 2.7) - let lineSegment2 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment2 = GeodesicLineSegment(point: point, otherPoint: otherPoint) - let intersects = geodesicCalculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 4) + let intersects = Calculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 4) XCTAssertEqual(intersects, false) } @@ -36,13 +34,13 @@ class GeodesicCalculatorTests: XCTestCase { func testHasIntersection_Overlaps_InsideLine_EnoughTolerence() { var point = SimplePoint(longitude: 1, latitude: 2) var otherPoint = SimplePoint(longitude: 1.5, latitude: 2.5) - let lineSegment1 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment1 = GeodesicLineSegment(point: point, otherPoint: otherPoint) point = SimplePoint(longitude: 1.2, latitude: 2.2) otherPoint = SimplePoint(longitude: 1.7, latitude: 2.7) - let lineSegment2 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment2 = GeodesicLineSegment(point: point, otherPoint: otherPoint) - let intersects = geodesicCalculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 5) + let intersects = Calculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 5) XCTAssertEqual(intersects, true) } @@ -50,13 +48,13 @@ class GeodesicCalculatorTests: XCTestCase { func testHasIntersection_SameTrajectoryNoOverlap_Ahead() { var point = SimplePoint(longitude: 1, latitude: 2) var otherPoint = SimplePoint(longitude: 1.5, latitude: 2.5) - let lineSegment1 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment1 = GeodesicLineSegment(point: point, otherPoint: otherPoint) point = SimplePoint(longitude: 2, latitude: 3) otherPoint = SimplePoint(longitude: 2.5, latitude: 3.5) - let lineSegment2 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment2 = GeodesicLineSegment(point: point, otherPoint: otherPoint) - let intersects = geodesicCalculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 0) XCTAssertEqual(intersects, false) } @@ -64,58 +62,58 @@ class GeodesicCalculatorTests: XCTestCase { func testHasIntersection_SameTrajectoryNoOverlap_Behind() { var point = SimplePoint(longitude: 1, latitude: 2) var otherPoint = SimplePoint(longitude: 1.5, latitude: 2.5) - let lineSegment1 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment1 = GeodesicLineSegment(point: point, otherPoint: otherPoint) point = SimplePoint(longitude: 0, latitude: 1) otherPoint = SimplePoint(longitude: 0.5, latitude: 1.5) - let lineSegment2 = LineSegment(point: point, otherPoint: otherPoint) + let lineSegment2 = GeodesicLineSegment(point: point, otherPoint: otherPoint) - let intersects = geodesicCalculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment1, with: lineSegment2, tolerance: 0) XCTAssertEqual(intersects, false) } func testHasIntersection_LineIntersectingPolygon_Inside() { - let lineSegment = LineSegment(point: SimplePoint(longitude: 0.2, latitude: 0.5), otherPoint: SimplePoint(longitude: 0.8, latitude: 0.5)) + let lineSegment = GeodesicLineSegment(point: SimplePoint(longitude: 0.2, latitude: 0.5), otherPoint: SimplePoint(longitude: 0.8, latitude: 0.5)) let polygon = MockData.box - let intersects = geodesicCalculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) XCTAssertEqual(intersects, true) } func testHasIntersection_LineIntersectingPolygon_OnLine() { - let lineSegment = LineSegment(point: SimplePoint(longitude: 1.5, latitude: 0.5), otherPoint: SimplePoint(longitude: 0.8, latitude: 0.5)) + let lineSegment = GeodesicLineSegment(point: SimplePoint(longitude: 1.5, latitude: 0.5), otherPoint: SimplePoint(longitude: 0.8, latitude: 0.5)) let polygon = MockData.box - let intersects = geodesicCalculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) XCTAssertEqual(intersects, true) } func testHasIntersection_LineIntersectingPolygon_CrossesTwice() { - let lineSegment = LineSegment(point: SimplePoint(longitude: 0.9, latitude: 0.5), otherPoint: SimplePoint(longitude: 2.0, latitude: 1.5)) + let lineSegment = GeodesicLineSegment(point: SimplePoint(longitude: 0.9, latitude: 0.5), otherPoint: SimplePoint(longitude: 2.0, latitude: 1.5)) let polygon = MockData.box - let intersects = geodesicCalculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) XCTAssertEqual(intersects, true) } func testHasIntersection_LineIntersectingPolygon_LineCrossesThrough() { - let lineSegment = LineSegment(point: SimplePoint(longitude: -1.0, latitude: 0.5), otherPoint: SimplePoint(longitude: 2.0, latitude: 0.5)) + let lineSegment = GeodesicLineSegment(point: SimplePoint(longitude: -1.0, latitude: 0.5), otherPoint: SimplePoint(longitude: 2.0, latitude: 0.5)) let polygon = MockData.box - let intersects = geodesicCalculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) XCTAssertEqual(intersects, true) } func testHasIntersection_LineIntersectingPolygon_LineOutside() { - let lineSegment = LineSegment(point: SimplePoint(longitude: 1.5, latitude: 0.5), otherPoint: SimplePoint(longitude: 2.0, latitude: 0.5)) + let lineSegment = GeodesicLineSegment(point: SimplePoint(longitude: 1.5, latitude: 0.5), otherPoint: SimplePoint(longitude: 2.0, latitude: 0.5)) let polygon = MockData.box - let intersects = geodesicCalculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) + let intersects = Calculator.hasIntersection(lineSegment, with: polygon, tolerance: 0) XCTAssertEqual(intersects, false) } @@ -128,7 +126,7 @@ class GeodesicCalculatorTests: XCTestCase { SimplePoint(longitude: 1, latitude: 1) ])! - let intersects = geodesicCalculator.hasIntersection(line, tolerance: 0) + let intersects = Calculator.hasIntersection(line, tolerance: 0) XCTAssertEqual(intersects, true) } @@ -140,7 +138,7 @@ class GeodesicCalculatorTests: XCTestCase { SimplePoint(longitude: 0, latitude: 0) ])! - let intersects = geodesicCalculator.hasIntersection(line, tolerance: 0) + let intersects = Calculator.hasIntersection(line, tolerance: 0) XCTAssertEqual(intersects, true) } @@ -152,7 +150,7 @@ class GeodesicCalculatorTests: XCTestCase { SimplePoint(longitude: 0, latitude: 2) ])! - let intersects = geodesicCalculator.hasIntersection(line, tolerance: 0) + let intersects = Calculator.hasIntersection(line, tolerance: 0) XCTAssertEqual(intersects, false) } diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/BoundingBoxTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/BoundingBoxTests.swift index 1ce33af..b81838b 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/BoundingBoxTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/BoundingBoxTests.swift @@ -3,45 +3,45 @@ import XCTest @testable import GeospatialSwift class BoundingBoxTests: XCTestCase { - private(set) var simpleBoundingBox: BoundingBox! + private(set) var simpleBoundingBox: GeodesicBoundingBox! - private(set) var pointBoundingBox: BoundingBox! - private(set) var horizontalBoundingBox: BoundingBox! - private(set) var verticalBoundingBox: BoundingBox! + private(set) var pointBoundingBox: GeodesicBoundingBox! + private(set) var horizontalBoundingBox: GeodesicBoundingBox! + private(set) var verticalBoundingBox: GeodesicBoundingBox! - private(set) var insideBoundingBox: BoundingBox! - private(set) var horizontalOverlapBoundingBox: BoundingBox! - private(set) var verticalOverlapBoundingBox: BoundingBox! - private(set) var horizontalVerticalOverlapBoundingBox: BoundingBox! - private(set) var noOverlapBoundingBox: BoundingBox! + private(set) var insideBoundingBox: GeodesicBoundingBox! + private(set) var horizontalOverlapBoundingBox: GeodesicBoundingBox! + private(set) var verticalOverlapBoundingBox: GeodesicBoundingBox! + private(set) var horizontalVerticalOverlapBoundingBox: GeodesicBoundingBox! + private(set) var noOverlapBoundingBox: GeodesicBoundingBox! let boundingBoxMinimumAdjustment = 0.00005 - private var boundingCoordinatesHorizontalOverlap: BoundingCoordinates { return (minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: horizontalOverlapBoundingBox.maxLongitude, maxLatitude: simpleBoundingBox.maxLatitude) } + private var boundingCoordinatesHorizontalOverlap: GeodesicBoundingBox { .init(minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: horizontalOverlapBoundingBox.maxLongitude, maxLatitude: simpleBoundingBox.maxLatitude) } - private var boundingCoordinatesVerticalOverlap: BoundingCoordinates { return (minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: simpleBoundingBox.maxLongitude, maxLatitude: verticalOverlapBoundingBox.maxLatitude) } + private var boundingCoordinatesVerticalOverlap: GeodesicBoundingBox { .init(minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: simpleBoundingBox.maxLongitude, maxLatitude: verticalOverlapBoundingBox.maxLatitude) } - private var boundingCoordinatesCornerOverlap: BoundingCoordinates { return (minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: horizontalOverlapBoundingBox.maxLongitude, maxLatitude: verticalOverlapBoundingBox.maxLatitude) } + private var boundingCoordinatesCornerOverlap: GeodesicBoundingBox { .init(minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: horizontalOverlapBoundingBox.maxLongitude, maxLatitude: verticalOverlapBoundingBox.maxLatitude) } - private var boundingCoordinatesNoOverlap: BoundingCoordinates { return (minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: noOverlapBoundingBox.maxLongitude, maxLatitude: noOverlapBoundingBox.maxLatitude) } + private var boundingCoordinatesNoOverlap: GeodesicBoundingBox { .init(minLongitude: simpleBoundingBox.minLongitude, minLatitude: simpleBoundingBox.minLatitude, maxLongitude: noOverlapBoundingBox.maxLongitude, maxLatitude: noOverlapBoundingBox.maxLatitude) } override func setUp() { super.setUp() - simpleBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 0, minLatitude: 1, maxLongitude: 2, maxLatitude: 4)) + simpleBoundingBox = .init(minLongitude: 0, minLatitude: 1, maxLongitude: 2, maxLatitude: 4) - pointBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 0, minLatitude: 1, maxLongitude: 0, maxLatitude: 1)) - horizontalBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 0, minLatitude: 1, maxLongitude: 2, maxLatitude: 1)) - verticalBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 0, minLatitude: 1, maxLongitude: 0, maxLatitude: 3)) + pointBoundingBox = .init(minLongitude: 0, minLatitude: 1, maxLongitude: 0, maxLatitude: 1) + horizontalBoundingBox = .init(minLongitude: 0, minLatitude: 1, maxLongitude: 2, maxLatitude: 1) + verticalBoundingBox = .init(minLongitude: 0, minLatitude: 1, maxLongitude: 0, maxLatitude: 3) // 0 - 2, 1 - 4 // 1 - 1.5, 2 - 3 - insideBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 1, minLatitude: 2, maxLongitude: 1.5, maxLatitude: 3)) + insideBoundingBox = .init(minLongitude: 1, minLatitude: 2, maxLongitude: 1.5, maxLatitude: 3) // 1 - 2, 3 - 3 - horizontalOverlapBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 1, minLatitude: 2, maxLongitude: 3, maxLatitude: 3)) - verticalOverlapBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 1, minLatitude: 2, maxLongitude: 1.5, maxLatitude: 5)) - horizontalVerticalOverlapBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 1, minLatitude: 2, maxLongitude: 3, maxLatitude: 5)) - noOverlapBoundingBox = BoundingBox(boundingCoordinates: (minLongitude: 5, minLatitude: 6, maxLongitude: 7, maxLatitude: 9)) + horizontalOverlapBoundingBox = .init(minLongitude: 1, minLatitude: 2, maxLongitude: 3, maxLatitude: 3) + verticalOverlapBoundingBox = .init(minLongitude: 1, minLatitude: 2, maxLongitude: 1.5, maxLatitude: 5) + horizontalVerticalOverlapBoundingBox = .init(minLongitude: 1, minLatitude: 2, maxLongitude: 3, maxLatitude: 5) + noOverlapBoundingBox = .init(minLongitude: 5, minLatitude: 6, maxLongitude: 7, maxLatitude: 9) } func testBoundingCoordinates() { @@ -186,48 +186,38 @@ class BoundingBoxTests: XCTestCase { } func testBest_WhenEmpty_ThenNil() { - XCTAssertEqual(BoundingBox.best([]) as? BoundingBox, nil) + XCTAssertEqual(GeodesicBoundingBox.best([]), nil) } func testBest_WhenOnlySelf_ThenSelf() { - XCTAssertEqual(BoundingBox.best([simpleBoundingBox]) as? BoundingBox, simpleBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox]), simpleBoundingBox) } func testBest_WhenSame_ThenSelf() { - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, simpleBoundingBox]) as? BoundingBox, simpleBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, simpleBoundingBox]), simpleBoundingBox) } func testBest_WhenInside_ThenSelf() { - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, insideBoundingBox]) as? BoundingBox, simpleBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, insideBoundingBox]), simpleBoundingBox) } func testBest_WhenHorizontalOverlap_ThenBest() { - let expectedBoundingBox = BoundingBox(boundingCoordinates: boundingCoordinatesHorizontalOverlap) - - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, horizontalOverlapBoundingBox]) as? BoundingBox, expectedBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, horizontalOverlapBoundingBox]), boundingCoordinatesHorizontalOverlap) } func testBest_WhenVerticalOverlap_ThenBest() { - let expectedBoundingBox = BoundingBox(boundingCoordinates: boundingCoordinatesVerticalOverlap) - - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, verticalOverlapBoundingBox]) as? BoundingBox, expectedBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, verticalOverlapBoundingBox]), boundingCoordinatesVerticalOverlap) } func testBest_WhenHorizontalVerticalOverlap_ThenBest() { - let expectedBoundingBox = BoundingBox(boundingCoordinates: boundingCoordinatesCornerOverlap) - - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, horizontalVerticalOverlapBoundingBox]) as? BoundingBox, expectedBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, horizontalVerticalOverlapBoundingBox]), boundingCoordinatesCornerOverlap) } func testBest_Multiple_ThenBest() { - let expectedBoundingBox = BoundingBox(boundingCoordinates: boundingCoordinatesCornerOverlap) - - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, pointBoundingBox, horizontalOverlapBoundingBox, verticalOverlapBoundingBox]) as? BoundingBox, expectedBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, pointBoundingBox, horizontalOverlapBoundingBox, verticalOverlapBoundingBox]), boundingCoordinatesCornerOverlap) } func testBest_WhenNoOverlap_ThenBest() { - let expectedBoundingBox = BoundingBox(boundingCoordinates: boundingCoordinatesNoOverlap) - - XCTAssertEqual(BoundingBox.best([simpleBoundingBox, noOverlapBoundingBox]) as? BoundingBox, expectedBoundingBox) + XCTAssertEqual(GeodesicBoundingBox.best([simpleBoundingBox, noOverlapBoundingBox]), boundingCoordinatesNoOverlap) } } diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/GeodesicLineSegmentTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/GeodesicLineSegmentTests.swift index 000e0b0..16a1114 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/GeodesicLineSegmentTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/GeodesicLineSegmentTests.swift @@ -14,8 +14,8 @@ class GeodesicLineSegmentTests: XCTestCase { point = SimplePoint(longitude: 1, latitude: 2, altitude: 3) otherPoint = SimplePoint(longitude: 10, latitude: 10, altitude: 10) - lineSegment = LineSegment(point: point, otherPoint: otherPoint) - reversedLineSegment = LineSegment(point: otherPoint, otherPoint: point) + lineSegment = .init(point: point, otherPoint: otherPoint) + reversedLineSegment = .init(point: otherPoint, otherPoint: point) } func testInitialBearing() { diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureCollectionTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureCollectionTests.swift index 30aa53a..2ec3235 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureCollectionTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureCollectionTests.swift @@ -11,7 +11,7 @@ class FeatureCollectionTests: XCTestCase { override func setUp() { super.setUp() - features = MockData.features as? [Feature] + features = MockData.features featureCollection = GeoTestHelper.featureCollection(features) @@ -27,7 +27,7 @@ class FeatureCollectionTests: XCTestCase { } func testObjectGeometries() { - XCTAssertEqual(featureCollection.objectGeometries?.count, 3) + XCTAssertEqual(featureCollection.objectGeometries.count, 3) } func testGeometryTypes() { @@ -43,9 +43,9 @@ class FeatureCollectionTests: XCTestCase { func testObjectBoundingBox() { let resultBoundingBox = featureCollection.objectBoundingBox - let boundingBox = BoundingBox.best(featureCollection.features.compactMap { $0.geometry?.objectBoundingBox }) + let boundingBox = GeodesicBoundingBox.best(featureCollection.features.compactMap { $0.geometry?.objectBoundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testGeoJson() { diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureTests.swift index b385e4b..025e7b7 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/FeatureTests.swift @@ -14,7 +14,7 @@ class FeatureTests: XCTestCase { var featureWithProperties2: Feature! var featureWithProperties1Mixed: Feature! - var point: GeoJsonPoint! + var point: GeoJson.Point! var distancePoint: SimplePoint! @@ -72,9 +72,9 @@ class FeatureTests: XCTestCase { func testObjectBoundingBox() { let resultBoundingBox = feature.objectBoundingBox - let boundingBox = BoundingBox.best([feature.geometry!.objectBoundingBox!]) + let boundingBox = GeodesicBoundingBox.best([feature.geometry!.objectBoundingBox!]) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) XCTAssertNil(featureEmpty.objectBoundingBox) } diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/GeometryCollectionTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/GeometryCollectionTests.swift index 28a766c..f39b018 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/GeometryCollectionTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/GeometryCollectionTests.swift @@ -9,7 +9,7 @@ class GeometryCollectionTests: XCTestCase { var nilGeometryCollection: GeometryCollection? var distancePoint: SimplePoint! - var point: GeoJsonPoint! + var point: GeoJson.Point! override func setUp() { super.setUp() @@ -32,13 +32,13 @@ class GeometryCollectionTests: XCTestCase { } func testObjectGeometries() { - XCTAssertEqual(geometryCollection.objectGeometries?.count, 6) - XCTAssertTrue(geometryCollection.objectGeometries?[0] is Point) - XCTAssertTrue(geometryCollection.objectGeometries?[1] is MultiPoint) - XCTAssertTrue(geometryCollection.objectGeometries?[2] is LineString) - XCTAssertTrue(geometryCollection.objectGeometries?[3] is MultiLineString) - XCTAssertTrue(geometryCollection.objectGeometries?[4] is Polygon) - XCTAssertTrue(geometryCollection.objectGeometries?[5] is MultiPolygon) + XCTAssertEqual(geometryCollection.objectGeometries.count, 6) + XCTAssertTrue(geometryCollection.objectGeometries[0] is Point) + XCTAssertTrue(geometryCollection.objectGeometries[1] is MultiPoint) + XCTAssertTrue(geometryCollection.objectGeometries[2] is LineString) + XCTAssertTrue(geometryCollection.objectGeometries[3] is MultiLineString) + XCTAssertTrue(geometryCollection.objectGeometries[4] is Polygon) + XCTAssertTrue(geometryCollection.objectGeometries[5] is MultiPolygon) } func testGeometryTypes() { @@ -54,9 +54,9 @@ class GeometryCollectionTests: XCTestCase { func testObjectBoundingBox() { let resultBoundingBox = geometryCollection.objectBoundingBox - let boundingBox = BoundingBox.best(geometryCollection.objectGeometries!.compactMap { $0.objectBoundingBox }) + let boundingBox = GeodesicBoundingBox.best(geometryCollection.objectGeometries.compactMap { $0.objectBoundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testGeoJson() { @@ -100,16 +100,16 @@ class GeometryCollectionTests: XCTestCase { } func testEquals_NoGeometries_Versus_NoGeometries() { - XCTAssertEqual(GeoTestHelper.geometryCollection(nil), GeoTestHelper.geometryCollection(nil)) + XCTAssertEqual(GeoTestHelper.geometryCollection([]), GeoTestHelper.geometryCollection([])) } func testNotEquals_Geometries_Versus_NilGeometries() { - XCTAssertNotEqual(GeoTestHelper.geometryCollection([point]), GeoTestHelper.geometryCollection(nil)) + XCTAssertNotEqual(GeoTestHelper.geometryCollection([point]), GeoTestHelper.geometryCollection([])) } // SOMEDAY: Comparing the Json test data and this is confusing. func testNotEquals_DifferentGeometries() { - let polygon = GeoTestHelper.polygon([GeoTestHelper.lineString([point, point, point, point])]) + let polygon = GeoTestHelper.polygon(GeoTestHelper.lineString([point, point, point, point])) XCTAssertNotEqual(geometryCollection, GeoTestHelper.geometryCollection([GeoTestHelper.multiPolygon([polygon, polygon])])) } diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/LineStringTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/LineStringTests.swift index c4fedc6..cda989c 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/LineStringTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/LineStringTests.swift @@ -35,7 +35,7 @@ class LineStringTests: XCTestCase { } func testObjectBoundingBox() { - XCTAssertEqual(lineString.objectBoundingBox as? BoundingBox, lineString.boundingBox as? BoundingBox) + XCTAssertEqual(lineString.objectBoundingBox, lineString.boundingBox) } func testGeoJson() { @@ -88,9 +88,9 @@ class LineStringTests: XCTestCase { func testBoundingBox() { let resultBoundingBox = lineString.boundingBox - let boundingBox = BoundingBox.best(points.compactMap { $0.boundingBox }) + let boundingBox = GeodesicBoundingBox.best(points.compactMap { $0.boundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testDistance() { diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiLineStringTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiLineStringTests.swift index 467ee41..b47ddb3 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiLineStringTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiLineStringTests.swift @@ -10,7 +10,7 @@ class MultiLineStringTests: XCTestCase { override func setUp() { super.setUp() - lineStrings = MockData.lineStrings as? [LineString] + lineStrings = MockData.lineStrings multiLineString = GeoTestHelper.multiLineString(lineStrings) @@ -35,7 +35,7 @@ class MultiLineStringTests: XCTestCase { } func testObjectBoundingBox() { - XCTAssertEqual(multiLineString.objectBoundingBox as? BoundingBox, multiLineString.boundingBox as? BoundingBox) + XCTAssertEqual(multiLineString.objectBoundingBox, multiLineString.boundingBox) } func testGeoJson() { @@ -50,34 +50,34 @@ class MultiLineStringTests: XCTestCase { func testContains() { let point = multiLineString.points.first! - XCTAssertEqual(multiLineString.contains(point), lineStrings.map { $0.contains(point) }.reduce(false) { $0 || $1 }) + XCTAssertEqual(multiLineString.contains(point), lineStrings.map { $0.contains(point) }.contains { $0 }) } func testContains_DoesNot() { let point = distancePoint! - XCTAssertEqual(multiLineString.contains(point), lineStrings.map { $0.contains(point) }.reduce(false) { $0 || $1 }) + XCTAssertEqual(multiLineString.contains(point), lineStrings.map { $0.contains(point) }.contains { $0 }) } func testContains_WithTolerance() { let point = multiLineString.points.first! let tolerance = 0.0 - XCTAssertEqual(multiLineString.contains(point, tolerance: tolerance), lineStrings.map { $0.contains(point, tolerance: tolerance) }.reduce(false) { $0 || $1 }) + XCTAssertEqual(multiLineString.contains(point, tolerance: tolerance), lineStrings.map { $0.contains(point, tolerance: tolerance) }.contains { $0 }) } func testContains_WithTolerance_Does_WithError() { let point = distancePoint! let tolerance = 200000000.0 - XCTAssertEqual(multiLineString.contains(point, tolerance: tolerance), lineStrings.map { $0.contains(point, tolerance: tolerance) }.reduce(false) { $0 || $1 }) + XCTAssertEqual(multiLineString.contains(point, tolerance: tolerance), lineStrings.map { $0.contains(point, tolerance: tolerance) }.contains { $0 }) } func testContains_WithTolerance_DoesNot() { let point = distancePoint! let tolerance = 0.0 - XCTAssertEqual(multiLineString.contains(point, tolerance: tolerance), lineStrings.map { $0.contains(point, tolerance: tolerance) }.reduce(false) { $0 || $1 }) + XCTAssertEqual(multiLineString.contains(point, tolerance: tolerance), lineStrings.map { $0.contains(point, tolerance: tolerance) }.contains { $0 }) } // GeoJsonCoordinatesGeometry Tests @@ -92,7 +92,7 @@ class MultiLineStringTests: XCTestCase { (coordinates as! [[[Double]]]).enumerated().forEach { lineStringsOffset, element in XCTAssertEqual(element.count, lineStrings[lineStringsOffset].points.count) element.enumerated().forEach { pointsOffset, element in - XCTAssertEqual(element, lineStrings[lineStringsOffset].geoJsonPoints[pointsOffset].geoJsonCoordinates as! [Double] ) + XCTAssertEqual(element, (lineStrings[lineStringsOffset].points[pointsOffset] as! Point).geoJsonCoordinates as! [Double] ) } } // swiftlint:enablce force_cast @@ -106,9 +106,9 @@ class MultiLineStringTests: XCTestCase { func testBoundingBox() { let resultBoundingBox = multiLineString.boundingBox - let boundingBox = BoundingBox.best(lineStrings.compactMap { $0.boundingBox }) + let boundingBox = GeodesicBoundingBox.best(lineStrings.compactMap { $0.boundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testDistance_On() { @@ -159,7 +159,7 @@ class MultiLineStringTests: XCTestCase { // MultiLineString Tests func testLineStrings() { - XCTAssertEqual((multiLineString.lineStrings as? [LineString])!, lineStrings) + XCTAssertEqual((multiLineString.lines as? [LineString])!, lineStrings) } func testEquals() { diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPointTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPointTests.swift index d1ebdb7..03f2bcf 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPointTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPointTests.swift @@ -35,7 +35,7 @@ class MultiPointTests: XCTestCase { } func testObjectBoundingBox() { - XCTAssertEqual(multiPoint.objectBoundingBox as? BoundingBox, multiPoint.boundingBox as? BoundingBox) + XCTAssertEqual(multiPoint.objectBoundingBox, multiPoint.boundingBox) } func testGeoJson() { @@ -105,9 +105,9 @@ class MultiPointTests: XCTestCase { func testBoundingBox() { let resultBoundingBox = multiPoint.boundingBox - let boundingBox = BoundingBox.best(points.compactMap { $0.boundingBox }) + let boundingBox = GeodesicBoundingBox.best(points.compactMap { $0.boundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testDistance() { diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPolygonTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPolygonTests.swift index 8381f38..076a198 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPolygonTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/MultiPolygonTests.swift @@ -7,12 +7,12 @@ class MultiPolygonTests: XCTestCase { var multiPolygon: MultiPolygon! var distancePoint: SimplePoint! - var point: GeoJsonPoint! + var point: GeoJson.Point! override func setUp() { super.setUp() - polygons = MockData.polygons as? [Polygon] + polygons = MockData.polygons multiPolygon = GeoTestHelper.multiPolygon(polygons) @@ -39,7 +39,7 @@ class MultiPolygonTests: XCTestCase { } func testObjectBoundingBox() { - XCTAssertEqual(multiPolygon.objectBoundingBox as? BoundingBox, multiPolygon.boundingBox as? BoundingBox) + XCTAssertEqual(multiPolygon.objectBoundingBox, multiPolygon.boundingBox) } func testGeoJson() { @@ -73,7 +73,7 @@ class MultiPolygonTests: XCTestCase { element.enumerated().forEach { linearRingsOffset, element in XCTAssertEqual(element.count, polygons[polygonsOffset].linearRings[linearRingsOffset].points.count) element.enumerated().forEach { pointsOffset, element in - XCTAssertEqual(element, polygons[polygonsOffset].geoJsonLinearRings[linearRingsOffset].geoJsonPoints[pointsOffset].geoJsonCoordinates as! [Double] ) + XCTAssertEqual(element, (polygons[polygonsOffset].linearRings[linearRingsOffset].points[pointsOffset] as! Point).geoJsonCoordinates as! [Double] ) } } } @@ -88,9 +88,9 @@ class MultiPolygonTests: XCTestCase { func testBoundingBox() { let resultBoundingBox = multiPolygon.boundingBox - let boundingBox = BoundingBox.best(polygons.compactMap { $0.boundingBox }) + let boundingBox = GeodesicBoundingBox.best(polygons.compactMap { $0.boundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testDistance() { @@ -128,7 +128,7 @@ class MultiPolygonTests: XCTestCase { // SOMEDAY: Comparing the Json test data and this is confusing. func testNotEquals() { - let polygon = GeoTestHelper.polygon([GeoTestHelper.lineString([point, point, point, point])]) + let polygon = GeoTestHelper.polygon(GeoTestHelper.lineString([point, point, point, point])) XCTAssertNotEqual(multiPolygon, GeoTestHelper.multiPolygon([polygon, polygon])) } diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PointTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PointTests.swift index f4e7eb6..da05ed9 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PointTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PointTests.swift @@ -4,12 +4,12 @@ import XCTest class PointTests: XCTestCase { var point: Point! - var distancePoint: GeoJsonPoint! + var distancePoint: GeoJson.Point! override func setUp() { super.setUp() - point = MockData.point as? Point + point = MockData.point distancePoint = GeoTestHelper.point(10, 10, 10) } @@ -32,7 +32,7 @@ class PointTests: XCTestCase { } func testObjectBoundingBox() { - XCTAssertEqual(point.objectBoundingBox as? BoundingBox, point.boundingBox as? BoundingBox) + XCTAssertEqual(point.objectBoundingBox, point.boundingBox) } func testGeoJson() { @@ -109,9 +109,9 @@ class PointTests: XCTestCase { func testBoundingBox() { let resultBoundingBox = point.boundingBox - let boundingBox = BoundingBox(boundingCoordinates: (minLongitude: point.longitude, minLatitude: point.latitude, maxLongitude: point.longitude, maxLatitude: point.latitude)) + let boundingBox = GeodesicBoundingBox(minLongitude: point.longitude, minLatitude: point.latitude, maxLongitude: point.longitude, maxLatitude: point.latitude) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testDistance() { diff --git a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PolygonTests.swift b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PolygonTests.swift index 0cf7a29..441212a 100644 --- a/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PolygonTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/GeoJson/Object/PolygonTests.swift @@ -4,23 +4,27 @@ import XCTest // swiftlint:disable type_body_length class PolygonTests: XCTestCase { + var mainRing: LineString! + var negativeRings: [LineString]! var linearRings: [LineString]! var polygon: Polygon! var polygonDistance: Polygon! var distancePoint: SimplePoint! - var point: GeoJsonPoint! - var otherPoint: GeoJsonPoint! - var point3: GeoJsonPoint! + var point: GeoJson.Point! + var otherPoint: GeoJson.Point! + var point3: GeoJson.Point! - var lineString1: GeoJsonLineString! - var lineString2: GeoJsonLineString! - var lineString3: GeoJsonLineString! + var lineString1: GeoJson.LineString! + var lineString2: GeoJson.LineString! + var lineString3: GeoJson.LineString! override func setUp() { super.setUp() - linearRings = MockData.linearRings as? [LineString] + mainRing = MockData.linearRings.first! + negativeRings = Array(MockData.linearRings.dropFirst()) + linearRings = [mainRing] + negativeRings //3 * // @@ -32,9 +36,9 @@ class PolygonTests: XCTestCase { // //1 // 0.5 1 1.5 2 - polygonDistance = GeoTestHelper.polygon([GeoTestHelper.lineString([GeoTestHelper.point(1, 2, 3), GeoTestHelper.point(2, 2, 4), GeoTestHelper.point(2, 3, 5), GeoTestHelper.point(1, 2, 3)])]) + polygonDistance = GeoTestHelper.polygon(GeoTestHelper.lineString([GeoTestHelper.point(1, 2, 3), GeoTestHelper.point(2, 2, 4), GeoTestHelper.point(2, 3, 5), GeoTestHelper.point(1, 2, 3)])) - polygon = GeoTestHelper.polygon(linearRings) + polygon = GeoTestHelper.polygon(mainRing, negativeRings) distancePoint = GeoTestHelper.simplePoint(10, 10, 10) @@ -65,7 +69,7 @@ class PolygonTests: XCTestCase { } func testObjectBoundingBox() { - XCTAssertEqual(polygon.objectBoundingBox as? BoundingBox, polygon.boundingBox as? BoundingBox) + XCTAssertEqual(polygon.objectBoundingBox, polygon.boundingBox) } func testGeoJson() { @@ -117,7 +121,7 @@ class PolygonTests: XCTestCase { (coordinates as! [[[Double]]]).enumerated().forEach { linearRingsOffset, element in XCTAssertEqual(element.count, linearRings[linearRingsOffset].points.count) element.enumerated().forEach { pointsOffset, element in - XCTAssertEqual(element, linearRings[linearRingsOffset].geoJsonPoints[pointsOffset].geoJsonCoordinates as! [Double] ) + XCTAssertEqual(element, (linearRings[linearRingsOffset].points[pointsOffset] as! Point).geoJsonCoordinates as! [Double] ) } } // swiftlint:enable force_cast @@ -131,9 +135,9 @@ class PolygonTests: XCTestCase { func testBoundingBox() { let resultBoundingBox = polygon.boundingBox - let boundingBox = BoundingBox.best(linearRings.compactMap { $0.boundingBox }) + let boundingBox = GeodesicBoundingBox.best(linearRings.compactMap { $0.boundingBox }) - XCTAssertEqual(resultBoundingBox as? BoundingBox, boundingBox as? BoundingBox) + XCTAssertEqual(resultBoundingBox, boundingBox) } func testDistance_FollowingLine() { @@ -232,7 +236,7 @@ class PolygonTests: XCTestCase { // SOMEDAY: Wrong? func testCentroid_NoHoles2() { let mainRing = GeoTestHelper.lineString([GeoTestHelper.point(-88.3254122, 39.5206294), GeoTestHelper.point(-88.3254123, 39.520643), GeoTestHelper.point(-88.3254549, 39.5206432), GeoTestHelper.point(-88.3254549, 39.5206296), GeoTestHelper.point(-88.3254122, 39.5206294)]) - let polygon = GeoTestHelper.polygon([mainRing]) + let polygon = GeoTestHelper.polygon(mainRing) XCTAssertEqual(polygon.centroid as! SimplePoint, GeoTestHelper.simplePoint(-88.325433565181825, 39.520636297343238)) } @@ -249,7 +253,7 @@ class PolygonTests: XCTestCase { GeoTestHelper.point(50, 50) ] let linearRings = [GeoTestHelper.lineString(points)] - let polygon = GeoTestHelper.polygon(linearRings) + let polygon = GeoTestHelper.polygon(linearRings.first!, Array(linearRings.dropFirst())) //let feature = geospatial.geoJson.feature(geometry: polygon, id: 1, properties: nil) let distance = polygon.distance(to: distancePoint) @@ -263,7 +267,7 @@ class PolygonTests: XCTestCase { func testCentroid_SmallHole() { let mainRing = GeoTestHelper.lineString([GeoTestHelper.point(0.5, 1.5, 3), GeoTestHelper.point(0.5, 3.5, 4), GeoTestHelper.point(2.5, 3.5, 5), GeoTestHelper.point(2.5, 1.5, 3), GeoTestHelper.point(0.5, 1.5, 3)]) let negativeRing = GeoTestHelper.lineString([GeoTestHelper.point(1.0, 2.0, 3), GeoTestHelper.point(1.9, 2.5, 4), GeoTestHelper.point(1.9, 2.9, 5), GeoTestHelper.point(1.5, 2.5, 3), GeoTestHelper.point(1.0, 2.0, 3)]) - let polygon = GeoTestHelper.polygon([mainRing, negativeRing]) + let polygon = GeoTestHelper.polygon(mainRing, [negativeRing]) XCTAssertEqual(polygon.centroid as! SimplePoint, GeoTestHelper.simplePoint(1.4909997590845703, 2.5030003816872175, 3.0)) } @@ -271,7 +275,7 @@ class PolygonTests: XCTestCase { func testCentroid_LargeHole() { let mainRing = GeoTestHelper.lineString([GeoTestHelper.point(100.0, 0.0, 3), GeoTestHelper.point(101.0, 0.0, 4), GeoTestHelper.point(101.0, 1.0, 5), GeoTestHelper.point(100.0, 1.0, 3), GeoTestHelper.point(100.0, 0.0, 3)]) let negativeRing = GeoTestHelper.lineString([GeoTestHelper.point(100.05, 0.05, 3), GeoTestHelper.point(100.5, 0.05), GeoTestHelper.point(100.5, 0.95, 5), GeoTestHelper.point(100.05, 0.95, 3), GeoTestHelper.point(100.05, 0.05, 3)]) - let polygon = GeoTestHelper.polygon([mainRing, negativeRing]) + let polygon = GeoTestHelper.polygon(mainRing, [negativeRing]) XCTAssertEqual(polygon.centroid as! SimplePoint, GeoTestHelper.simplePoint(100.68225043951259, 0.50000059329894664, 3.0)) } @@ -279,7 +283,7 @@ class PolygonTests: XCTestCase { func testCentroid_CenterHole() { let mainRing = GeoTestHelper.lineString([GeoTestHelper.point(100.0, 0.0), GeoTestHelper.point(101.0, 0.0), GeoTestHelper.point(101.0, 1.0), GeoTestHelper.point(100.0, 1.0), GeoTestHelper.point(100.0, 0.0)]) let negativeRing = GeoTestHelper.lineString([GeoTestHelper.point(100.2, 0.2), GeoTestHelper.point(100.8, 0.2), GeoTestHelper.point(100.8, 0.8), GeoTestHelper.point(100.2, 0.8), GeoTestHelper.point(100.2, 0.2)]) - let polygon = GeoTestHelper.polygon([mainRing, negativeRing]) + let polygon = GeoTestHelper.polygon(mainRing, [negativeRing]) XCTAssertEqual(polygon.centroid as! SimplePoint, GeoTestHelper.simplePoint(100.5, 0.49999999999999994)) } @@ -376,15 +380,15 @@ class PolygonTests: XCTestCase { func testEquals() { XCTAssertEqual(polygon, polygon) - XCTAssertEqual(GeoTestHelper.polygon([lineString1]), GeoTestHelper.polygon([lineString1])) + XCTAssertEqual(GeoTestHelper.polygon(lineString1), GeoTestHelper.polygon(lineString1)) - XCTAssertEqual(GeoTestHelper.polygon([lineString1, lineString2]), GeoTestHelper.polygon([lineString1, lineString2])) + XCTAssertEqual(GeoTestHelper.polygon(lineString1, [lineString2]), GeoTestHelper.polygon(lineString1, [lineString2])) } // SOMEDAY: Comparing the Json test data and this is confusing. func testNotEquals() { - XCTAssertNotEqual(polygon, GeoTestHelper.polygon([lineString1])) + XCTAssertNotEqual(polygon, GeoTestHelper.polygon(lineString1)) - XCTAssertNotEqual(GeoTestHelper.polygon([lineString1, lineString2]), GeoTestHelper.polygon([lineString1, lineString3])) + XCTAssertNotEqual(GeoTestHelper.polygon(lineString1, [lineString2]), GeoTestHelper.polygon(lineString1, [lineString3])) } } diff --git a/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashBoxTests.swift b/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashBoxTests.swift deleted file mode 100644 index 824d96b..0000000 --- a/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashBoxTests.swift +++ /dev/null @@ -1,82 +0,0 @@ -import XCTest - -@testable import GeospatialSwift - -class GeohashBoxTests: XCTestCase { - var geohashCoder: GeohashCoderProtocol! - - private(set) var simpleGeohashBox: GeohashBox! - - // Neighbors - // 9yzsnmkm8 9yzsnmkm9 9yzsnmkmd - // 9yzsnmkm2 9yzsnmkm3 9yzsnmkm6 - // 9yzsnmkm0 9yzsnmkm1 9yzsnmkm4 - - // Centers - // -90.422609, 38.701594 -90.422566, 38.701594 -90.422523, 38.701594 - // -90.422609, 38.701637 -90.422566, 38.701637 -90.422523, 38.701637 - // -90.422609, 38.70168 -90.422566, 38.70168 -90.422523, 38.70168 - - // BoundingBox for 9yzsnmkm3 - // -90.422587, 38.7016155 -90.4225445, 38.7016585 - - override func setUp() { - geohashCoder = GeohashCoder() - - let boundingCoordinates = (minLongitude: -90.422587, minLatitude: 38.7016155, maxLongitude: -90.4225445, maxLatitude: 38.7016585) - - simpleGeohashBox = GeohashBox(boundingCoordinates: boundingCoordinates, geohashCoder: geohashCoder, geohash: "9yzsnmkm3") - } - - func testGeohash() { - XCTAssertEqual(simpleGeohashBox.geohash, "9yzsnmkm3") - } - - func testGeohashNeighbor_North() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .north, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm9") - } - - func testGeohashNeighbor_South() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .south, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm1") - } - - func testGeohashNeighbor_East() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .east, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm6") - } - - func testGeohashNeighbor_West() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .west, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm2") - } - - func testGeohashNeighbor_Northeast() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .north, precision: 9).geohashNeighbor(direction: .east, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkmd") - } - - func testGeohashNeighbor_Northwest() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .north, precision: 9).geohashNeighbor(direction: .west, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm8") - } - - func testGeohashNeighbor_Southeast() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .south, precision: 9).geohashNeighbor(direction: .east, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm4") - } - - func testGeohashNeighbor_Southwest() { - let neighbor = simpleGeohashBox.geohashNeighbor(direction: .south, precision: 9).geohashNeighbor(direction: .west, precision: 9) - - XCTAssertEqual(neighbor.geohash, "9yzsnmkm0") - } -} diff --git a/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashCoderTests.swift b/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashCoderTests.swift index 7611848..bba2e82 100644 --- a/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashCoderTests.swift +++ b/Tests/GeospatialSwiftTests/Test/API/Geohash/GeohashCoderTests.swift @@ -3,7 +3,11 @@ import XCTest @testable import GeospatialSwift class GeohashCoderTests: XCTestCase { - var geohashCoder: GeohashCoderProtocol! + var geohashCoder: GeohashCoder! + + var geohash: String! + var geohashNeighbors: [String]! + var geohashWithNeighbors: [String]! var geohashCenterPoint: SimplePoint! @@ -20,16 +24,94 @@ class GeohashCoderTests: XCTestCase { // BoundingBox for 9yzsnmkm3 // -90.422587, 38.7016155 -90.4225445, 38.7016585 + // GeoJson for 9yzsnmkm3 (Geohash) and 9yzsnmkm9 (North neighbor) + // { + // "type": "FeatureCollection", + // "features": [ + // { + // "type": "Feature", + // "properties": { + // "name": "9yzsnmkm3" + // }, + // "geometry": { + // "type": "Polygon", + // "coordinates": [ + // [ + // [ + // -90.4225873947144, + // 38.7016153335571 + // ], + // [ + // -90.4225873947144, + // 38.7016582489014 + // ], + // [ + // -90.4225444793701, + // 38.7016582489014 + // ], + // [ + // -90.4225444793701, + // 38.7016153335571 + // ], + // [ + // -90.4225873947144, + // 38.7016153335571 + // ] + // ] + // ] + // } + // }, + // { + // "type": "Feature", + // "properties": { + // "name": "9yzsnmkm9" + // }, + // "geometry": { + // "type": "Polygon", + // "coordinates": [ + // [ + // [ + // -90.42258739471436, + // 38.70165824890137 + // ], + // [ + // -90.42258739471436, + // 38.701701164245605 + // ], + // [ + // -90.42254447937012, + // 38.701701164245605 + // ], + // [ + // -90.42254447937012, + // 38.70165824890137 + // ], + // [ + // -90.42258739471436, + // 38.70165824890137 + // ] + // ] + // ] + // } + // } + // ] + // } + override func setUp() { geohashCoder = GeohashCoder() + geohash = "9yzsnmkm3" + // Order matters! Starts with north and goes clockwise. + geohashNeighbors = ["9yzsnmkm9", "9yzsnmkmd", "9yzsnmkm6", "9yzsnmkm4", "9yzsnmkm1", "9yzsnmkm0", "9yzsnmkm2", "9yzsnmkm8"] + // Order matters! Starts with the geohash and appends the geohashNeighbors + geohashWithNeighbors = ["9yzsnmkm3"] + geohashNeighbors geohashCenterPoint = SimplePoint(longitude: -90.422566, latitude: 38.701637) } func testGeohash() { let geohash = geohashCoder.geohash(for: geohashCenterPoint, precision: 9) - XCTAssertEqual(geohash, "9yzsnmkm3") + XCTAssertEqual(geohash, geohash) } func testGeohash_NoPrecision() { @@ -54,57 +136,123 @@ class GeohashCoderTests: XCTestCase { func testGeohash_NormalizesPoint() { let geohash = geohashCoder.geohash(for: SimplePoint(longitude: -450.422566, latitude: -321.298363), precision: 9) - XCTAssertEqual(geohash, "9yzsnmkm3") + XCTAssertEqual(geohash, geohash) } func testGeohashBoxFromPoint() { let geohashBox = geohashCoder.geohashBox(for: SimplePoint(longitude: -450.422566, latitude: -321.298363), precision: 9) - XCTAssertEqual(geohashBox.geohash, "9yzsnmkm3") - XCTAssertEqual(geohashBox.minLongitude, -90.4225873947144, accuracy: 10) - XCTAssertEqual(geohashBox.minLatitude, 38.7016153335571, accuracy: 10) - XCTAssertEqual(geohashBox.maxLongitude, -90.4225444793701, accuracy: 10) - XCTAssertEqual(geohashBox.maxLatitude, 38.7016582489014, accuracy: 10) + XCTAssertEqual(geohashBox.geohash, geohash) + XCTAssertEqual(geohashBox.boundingBox.minLongitude, -90.4225873947144, accuracy: 10) + XCTAssertEqual(geohashBox.boundingBox.minLatitude, 38.7016153335571, accuracy: 10) + XCTAssertEqual(geohashBox.boundingBox.maxLongitude, -90.4225444793701, accuracy: 10) + XCTAssertEqual(geohashBox.boundingBox.maxLatitude, 38.7016582489014, accuracy: 10) } func testGeohashBoxFromGeohash() { - let geohashBox = geohashCoder.geohashBox(geohash: "9yzsnmkm3")! - - XCTAssertEqual(geohashBox.geohash, "9yzsnmkm3") - XCTAssertEqual(geohashBox.minLongitude, -90.4225873947144, accuracy: 10) - XCTAssertEqual(geohashBox.minLatitude, 38.7016153335571, accuracy: 10) - XCTAssertEqual(geohashBox.maxLongitude, -90.4225444793701, accuracy: 10) - XCTAssertEqual(geohashBox.maxLatitude, 38.7016582489014, accuracy: 10) - } - - func testGeohashBoxFromGeohash_BadGeohash() { - let geohashBox = geohashCoder.geohashBox(geohash: "!!!!!") + let geohashBox = geohashCoder.geohashBox(forGeohash: geohash) - XCTAssertNil(geohashBox) + XCTAssertEqual(geohashBox.geohash, geohash) + XCTAssertEqual(geohashBox.boundingBox.minLongitude, -90.4225873947144, accuracy: 10) + XCTAssertEqual(geohashBox.boundingBox.minLatitude, 38.7016153335571, accuracy: 10) + XCTAssertEqual(geohashBox.boundingBox.maxLongitude, -90.4225444793701, accuracy: 10) + XCTAssertEqual(geohashBox.boundingBox.maxLatitude, 38.7016582489014, accuracy: 10) } func testGeohashes() { - let boundingCoordinates = (minLongitude: -90.422609, minLatitude: 38.701594, maxLongitude: -90.422523, maxLatitude: 38.70168) - let boundingBox = BoundingBox(boundingCoordinates: boundingCoordinates) + let boundingBox = GeodesicBoundingBox(minLongitude: -90.422609, minLatitude: 38.701594, maxLongitude: -90.422523, maxLatitude: 38.70168) let geohashes = geohashCoder.geohashes(for: boundingBox, precision: 9) XCTAssertEqual(geohashes.count, 9) - XCTAssertEqual(geohashes, ["9yzsnmkm0", "9yzsnmkm2", "9yzsnmkm8", "9yzsnmkm1", "9yzsnmkm3", "9yzsnmkm9", "9yzsnmkm4", "9yzsnmkm6", "9yzsnmkmd"]) + XCTAssertEqual(geohashes, ["9yzsnmkm0", "9yzsnmkm2", "9yzsnmkm8", "9yzsnmkm1", geohash, "9yzsnmkm9", "9yzsnmkm4", "9yzsnmkm6", "9yzsnmkmd"]) } func testGeohashBoxes() { - let boundingCoordinates = (minLongitude: -90.422609, minLatitude: 38.701594, maxLongitude: -90.422523, maxLatitude: 38.70168) - let boundingBox = BoundingBox(boundingCoordinates: boundingCoordinates) + let boundingBox = GeodesicBoundingBox(minLongitude: -90.422609, minLatitude: 38.701594, maxLongitude: -90.422523, maxLatitude: 38.70168) let geohashBoxes = geohashCoder.geohashBoxes(for: boundingBox, precision: 9) XCTAssertEqual(geohashBoxes.count, 9) - XCTAssertEqual(geohashBoxes.map { $0.geohash }, ["9yzsnmkm0", "9yzsnmkm2", "9yzsnmkm8", "9yzsnmkm1", "9yzsnmkm3", "9yzsnmkm9", "9yzsnmkm4", "9yzsnmkm6", "9yzsnmkmd"]) + XCTAssertEqual(geohashBoxes.map { $0.geohash }, ["9yzsnmkm0", "9yzsnmkm2", "9yzsnmkm8", "9yzsnmkm1", geohash, "9yzsnmkm9", "9yzsnmkm4", "9yzsnmkm6", "9yzsnmkmd"]) + } + + func testGeohashNeighbor_North() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .north) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm9") + } + + func testGeohashNeighbor_South() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .south) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm1") + } + + func testGeohashNeighbor_East() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .east) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm6") + } + + func testGeohashNeighbor_West() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .west) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm2") + } + + func testGeohashNeighbor_Northeast() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .north), direction: .east) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkmd") + } + + func testGeohashNeighbor_Northwest() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .north), direction: .west) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm8") + } + + func testGeohashNeighbor_Southeast() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .south), direction: .east) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm4") + } + + func testGeohashNeighbor_Southwest() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .south), direction: .west) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm0") + } + + func testGeohashBoxNeighbor_North() { + let geohashNeighbor = geohashCoder.geohashNeighbor(forGeohash: geohash, direction: .north) + let geohashBoxNeighbor = geohashCoder.geohashBox(forGeohash: geohashNeighbor) + + XCTAssertEqual(geohashNeighbor, "9yzsnmkm9") + XCTAssertEqual(geohashBoxNeighbor.geohash, "9yzsnmkm9") + XCTAssertEqual(geohashBoxNeighbor.boundingBox.minLongitude, -90.42258739471436, accuracy: 10) + XCTAssertEqual(geohashBoxNeighbor.boundingBox.minLatitude, 38.70165824890137, accuracy: 10) + XCTAssertEqual(geohashBoxNeighbor.boundingBox.maxLongitude, -90.42254447937012, accuracy: 10) + XCTAssertEqual(geohashBoxNeighbor.boundingBox.maxLatitude, 38.701701164245605, accuracy: 10) + } + + func testGeohashNeighbors() { + let geohashNeighbors = geohashCoder.geohashNeighbors(forGeohash: geohash) + + XCTAssertEqual(geohashNeighbors.count, 8) + XCTAssertEqual(geohashNeighbors, self.geohashNeighbors) } func testGeohashWithNeighbors() { - let geohashWithNeighbors = geohashCoder.geohashWithNeighbors(for: geohashCenterPoint, precision: 9) + let geohashWithNeighbors = geohashCoder.geohashWithNeighbors(forGeohash: geohash) XCTAssertEqual(geohashWithNeighbors.count, 9) - XCTAssertEqual(geohashWithNeighbors, ["9yzsnmkm8", "9yzsnmkm9", "9yzsnmkmd", "9yzsnmkm6", "9yzsnmkm4", "9yzsnmkm1", "9yzsnmkm0", "9yzsnmkm2", "9yzsnmkm3"]) + XCTAssertEqual(geohashWithNeighbors, self.geohashWithNeighbors) + } + + func testGeohashNeighbors_EdgePrefixDoesNotMatch() { + let geohashNeighbors = geohashCoder.geohashNeighbors(forGeohash: "u000") + + XCTAssertEqual(geohashNeighbors.count, 8) + XCTAssertEqual(geohashNeighbors, ["u001", "u003", "u002", "spbr", "spbp", "ezzz", "gbpb", "gbpc"]) } } diff --git a/Tests/GeospatialSwiftTests/Test/Extensions/Equatable.swift b/Tests/GeospatialSwiftTests/Test/Extensions/Equatable.swift index 02125f2..8286db4 100644 --- a/Tests/GeospatialSwiftTests/Test/Extensions/Equatable.swift +++ b/Tests/GeospatialSwiftTests/Test/Extensions/Equatable.swift @@ -11,45 +11,43 @@ public typealias Feature = GeoJson.Feature public typealias FeatureCollection = GeoJson.FeatureCollection extension SimplePoint: Equatable { - public static func == (lhs: SimplePoint, rhs: SimplePoint) -> Bool { return lhs as GeodesicPoint == rhs as GeodesicPoint } + public static func == (lhs: SimplePoint, rhs: SimplePoint) -> Bool { lhs as GeodesicPoint == rhs as GeodesicPoint } } -extension BoundingBox: Equatable { - public static func == (lhs: BoundingBox, rhs: BoundingBox) -> Bool { return lhs as GeodesicBoundingBox == rhs as GeodesicBoundingBox } -} +extension GeodesicBoundingBox: Equatable { } extension Point: Equatable { - public static func == (lhs: Point, rhs: Point) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: Point, rhs: Point) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension MultiPoint: Equatable { - public static func == (lhs: MultiPoint, rhs: MultiPoint) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: MultiPoint, rhs: MultiPoint) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension LineString: Equatable { - public static func == (lhs: LineString, rhs: LineString) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: LineString, rhs: LineString) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension MultiLineString: Equatable { - public static func == (lhs: MultiLineString, rhs: MultiLineString) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: MultiLineString, rhs: MultiLineString) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension Polygon: Equatable { - public static func == (lhs: Polygon, rhs: Polygon) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: Polygon, rhs: Polygon) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension MultiPolygon: Equatable { - public static func == (lhs: MultiPolygon, rhs: MultiPolygon) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: MultiPolygon, rhs: MultiPolygon) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension GeometryCollection: Equatable { - public static func == (lhs: GeometryCollection, rhs: GeometryCollection) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: GeometryCollection, rhs: GeometryCollection) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension Feature: Equatable { - public static func == (lhs: Feature, rhs: Feature) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: Feature, rhs: Feature) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } extension FeatureCollection: Equatable { - public static func == (lhs: FeatureCollection, rhs: FeatureCollection) -> Bool { return lhs as GeoJsonObject == rhs as GeoJsonObject } + public static func == (lhs: FeatureCollection, rhs: FeatureCollection) -> Bool { lhs as GeoJsonObject == rhs as GeoJsonObject } } diff --git a/Tests/GeospatialSwiftTests/Test/Parser/GeoJsonParserTests.swift b/Tests/GeospatialSwiftTests/Test/Parser/GeoJsonParserTests.swift index 11deb33..d6f1685 100644 --- a/Tests/GeospatialSwiftTests/Test/Parser/GeoJsonParserTests.swift +++ b/Tests/GeospatialSwiftTests/Test/Parser/GeoJsonParserTests.swift @@ -2,6 +2,7 @@ import XCTest @testable import GeospatialSwift +// swiftlint:disable type_body_length file_length class GeoJsonParserTests: XCTestCase { var geoJsonParser: GeoJsonParser! @@ -12,19 +13,40 @@ class GeoJsonParserTests: XCTestCase { } func testBadGeoJson() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: [:]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: [:]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["A valid geoJson must have a \"type\" key"]) } func testBadGeoJsonType() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Nothing"]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Nothing"]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid GeoJson Geometry type: Nothing"]) } func testPoint() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("Point")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("Point")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } + + XCTAssertTrue(geoJsonObject is Point) + XCTAssertEqual((geoJsonObject as? Point)?.longitude, 100.0) + XCTAssertEqual((geoJsonObject as? Point)?.latitude, 0.0) + XCTAssertNil((geoJsonObject as? Point)?.altitude) + } + + func testPoint_ValidatedJson() { + let geoJson = MockData.testGeoJson("Point") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) XCTAssertTrue(geoJsonObject is Point) XCTAssertEqual((geoJsonObject as? Point)?.longitude, 100.0) @@ -32,8 +54,40 @@ class GeoJsonParserTests: XCTestCase { XCTAssertNil((geoJsonObject as? Point)?.altitude) } + func testPoint_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("Point") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is Point) + XCTAssertEqual((geoJsonGeometry as? Point)?.longitude, 100.0) + XCTAssertEqual((geoJsonGeometry as? Point)?.latitude, 0.0) + XCTAssertNil((geoJsonGeometry as? Point)?.altitude) + } + + func testPoint_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("Point") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonCoordinatesGeometry is Point) + XCTAssertEqual((geoJsonCoordinatesGeometry as? Point)?.longitude, 100.0) + XCTAssertEqual((geoJsonCoordinatesGeometry as? Point)?.latitude, 0.0) + XCTAssertNil((geoJsonCoordinatesGeometry as? Point)?.altitude) + } + func testPointWithAltitude() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Point", "coordinates": [1, 2, 3]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Point", "coordinates": [1, 2, 3]]) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is Point) XCTAssertEqual((geoJsonObject as? Point)?.longitude, 1) @@ -42,19 +96,25 @@ class GeoJsonParserTests: XCTestCase { } func testPointNoCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Point", "coordinates": NSNull()]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Point", "coordinates": NSNull()]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["A valid GeoJson Coordinates Geometry must have a valid \"coordinates\" array"]) } func testPointBadCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Point", "coordinates": [1]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Point", "coordinates": [1]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid Point must have at least a longitude and latitude"]) } func testMultiPoint() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("MultiPoint")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("MultiPoint")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is MultiPoint) XCTAssertEqual((geoJsonObject as? MultiPoint)?.points.count, 2) @@ -66,20 +126,83 @@ class GeoJsonParserTests: XCTestCase { XCTAssertNil((geoJsonObject as? MultiPoint)?.points[1].altitude) } + func testMultiPoint_ValidatedJson() { + let geoJson = MockData.testGeoJson("MultiPoint") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonObject is MultiPoint) + XCTAssertEqual((geoJsonObject as? MultiPoint)?.points.count, 2) + XCTAssertEqual((geoJsonObject as? MultiPoint)?.points[0].longitude, 100.0) + XCTAssertEqual((geoJsonObject as? MultiPoint)?.points[0].longitude, 100.0) + XCTAssertNil((geoJsonObject as? MultiPoint)?.points[0].altitude) + XCTAssertEqual((geoJsonObject as? MultiPoint)?.points[1].longitude, 101.0) + XCTAssertEqual((geoJsonObject as? MultiPoint)?.points[1].longitude, 101.0) + XCTAssertNil((geoJsonObject as? MultiPoint)?.points[1].altitude) + } + + func testMultiPoint_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("MultiPoint") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is MultiPoint) + XCTAssertEqual((geoJsonGeometry as? MultiPoint)?.points.count, 2) + XCTAssertEqual((geoJsonGeometry as? MultiPoint)?.points[0].longitude, 100.0) + XCTAssertEqual((geoJsonGeometry as? MultiPoint)?.points[0].longitude, 100.0) + XCTAssertNil((geoJsonGeometry as? MultiPoint)?.points[0].altitude) + XCTAssertEqual((geoJsonGeometry as? MultiPoint)?.points[1].longitude, 101.0) + XCTAssertEqual((geoJsonGeometry as? MultiPoint)?.points[1].longitude, 101.0) + XCTAssertNil((geoJsonGeometry as? MultiPoint)?.points[1].altitude) + } + + func testMultiPoint_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("MultiPoint") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonCoordinatesGeometry is MultiPoint) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiPoint)?.points.count, 2) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiPoint)?.points[0].longitude, 100.0) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiPoint)?.points[0].longitude, 100.0) + XCTAssertNil((geoJsonCoordinatesGeometry as? MultiPoint)?.points[0].altitude) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiPoint)?.points[1].longitude, 101.0) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiPoint)?.points[1].longitude, 101.0) + XCTAssertNil((geoJsonCoordinatesGeometry as? MultiPoint)?.points[1].altitude) + } + func testMultiPointNoCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiPoint", "coordinates": []]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiPoint", "coordinates": []]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid MultiPoint must have at least one Point"]) } func testMultiPointBadCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiPoint", "coordinates": [[""]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiPoint", "coordinates": [[""]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Point(s) in MultiPoint", "A valid Point must have at least a longitude and latitude"]) } func testLineString() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("LineString")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("LineString")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is LineString) XCTAssertEqual((geoJsonObject as? LineString)?.points.count, 2) @@ -91,141 +214,415 @@ class GeoJsonParserTests: XCTestCase { XCTAssertNil((geoJsonObject as? LineString)?.points[1].altitude) } + func testLineString_ValidatedJson() { + let geoJson = MockData.testGeoJson("LineString") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonObject is LineString) + XCTAssertEqual((geoJsonObject as? LineString)?.points.count, 2) + XCTAssertEqual((geoJsonObject as? LineString)?.points[0].longitude, 100.0) + XCTAssertEqual((geoJsonObject as? LineString)?.points[0].longitude, 100.0) + XCTAssertNil((geoJsonObject as? LineString)?.points[0].altitude) + XCTAssertEqual((geoJsonObject as? LineString)?.points[1].longitude, 101.0) + XCTAssertEqual((geoJsonObject as? LineString)?.points[1].longitude, 101.0) + XCTAssertNil((geoJsonObject as? LineString)?.points[1].altitude) + } + + func testLineString_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("LineString") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is LineString) + XCTAssertEqual((geoJsonGeometry as? LineString)?.points.count, 2) + XCTAssertEqual((geoJsonGeometry as? LineString)?.points[0].longitude, 100.0) + XCTAssertEqual((geoJsonGeometry as? LineString)?.points[0].longitude, 100.0) + XCTAssertNil((geoJsonGeometry as? LineString)?.points[0].altitude) + XCTAssertEqual((geoJsonGeometry as? LineString)?.points[1].longitude, 101.0) + XCTAssertEqual((geoJsonGeometry as? LineString)?.points[1].longitude, 101.0) + XCTAssertNil((geoJsonGeometry as? LineString)?.points[1].altitude) + } + + func testLineString_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("LineString") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonCoordinatesGeometry is LineString) + XCTAssertEqual((geoJsonCoordinatesGeometry as? LineString)?.points.count, 2) + XCTAssertEqual((geoJsonCoordinatesGeometry as? LineString)?.points[0].longitude, 100.0) + XCTAssertEqual((geoJsonCoordinatesGeometry as? LineString)?.points[0].longitude, 100.0) + XCTAssertNil((geoJsonCoordinatesGeometry as? LineString)?.points[0].altitude) + XCTAssertEqual((geoJsonCoordinatesGeometry as? LineString)?.points[1].longitude, 101.0) + XCTAssertEqual((geoJsonCoordinatesGeometry as? LineString)?.points[1].longitude, 101.0) + XCTAssertNil((geoJsonCoordinatesGeometry as? LineString)?.points[1].altitude) + } + func testLineStringNoCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "LineString", "coordinates": []]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "LineString", "coordinates": []]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid LineString must have at least two Points"]) } func testLineStringNotEnoughCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "LineString", "coordinates": [[0, 1]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "LineString", "coordinates": [[0, 1]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["A valid LineString must have at least two Points"]) } func testLineStringBadCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "LineString", "coordinates": [[""], [""]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "LineString", "coordinates": [[""], [""]]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Point(s) in LineString", "A valid Point must have at least a longitude and latitude", "A valid Point must have at least a longitude and latitude"]) } func testMultiLineString() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("MultiLineString")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("MultiLineString")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } + + XCTAssertTrue(geoJsonObject is MultiLineString) + XCTAssertEqual((geoJsonObject as? MultiLineString)?.lines.count, 2) + } + + func testMultiLineString_ValidatedJson() { + let geoJson = MockData.testGeoJson("MultiLineString") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) XCTAssertTrue(geoJsonObject is MultiLineString) - XCTAssertEqual((geoJsonObject as? MultiLineString)?.lineStrings.count, 2) + XCTAssertEqual((geoJsonObject as? MultiLineString)?.lines.count, 2) + } + + func testMultiLineString_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("MultiLineString") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is MultiLineString) + XCTAssertEqual((geoJsonGeometry as? MultiLineString)?.lines.count, 2) + } + + func testMultiLineString_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("MultiLineString") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonCoordinatesGeometry is MultiLineString) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiLineString)?.lines.count, 2) } func testMultiLineStringNoCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiLineString", "coordinates": []]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiLineString", "coordinates": []]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid MultiLineString must have at least one LineString"]) } func testMultiLineStringNotEnoughCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiLineString", "coordinates": [[[0, 1]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiLineString", "coordinates": [[[0, 1]]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid LineString(s) in MultiLineString", "A valid LineString must have at least two Points"]) } func testMultiLineStringBadCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiLineString", "coordinates": [[""], [""]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiLineString", "coordinates": [[""], [""]]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid LineString(s) in MultiLineString", "A valid LineString must have valid coordinates", "A valid LineString must have valid coordinates"]) } func testPolygon() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("Polygon")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("Polygon")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is Polygon) XCTAssertEqual((geoJsonObject as? Polygon)?.linearRings.count, 1) } + func testPolygon_ValidatedJson() { + let geoJson = MockData.testGeoJson("Polygon") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonObject is Polygon) + XCTAssertEqual((geoJsonObject as? Polygon)?.linearRings.count, 1) + } + + func testPolygon_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("Polygon") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is Polygon) + XCTAssertEqual((geoJsonGeometry as? Polygon)?.linearRings.count, 1) + } + + func testPolygon_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("Polygon") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonCoordinatesGeometry is Polygon) + XCTAssertEqual((geoJsonCoordinatesGeometry as? Polygon)?.linearRings.count, 1) + } + func testPolygonMultipleRings() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("Polygon: Multiple Rings")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("Polygon: Multiple Rings")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is Polygon) XCTAssertEqual((geoJsonObject as? Polygon)?.linearRings.count, 2) } func testPolygonNoCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Polygon", "coordinates": []]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Polygon", "coordinates": []]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid Polygon must have at least one LinearRing"]) } func testPolygonNotEnoughCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Polygon", "coordinates": [[[]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Polygon", "coordinates": [[[]]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid LinearRing(s) in Polygon", "A valid LinearRing must have at least 4 points"]) } func testPolygonBadCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Polygon", "coordinates": [[[""], [""]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Polygon", "coordinates": [[[""], [""]]]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid LinearRing(s) in Polygon", "A valid LinearRing must have valid coordinates"]) } func testPolygonNotALinearRing() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Polygon", "coordinates": [[[0, 1], [0, 2], [0, 3], [0, 4]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Polygon", "coordinates": [[[0, 1], [0, 2], [0, 3], [0, 4]]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid LinearRing(s) in Polygon", "A valid LinearRing must have valid coordinates"]) } func testMultiPolygon() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("MultiPolygon")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("MultiPolygon")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is MultiPolygon) XCTAssertEqual((geoJsonObject as? MultiPolygon)?.polygons.count, 2) } + func testMultiPolygon_ValidatedJson() { + let geoJson = MockData.testGeoJson("MultiPolygon") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonObject is MultiPolygon) + XCTAssertEqual((geoJsonObject as? MultiPolygon)?.polygons.count, 2) + } + + func testMultiPolygon_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("MultiPolygon") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is MultiPolygon) + XCTAssertEqual((geoJsonGeometry as? MultiPolygon)?.polygons.count, 2) + } + + func testMultiPolygon_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("MultiPolygon") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonCoordinatesGeometry is MultiPolygon) + XCTAssertEqual((geoJsonCoordinatesGeometry as? MultiPolygon)?.polygons.count, 2) + } + func testMultiPolygonNoCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiPolygon", "coordinates": []]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiPolygon", "coordinates": []]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid FeatureCollection must have at least one feature"]) } func testMultiPolygonNotEnoughCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiPolygon", "coordinates": [[[[]]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiPolygon", "coordinates": [[[[]]]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Polygon(s) in MultiPolygon", "Invalid LinearRing(s) in Polygon", "A valid LinearRing must have at least 4 points"]) } func testMultiPolygonBadCoordinates() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "MultiPolygon", "coordinates": [[[[""], [""]]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "MultiPolygon", "coordinates": [[[[""], [""]]]]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Polygon(s) in MultiPolygon", "Invalid LinearRing(s) in Polygon", "A valid LinearRing must have valid coordinates"]) } func testGeometryCollection() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("GeometryCollection")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("GeometryCollection")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } + + XCTAssertTrue(geoJsonObject is GeometryCollection) + XCTAssertNotNil((geoJsonObject as? GeometryCollection)?.objectGeometries) + XCTAssertEqual((geoJsonObject as? GeometryCollection)?.objectGeometries.count, 2) + } + + func testGeometryCollection_ValidatedJson() { + let geoJson = MockData.testGeoJson("GeometryCollection") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) XCTAssertTrue(geoJsonObject is GeometryCollection) XCTAssertNotNil((geoJsonObject as? GeometryCollection)?.objectGeometries) - XCTAssertEqual((geoJsonObject as? GeometryCollection)?.objectGeometries?.count, 2) + XCTAssertEqual((geoJsonObject as? GeometryCollection)?.objectGeometries.count, 2) + } + + func testGeometryCollection_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("GeometryCollection") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromValidatedGeoJson: geoJson) + + XCTAssertTrue(geoJsonGeometry is GeometryCollection) + XCTAssertNotNil((geoJsonGeometry as? GeometryCollection)?.objectGeometries) + XCTAssertEqual((geoJsonGeometry as? GeometryCollection)?.objectGeometries.count, 2) + } + + func testGeometryCollection_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("GeometryCollection") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard !isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromGeoJson: geoJson) + + guard geoJsonCoordinatesGeometry.failed else { XCTFail("ValidatedJson"); return } } func testGeometryCollectionEmptyGeometries() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("GeometryCollection: Empty geometries")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("GeometryCollection: Empty geometries")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is GeometryCollection) - XCTAssertEqual((geoJsonObject as? GeometryCollection)?.objectGeometries?.count ?? -1, 0) + XCTAssertEqual((geoJsonObject as? GeometryCollection)?.objectGeometries.count ?? -1, 0) } func testGeometryCollectionNoGeometriesKey() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "GeometryCollection"]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "GeometryCollection"]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["A valid GeometryCollection must have a \"geometries\" key"]) } func testGeometryCollectionBadGeometry() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "GeometryCollection", "geometries": [["type": "Point", "coordinates": [1]]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "GeometryCollection", "geometries": [["type": "Point", "coordinates": [1]]]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Geometry(s) in GeometryCollection", "A valid Point must have at least a longitude and latitude"]) } func testFeature() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("Feature")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("Feature")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } + + XCTAssertTrue(geoJsonObject is Feature) + XCTAssertTrue((geoJsonObject as? Feature)?.geometry is Polygon) + XCTAssertEqual((geoJsonObject as? Feature)?.idAsString, "12345") + XCTAssertEqual((geoJsonObject as? Feature)?.properties?["prop0"] as? String, "value0") + XCTAssertEqual(((geoJsonObject as? Feature)?.properties?["prop1"] as? [String: String])?["this"], "that") + } + + func testFeature_ValidatedJson() { + let geoJson = MockData.testGeoJson("Feature") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) XCTAssertTrue(geoJsonObject is Feature) XCTAssertTrue((geoJsonObject as? Feature)?.geometry is Polygon) @@ -234,15 +631,43 @@ class GeoJsonParserTests: XCTestCase { XCTAssertEqual(((geoJsonObject as? Feature)?.properties?["prop1"] as? [String: String])?["this"], "that") } + func testFeature_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("Feature") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard !isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromGeoJson: geoJson) + + guard geoJsonGeometry.failed else { XCTFail("ValidatedJson"); return } + } + + func testFeature_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("Feature") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard !isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromGeoJson: geoJson) + + guard geoJsonCoordinatesGeometry.failed else { XCTFail("ValidatedJson"); return } + } + func testFeatureGeometryCollection() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("Feature: Geometry Collection")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("Feature: Geometry Collection")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is Feature) XCTAssertTrue((geoJsonObject as? Feature)?.geometry is GeometryCollection) } func testFeatureNullGeometry() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("Feature: null geometry")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("Feature: null geometry")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is Feature) XCTAssertNil((geoJsonObject as? Feature)?.geometry) @@ -251,19 +676,41 @@ class GeoJsonParserTests: XCTestCase { } func testFeatureNoGeometryKey() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Feature"]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Feature"]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["A valid Feature must have a \"geometry\" key"]) } func testFeatureBadGeometry() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "Feature", "geometry": ["type": "Point", "coordinates": [1]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "Feature", "geometry": ["type": "Point", "coordinates": [1]]]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Geometry in Feature", "A valid Point must have at least a longitude and latitude"]) } func testFeatureCollection() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("FeatureCollection")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("FeatureCollection")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } + + XCTAssertTrue(geoJsonObject is FeatureCollection) + XCTAssertEqual((geoJsonObject as? FeatureCollection)?.features.count, 3) + XCTAssertTrue((geoJsonObject as? FeatureCollection)?.features[0].geometry is Point) + XCTAssertTrue((geoJsonObject as? FeatureCollection)?.features[1].geometry is LineString) + XCTAssertTrue((geoJsonObject as? FeatureCollection)?.features[2].geometry is Polygon) + } + + func testFeatureCollection_ValidatedJson() { + let geoJson = MockData.testGeoJson("FeatureCollection") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonObject(geoJson: geoJson) == nil + + guard isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJson) XCTAssertTrue(geoJsonObject is FeatureCollection) XCTAssertEqual((geoJsonObject as? FeatureCollection)?.features.count, 3) @@ -272,8 +719,34 @@ class GeoJsonParserTests: XCTestCase { XCTAssertTrue((geoJsonObject as? FeatureCollection)?.features[2].geometry is Polygon) } + func testFeatureCollection_ValidatedGeometryJson() { + let geoJson = MockData.testGeoJson("FeatureCollection") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonGeometry(geoJson: geoJson) == nil + + guard !isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonGeometry = geoJsonParser.geoJsonGeometry(fromGeoJson: geoJson) + + guard geoJsonGeometry.failed else { XCTFail("ValidatedJson"); return } + } + + func testFeatureCollection_ValidatedCoordinatesGeometryJson() { + let geoJson = MockData.testGeoJson("FeatureCollection") + + let isGeoJsonValid = geoJsonParser.validateGeoJsonCoordinatesGeometry(geoJson: geoJson) == nil + + guard !isGeoJsonValid else { XCTFail("ValidatedJson"); return } + + let geoJsonCoordinatesGeometry = geoJsonParser.geoJsonCoordinatesGeometry(fromGeoJson: geoJson) + + guard geoJsonCoordinatesGeometry.failed else { XCTFail("ValidatedJson"); return } + } + func testFeatureCollection2Features1NullGeometry() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("FeatureCollection: 2 Features, 1 null geometry")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("FeatureCollection: 2 Features, 1 null geometry")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is FeatureCollection) XCTAssertEqual((geoJsonObject as? FeatureCollection)?.features.count, 2) @@ -282,7 +755,9 @@ class GeoJsonParserTests: XCTestCase { } func testFeatureCollection1FeatureNullGeometry() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: MockData.testGeoJson("FeatureCollection: 1 Feature, null geometry")) + let result = geoJsonParser.geoJsonObject(fromGeoJson: MockData.testGeoJson("FeatureCollection: 1 Feature, null geometry")) + + guard case .success(let geoJsonObject) = result else { XCTFail("Failed to parse GeoJson"); return } XCTAssertTrue(geoJsonObject is FeatureCollection) XCTAssertEqual((geoJsonObject as? FeatureCollection)?.features.count, 1) @@ -290,29 +765,42 @@ class GeoJsonParserTests: XCTestCase { } func testFeatureCollectionNoFeaturesKey() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "FeatureCollection"]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "FeatureCollection"]) - XCTAssertNil(geoJsonObject) + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } + + XCTAssertEqual(invalidGeoJson.reasons, ["A valid FeatureCollection must have a \"features\" key"]) } func testFeatureCollectionBadFeature() { - let geoJsonObject = geoJsonParser.geoJsonObject(from: ["type": "FeatureCollection", "features": [["": ""]]]) + let result = geoJsonParser.geoJsonObject(fromGeoJson: ["type": "FeatureCollection", "features": [["": ""]]]) + + guard case .failure(let invalidGeoJson) = result else { XCTFail("Successfully parsed invalid GeoJson"); return } - XCTAssertNil(geoJsonObject) + XCTAssertEqual(invalidGeoJson.reasons, ["Invalid Feature(s) in FeatureCollection", "A valid geoJson must have a \"type\" key"]) } func testAllMockData() { XCTAssertEqual(MockData.geoJsonTestData.count, 15) + var success = true MockData.geoJsonTestData.forEach { geoJsonData in // swiftlint:disable:next force_cast - let geoJsonObject = geoJsonParser.geoJsonObject(from: geoJsonData["geoJson"] as! GeoJsonDictionary) - - XCTAssertNotNil(geoJsonObject) + let result = geoJsonParser.geoJsonObject(fromGeoJson: geoJsonData["geoJson"] as! GeoJsonDictionary) - if geoJsonObject != nil { - Log.warning("Test Passed: \(geoJsonData["name"] ?? "")") + if case .failure = result { + XCTFail("Failed to parse GeoJson") + success = false } } + + guard success else { XCTFail("AllMockData"); return } + + MockData.geoJsonTestData.forEach { geoJsonData in + // swiftlint:disable:next force_cast + let geoJsonObject = geoJsonParser.geoJsonObject(fromValidatedGeoJson: geoJsonData["geoJson"] as! GeoJsonDictionary) + + XCTAssertNotNil(geoJsonObject) + } } } diff --git a/Tests/GeospatialSwiftTests/Test/Parser/WktParserTests.swift b/Tests/GeospatialSwiftTests/Test/Parser/WktParserTests.swift index 10ecdc2..133cc2d 100644 --- a/Tests/GeospatialSwiftTests/Test/Parser/WktParserTests.swift +++ b/Tests/GeospatialSwiftTests/Test/Parser/WktParserTests.swift @@ -3,7 +3,7 @@ import XCTest @testable import GeospatialSwift class WktParserTests: XCTestCase { - var geoJson: GeoJsonProtocol! + var geoJson: GeoJson! let wktTestData = MockData.wktTestData @@ -86,7 +86,7 @@ class WktParserTests: XCTestCase { wktTestData.forEach { wktData in // SOMEDAY: Lots of Unsupported types, check WktTestData.json for names with prefix "Unsupported" guard !((wktData["name"] as? String)?.hasPrefix("Unsupported ") ?? false) else { - Log.warning("Test Unsupported: \(wktData["name"] ?? "")") + print("Test Unsupported: \(wktData["name"] ?? "")") return } @@ -95,7 +95,7 @@ class WktParserTests: XCTestCase { XCTAssertNotNil(geoJsonObject) - Log.warning("Test \(geoJsonObject == nil ? "Failed" : "Passed"): \(wktData["name"] ?? "")") + print("Test \(geoJsonObject == nil ? "Failed" : "Passed"): \(wktData["name"] ?? "")") } } }