expo-gaode-map-navigation 1.1.5 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/README.md +213 -73
  2. package/android/build.gradle +10 -0
  3. package/android/src/main/cpp/CMakeLists.txt +24 -0
  4. package/android/src/main/cpp/cluster_jni.cpp +848 -0
  5. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +616 -92
  6. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +493 -0
  7. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +230 -14
  8. package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapViewModule.kt +37 -27
  9. package/android/src/main/java/expo/modules/gaodemap/map/MapPreloadManager.kt +494 -0
  10. package/android/src/main/java/expo/modules/gaodemap/map/companion/BitmapDescriptorCache.kt +30 -0
  11. package/android/src/main/java/expo/modules/gaodemap/map/companion/IconBitmapCache.kt +37 -0
  12. package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +76 -0
  13. package/android/src/main/java/expo/modules/gaodemap/map/modules/LocationManager.kt +15 -3
  14. package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +4 -59
  15. package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleView.kt +9 -12
  16. package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleViewModule.kt +5 -6
  17. package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +539 -66
  18. package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterViewModule.kt +17 -1
  19. package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +165 -33
  20. package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +15 -3
  21. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +1249 -672
  22. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +40 -17
  23. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointView.kt +177 -22
  24. package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointViewModule.kt +11 -3
  25. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonView.kt +57 -14
  26. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonViewModule.kt +9 -5
  27. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineView.kt +90 -63
  28. package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineViewModule.kt +7 -3
  29. package/android/src/main/java/expo/modules/gaodemap/map/services/LocationForegroundService.kt +3 -2
  30. package/android/src/main/java/expo/modules/gaodemap/map/utils/BitmapDescriptorCache.kt +20 -0
  31. package/android/src/main/java/expo/modules/gaodemap/map/utils/ClusterNative.kt +13 -0
  32. package/android/src/main/java/expo/modules/gaodemap/map/utils/ColorParser.kt +20 -0
  33. package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +515 -0
  34. package/android/src/main/java/expo/modules/gaodemap/map/utils/LatLngParser.kt +91 -0
  35. package/android/src/main/java/expo/modules/gaodemap/map/utils/PermissionHelper.kt +248 -0
  36. package/build/ExpoGaodeMapNaviView.d.ts +7 -7
  37. package/build/ExpoGaodeMapNaviView.js +10 -11
  38. package/build/ExpoGaodeMapNavigationModule.d.ts +2 -1
  39. package/build/index.d.ts +35 -33
  40. package/build/index.js +70 -106
  41. package/build/map/ExpoGaodeMapModule.d.ts +2 -201
  42. package/build/map/ExpoGaodeMapModule.js +586 -18
  43. package/build/map/ExpoGaodeMapOfflineModule.d.ts +139 -0
  44. package/build/map/ExpoGaodeMapOfflineModule.js +8 -0
  45. package/build/map/ExpoGaodeMapView.js +66 -58
  46. package/build/map/components/FoldableMapView.d.ts +38 -0
  47. package/build/map/components/FoldableMapView.js +209 -0
  48. package/build/map/components/MapContext.d.ts +12 -0
  49. package/build/map/components/MapContext.js +54 -0
  50. package/build/map/components/MapUI.d.ts +18 -0
  51. package/build/map/components/MapUI.js +29 -0
  52. package/build/map/components/overlays/Circle.js +34 -3
  53. package/build/map/components/overlays/Cluster.d.ts +3 -1
  54. package/build/map/components/overlays/Cluster.js +31 -2
  55. package/build/map/components/overlays/HeatMap.d.ts +3 -1
  56. package/build/map/components/overlays/HeatMap.js +33 -3
  57. package/build/map/components/overlays/Marker.d.ts +1 -1
  58. package/build/map/components/overlays/Marker.js +37 -32
  59. package/build/map/components/overlays/MultiPoint.js +1 -1
  60. package/build/map/components/overlays/Polygon.js +30 -3
  61. package/build/map/components/overlays/Polyline.js +36 -3
  62. package/build/map/index.d.ts +25 -5
  63. package/build/map/index.js +59 -18
  64. package/build/map/types/common.types.d.ts +40 -0
  65. package/build/map/types/common.types.js +0 -4
  66. package/build/map/types/index.d.ts +3 -2
  67. package/build/map/types/map-view.types.d.ts +108 -3
  68. package/build/map/types/native-module.types.d.ts +363 -0
  69. package/build/map/types/native-module.types.js +5 -0
  70. package/build/map/types/offline.types.d.ts +132 -0
  71. package/build/map/types/offline.types.js +5 -0
  72. package/build/map/types/overlays.types.d.ts +137 -24
  73. package/build/map/utils/ErrorHandler.d.ts +110 -0
  74. package/build/map/utils/ErrorHandler.js +421 -0
  75. package/build/map/utils/GeoUtils.d.ts +20 -0
  76. package/build/map/utils/GeoUtils.js +76 -0
  77. package/build/map/utils/OfflineMapManager.d.ts +148 -0
  78. package/build/map/utils/OfflineMapManager.js +217 -0
  79. package/build/map/utils/PermissionUtils.d.ts +91 -0
  80. package/build/map/utils/PermissionUtils.js +255 -0
  81. package/build/map/utils/PlatformDetector.d.ts +102 -0
  82. package/build/map/utils/PlatformDetector.js +186 -0
  83. package/build/types/index.d.ts +1 -0
  84. package/build/types/index.js +1 -0
  85. package/build/types/native-module.types.d.ts +69 -0
  86. package/build/types/native-module.types.js +2 -0
  87. package/build/types/naviview.types.d.ts +1 -1
  88. package/expo-module.config.json +12 -10
  89. package/ios/ExpoGaodeMapNavigation.podspec +9 -0
  90. package/ios/map/ExpoGaodeMapModule.swift +485 -75
  91. package/ios/map/ExpoGaodeMapOfflineModule.swift +479 -0
  92. package/ios/map/ExpoGaodeMapView.swift +611 -62
  93. package/ios/map/ExpoGaodeMapViewModule.swift +48 -26
  94. package/ios/map/MapPreloadManager.swift +348 -0
  95. package/ios/map/cpp/ClusterEngine.cpp +110 -0
  96. package/ios/map/cpp/ClusterEngine.hpp +20 -0
  97. package/ios/map/cpp/ColorParser.cpp +135 -0
  98. package/ios/map/cpp/ColorParser.hpp +14 -0
  99. package/ios/map/cpp/GeometryEngine.cpp +574 -0
  100. package/ios/map/cpp/GeometryEngine.hpp +159 -0
  101. package/ios/map/cpp/QuadTree.cpp +92 -0
  102. package/ios/map/cpp/QuadTree.hpp +42 -0
  103. package/ios/map/cpp/README.md +55 -0
  104. package/ios/map/managers/UIManager.swift +72 -1
  105. package/ios/map/modules/LocationManager.swift +123 -166
  106. package/ios/map/overlays/CircleView.swift +16 -32
  107. package/ios/map/overlays/CircleViewModule.swift +12 -12
  108. package/ios/map/overlays/ClusterAnnotation.swift +32 -0
  109. package/ios/map/overlays/ClusterView.swift +331 -45
  110. package/ios/map/overlays/ClusterViewModule.swift +20 -6
  111. package/ios/map/overlays/HeatMapView.swift +135 -32
  112. package/ios/map/overlays/HeatMapViewModule.swift +20 -8
  113. package/ios/map/overlays/MarkerView.swift +613 -130
  114. package/ios/map/overlays/MarkerViewModule.swift +38 -18
  115. package/ios/map/overlays/MultiPointView.swift +168 -10
  116. package/ios/map/overlays/MultiPointViewModule.swift +27 -5
  117. package/ios/map/overlays/PolygonView.swift +62 -23
  118. package/ios/map/overlays/PolygonViewModule.swift +18 -12
  119. package/ios/map/overlays/PolylineView.swift +21 -13
  120. package/ios/map/overlays/PolylineViewModule.swift +18 -12
  121. package/ios/map/utils/ClusterNative.h +96 -0
  122. package/ios/map/utils/ClusterNative.mm +377 -0
  123. package/ios/map/utils/ColorParser.swift +12 -1
  124. package/ios/map/utils/CppBridging.mm +13 -0
  125. package/ios/map/utils/GeometryUtils.swift +34 -0
  126. package/ios/map/utils/LatLngParser.swift +87 -0
  127. package/ios/map/utils/PermissionManager.swift +135 -6
  128. package/package.json +3 -2
  129. package/shared/cpp/ClusterEngine.cpp +110 -0
  130. package/shared/cpp/ClusterEngine.hpp +20 -0
  131. package/shared/cpp/ColorParser.cpp +135 -0
  132. package/shared/cpp/ColorParser.hpp +14 -0
  133. package/shared/cpp/GeometryEngine.cpp +574 -0
  134. package/shared/cpp/GeometryEngine.hpp +159 -0
  135. package/shared/cpp/QuadTree.cpp +92 -0
  136. package/shared/cpp/QuadTree.hpp +42 -0
  137. package/shared/cpp/README.md +55 -0
  138. package/shared/cpp/tests/benchmark_js.js +41 -0
  139. package/shared/cpp/tests/run.sh +17 -0
  140. package/shared/cpp/tests/test_main.cpp +276 -0
  141. package/build/map/ExpoGaodeMap.types.d.ts +0 -41
  142. package/build/map/ExpoGaodeMap.types.js +0 -24
  143. package/build/map/utils/EventManager.d.ts +0 -10
  144. package/build/map/utils/EventManager.js +0 -26
  145. package/build/map/utils/ModuleLoader.d.ts +0 -73
  146. package/build/map/utils/ModuleLoader.js +0 -112
