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.
- package/README.md +213 -73
- package/android/build.gradle +10 -0
- package/android/src/main/cpp/CMakeLists.txt +24 -0
- package/android/src/main/cpp/cluster_jni.cpp +848 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapModule.kt +616 -92
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapOfflineModule.kt +493 -0
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapView.kt +230 -14
- package/android/src/main/java/expo/modules/gaodemap/map/ExpoGaodeMapViewModule.kt +37 -27
- package/android/src/main/java/expo/modules/gaodemap/map/MapPreloadManager.kt +494 -0
- package/android/src/main/java/expo/modules/gaodemap/map/companion/BitmapDescriptorCache.kt +30 -0
- package/android/src/main/java/expo/modules/gaodemap/map/companion/IconBitmapCache.kt +37 -0
- package/android/src/main/java/expo/modules/gaodemap/map/managers/UIManager.kt +76 -0
- package/android/src/main/java/expo/modules/gaodemap/map/modules/LocationManager.kt +15 -3
- package/android/src/main/java/expo/modules/gaodemap/map/modules/SDKInitializer.kt +4 -59
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleView.kt +9 -12
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/CircleViewModule.kt +5 -6
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterView.kt +539 -66
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/ClusterViewModule.kt +17 -1
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapView.kt +165 -33
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/HeatMapViewModule.kt +15 -3
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerView.kt +1249 -672
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MarkerViewModule.kt +40 -17
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointView.kt +177 -22
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/MultiPointViewModule.kt +11 -3
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonView.kt +57 -14
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolygonViewModule.kt +9 -5
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineView.kt +90 -63
- package/android/src/main/java/expo/modules/gaodemap/map/overlays/PolylineViewModule.kt +7 -3
- package/android/src/main/java/expo/modules/gaodemap/map/services/LocationForegroundService.kt +3 -2
- package/android/src/main/java/expo/modules/gaodemap/map/utils/BitmapDescriptorCache.kt +20 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/ClusterNative.kt +13 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/ColorParser.kt +20 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/GeometryUtils.kt +515 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/LatLngParser.kt +91 -0
- package/android/src/main/java/expo/modules/gaodemap/map/utils/PermissionHelper.kt +248 -0
- package/build/ExpoGaodeMapNaviView.d.ts +7 -7
- package/build/ExpoGaodeMapNaviView.js +10 -11
- package/build/ExpoGaodeMapNavigationModule.d.ts +2 -1
- package/build/index.d.ts +35 -33
- package/build/index.js +70 -106
- package/build/map/ExpoGaodeMapModule.d.ts +2 -201
- package/build/map/ExpoGaodeMapModule.js +586 -18
- package/build/map/ExpoGaodeMapOfflineModule.d.ts +139 -0
- package/build/map/ExpoGaodeMapOfflineModule.js +8 -0
- package/build/map/ExpoGaodeMapView.js +66 -58
- package/build/map/components/FoldableMapView.d.ts +38 -0
- package/build/map/components/FoldableMapView.js +209 -0
- package/build/map/components/MapContext.d.ts +12 -0
- package/build/map/components/MapContext.js +54 -0
- package/build/map/components/MapUI.d.ts +18 -0
- package/build/map/components/MapUI.js +29 -0
- package/build/map/components/overlays/Circle.js +34 -3
- package/build/map/components/overlays/Cluster.d.ts +3 -1
- package/build/map/components/overlays/Cluster.js +31 -2
- package/build/map/components/overlays/HeatMap.d.ts +3 -1
- package/build/map/components/overlays/HeatMap.js +33 -3
- package/build/map/components/overlays/Marker.d.ts +1 -1
- package/build/map/components/overlays/Marker.js +37 -32
- package/build/map/components/overlays/MultiPoint.js +1 -1
- package/build/map/components/overlays/Polygon.js +30 -3
- package/build/map/components/overlays/Polyline.js +36 -3
- package/build/map/index.d.ts +25 -5
- package/build/map/index.js +59 -18
- package/build/map/types/common.types.d.ts +40 -0
- package/build/map/types/common.types.js +0 -4
- package/build/map/types/index.d.ts +3 -2
- package/build/map/types/map-view.types.d.ts +108 -3
- package/build/map/types/native-module.types.d.ts +363 -0
- package/build/map/types/native-module.types.js +5 -0
- package/build/map/types/offline.types.d.ts +132 -0
- package/build/map/types/offline.types.js +5 -0
- package/build/map/types/overlays.types.d.ts +137 -24
- package/build/map/utils/ErrorHandler.d.ts +110 -0
- package/build/map/utils/ErrorHandler.js +421 -0
- package/build/map/utils/GeoUtils.d.ts +20 -0
- package/build/map/utils/GeoUtils.js +76 -0
- package/build/map/utils/OfflineMapManager.d.ts +148 -0
- package/build/map/utils/OfflineMapManager.js +217 -0
- package/build/map/utils/PermissionUtils.d.ts +91 -0
- package/build/map/utils/PermissionUtils.js +255 -0
- package/build/map/utils/PlatformDetector.d.ts +102 -0
- package/build/map/utils/PlatformDetector.js +186 -0
- package/build/types/index.d.ts +1 -0
- package/build/types/index.js +1 -0
- package/build/types/native-module.types.d.ts +69 -0
- package/build/types/native-module.types.js +2 -0
- package/build/types/naviview.types.d.ts +1 -1
- package/expo-module.config.json +12 -10
- package/ios/ExpoGaodeMapNavigation.podspec +9 -0
- package/ios/map/ExpoGaodeMapModule.swift +485 -75
- package/ios/map/ExpoGaodeMapOfflineModule.swift +479 -0
- package/ios/map/ExpoGaodeMapView.swift +611 -62
- package/ios/map/ExpoGaodeMapViewModule.swift +48 -26
- package/ios/map/MapPreloadManager.swift +348 -0
- package/ios/map/cpp/ClusterEngine.cpp +110 -0
- package/ios/map/cpp/ClusterEngine.hpp +20 -0
- package/ios/map/cpp/ColorParser.cpp +135 -0
- package/ios/map/cpp/ColorParser.hpp +14 -0
- package/ios/map/cpp/GeometryEngine.cpp +574 -0
- package/ios/map/cpp/GeometryEngine.hpp +159 -0
- package/ios/map/cpp/QuadTree.cpp +92 -0
- package/ios/map/cpp/QuadTree.hpp +42 -0
- package/ios/map/cpp/README.md +55 -0
- package/ios/map/managers/UIManager.swift +72 -1
- package/ios/map/modules/LocationManager.swift +123 -166
- package/ios/map/overlays/CircleView.swift +16 -32
- package/ios/map/overlays/CircleViewModule.swift +12 -12
- package/ios/map/overlays/ClusterAnnotation.swift +32 -0
- package/ios/map/overlays/ClusterView.swift +331 -45
- package/ios/map/overlays/ClusterViewModule.swift +20 -6
- package/ios/map/overlays/HeatMapView.swift +135 -32
- package/ios/map/overlays/HeatMapViewModule.swift +20 -8
- package/ios/map/overlays/MarkerView.swift +613 -130
- package/ios/map/overlays/MarkerViewModule.swift +38 -18
- package/ios/map/overlays/MultiPointView.swift +168 -10
- package/ios/map/overlays/MultiPointViewModule.swift +27 -5
- package/ios/map/overlays/PolygonView.swift +62 -23
- package/ios/map/overlays/PolygonViewModule.swift +18 -12
- package/ios/map/overlays/PolylineView.swift +21 -13
- package/ios/map/overlays/PolylineViewModule.swift +18 -12
- package/ios/map/utils/ClusterNative.h +96 -0
- package/ios/map/utils/ClusterNative.mm +377 -0
- package/ios/map/utils/ColorParser.swift +12 -1
- package/ios/map/utils/CppBridging.mm +13 -0
- package/ios/map/utils/GeometryUtils.swift +34 -0
- package/ios/map/utils/LatLngParser.swift +87 -0
- package/ios/map/utils/PermissionManager.swift +135 -6
- package/package.json +3 -2
- package/shared/cpp/ClusterEngine.cpp +110 -0
- package/shared/cpp/ClusterEngine.hpp +20 -0
- package/shared/cpp/ColorParser.cpp +135 -0
- package/shared/cpp/ColorParser.hpp +14 -0
- package/shared/cpp/GeometryEngine.cpp +574 -0
- package/shared/cpp/GeometryEngine.hpp +159 -0
- package/shared/cpp/QuadTree.cpp +92 -0
- package/shared/cpp/QuadTree.hpp +42 -0
- package/shared/cpp/README.md +55 -0
- package/shared/cpp/tests/benchmark_js.js +41 -0
- package/shared/cpp/tests/run.sh +17 -0
- package/shared/cpp/tests/test_main.cpp +276 -0
- package/build/map/ExpoGaodeMap.types.d.ts +0 -41
- package/build/map/ExpoGaodeMap.types.js +0 -24
- package/build/map/utils/EventManager.d.ts +0 -10
- package/build/map/utils/EventManager.js +0 -26
- package/build/map/utils/ModuleLoader.d.ts +0 -73
- package/build/map/utils/ModuleLoader.js +0 -112
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <vector>
|
|
4
|
+
#include <string>
|
|
5
|
+
|
|
6
|
+
namespace gaodemap {
|
|
7
|
+
|
|
8
|
+
struct GeoPoint {
|
|
9
|
+
double lat;
|
|
10
|
+
double lon;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
double calculateDistance(double lat1, double lon1, double lat2, double lon2);
|
|
14
|
+
bool isPointInCircle(double pointLat, double pointLon, double centerLat, double centerLon, double radiusMeters);
|
|
15
|
+
bool isPointInPolygon(double pointLat, double pointLon, const std::vector<GeoPoint>& polygon);
|
|
16
|
+
double calculatePolygonArea(const std::vector<GeoPoint>& polygon);
|
|
17
|
+
double calculateRectangleArea(double swLat, double swLon, double neLat, double neLon);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Ramer-Douglas-Peucker 轨迹抽稀算法
|
|
21
|
+
* @param points 原始轨迹点
|
|
22
|
+
* @param toleranceMeters 允许的误差(米),值越大点越少
|
|
23
|
+
* @return 简化后的轨迹点
|
|
24
|
+
*/
|
|
25
|
+
std::vector<GeoPoint> simplifyPolyline(const std::vector<GeoPoint>& points, double toleranceMeters);
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 计算路径总长度(米)
|
|
29
|
+
*/
|
|
30
|
+
double calculatePathLength(const std::vector<GeoPoint>& points);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 获取路径上指定距离的点和方向
|
|
34
|
+
* @param points 路径点
|
|
35
|
+
* @param distanceMeters 距离起点的米数
|
|
36
|
+
* @param outLat 输出纬度
|
|
37
|
+
* @param outLon 输出经度
|
|
38
|
+
* @param outAngle 输出方向角度 (0-360)
|
|
39
|
+
* @return 是否成功找到点
|
|
40
|
+
*/
|
|
41
|
+
bool getPointAtDistance(const std::vector<GeoPoint>& points, double distanceMeters, double* outLat, double* outLon, double* outAngle);
|
|
42
|
+
|
|
43
|
+
// Result structure for nearest point calculation
|
|
44
|
+
struct NearestPointResult {
|
|
45
|
+
double latitude;
|
|
46
|
+
double longitude;
|
|
47
|
+
int index; // Index of the point in the path that starts the segment (or the point itself)
|
|
48
|
+
double distanceMeters;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Find the nearest point on the path to a target point
|
|
52
|
+
// Returns the nearest point on the polyline segments
|
|
53
|
+
NearestPointResult getNearestPointOnPath(const std::vector<GeoPoint>& path, const GeoPoint& target);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 计算多边形的质心
|
|
57
|
+
* @param polygon 多边形点集
|
|
58
|
+
* @return 质心坐标
|
|
59
|
+
*/
|
|
60
|
+
GeoPoint calculateCentroid(const std::vector<GeoPoint>& polygon);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* GeoHash 编码
|
|
64
|
+
* @param lat 纬度
|
|
65
|
+
* @param lon 经度
|
|
66
|
+
* @param precision 精度 (1-12)
|
|
67
|
+
* @return GeoHash 字符串
|
|
68
|
+
*/
|
|
69
|
+
std::string encodeGeoHash(double lat, double lon, int precision);
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 解析高德地图 API 返回的 Polyline 字符串
|
|
73
|
+
* 格式: "lng,lat;lng,lat;..."
|
|
74
|
+
* @param polylineStr 高德原始 polyline 字符串
|
|
75
|
+
* @return 解析后的点集
|
|
76
|
+
*/
|
|
77
|
+
std::vector<GeoPoint> parsePolyline(const std::string& polylineStr);
|
|
78
|
+
|
|
79
|
+
struct PathBounds {
|
|
80
|
+
double north;
|
|
81
|
+
double south;
|
|
82
|
+
double east;
|
|
83
|
+
double west;
|
|
84
|
+
double centerLat;
|
|
85
|
+
double centerLon;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 计算路径的边界和中心点
|
|
90
|
+
* @param points 路径点
|
|
91
|
+
* @return 边界信息
|
|
92
|
+
*/
|
|
93
|
+
PathBounds calculatePathBounds(const std::vector<GeoPoint>& points);
|
|
94
|
+
|
|
95
|
+
// --- 瓦片与坐标转换 ---
|
|
96
|
+
|
|
97
|
+
struct TileResult {
|
|
98
|
+
int x;
|
|
99
|
+
int y;
|
|
100
|
+
int z;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
struct PixelResult {
|
|
104
|
+
double x;
|
|
105
|
+
double y;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 经纬度转瓦片坐标
|
|
110
|
+
*/
|
|
111
|
+
TileResult latLngToTile(double lat, double lon, int zoom);
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 瓦片坐标转经纬度
|
|
115
|
+
*/
|
|
116
|
+
GeoPoint tileToLatLng(int x, int y, int zoom);
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 经纬度转像素坐标
|
|
120
|
+
*/
|
|
121
|
+
PixelResult latLngToPixel(double lat, double lon, int zoom);
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 像素坐标转经纬度
|
|
125
|
+
*/
|
|
126
|
+
GeoPoint pixelToLatLng(double x, double y, int zoom);
|
|
127
|
+
|
|
128
|
+
// --- 批量地理围栏与热力图 ---
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 批量判断点是否在多个多边形内 (优化版)
|
|
132
|
+
* @param pointLat 点纬度
|
|
133
|
+
* @param pointLon 点经度
|
|
134
|
+
* @param polygons 多个多边形的集合
|
|
135
|
+
* @return 所在的第一个多边形的索引,若不在任何多边形内返回 -1
|
|
136
|
+
*/
|
|
137
|
+
int findPointInPolygons(double pointLat, double pointLon, const std::vector<std::vector<GeoPoint>>& polygons);
|
|
138
|
+
|
|
139
|
+
struct HeatmapPoint {
|
|
140
|
+
double lat;
|
|
141
|
+
double lon;
|
|
142
|
+
double weight;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
struct HeatmapGridCell {
|
|
146
|
+
double lat;
|
|
147
|
+
double lon;
|
|
148
|
+
double intensity;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 生成热力图网格数据
|
|
153
|
+
* @param points 原始点集
|
|
154
|
+
* @param gridSizeMeters 网格大小(米)
|
|
155
|
+
* @return 网格中心点及其强度
|
|
156
|
+
*/
|
|
157
|
+
std::vector<HeatmapGridCell> generateHeatmapGrid(const std::vector<HeatmapPoint>& points, double gridSizeMeters);
|
|
158
|
+
|
|
159
|
+
} // namespace gaodemap
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#include "QuadTree.hpp"
|
|
2
|
+
|
|
3
|
+
namespace gaodemap {
|
|
4
|
+
|
|
5
|
+
bool BoundingBox::contains(double lat, double lon) const {
|
|
6
|
+
return lat >= minLat && lat <= maxLat && lon >= minLon && lon <= maxLon;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
bool BoundingBox::intersects(const BoundingBox& other) const {
|
|
10
|
+
return !(other.minLat > maxLat || other.maxLat < minLat ||
|
|
11
|
+
other.minLon > maxLon || other.maxLon < minLon);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
QuadTree::QuadTree(const BoundingBox& bounds, int capacity)
|
|
15
|
+
: bounds(bounds), capacity(capacity) {}
|
|
16
|
+
|
|
17
|
+
bool QuadTree::insert(const ClusterPoint& point) {
|
|
18
|
+
if (!bounds.contains(point.lat, point.lon)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (points.size() < capacity && !subdivided) {
|
|
23
|
+
points.push_back(point);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!subdivided) {
|
|
28
|
+
subdivide();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (northWest->insert(point)) return true;
|
|
32
|
+
if (northEast->insert(point)) return true;
|
|
33
|
+
if (southWest->insert(point)) return true;
|
|
34
|
+
if (southEast->insert(point)) return true;
|
|
35
|
+
|
|
36
|
+
// Point might be exactly on the boundary of the QuadTree but not accepted by children?
|
|
37
|
+
// In our logic, children cover the full range of the parent.
|
|
38
|
+
// However, floating point precision might be tricky.
|
|
39
|
+
// As a fallback, if we are subdivided but children didn't take it (rare),
|
|
40
|
+
// we can keep it here or force insert.
|
|
41
|
+
// Given the subdivision logic, it should cover all space.
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
void QuadTree::subdivide() {
|
|
46
|
+
double midLat = (bounds.minLat + bounds.maxLat) / 2.0;
|
|
47
|
+
double midLon = (bounds.minLon + bounds.maxLon) / 2.0;
|
|
48
|
+
|
|
49
|
+
northWest = std::make_unique<QuadTree>(BoundingBox{midLat, bounds.minLon, bounds.maxLat, midLon}, capacity);
|
|
50
|
+
northEast = std::make_unique<QuadTree>(BoundingBox{midLat, midLon, bounds.maxLat, bounds.maxLon}, capacity);
|
|
51
|
+
southWest = std::make_unique<QuadTree>(BoundingBox{bounds.minLat, bounds.minLon, midLat, midLon}, capacity);
|
|
52
|
+
southEast = std::make_unique<QuadTree>(BoundingBox{bounds.minLat, midLon, midLat, bounds.maxLon}, capacity);
|
|
53
|
+
|
|
54
|
+
subdivided = true;
|
|
55
|
+
|
|
56
|
+
// Redistribute existing points
|
|
57
|
+
for (const auto& p : points) {
|
|
58
|
+
northWest->insert(p) || northEast->insert(p) ||
|
|
59
|
+
southWest->insert(p) || southEast->insert(p);
|
|
60
|
+
}
|
|
61
|
+
points.clear();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
void QuadTree::query(const BoundingBox& range, std::vector<ClusterPoint>& found) const {
|
|
65
|
+
if (!bounds.intersects(range)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const auto& p : points) {
|
|
70
|
+
if (range.contains(p.lat, p.lon)) {
|
|
71
|
+
found.push_back(p);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (subdivided) {
|
|
76
|
+
northWest->query(range, found);
|
|
77
|
+
northEast->query(range, found);
|
|
78
|
+
southWest->query(range, found);
|
|
79
|
+
southEast->query(range, found);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void QuadTree::clear() {
|
|
84
|
+
points.clear();
|
|
85
|
+
northWest.reset();
|
|
86
|
+
northEast.reset();
|
|
87
|
+
southWest.reset();
|
|
88
|
+
southEast.reset();
|
|
89
|
+
subdivided = false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <vector>
|
|
4
|
+
#include <memory>
|
|
5
|
+
#include "ClusterEngine.hpp"
|
|
6
|
+
|
|
7
|
+
namespace gaodemap {
|
|
8
|
+
|
|
9
|
+
struct BoundingBox {
|
|
10
|
+
double minLat;
|
|
11
|
+
double minLon;
|
|
12
|
+
double maxLat;
|
|
13
|
+
double maxLon;
|
|
14
|
+
|
|
15
|
+
bool contains(double lat, double lon) const;
|
|
16
|
+
bool intersects(const BoundingBox& other) const;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
class QuadTree {
|
|
20
|
+
public:
|
|
21
|
+
QuadTree(const BoundingBox& bounds, int capacity = 20);
|
|
22
|
+
~QuadTree() = default;
|
|
23
|
+
|
|
24
|
+
bool insert(const ClusterPoint& point);
|
|
25
|
+
void query(const BoundingBox& range, std::vector<ClusterPoint>& found) const;
|
|
26
|
+
void clear();
|
|
27
|
+
|
|
28
|
+
private:
|
|
29
|
+
BoundingBox bounds;
|
|
30
|
+
int capacity;
|
|
31
|
+
std::vector<ClusterPoint> points;
|
|
32
|
+
bool subdivided = false;
|
|
33
|
+
|
|
34
|
+
std::unique_ptr<QuadTree> northWest;
|
|
35
|
+
std::unique_ptr<QuadTree> northEast;
|
|
36
|
+
std::unique_ptr<QuadTree> southWest;
|
|
37
|
+
std::unique_ptr<QuadTree> southEast;
|
|
38
|
+
|
|
39
|
+
void subdivide();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# C++ 共享核心库 (Shared Core)
|
|
2
|
+
|
|
3
|
+
该目录包含了 `expo-gaode-map` 跨平台核心逻辑的 C++ 实现。这些代码被 Android 和 iOS 平台共享,以确保计算逻辑的一致性并提升高性能计算场景(如点聚合、几何计算)的处理速度。
|
|
4
|
+
|
|
5
|
+
## 模块说明
|
|
6
|
+
|
|
7
|
+
### 1. GeometryEngine (几何引擎)
|
|
8
|
+
[GeometryEngine.hpp](file:///Users/wangqiang/Desktop/expo-gaode-map/packages/core/shared/cpp/GeometryEngine.hpp)
|
|
9
|
+
提供地理空间相关的数学计算:
|
|
10
|
+
- **距离计算**: 基于 Haversine 公式计算经纬度点之间的球面距离。
|
|
11
|
+
- **点位判断**: 判断点是否在多边形 (Point-in-Polygon) 或圆形内。
|
|
12
|
+
- **面积计算**: 计算多边形或矩形的地理面积。
|
|
13
|
+
- **轨迹处理**:
|
|
14
|
+
- **抽稀算法**: 实现 Ramer-Douglas-Peucker 算法,用于简化复杂的折线轨迹。
|
|
15
|
+
- **路径长度**: 计算折线段的总长度。
|
|
16
|
+
- **路径插值**: 获取路径上指定距离的点坐标及其切线方向。
|
|
17
|
+
- **GeoHash**: 支持经纬度到 GeoHash 字符串的编码。
|
|
18
|
+
- **质心计算**: 计算多边形的几何质心。
|
|
19
|
+
|
|
20
|
+
### 2. ClusterEngine (点聚合引擎)
|
|
21
|
+
[ClusterEngine.hpp](file:///Users/wangqiang/Desktop/expo-gaode-map/packages/core/shared/cpp/ClusterEngine.hpp)
|
|
22
|
+
负责大规模地图标记点的聚合计算:
|
|
23
|
+
- 使用 **QuadTree** 进行空间索引优化。
|
|
24
|
+
- 支持基于半径的聚合逻辑。
|
|
25
|
+
- 高性能处理,适用于数千甚至数万个点的实时聚合。
|
|
26
|
+
|
|
27
|
+
### 3. QuadTree (四叉树)
|
|
28
|
+
[QuadTree.hpp](file:///Users/wangqiang/Desktop/expo-gaode-map/packages/core/shared/cpp/QuadTree.hpp)
|
|
29
|
+
为地理坐标提供高效的空间索引结构:
|
|
30
|
+
- **空间分割**: 自动将空间划分为四个象限。
|
|
31
|
+
- **范围查询**: 快速检索指定矩形区域内的所有点位。
|
|
32
|
+
- 被 `ClusterEngine` 用于加速近邻点搜索。
|
|
33
|
+
|
|
34
|
+
### 4. ColorParser (颜色解析器)
|
|
35
|
+
[ColorParser.hpp](file:///Users/wangqiang/Desktop/expo-gaode-map/packages/core/shared/cpp/ColorParser.hpp)
|
|
36
|
+
跨平台的颜色字符串解析工具:
|
|
37
|
+
- 支持 **Hex** 格式 (如 `#RRGGBB`, `#AARRGGBB`, `#RGB`)。
|
|
38
|
+
- 支持 **RGB/RGBA** 函数格式 (如 `rgba(255, 0, 0, 0.5)`)。
|
|
39
|
+
- 支持 **命名颜色** (如 `red`, `blue`, `transparent`)。
|
|
40
|
+
- 统一输出为 `0xAARRGGBB` 格式的 32 位整数。
|
|
41
|
+
|
|
42
|
+
## 测试
|
|
43
|
+
|
|
44
|
+
测试用例位于 `tests/` 目录。
|
|
45
|
+
|
|
46
|
+
### 运行测试
|
|
47
|
+
在 macOS/Linux 环境下,可以通过以下命令运行 C++ 单元测试:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cd tests
|
|
51
|
+
chmod +x run.sh
|
|
52
|
+
./run.sh
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
该脚本会使用 `clang++` 编译源代码并运行生成的测试二进制文件,验证各核心模块的逻辑准确性。
|
|
@@ -17,6 +17,9 @@ class UIManager: NSObject, MAMapViewDelegate {
|
|
|
17
17
|
/// 定位变化回调
|
|
18
18
|
var onLocationChanged: ((_ latitude: Double, _ longitude: Double, _ accuracy: Double) -> Void)?
|
|
19
19
|
|
|
20
|
+
/// 缓存的自定义样式配置
|
|
21
|
+
private var cachedCustomStyleOptions: MAMapCustomStyleOptions?
|
|
22
|
+
|
|
20
23
|
init(mapView: MAMapView) {
|
|
21
24
|
self.mapView = mapView
|
|
22
25
|
super.init()
|
|
@@ -36,6 +39,13 @@ class UIManager: NSObject, MAMapViewDelegate {
|
|
|
36
39
|
case 3: mapView.mapType = .navi
|
|
37
40
|
default: mapView.mapType = .standard
|
|
38
41
|
}
|
|
42
|
+
|
|
43
|
+
// 🔑 关键修复:切换地图类型后重新应用自定义样式
|
|
44
|
+
// 某些地图类型切换可能会重置样式设置
|
|
45
|
+
if let cachedOptions = cachedCustomStyleOptions {
|
|
46
|
+
mapView.setCustomMapStyleOptions(cachedOptions)
|
|
47
|
+
mapView.customMapStyleEnabled = true
|
|
48
|
+
}
|
|
39
49
|
}
|
|
40
50
|
|
|
41
51
|
// MARK: - 控件显示
|
|
@@ -109,7 +119,8 @@ class UIManager: NSObject, MAMapViewDelegate {
|
|
|
109
119
|
}
|
|
110
120
|
mapView.showsUserLocation = true
|
|
111
121
|
if followUser {
|
|
112
|
-
|
|
122
|
+
// 🔑 使用 followWithHeading 模式以支持方向指示器
|
|
123
|
+
mapView.userTrackingMode = .followWithHeading
|
|
113
124
|
} else {
|
|
114
125
|
mapView.userTrackingMode = .none
|
|
115
126
|
}
|
|
@@ -146,6 +157,12 @@ class UIManager: NSObject, MAMapViewDelegate {
|
|
|
146
157
|
guard let mapView = mapView else { return }
|
|
147
158
|
let representation = MAUserLocationRepresentation()
|
|
148
159
|
|
|
160
|
+
// 是否显示定位蓝点 (showMyLocation) - 对应 Android 的 showMyLocation
|
|
161
|
+
// iOS 通过 mapView.showsUserLocation 控制,这里提供统一的 API
|
|
162
|
+
if let showMyLocation = config["showMyLocation"] as? Bool {
|
|
163
|
+
mapView.showsUserLocation = showMyLocation
|
|
164
|
+
}
|
|
165
|
+
|
|
149
166
|
// 精度圈是否显示
|
|
150
167
|
if let showsAccuracyRing = config["showsAccuracyRing"] as? Bool {
|
|
151
168
|
representation.showsAccuracyRing = showsAccuracyRing
|
|
@@ -265,4 +282,58 @@ class UIManager: NSObject, MAMapViewDelegate {
|
|
|
265
282
|
func setShowsIndoorMap(_ show: Bool) {
|
|
266
283
|
mapView?.isShowsIndoorMap = show
|
|
267
284
|
}
|
|
285
|
+
|
|
286
|
+
// MARK: - 自定义地图样式
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* 设置自定义地图样式
|
|
290
|
+
* @param styleData 样式数据,支持以下格式:
|
|
291
|
+
* - styleId: String - 在线样式ID(从高德开放平台获取)
|
|
292
|
+
* - styleDataPath: String - 本地样式文件路径
|
|
293
|
+
* - extraStyleDataPath: String - 额外样式文件路径(可选)
|
|
294
|
+
*/
|
|
295
|
+
func setCustomMapStyle(_ styleData: [String: Any]) {
|
|
296
|
+
guard let mapView = mapView else { return }
|
|
297
|
+
|
|
298
|
+
// 在线样式 ID
|
|
299
|
+
if let styleId = styleData["styleId"] as? String, !styleId.isEmpty {
|
|
300
|
+
let customStyle = MAMapCustomStyleOptions()
|
|
301
|
+
customStyle.styleId = styleId
|
|
302
|
+
|
|
303
|
+
// 🔑 缓存样式配置
|
|
304
|
+
cachedCustomStyleOptions = customStyle
|
|
305
|
+
|
|
306
|
+
mapView.setCustomMapStyleOptions(customStyle)
|
|
307
|
+
mapView.customMapStyleEnabled = true
|
|
308
|
+
return
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// 本地样式文件
|
|
312
|
+
if let styleDataPath = styleData["styleDataPath"] as? String, !styleDataPath.isEmpty {
|
|
313
|
+
// 读取样式文件数据
|
|
314
|
+
if let stylePath = Bundle.main.path(forResource: styleDataPath, ofType: nil),
|
|
315
|
+
let styleFileData = try? Data(contentsOf: URL(fileURLWithPath: stylePath)) {
|
|
316
|
+
let customStyle = MAMapCustomStyleOptions()
|
|
317
|
+
customStyle.styleData = styleFileData
|
|
318
|
+
|
|
319
|
+
// 额外样式文件(可选)
|
|
320
|
+
if let extraPath = styleData["extraStyleDataPath"] as? String, !extraPath.isEmpty,
|
|
321
|
+
let extraFilePath = Bundle.main.path(forResource: extraPath, ofType: nil),
|
|
322
|
+
let extraFileData = try? Data(contentsOf: URL(fileURLWithPath: extraFilePath)) {
|
|
323
|
+
customStyle.styleExtraData = extraFileData
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// 🔑 缓存样式配置
|
|
327
|
+
cachedCustomStyleOptions = customStyle
|
|
328
|
+
|
|
329
|
+
mapView.setCustomMapStyleOptions(customStyle)
|
|
330
|
+
mapView.customMapStyleEnabled = true
|
|
331
|
+
return
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// 如果没有提供任何样式,禁用自定义样式并清除缓存
|
|
336
|
+
cachedCustomStyleOptions = nil
|
|
337
|
+
mapView.customMapStyleEnabled = false
|
|
338
|
+
}
|
|
268
339
|
}
|