1+ //
2+ // NaturalEarthTests.swift
3+ // GeoProjector
4+ //
5+ // Created by Adrian Schönig on 3/5/2025.
6+ //
7+
8+ #if canImport(Testing)
9+ import Testing
10+
11+ @testable import GeoProjector
12+
13+ struct NaturalEarthTests {
14+
15+ @Test func matchesReferencePoints( ) async throws {
16+ // Reference coordinates projected with the polynomial Natural Earth projection (lon, lat, X, Y):
17+ // The radius of the sphere is 6371008.7714
18+ let reference = """
19+ 0.0 0.0 0.0 0.0
20+ 0.0 22.5 0.0 2525419.569383768
21+ 0.0 45.0 0.0 5052537.389973222
22+ 0.0 67.5 0.0 7400065.6562573705
23+ 0.0 90.0 0.0 9062062.394736718
24+ 45.0 0.0 4356790.016612169 0.0
25+ 45.0 22.5 4253309.544984069 2525419.569383768
26+ 45.0 45.0 3924521.5829515466 5052537.389973222
27+ 45.0 67.5 3354937.47115583 7400065.6562573705
28+ 45.0 90.0 2397978.2448443635 9062062.394736718
29+ 90.0 0.0 8713580.033224339 0.0
30+ 90.0 22.5 8506619.089968137 2525419.569383768
31+ 90.0 45.0 7849043.165903093 5052537.389973222
32+ 90.0 67.5 6709874.94231166 7400065.6562573705
33+ 90.0 90.0 4795956.489688727 9062062.394736718
34+ 135.0 0.0 1.3070370049836507E7 0.0
35+ 135.0 22.5 1.2759928634952208E7 2525419.569383768
36+ 135.0 45.0 1.177356474885464E7 5052537.389973222
37+ 135.0 67.5 1.0064812413467491E7 7400065.6562573705
38+ 135.0 90.0 7193934.734533091 9062062.394736718
39+ 180.0 0.0 1.7427160066448677E7 0.0
40+ 180.0 22.5 1.7013238179936275E7 2525419.569383768
41+ 180.0 45.0 1.5698086331806187E7 5052537.389973222
42+ 180.0 67.5 1.341974988462332E7 7400065.6562573705
43+ 180.0 90.0 9591912.979377454 9062062.394736718
44+ """
45+
46+ // Parse reference data
47+ let lines = reference. split ( separator: " \n " ) . map { $0. trimmingCharacters ( in: . whitespaces) }
48+ let referencePoints = lines. compactMap { line -> ( lon: Double , lat: Double , x: Double , y: Double ) ? in
49+ let components = line. split ( separator: " " ) . compactMap { Double ( $0. trimmingCharacters ( in: . whitespaces) ) }
50+ guard components. count == 4 else { return nil }
51+ return ( lon: components [ 0 ] , lat: components [ 1 ] , x: components [ 2 ] , y: components [ 3 ] )
52+ }
53+
54+ // Earth radius used in reference data
55+ let earthRadius = 6371008.7714
56+
57+ // Create projection
58+ let projection = Projections . NaturalEarth ( reference: . init( x: 0 , y: 0 ) )
59+
60+ // Test reference points
61+ for point in referencePoints {
62+ // Convert degrees to radians for input
63+ let lonRad = point. lon * . pi / 180.0
64+ let latRad = point. lat * . pi / 180.0
65+
66+ // Project the point
67+ let projected = try #require( projection. project ( . init( x: lonRad, y: latRad) ) , " Failed to project point at lon: \( point. lon) , lat: \( point. lat) " )
68+
69+ // Scale to match reference earth radius
70+ let scaledX = projected. x * earthRadius
71+ let scaledY = projected. y * earthRadius
72+
73+ // Compare with reference data within tolerance
74+ #expect( abs ( scaledX - point. x) < 0.1 , " X coordinate doesn't match for lon: \( point. lon) , lat: \( point. lat) . Expected: \( point. x) , got: \( scaledX) " )
75+ #expect( abs ( scaledY - point. y) < 0.1 , " Y coordinate doesn't match for lon: \( point. lon) , lat: \( point. lat) . Expected: \( point. y) , got: \( scaledY) " )
76+ }
77+ }
78+ }
79+
80+ #endif
0 commit comments