From d2905b06c35cca22df78fc78495d344860539032 Mon Sep 17 00:00:00 2001 From: Thomas Rasch Date: Sat, 14 Oct 2023 18:10:48 +0200 Subject: [PATCH] Bugfix: Query bounding boxes in the western hemisphere --- Sources/MVTTools/VectorTileQuery.swift | 6 ++- Tests/MVTToolsTests/QueryTests.swift | 56 +++++++++++++++++++++++ Tests/MVTToolsTests/VectorTileTests.swift | 38 --------------- 3 files changed, 60 insertions(+), 40 deletions(-) create mode 100644 Tests/MVTToolsTests/QueryTests.swift diff --git a/Sources/MVTTools/VectorTileQuery.swift b/Sources/MVTTools/VectorTileQuery.swift index f3515d0..a4e293f 100644 --- a/Sources/MVTTools/VectorTileQuery.swift +++ b/Sources/MVTTools/VectorTileQuery.swift @@ -241,12 +241,14 @@ extension VectorTile { return (features: features, results: results) } - private static func queryBoundingBox( + static func queryBoundingBox( at coordinate: Coordinate3D, tolerance: CLLocationDistance, projection: Projection) -> BoundingBox { + let tolerance = fabs(tolerance) + switch projection { case .epsg3857, .noSRID: return BoundingBox( @@ -261,8 +263,8 @@ extension VectorTile { case .epsg4326: // Length of one minute at this latitude - let oneDegreeLongitudeDistanceInMeters: Double = cos(coordinate.longitude * Double.pi / 180.0) * 111_000.0 let oneDegreeLatitudeDistanceInMeters = 111_000.0 + let oneDegreeLongitudeDistanceInMeters: Double = fabs(cos(coordinate.longitude * Double.pi / 180.0) * oneDegreeLatitudeDistanceInMeters) let longitudeDistance: Double = (tolerance / oneDegreeLongitudeDistanceInMeters) let latitudeDistance: Double = (tolerance / oneDegreeLatitudeDistanceInMeters) diff --git a/Tests/MVTToolsTests/QueryTests.swift b/Tests/MVTToolsTests/QueryTests.swift new file mode 100644 index 0000000..8fe41e8 --- /dev/null +++ b/Tests/MVTToolsTests/QueryTests.swift @@ -0,0 +1,56 @@ +#if !os(Linux) +import CoreLocation +#endif +import GISTools +import XCTest + +@testable import MVTTools + +final class QueryTests: XCTestCase { + + func testQueryBoundingBox() { + let coordinate = Coordinate3D(latitude: 47.0, longitude: -120.0) + let queryBoundingBox = VectorTile.queryBoundingBox(at: coordinate, tolerance: 15.0, projection: .epsg4326) + XCTAssertGreaterThan(queryBoundingBox.northEast.latitude, queryBoundingBox.southWest.latitude) + XCTAssertGreaterThan(queryBoundingBox.northEast.longitude, queryBoundingBox.southWest.longitude) + } + + func testQuery() { + let tileName: String = "14_8716_8015.vector.mvt" + let mvt = TestData.dataFromFile(name: tileName) + XCTAssertFalse(mvt.isEmpty) + + guard let tile = VectorTile(data: mvt, x: 8716, y: 8015, z: 14) else { + XCTAssert(false, "Unable to parse the vector tile \(tileName)") + return + } + + XCTAssertFalse(tile.isIndexed) + + measure { + let result = tile.query(at: Coordinate3D(latitude: 3.870163, longitude: 11.518585), tolerance: 100.0) + XCTAssertNotNil(result) + XCTAssertEqual(result.count, 68) + } + } + + func testQueryWithIndex() { + let tileName: String = "14_8716_8015.vector.mvt" + let mvt = TestData.dataFromFile(name: tileName) + XCTAssertFalse(mvt.isEmpty) + + guard let tile = VectorTile(data: mvt, x: 8716, y: 8015, z: 14, indexed: .hilbert) else { + XCTAssert(false, "Unable to parse the vector tile \(tileName)") + return + } + + XCTAssertTrue(tile.isIndexed) + + measure { + let resultWithIndex = tile.query(at: Coordinate3D(latitude: 3.870163, longitude: 11.518585), tolerance: 100.0) + XCTAssertNotNil(resultWithIndex) + XCTAssertEqual(resultWithIndex.count, 68) + } + } + +} diff --git a/Tests/MVTToolsTests/VectorTileTests.swift b/Tests/MVTToolsTests/VectorTileTests.swift index ddc1c1a..9fbdf30 100644 --- a/Tests/MVTToolsTests/VectorTileTests.swift +++ b/Tests/MVTToolsTests/VectorTileTests.swift @@ -37,44 +37,6 @@ final class VectorTileTests: XCTestCase { // try? string?.write(to: URL(fileURLWithPath: "/\(NSHomeDirectory())/Desktop/test.json"), atomically: true, encoding: .utf8) } - func testQuery() { - let tileName: String = "14_8716_8015.vector.mvt" - let mvt = TestData.dataFromFile(name: tileName) - XCTAssertFalse(mvt.isEmpty) - - guard let tile = VectorTile(data: mvt, x: 8716, y: 8015, z: 14) else { - XCTAssert(false, "Unable to parse the vector tile \(tileName)") - return - } - - XCTAssertFalse(tile.isIndexed) - - measure { - let result = tile.query(at: Coordinate3D(latitude: 3.870163, longitude: 11.518585), tolerance: 100.0) - XCTAssertNotNil(result) - XCTAssertEqual(result.count, 68) - } - } - - func testQueryWithIndex() { - let tileName: String = "14_8716_8015.vector.mvt" - let mvt = TestData.dataFromFile(name: tileName) - XCTAssertFalse(mvt.isEmpty) - - guard let tile = VectorTile(data: mvt, x: 8716, y: 8015, z: 14, indexed: .hilbert) else { - XCTAssert(false, "Unable to parse the vector tile \(tileName)") - return - } - - XCTAssertTrue(tile.isIndexed) - - measure { - let resultWithIndex = tile.query(at: Coordinate3D(latitude: 3.870163, longitude: 11.518585), tolerance: 100.0) - XCTAssertNotNil(resultWithIndex) - XCTAssertEqual(resultWithIndex.count, 68) - } - } - func testWriteMvt() { guard var tile = VectorTile(x: 8716, y: 8015, z: 14) else { XCTAssert(false, "Unable to create a vector tile")