@@ -1,37 +1,43 @@
1
1
  import ExpoModulesCore
2
2
 
3
- public class NaviPolylineViewModule: Module {
3
+ public class PolylineViewModule: Module {
4
4
  public func definition() -> ModuleDefinition {
5
- Name("NaviPolylineView")
5
+ Name("PolylineView")
6
6
 
7
- View(NaviPolylineView.self) {
7
+ View(PolylineView.self) {
8
8
  Events("onPolylinePress")
9
9
 
10
- Prop("points") { (view: NaviPolylineView, points: [[String: Double]]) in
11
- view.setPoints(points)
12
- }
10
+ Prop("points") { (view: PolylineView, points: [[String: Double]]) in
11
+ view.setPoints(points)
12
+ }
13
13
 
14
- Prop("strokeWidth") { (view: NaviPolylineView, width: Double) in
14
+ Prop("strokeWidth") { (view: PolylineView, width: Double) in
15
15
  view.setStrokeWidth(Float(width))
16
16
  }
17
17
 
18
- Prop("strokeColor") { (view: NaviPolylineView, color: String) in
18
+ Prop("strokeColor") { (view: PolylineView, color: String?) in
19
19
  view.setStrokeColor(color)
20
20
  }
21
21
 
22
- Prop("texture") { (view: NaviPolylineView, url: String?) in
22
+ Prop("texture") { (view: PolylineView, url: String?) in
23
23
  view.setTexture(url)
24
24
  }
25
25
 
26
- Prop("dotted") { (view: NaviPolylineView, dotted: Bool) in
26
+ Prop("dotted") { (view: PolylineView, dotted: Bool) in
27
27
  view.setDotted(dotted)
28
28
  }
29
+
30
+ Prop("simplificationTolerance") { (view: PolylineView, tolerance: Double) in
31
+ view.setSimplificationTolerance(tolerance)
32
+ }
29
33
 
30
- OnViewDidUpdateProps { (view: NaviPolylineView) in
34
+ OnViewDidUpdateProps { (view: PolylineView) in
35
+ // 属性更新完成后,如果还没连接地图,尝试连接
31
36
  if !view.isMapConnected() {
37
+ // 查找父视图 ExpoGaodeMapView
32
38
  var parent = view.superview
33
39
  while parent != nil {
34
- if let mapView = parent as? NaviMapView {
40
+ if let mapView = parent as? ExpoGaodeMapView {
35
41
  view.setMap(mapView.mapView)
36
42
  return
37
43
  }
@@ -0,0 +1,96 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <CoreLocation/CoreLocation.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ @interface ClusterNative : NSObject
7
+
8
+ + (NSArray<NSNumber *> *)clusterPointsWithLatitudes:(NSArray<NSNumber *> *)latitudes
9
+ longitudes:(NSArray<NSNumber *> *)longitudes
10
+ radiusMeters:(double)radiusMeters NS_SWIFT_NAME(clusterPoints(latitudes:longitudes:radiusMeters:));
11
+
12
+ + (BOOL)isPointInCircleWithPointLat:(double)pointLat
13
+ pointLon:(double)pointLon
14
+ centerLat:(double)centerLat
15
+ centerLon:(double)centerLon
16
+ radiusMeters:(double)radiusMeters NS_SWIFT_NAME(isPointInCircle(pointLat:pointLon:centerLat:centerLon:radiusMeters:));
17
+
18
+ + (BOOL)isPointInPolygonWithPointLat:(double)pointLat
19
+ pointLon:(double)pointLon
20
+ latitudes:(NSArray<NSNumber *> *)latitudes
21
+ longitudes:(NSArray<NSNumber *> *)longitudes NS_SWIFT_NAME(isPointInPolygon(pointLat:pointLon:latitudes:longitudes:));
22
+
23
+ + (double)calculatePolygonAreaWithLatitudes:(NSArray<NSNumber *> *)latitudes
24
+ longitudes:(NSArray<NSNumber *> *)longitudes NS_SWIFT_NAME(calculatePolygonArea(latitudes:longitudes:));
25
+
26
+ + (double)calculateRectangleAreaWithSouthWestLat:(double)swLat
27
+ southWestLon:(double)swLon
28
+ northEastLat:(double)neLat
29
+ northEastLon:(double)neLon NS_SWIFT_NAME(calculateRectangleArea(swLat:swLon:neLat:neLon:));
30
+
31
+ + (double)calculateDistanceWithLat1:(double)lat1
32
+ lon1:(double)lon1
33
+ lat2:(double)lat2
34
+ lon2:(double)lon2 NS_SWIFT_NAME(calculateDistance(lat1:lon1:lat2:lon2:));
35
+
36
+ + (NSArray<NSNumber *> *)simplifyPolylineWithLatitudes:(NSArray<NSNumber *> *)latitudes
37
+ longitudes:(NSArray<NSNumber *> *)longitudes
38
+ toleranceMeters:(double)toleranceMeters NS_SWIFT_NAME(simplifyPolyline(latitudes:longitudes:tolerance:));
39
+
40
+ + (double)calculatePathLengthWithLatitudes:(NSArray<NSNumber *> *)latitudes
41
+ longitudes:(NSArray<NSNumber *> *)longitudes NS_SWIFT_NAME(calculatePathLength(latitudes:longitudes:));
42
+
43
+ + (NSDictionary * _Nullable)getPointAtDistanceWithLatitudes:(NSArray<NSNumber *> *)latitudes
44
+ longitudes:(NSArray<NSNumber *> *)longitudes
45
+ distanceMeters:(double)distanceMeters NS_SWIFT_NAME(getPointAtDistance(latitudes:longitudes:distanceMeters:));
46
+
47
+ + (NSDictionary * _Nullable)getNearestPointOnPathWithLatitudes:(NSArray<NSNumber *> *)latitudes
48
+ longitudes:(NSArray<NSNumber *> *)longitudes
49
+ targetLat:(double)targetLat
50
+ targetLon:(double)targetLon NS_SWIFT_NAME(getNearestPointOnPath(latitudes:longitudes:targetLat:targetLon:));
51
+
52
+ + (NSDictionary * _Nullable)calculateCentroidWithLatitudes:(NSArray<NSNumber *> *)latitudes
53
+ longitudes:(NSArray<NSNumber *> *)longitudes NS_SWIFT_NAME(calculateCentroid(latitudes:longitudes:));
54
+
55
+ + (NSDictionary * _Nullable)calculatePathBoundsWithLatitudes:(NSArray<NSNumber *> *)latitudes
56
+ longitudes:(NSArray<NSNumber *> *)longitudes NS_SWIFT_NAME(calculatePathBounds(latitudes:longitudes:));
57
+
58
+ + (NSString *)encodeGeoHashWithLat:(double)lat
59
+ lon:(double)lon
60
+ precision:(int)precision NS_SWIFT_NAME(encodeGeoHash(lat:lon:precision:));
61
+
62
+ + (uint32_t)parseColorWithString:(NSString *)colorString NS_SWIFT_NAME(parseColor(colorString:));
63
+
64
+ + (CLLocationCoordinate2D)coordinateForMapPointWithX:(double)x y:(double)y NS_SWIFT_NAME(coordinateForMapPoint(x:y:));
65
+
66
+ /**
67
+ * 解析高德地图 API 返回的 Polyline 字符串
68
+ * 格式: "lng,lat;lng,lat;..."
69
+ * @param polylineStr 高德原始 polyline 字符串
70
+ * @return 扁平化的坐标数组 [lat1, lon1, lat2, lon2, ...]
71
+ */
72
+ + (NSArray<NSNumber *> *)parsePolyline:(NSString *)polylineStr NS_SWIFT_NAME(parsePolyline(polylineStr:));
73
+
74
+ // --- 瓦片与坐标转换 ---
75
+ + (NSDictionary *)latLngToTileWithLat:(double)lat lon:(double)lon zoom:(int)zoom NS_SWIFT_NAME(latLngToTile(lat:lon:zoom:));
76
+ + (NSDictionary *)tileToLatLngWithX:(int)x y:(int)y zoom:(int)zoom NS_SWIFT_NAME(tileToLatLng(x:y:zoom:));
77
+ + (NSDictionary *)latLngToPixelWithLat:(double)lat lon:(double)lon zoom:(int)zoom NS_SWIFT_NAME(latLngToPixel(lat:lon:zoom:));
78
+ + (NSDictionary *)pixelToLatLngWithX:(double)x y:(double)y zoom:(int)zoom NS_SWIFT_NAME(pixelToLatLng(x:y:zoom:));
79
+
80
+ // --- 批量地理围栏与网格聚合 ---
81
+ + (int)findPointInPolygonsWithPointLat:(double)pointLat
82
+ pointLon:(double)pointLon
83
+ polygons:(NSArray<NSArray<NSDictionary *> *> *)polygons NS_SWIFT_NAME(findPointInPolygons(pointLat:pointLon:polygons:));
84
+
85
+ /**
86
+ * 生成网格聚合数据 (常用于展示网格聚合图或大规模点数据处理)
87
+ * 将大量散点按照网格大小进行聚合,返回每个网格的中心点和强度
88
+ */
89
+ + (NSArray<NSDictionary *> *)generateHeatmapGridWithLatitudes:(NSArray<NSNumber *> *)latitudes
90
+ longitudes:(NSArray<NSNumber *> *)longitudes
91
+ weights:(NSArray<NSNumber *> *)weights
92
+ gridSizeMeters:(double)gridSizeMeters NS_SWIFT_NAME(generateHeatmapGrid(latitudes:longitudes:weights:gridSizeMeters:));
93
+
94
+ @end
95
+
96
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,377 @@
1
+ #import "ClusterNative.h"
2
+
3
+ #if __has_include(<MAMapKit/MAMapKit.h>)
4
+ #import <MAMapKit/MAMapKit.h>
5
+ #define HAS_MAMAPKIT 1
6
+ #else
7
+ #define HAS_MAMAPKIT 0
8
+ #endif
9
+
10
+ #include <vector>
11
+ #include <string>
12
+
13
+ #include "../cpp/ClusterEngine.hpp"
14
+ #include "../cpp/GeometryEngine.hpp"
15
+ #include "../cpp/ColorParser.hpp"
16
+
17
+ @implementation ClusterNative
18
+
19
+ + (NSArray<NSNumber *> *)clusterPointsWithLatitudes:(NSArray<NSNumber *> *)latitudes
20
+ longitudes:(NSArray<NSNumber *> *)longitudes
21
+ radiusMeters:(double)radiusMeters {
22
+ if (latitudes.count == 0 || latitudes.count != longitudes.count) {
23
+ return @[@0];
24
+ }
25
+
26
+ std::vector<gaodemap::ClusterPoint> points;
27
+ points.reserve(latitudes.count);
28
+
29
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
30
+ gaodemap::ClusterPoint point;
31
+ point.lat = latitudes[i].doubleValue;
32
+ point.lon = longitudes[i].doubleValue;
33
+ point.index = (int)i;
34
+ points.push_back(point);
35
+ }
36
+
37
+ const auto clusters = gaodemap::clusterPoints(points, radiusMeters);
38
+
39
+ NSMutableArray<NSNumber *> *result = [NSMutableArray array];
40
+ [result addObject:@(clusters.size())];
41
+
42
+ for (const auto &cluster : clusters) {
43
+ [result addObject:@(cluster.centerIndex)];
44
+ [result addObject:@(cluster.indices.size())];
45
+ for (int idx : cluster.indices) {
46
+ [result addObject:@(idx)];
47
+ }
48
+ }
49
+
50
+ return result;
51
+ }
52
+
53
+ + (BOOL)isPointInCircleWithPointLat:(double)pointLat
54
+ pointLon:(double)pointLon
55
+ centerLat:(double)centerLat
56
+ centerLon:(double)centerLon
57
+ radiusMeters:(double)radiusMeters {
58
+ return gaodemap::isPointInCircle(pointLat, pointLon, centerLat, centerLon, radiusMeters);
59
+ }
60
+
61
+ + (BOOL)isPointInPolygonWithPointLat:(double)pointLat
62
+ pointLon:(double)pointLon
63
+ latitudes:(NSArray<NSNumber *> *)latitudes
64
+ longitudes:(NSArray<NSNumber *> *)longitudes {
65
+ if (latitudes.count < 3 || latitudes.count != longitudes.count) {
66
+ return NO;
67
+ }
68
+
69
+ std::vector<gaodemap::GeoPoint> polygon;
70
+ polygon.reserve(latitudes.count);
71
+
72
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
73
+ polygon.push_back({latitudes[i].doubleValue, longitudes[i].doubleValue});
74
+ }
75
+
76
+ return gaodemap::isPointInPolygon(pointLat, pointLon, polygon);
77
+ }
78
+
79
+ + (double)calculatePolygonAreaWithLatitudes:(NSArray<NSNumber *> *)latitudes
80
+ longitudes:(NSArray<NSNumber *> *)longitudes {
81
+ if (latitudes.count < 3 || latitudes.count != longitudes.count) {
82
+ return 0.0;
83
+ }
84
+
85
+ std::vector<gaodemap::GeoPoint> polygon;
86
+ polygon.reserve(latitudes.count);
87
+
88
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
89
+ polygon.push_back({latitudes[i].doubleValue, longitudes[i].doubleValue});
90
+ }
91
+
92
+ return gaodemap::calculatePolygonArea(polygon);
93
+ }
94
+
95
+ + (double)calculateRectangleAreaWithSouthWestLat:(double)swLat
96
+ southWestLon:(double)swLon
97
+ northEastLat:(double)neLat
98
+ northEastLon:(double)neLon {
99
+ return gaodemap::calculateRectangleArea(swLat, swLon, neLat, neLon);
100
+ }
101
+
102
+ + (double)calculateDistanceWithLat1:(double)lat1
103
+ lon1:(double)lon1
104
+ lat2:(double)lat2
105
+ lon2:(double)lon2 {
106
+ return gaodemap::calculateDistance(lat1, lon1, lat2, lon2);
107
+ }
108
+
109
+ + (NSArray<NSNumber *> *)simplifyPolylineWithLatitudes:(NSArray<NSNumber *> *)latitudes
110
+ longitudes:(NSArray<NSNumber *> *)longitudes
111
+ toleranceMeters:(double)toleranceMeters {
112
+ if (latitudes.count == 0 || latitudes.count != longitudes.count) {
113
+ return @[];
114
+ }
115
+
116
+ std::vector<gaodemap::GeoPoint> points;
117
+ points.reserve(latitudes.count);
118
+
119
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
120
+ points.push_back({latitudes[i].doubleValue, longitudes[i].doubleValue});
121
+ }
122
+
123
+ const auto simplified = gaodemap::simplifyPolyline(points, toleranceMeters);
124
+
125
+ NSMutableArray<NSNumber *> *result = [NSMutableArray arrayWithCapacity:simplified.size() * 2];
126
+ for (const auto &p : simplified) {
127
+ [result addObject:@(p.lat)];
128
+ [result addObject:@(p.lon)];
129
+ }
130
+
131
+ return result;
132
+ }
133
+
134
+ + (double)calculatePathLengthWithLatitudes:(NSArray<NSNumber *> *)latitudes
135
+ longitudes:(NSArray<NSNumber *> *)longitudes {
136
+ if (latitudes.count != longitudes.count || latitudes.count < 2) {
137
+ return 0.0;
138
+ }
139
+
140
+ std::vector<gaodemap::GeoPoint> points;
141
+ points.reserve(latitudes.count);
142
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
143
+ points.push_back({[latitudes[i] doubleValue], [longitudes[i] doubleValue]});
144
+ }
145
+
146
+ return gaodemap::calculatePathLength(points);
147
+ }
148
+
149
+ + (NSDictionary * _Nullable)getPointAtDistanceWithLatitudes:(NSArray<NSNumber *> *)latitudes
150
+ longitudes:(NSArray<NSNumber *> *)longitudes
151
+ distanceMeters:(double)distanceMeters {
152
+ if (latitudes.count != longitudes.count || latitudes.count < 2) {
153
+ return nil;
154
+ }
155
+
156
+ std::vector<gaodemap::GeoPoint> points;
157
+ points.reserve(latitudes.count);
158
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
159
+ points.push_back({[latitudes[i] doubleValue], [longitudes[i] doubleValue]});
160
+ }
161
+
162
+ double outLat, outLon, outAngle;
163
+ if (gaodemap::getPointAtDistance(points, distanceMeters, &outLat, &outLon, &outAngle)) {
164
+ return @{
165
+ @"latitude": @(outLat),
166
+ @"longitude": @(outLon),
167
+ @"angle": @(outAngle)
168
+ };
169
+ }
170
+
171
+ return nil;
172
+ }
173
+
174
+ + (NSDictionary * _Nullable)getNearestPointOnPathWithLatitudes:(NSArray<NSNumber *> *)latitudes
175
+ longitudes:(NSArray<NSNumber *> *)longitudes
176
+ targetLat:(double)targetLat
177
+ targetLon:(double)targetLon {
178
+ if (latitudes.count != longitudes.count || latitudes.count < 2) {
179
+ return nil;
180
+ }
181
+
182
+ std::vector<gaodemap::GeoPoint> points;
183
+ points.reserve(latitudes.count);
184
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
185
+ points.push_back({[latitudes[i] doubleValue], [longitudes[i] doubleValue]});
186
+ }
187
+
188
+ gaodemap::GeoPoint target = {targetLat, targetLon};
189
+ gaodemap::NearestPointResult result = gaodemap::getNearestPointOnPath(points, target);
190
+
191
+ return @{
192
+ @"latitude": @(result.latitude),
193
+ @"longitude": @(result.longitude),
194
+ @"index": @(result.index),
195
+ @"distanceMeters": @(result.distanceMeters)
196
+ };
197
+ }
198
+
199
+ + (NSDictionary * _Nullable)calculateCentroidWithLatitudes:(NSArray<NSNumber *> *)latitudes
200
+ longitudes:(NSArray<NSNumber *> *)longitudes {
201
+ if (latitudes.count != longitudes.count || latitudes.count < 3) {
202
+ return nil;
203
+ }
204
+
205
+ std::vector<gaodemap::GeoPoint> polygon;
206
+ polygon.reserve(latitudes.count);
207
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
208
+ polygon.push_back({[latitudes[i] doubleValue], [longitudes[i] doubleValue]});
209
+ }
210
+
211
+ gaodemap::GeoPoint centroid = gaodemap::calculateCentroid(polygon);
212
+
213
+ return @{
214
+ @"latitude": @(centroid.lat),
215
+ @"longitude": @(centroid.lon)
216
+ };
217
+ }
218
+
219
+ + (NSDictionary * _Nullable)calculatePathBoundsWithLatitudes:(NSArray<NSNumber *> *)latitudes
220
+ longitudes:(NSArray<NSNumber *> *)longitudes {
221
+ if (latitudes.count != longitudes.count || latitudes.count == 0) {
222
+ return nil;
223
+ }
224
+
225
+ std::vector<gaodemap::GeoPoint> points;
226
+ points.reserve(latitudes.count);
227
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
228
+ points.push_back({[latitudes[i] doubleValue], [longitudes[i] doubleValue]});
229
+ }
230
+
231
+ gaodemap::PathBounds bounds = gaodemap::calculatePathBounds(points);
232
+
233
+ return @{
234
+ @"north": @(bounds.north),
235
+ @"south": @(bounds.south),
236
+ @"east": @(bounds.east),
237
+ @"west": @(bounds.west),
238
+ @"center": @{
239
+ @"latitude": @(bounds.centerLat),
240
+ @"longitude": @(bounds.centerLon)
241
+ }
242
+ };
243
+ }
244
+
245
+ + (NSString *)encodeGeoHashWithLat:(double)lat
246
+ lon:(double)lon
247
+ precision:(int)precision {
248
+ std::string geoHash = gaodemap::encodeGeoHash(lat, lon, precision);
249
+ return [NSString stringWithUTF8String:geoHash.c_str()];
250
+ }
251
+
252
+ + (uint32_t)parseColorWithString:(NSString *)colorString {
253
+ if (!colorString) return 0;
254
+ std::string colorStr = [colorString UTF8String];
255
+ return gaodemap::parseColor(colorStr);
256
+ }
257
+
258
+ + (CLLocationCoordinate2D)coordinateForMapPointWithX:(double)x y:(double)y {
259
+ #if HAS_MAMAPKIT
260
+ MAMapPoint point;
261
+ point.x = x;
262
+ point.y = y;
263
+ return MACoordinateForMapPoint(point);
264
+ #else
265
+ return CLLocationCoordinate2DMake(0, 0);
266
+ #endif
267
+ }
268
+
269
+ + (NSArray<NSNumber *> *)parsePolyline:(NSString *)polylineStr {
270
+ if (!polylineStr || polylineStr.length == 0) {
271
+ return @[];
272
+ }
273
+
274
+ std::string cppPolylineStr([polylineStr UTF8String]);
275
+ const auto points = gaodemap::parsePolyline(cppPolylineStr);
276
+
277
+ NSMutableArray<NSNumber *> *result = [NSMutableArray arrayWithCapacity:points.size() * 2];
278
+ for (const auto &p : points) {
279
+ [result addObject:@(p.lat)];
280
+ [result addObject:@(p.lon)];
281
+ }
282
+
283
+ return result;
284
+ }
285
+
286
+ // --- 瓦片与坐标转换 ---
287
+
288
+ + (NSDictionary *)latLngToTileWithLat:(double)lat lon:(double)lon zoom:(int)zoom {
289
+ gaodemap::TileResult result = gaodemap::latLngToTile(lat, lon, zoom);
290
+ return @{
291
+ @"x": @(result.x),
292
+ @"y": @(result.y),
293
+ @"z": @(result.z)
294
+ };
295
+ }
296
+
297
+ + (NSDictionary *)tileToLatLngWithX:(int)x y:(int)y zoom:(int)zoom {
298
+ gaodemap::GeoPoint result = gaodemap::tileToLatLng(x, y, zoom);
299
+ return @{
300
+ @"latitude": @(result.lat),
301
+ @"longitude": @(result.lon)
302
+ };
303
+ }
304
+
305
+ + (NSDictionary *)latLngToPixelWithLat:(double)lat lon:(double)lon zoom:(int)zoom {
306
+ gaodemap::PixelResult result = gaodemap::latLngToPixel(lat, lon, zoom);
307
+ return @{
308
+ @"x": @(result.x),
309
+ @"y": @(result.y)
310
+ };
311
+ }
312
+
313
+ + (NSDictionary *)pixelToLatLngWithX:(double)x y:(double)y zoom:(int)zoom {
314
+ gaodemap::GeoPoint result = gaodemap::pixelToLatLng(x, y, zoom);
315
+ return @{
316
+ @"latitude": @(result.lat),
317
+ @"longitude": @(result.lon)
318
+ };
319
+ }
320
+
321
+ // --- 批量地理围栏与热力图 ---
322
+
323
+ + (int)findPointInPolygonsWithPointLat:(double)pointLat
324
+ pointLon:(double)pointLon
325
+ polygons:(NSArray<NSArray<NSDictionary *> *> *)polygons {
326
+ if (polygons.count == 0) return -1;
327
+
328
+ std::vector<std::vector<gaodemap::GeoPoint>> cppPolygons;
329
+ cppPolygons.reserve(polygons.count);
330
+
331
+ for (NSArray<NSDictionary *> *polygon in polygons) {
332
+ std::vector<gaodemap::GeoPoint> cppPolygon;
333
+ cppPolygon.reserve(polygon.count);
334
+ for (NSDictionary *point in polygon) {
335
+ cppPolygon.push_back({
336
+ [point[@"latitude"] doubleValue],
337
+ [point[@"longitude"] doubleValue]
338
+ });
339
+ }
340
+ cppPolygons.push_back(std::move(cppPolygon));
341
+ }
342
+
343
+ return gaodemap::findPointInPolygons(pointLat, pointLon, cppPolygons);
344
+ }
345
+
346
+ + (NSArray<NSDictionary *> *)generateHeatmapGridWithLatitudes:(NSArray<NSNumber *> *)latitudes
347
+ longitudes:(NSArray<NSNumber *> *)longitudes
348
+ weights:(NSArray<NSNumber *> *)weights
349
+ gridSizeMeters:(double)gridSizeMeters {
350
+ if (latitudes.count == 0 || latitudes.count != longitudes.count || latitudes.count != weights.count) {
351
+ return @[];
352
+ }
353
+
354
+ std::vector<gaodemap::HeatmapPoint> points;
355
+ points.reserve(latitudes.count);
356
+ for (NSUInteger i = 0; i < latitudes.count; i++) {
357
+ points.push_back({
358
+ [latitudes[i] doubleValue],
359
+ [longitudes[i] doubleValue],
360
+ [weights[i] doubleValue]
361
+ });
362
+ }
363
+
364
+ auto cells = gaodemap::generateHeatmapGrid(points, gridSizeMeters);
365
+
366
+ NSMutableArray *result = [NSMutableArray arrayWithCapacity:cells.size()];
367
+ for (const auto &c : cells) {
368
+ [result addObject:@{
369
+ @"latitude": @(c.lat),
370
+ @"longitude": @(c.lon),
371
+ @"intensity": @(c.intensity)
372
+ }];
373
+ }
374
+ return result;
375
+ }
376
+
377
+ @end
@@ -27,6 +27,17 @@ class ColorParser {
27
27
  * 解析字符串颜色值
28
28
  */
29
29
  private static func parseColorString(_ colorString: String) -> UIColor? {
30
+ // Try native parser first
31
+ let nativeColor = ClusterNative.parseColor(colorString: colorString)
32
+ if nativeColor != 0 {
33
+ // ARGB -> UIColor
34
+ let a = CGFloat((nativeColor >> 24) & 0xFF) / 255.0
35
+ let r = CGFloat((nativeColor >> 16) & 0xFF) / 255.0
36
+ let g = CGFloat((nativeColor >> 8) & 0xFF) / 255.0
37
+ let b = CGFloat(nativeColor & 0xFF) / 255.0
38
+ return UIColor(red: r, green: g, blue: b, alpha: a)
39
+ }
40
+
30
41
  let trimmedString = colorString.trimmingCharacters(in: .whitespacesAndNewlines)
31
42
 
32
43
  // 处理 rgba() 格式
@@ -97,7 +108,7 @@ class ColorParser {
97
108
  */
98
109
  private static func parseHexColor(_ hexString: String) -> UIColor? {
99
110
  var hex = hexString.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
100
- var alpha: CGFloat = 1.0
111
+ let alpha: CGFloat = 1.0
101
112
 
102
113
  // 处理 #RGB 格式
103
114
  if hex.count == 3 {
@@ -0,0 +1,13 @@
1
+ #include <vector>
2
+ #include <string>
3
+ #include <cmath>
4
+ #include <algorithm>
5
+ #include <sstream>
6
+ #include <map>
7
+
8
+ // 直接包含 C++ 实现文件,强制编译
9
+ // 这种方式规避了 CocoaPods 对外部源文件的处理问题
10
+ #include "../cpp/ClusterEngine.cpp"
11
+ #include "../cpp/GeometryEngine.cpp"
12
+ #include "../cpp/ColorParser.cpp"
13
+ #include "../cpp/QuadTree.cpp"
@@ -0,0 +1,34 @@
1
+ import CoreLocation
2
+
3
+ /**
4
+ * 几何计算工具类 (iOS)
5
+ *
6
+ * 桥接 ClusterNative (C++) 实现的几何计算功能
7
+ */
8
+ public enum GeometryUtils {
9
+
10
+ /**
11
+ * 轨迹抽稀 (RDP 算法)
12
+ * @param points 原始轨迹点
13
+ * @param tolerance 允许误差 (米)
14
+ * @return 简化后的轨迹点
15
+ */
16
+ public static func simplifyPolyline(_ points: [CLLocationCoordinate2D], tolerance: Double) -> [CLLocationCoordinate2D] {
17
+ if points.count < 3 || tolerance <= 0 {
18
+ return points
19
+ }
20
+
21
+ let lats = points.map { NSNumber(value: $0.latitude) }
22
+ let lons = points.map { NSNumber(value: $0.longitude) }
23
+
24
+ let result = ClusterNative.simplifyPolyline(latitudes: lats, longitudes: lons, tolerance: tolerance)
25
+
26
+ var simplified: [CLLocationCoordinate2D] = []
27
+ for i in stride(from: 0, to: result.count, by: 2) {
28
+ if i + 1 < result.count {
29
+ simplified.append(CLLocationCoordinate2D(latitude: result[i].doubleValue, longitude: result[i+1].doubleValue))
30
+ }
31
+ }
32
+ return simplified
33
+ }
34
+ }