expo-gaode-map-navigation 1.1.5-next.2 → 1.1.5-next.4

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.
@@ -0,0 +1,110 @@
1
+ #include "ClusterEngine.hpp"
2
+ #include "QuadTree.hpp"
3
+ #include <cmath>
4
+ #include <algorithm>
5
+
6
+ namespace gaodemap {
7
+
8
+ // Removed duplicate toRadians definition, using inline or shared utility in future
9
+ // For now, let's keep it static but rename to avoid conflict in unity build
10
+ static inline double cluster_toRadians(double degrees) {
11
+ return degrees * 0.017453292519943295;
12
+ }
13
+
14
+ static double haversineMeters(const ClusterPoint& a, const ClusterPoint& b) {
15
+ const double lat1 = cluster_toRadians(a.lat);
16
+ const double lat2 = cluster_toRadians(b.lat);
17
+ const double dLat = lat2 - lat1;
18
+ const double dLon = cluster_toRadians(b.lon - a.lon);
19
+
20
+ const double sinHalfLat = std::sin(dLat * 0.5);
21
+ const double sinHalfLon = std::sin(dLon * 0.5);
22
+
23
+ const double h = sinHalfLat * sinHalfLat + std::cos(lat1) * std::cos(lat2) * sinHalfLon * sinHalfLon;
24
+ const double c = 2.0 * std::atan2(std::sqrt(h), std::sqrt(1.0 - h));
25
+
26
+ return 6371000.0 * c;
27
+ }
28
+
29
+ std::vector<ClusterOutput> clusterPoints(const std::vector<ClusterPoint>& points, double radiusMeters) {
30
+ std::vector<ClusterOutput> clusters;
31
+
32
+ if (points.empty() || radiusMeters <= 0.0) {
33
+ return clusters;
34
+ }
35
+
36
+ // 1. Build QuadTree
37
+ // Determine bounds
38
+ double minLat = 90.0, maxLat = -90.0, minLon = 180.0, maxLon = -180.0;
39
+ int maxIndex = -1;
40
+
41
+ for (const auto& p : points) {
42
+ if (p.lat < minLat) minLat = p.lat;
43
+ if (p.lat > maxLat) maxLat = p.lat;
44
+ if (p.lon < minLon) minLon = p.lon;
45
+ if (p.lon > maxLon) maxLon = p.lon;
46
+ if (p.index > maxIndex) maxIndex = p.index;
47
+ }
48
+
49
+ // Add some buffer
50
+ BoundingBox worldBounds{minLat - 1.0, minLon - 1.0, maxLat + 1.0, maxLon + 1.0};
51
+ QuadTree tree(worldBounds);
52
+
53
+ for (const auto& p : points) {
54
+ tree.insert(p);
55
+ }
56
+
57
+ // 2. Cluster
58
+ // Use maxIndex to size the visited array correctly.
59
+ // If points is empty, maxIndex is -1, but we checked empty above.
60
+ // Ensure vector size is at least maxIndex + 1
61
+ std::vector<bool> globalVisited((maxIndex >= 0 ? maxIndex + 1 : 0), false);
62
+
63
+ // Approximate degrees for radius (very rough, improves performance)
64
+ // 1 degree lat ~= 111km.
65
+ double latDegree = radiusMeters / 111000.0;
66
+
67
+ for (const auto& p : points) {
68
+ if (p.index < 0 || p.index >= globalVisited.size()) continue; // Safety check
69
+ if (globalVisited[p.index]) continue;
70
+
71
+ ClusterOutput cluster;
72
+ cluster.centerIndex = p.index;
73
+ cluster.indices.push_back(p.index);
74
+ globalVisited[p.index] = true;
75
+
76
+ // Query QuadTree
77
+ // Adjust lonDegree based on current latitude
78
+ // cos can be 0 at poles, handle it
79
+ double cosLat = std::cos(cluster_toRadians(p.lat));
80
+ double lonDegree;
81
+ if (std::abs(cosLat) < 0.00001) {
82
+ lonDegree = 360.0; // At poles, everything is close in longitude
83
+ } else {
84
+ lonDegree = radiusMeters / (111000.0 * std::abs(cosLat));
85
+ }
86
+
87
+ // Bounding box for query
88
+ BoundingBox range{p.lat - latDegree, p.lon - lonDegree, p.lat + latDegree, p.lon + lonDegree};
89
+
90
+ std::vector<ClusterPoint> neighbors;
91
+ tree.query(range, neighbors);
92
+
93
+ for (const auto& neighbor : neighbors) {
94
+ if (neighbor.index < 0 || neighbor.index >= globalVisited.size()) continue;
95
+ if (globalVisited[neighbor.index]) continue;
96
+
97
+ // Precise check
98
+ if (haversineMeters(p, neighbor) <= radiusMeters) {
99
+ cluster.indices.push_back(neighbor.index);
100
+ globalVisited[neighbor.index] = true;
101
+ }
102
+ }
103
+
104
+ clusters.push_back(std::move(cluster));
105
+ }
106
+
107
+ return clusters;
108
+ }
109
+
110
+ }
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+
3
+ #include <vector>
4
+
5
+ namespace gaodemap {
6
+
7
+ struct ClusterPoint {
8
+ double lat;
9
+ double lon;
10
+ int index;
11
+ };
12
+
13
+ struct ClusterOutput {
14
+ int centerIndex;
15
+ std::vector<int> indices;
16
+ };
17
+
18
+ std::vector<ClusterOutput> clusterPoints(const std::vector<ClusterPoint>& points, double radiusMeters);
19
+
20
+ }
@@ -0,0 +1,135 @@
1
+ #include "ColorParser.hpp"
2
+ #include <algorithm>
3
+ #include <sstream>
4
+ #include <vector>
5
+ #include <map>
6
+ #include <cmath>
7
+
8
+ namespace gaodemap {
9
+
10
+ static uint32_t argb(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
11
+ return (static_cast<uint32_t>(a) << 24) |
12
+ (static_cast<uint32_t>(r) << 16) |
13
+ (static_cast<uint32_t>(g) << 8) |
14
+ static_cast<uint32_t>(b);
15
+ }
16
+
17
+ static uint32_t parseHex(const std::string& hexStr) {
18
+ std::string cleanHex = hexStr;
19
+ if (cleanHex.empty()) return 0;
20
+ if (cleanHex[0] == '#') {
21
+ cleanHex = cleanHex.substr(1);
22
+ }
23
+
24
+ uint32_t val = 0;
25
+ try {
26
+ val = static_cast<uint32_t>(std::stoul(cleanHex, nullptr, 16));
27
+ } catch (...) {
28
+ return 0;
29
+ }
30
+
31
+ if (cleanHex.length() == 6) {
32
+ // RRGGBB -> 0xFFRRGGBB
33
+ return 0xFF000000 | val;
34
+ } else if (cleanHex.length() == 8) {
35
+ // AARRGGBB -> AARRGGBB (Android style)
36
+ // Wait, web usually uses #RRGGBBAA.
37
+ // Android Color.parseColor("#RRGGBB") or "#AARRGGBB".
38
+ // Let's assume Android style #AARRGGBB for consistency with existing Kotlin code.
39
+ return val;
40
+ } else if (cleanHex.length() == 3) {
41
+ // RGB -> RRGGBB
42
+ uint32_t r = (val >> 8) & 0xF;
43
+ uint32_t g = (val >> 4) & 0xF;
44
+ uint32_t b = val & 0xF;
45
+ return 0xFF000000 | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b;
46
+ } else if (cleanHex.length() == 4) {
47
+ // ARGB -> AARRGGBB
48
+ uint32_t a = (val >> 12) & 0xF;
49
+ uint32_t r = (val >> 8) & 0xF;
50
+ uint32_t g = (val >> 4) & 0xF;
51
+ uint32_t b = val & 0xF;
52
+ return (a << 28) | (a << 24) | (r << 20) | (r << 16) | (g << 12) | (g << 8) | (b << 4) | b;
53
+ }
54
+
55
+ return 0;
56
+ }
57
+
58
+ static uint32_t parseRgba(const std::string& str) {
59
+ // rgba(r, g, b, a) or rgb(r, g, b)
60
+ bool hasAlpha = str.find("rgba") == 0;
61
+ size_t start = str.find('(');
62
+ size_t end = str.find(')');
63
+ if (start == std::string::npos || end == std::string::npos) return 0;
64
+
65
+ std::string content = str.substr(start + 1, end - start - 1);
66
+ std::stringstream ss(content);
67
+ std::string segment;
68
+ std::vector<std::string> parts;
69
+
70
+ while (std::getline(ss, segment, ',')) {
71
+ parts.push_back(segment);
72
+ }
73
+
74
+ if (parts.size() < 3) return 0;
75
+
76
+ try {
77
+ int r = std::stoi(parts[0]);
78
+ int g = std::stoi(parts[1]);
79
+ int b = std::stoi(parts[2]);
80
+ int a = 255;
81
+
82
+ if (hasAlpha && parts.size() >= 4) {
83
+ float alphaFloat = std::stof(parts[3]);
84
+ a = static_cast<int>(alphaFloat * 255.0f);
85
+ }
86
+
87
+ return argb(
88
+ static_cast<uint8_t>(std::max(0, std::min(255, a))),
89
+ static_cast<uint8_t>(std::max(0, std::min(255, r))),
90
+ static_cast<uint8_t>(std::max(0, std::min(255, g))),
91
+ static_cast<uint8_t>(std::max(0, std::min(255, b)))
92
+ );
93
+ } catch (...) {
94
+ return 0;
95
+ }
96
+ }
97
+
98
+ static const std::map<std::string, uint32_t> NAMED_COLORS = {
99
+ {"red", 0xFFFF0000},
100
+ {"blue", 0xFF0000FF},
101
+ {"green", 0xFF00FF00},
102
+ {"yellow", 0xFFFFFF00},
103
+ {"black", 0xFF000000},
104
+ {"white", 0xFFFFFFFF},
105
+ {"gray", 0xFF888888},
106
+ {"grey", 0xFF888888},
107
+ {"cyan", 0xFF00FFFF},
108
+ {"magenta", 0xFFFF00FF},
109
+ {"transparent", 0x00000000}
110
+ };
111
+
112
+ uint32_t parseColor(const std::string& colorString) {
113
+ std::string str = colorString;
114
+ // Remove whitespace
115
+ str.erase(std::remove_if(str.begin(), str.end(), ::isspace), str.end());
116
+ // Lowercase for named colors check
117
+ std::string lowerStr = str;
118
+ std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower);
119
+
120
+ if (NAMED_COLORS.count(lowerStr)) {
121
+ return NAMED_COLORS.at(lowerStr);
122
+ }
123
+
124
+ if (lowerStr.find("rgb") == 0) {
125
+ return parseRgba(str); // pass original str with potential spaces if needed, but we removed them
126
+ }
127
+
128
+ if (lowerStr.find("#") == 0 || std::all_of(lowerStr.begin(), lowerStr.end(), ::isxdigit)) {
129
+ return parseHex(str);
130
+ }
131
+
132
+ return 0; // Default black -> Default failure (0)
133
+ }
134
+
135
+ }
@@ -0,0 +1,14 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <cstdint>
5
+
6
+ namespace gaodemap {
7
+
8
+ // Returns color as ARGB integer (0xAARRGGBB)
9
+ // Returns 0 (transparent/black) if parsing fails, but 0 is also valid (transparent).
10
+ // Maybe return a bool success? Or default to Black (0xFF000000) or Transparent (0x00000000).
11
+ // Android defaults to Black in existing code.
12
+ uint32_t parseColor(const std::string& colorString);
13
+
14
+ }