@maydon_tech/react-native-nitro-maps 0.1.0
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/LICENSE +20 -0
- package/NitroMap.podspec +42 -0
- package/README.md +172 -0
- package/android/CMakeLists.txt +27 -0
- package/android/build.gradle +141 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/ClusterIconGenerator.kt +108 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/ColorUtils.kt +63 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/HybridNitroMap.kt +408 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/HybridNitroMapConfig.kt +68 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/MarkerIconCache.kt +176 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/MarkerIconFactory.kt +252 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/NitroMapPackage.kt +33 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/clustering/NitroClusterEngine.kt +252 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/clustering/QuadTree.kt +195 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/providers/GoogleMapProvider.kt +912 -0
- package/android/src/main/java/com/margelo/nitro/nitromap/providers/MapProviderInterface.kt +70 -0
- package/cpp/ClusterEngine.hpp +411 -0
- package/cpp/KDBush.hpp +238 -0
- package/cpp/QuadTree.hpp +246 -0
- package/ios/Clustering/ClusterEngineWrapper.h +58 -0
- package/ios/Clustering/ClusterEngineWrapper.mm +142 -0
- package/ios/Clustering/ClusterIconRenderer.swift +80 -0
- package/ios/Clustering/NitroClusterEngine.swift +117 -0
- package/ios/Clustering/NitroClusterIconGenerator.swift +35 -0
- package/ios/MarkerRenderer/MarkerIconFactory.swift +322 -0
- package/ios/MarkerRenderer/PriceMarkerRenderer.swift +140 -0
- package/ios/NitroMap.swift +332 -0
- package/ios/NitroMapConfig/HybridNitroMapConfig.swift +33 -0
- package/ios/Providers/GoogleMapDelegate.swift +310 -0
- package/ios/Providers/GoogleMapProvider+Camera.swift +164 -0
- package/ios/Providers/GoogleMapProvider.swift +924 -0
- package/ios/Providers/MapProviderProtocol.swift +78 -0
- package/ios/Shared/ClusterConfig+Factory.swift +58 -0
- package/ios/Shared/ClusteringManager.swift +211 -0
- package/ios/Shared/MapStyleProvider.swift +135 -0
- package/ios/Shared/MarkerSelectionHandler.swift +116 -0
- package/ios/Utils/ColorValueExtension.swift +54 -0
- package/lib/module/components/ImageMarker.js +146 -0
- package/lib/module/components/ImageMarker.js.map +1 -0
- package/lib/module/components/NitroMap.js +320 -0
- package/lib/module/components/NitroMap.js.map +1 -0
- package/lib/module/components/PriceMarker.js +165 -0
- package/lib/module/components/PriceMarker.js.map +1 -0
- package/lib/module/context/NitroMapContext.js +15 -0
- package/lib/module/context/NitroMapContext.js.map +1 -0
- package/lib/module/hooks/useNitroMarker.js +104 -0
- package/lib/module/hooks/useNitroMarker.js.map +1 -0
- package/lib/module/index.js +21 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/modules/index.js +4 -0
- package/lib/module/modules/index.js.map +1 -0
- package/lib/module/modules/module.js +30 -0
- package/lib/module/modules/module.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/specs/NitroMap.nitro.js +4 -0
- package/lib/module/specs/NitroMap.nitro.js.map +1 -0
- package/lib/module/specs/NitroMapConfig.nitro.js +4 -0
- package/lib/module/specs/NitroMapConfig.nitro.js.map +1 -0
- package/lib/module/types/map.js +2 -0
- package/lib/module/types/map.js.map +1 -0
- package/lib/module/types/marker.js +4 -0
- package/lib/module/types/marker.js.map +1 -0
- package/lib/module/utils/colors.js +147 -0
- package/lib/module/utils/colors.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/components/ImageMarker.d.ts +70 -0
- package/lib/typescript/src/components/ImageMarker.d.ts.map +1 -0
- package/lib/typescript/src/components/NitroMap.d.ts +14 -0
- package/lib/typescript/src/components/NitroMap.d.ts.map +1 -0
- package/lib/typescript/src/components/PriceMarker.d.ts +88 -0
- package/lib/typescript/src/components/PriceMarker.d.ts.map +1 -0
- package/lib/typescript/src/context/NitroMapContext.d.ts +16 -0
- package/lib/typescript/src/context/NitroMapContext.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useNitroMarker.d.ts +78 -0
- package/lib/typescript/src/hooks/useNitroMarker.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +12 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/modules/index.d.ts +2 -0
- package/lib/typescript/src/modules/index.d.ts.map +1 -0
- package/lib/typescript/src/modules/module.d.ts +22 -0
- package/lib/typescript/src/modules/module.d.ts.map +1 -0
- package/lib/typescript/src/specs/NitroMap.nitro.d.ts +227 -0
- package/lib/typescript/src/specs/NitroMap.nitro.d.ts.map +1 -0
- package/lib/typescript/src/specs/NitroMapConfig.nitro.d.ts +10 -0
- package/lib/typescript/src/specs/NitroMapConfig.nitro.d.ts.map +1 -0
- package/lib/typescript/src/types/map.d.ts +154 -0
- package/lib/typescript/src/types/map.d.ts.map +1 -0
- package/lib/typescript/src/types/marker.d.ts +248 -0
- package/lib/typescript/src/types/marker.d.ts.map +1 -0
- package/lib/typescript/src/utils/colors.d.ts +82 -0
- package/lib/typescript/src/utils/colors.d.ts.map +1 -0
- package/nitro.json +21 -0
- package/nitrogen/generated/android/c++/JCamera.hpp +74 -0
- package/nitrogen/generated/android/c++/JClusterAnimationStyle.hpp +68 -0
- package/nitrogen/generated/android/c++/JClusterConfig.hpp +121 -0
- package/nitrogen/generated/android/c++/JClusterPressEvent.hpp +86 -0
- package/nitrogen/generated/android/c++/JClusterStrategy.hpp +59 -0
- package/nitrogen/generated/android/c++/JColorValue.cpp +26 -0
- package/nitrogen/generated/android/c++/JColorValue.hpp +70 -0
- package/nitrogen/generated/android/c++/JCoordinate.hpp +61 -0
- package/nitrogen/generated/android/c++/JEdgePadding.hpp +69 -0
- package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_ClusterPressEvent.hpp +81 -0
- package/nitrogen/generated/android/c++/JFunc_void_MapError.hpp +78 -0
- package/nitrogen/generated/android/c++/JFunc_void_MapPressEvent.hpp +81 -0
- package/nitrogen/generated/android/c++/JFunc_void_MarkerDragEvent.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_MarkerPressEvent.hpp +80 -0
- package/nitrogen/generated/android/c++/JFunc_void_RegionChangeEvent.hpp +79 -0
- package/nitrogen/generated/android/c++/JHybridNitroMapConfigSpec.cpp +59 -0
- package/nitrogen/generated/android/c++/JHybridNitroMapConfigSpec.hpp +66 -0
- package/nitrogen/generated/android/c++/JHybridNitroMapSpec.cpp +593 -0
- package/nitrogen/generated/android/c++/JHybridNitroMapSpec.hpp +125 -0
- package/nitrogen/generated/android/c++/JImageMarkerConfig.hpp +86 -0
- package/nitrogen/generated/android/c++/JMapBoundaries.hpp +62 -0
- package/nitrogen/generated/android/c++/JMapError.hpp +61 -0
- package/nitrogen/generated/android/c++/JMapPressEvent.hpp +64 -0
- package/nitrogen/generated/android/c++/JMapProvider.hpp +62 -0
- package/nitrogen/generated/android/c++/JMapStyleElement.hpp +87 -0
- package/nitrogen/generated/android/c++/JMapStyler.hpp +78 -0
- package/nitrogen/generated/android/c++/JMapType.hpp +62 -0
- package/nitrogen/generated/android/c++/JMarkerAnimation.hpp +62 -0
- package/nitrogen/generated/android/c++/JMarkerColor.hpp +69 -0
- package/nitrogen/generated/android/c++/JMarkerConfig.hpp +77 -0
- package/nitrogen/generated/android/c++/JMarkerData.hpp +121 -0
- package/nitrogen/generated/android/c++/JMarkerDragEvent.hpp +63 -0
- package/nitrogen/generated/android/c++/JMarkerPressEvent.hpp +63 -0
- package/nitrogen/generated/android/c++/JMarkerStyle.hpp +62 -0
- package/nitrogen/generated/android/c++/JPoint.hpp +61 -0
- package/nitrogen/generated/android/c++/JPriceMarkerStyle.hpp +102 -0
- package/nitrogen/generated/android/c++/JRegion.hpp +69 -0
- package/nitrogen/generated/android/c++/JRegionChangeEvent.hpp +62 -0
- package/nitrogen/generated/android/c++/JVariant_String_MarkerColor.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_String_MarkerColor.hpp +70 -0
- package/nitrogen/generated/android/c++/views/JHybridNitroMapStateUpdater.cpp +144 -0
- package/nitrogen/generated/android/c++/views/JHybridNitroMapStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Camera.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterAnimationStyle.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterConfig.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterPressEvent.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ClusterStrategy.kt +21 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ColorValue.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Coordinate.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/EdgePadding.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_ClusterPressEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MapError.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MapPressEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MarkerDragEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_MarkerPressEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Func_void_RegionChangeEvent.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/HybridNitroMapConfigSpec.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/HybridNitroMapSpec.kt +342 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/ImageMarkerConfig.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapBoundaries.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapError.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapPressEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapProvider.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapStyleElement.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapStyler.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MapType.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerAnimation.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerColor.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerConfig.kt +44 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerData.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerDragEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerPressEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/MarkerStyle.kt +22 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Point.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/PriceMarkerStyle.kt +68 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Region.kt +47 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/RegionChangeEvent.kt +41 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/Variant_String_MarkerColor.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/nitromapOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/views/HybridNitroMapManager.kt +50 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromap/views/HybridNitroMapStateUpdater.kt +23 -0
- package/nitrogen/generated/android/nitromap+autolinking.cmake +87 -0
- package/nitrogen/generated/android/nitromap+autolinking.gradle +27 -0
- package/nitrogen/generated/android/nitromapOnLoad.cpp +70 -0
- package/nitrogen/generated/android/nitromapOnLoad.hpp +25 -0
- package/nitrogen/generated/ios/NitroMap+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Bridge.cpp +130 -0
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Bridge.hpp +793 -0
- package/nitrogen/generated/ios/NitroMap-Swift-Cxx-Umbrella.hpp +132 -0
- package/nitrogen/generated/ios/NitroMapAutolinking.mm +41 -0
- package/nitrogen/generated/ios/NitroMapAutolinking.swift +40 -0
- package/nitrogen/generated/ios/c++/HybridNitroMapConfigSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroMapConfigSpecSwift.hpp +84 -0
- package/nitrogen/generated/ios/c++/HybridNitroMapSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroMapSpecSwift.hpp +410 -0
- package/nitrogen/generated/ios/c++/views/HybridNitroMapComponent.mm +206 -0
- package/nitrogen/generated/ios/swift/Camera.swift +80 -0
- package/nitrogen/generated/ios/swift/ClusterAnimationStyle.swift +52 -0
- package/nitrogen/generated/ios/swift/ClusterConfig.swift +268 -0
- package/nitrogen/generated/ios/swift/ClusterPressEvent.swift +70 -0
- package/nitrogen/generated/ios/swift/ClusterStrategy.swift +40 -0
- package/nitrogen/generated/ios/swift/ColorValue.swift +18 -0
- package/nitrogen/generated/ios/swift/Coordinate.swift +47 -0
- package/nitrogen/generated/ios/swift/EdgePadding.swift +69 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_Camera.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_ClusterPressEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_MapBoundaries.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_MapError.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_MapPressEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_MarkerDragEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_MarkerPressEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_RegionChangeEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridNitroMapConfigSpec.swift +57 -0
- package/nitrogen/generated/ios/swift/HybridNitroMapConfigSpec_cxx.swift +142 -0
- package/nitrogen/generated/ios/swift/HybridNitroMapSpec.swift +93 -0
- package/nitrogen/generated/ios/swift/HybridNitroMapSpec_cxx.swift +953 -0
- package/nitrogen/generated/ios/swift/ImageMarkerConfig.swift +166 -0
- package/nitrogen/generated/ios/swift/MapBoundaries.swift +47 -0
- package/nitrogen/generated/ios/swift/MapError.swift +47 -0
- package/nitrogen/generated/ios/swift/MapPressEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/MapProvider.swift +44 -0
- package/nitrogen/generated/ios/swift/MapStyleElement.swift +108 -0
- package/nitrogen/generated/ios/swift/MapStyler.swift +177 -0
- package/nitrogen/generated/ios/swift/MapType.swift +44 -0
- package/nitrogen/generated/ios/swift/MarkerAnimation.swift +44 -0
- package/nitrogen/generated/ios/swift/MarkerColor.swift +69 -0
- package/nitrogen/generated/ios/swift/MarkerConfig.swift +82 -0
- package/nitrogen/generated/ios/swift/MarkerData.swift +195 -0
- package/nitrogen/generated/ios/swift/MarkerDragEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/MarkerPressEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/MarkerStyle.swift +44 -0
- package/nitrogen/generated/ios/swift/Point.swift +47 -0
- package/nitrogen/generated/ios/swift/PriceMarkerStyle.swift +374 -0
- package/nitrogen/generated/ios/swift/Region.swift +69 -0
- package/nitrogen/generated/ios/swift/RegionChangeEvent.swift +47 -0
- package/nitrogen/generated/ios/swift/Variant_String_MarkerColor.swift +18 -0
- package/nitrogen/generated/shared/c++/Camera.hpp +92 -0
- package/nitrogen/generated/shared/c++/ClusterAnimationStyle.hpp +88 -0
- package/nitrogen/generated/shared/c++/ClusterConfig.hpp +140 -0
- package/nitrogen/generated/shared/c++/ClusterPressEvent.hpp +86 -0
- package/nitrogen/generated/shared/c++/ClusterStrategy.hpp +76 -0
- package/nitrogen/generated/shared/c++/Coordinate.hpp +79 -0
- package/nitrogen/generated/shared/c++/EdgePadding.hpp +87 -0
- package/nitrogen/generated/shared/c++/HybridNitroMapConfigSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridNitroMapConfigSpec.hpp +65 -0
- package/nitrogen/generated/shared/c++/HybridNitroMapSpec.cpp +82 -0
- package/nitrogen/generated/shared/c++/HybridNitroMapSpec.hpp +173 -0
- package/nitrogen/generated/shared/c++/ImageMarkerConfig.hpp +103 -0
- package/nitrogen/generated/shared/c++/MapBoundaries.hpp +80 -0
- package/nitrogen/generated/shared/c++/MapError.hpp +79 -0
- package/nitrogen/generated/shared/c++/MapPressEvent.hpp +83 -0
- package/nitrogen/generated/shared/c++/MapProvider.hpp +80 -0
- package/nitrogen/generated/shared/c++/MapStyleElement.hpp +87 -0
- package/nitrogen/generated/shared/c++/MapStyler.hpp +96 -0
- package/nitrogen/generated/shared/c++/MapType.hpp +80 -0
- package/nitrogen/generated/shared/c++/MarkerAnimation.hpp +80 -0
- package/nitrogen/generated/shared/c++/MarkerColor.hpp +87 -0
- package/nitrogen/generated/shared/c++/MarkerConfig.hpp +91 -0
- package/nitrogen/generated/shared/c++/MarkerData.hpp +131 -0
- package/nitrogen/generated/shared/c++/MarkerDragEvent.hpp +81 -0
- package/nitrogen/generated/shared/c++/MarkerPressEvent.hpp +81 -0
- package/nitrogen/generated/shared/c++/MarkerStyle.hpp +80 -0
- package/nitrogen/generated/shared/c++/Point.hpp +79 -0
- package/nitrogen/generated/shared/c++/PriceMarkerStyle.hpp +119 -0
- package/nitrogen/generated/shared/c++/Region.hpp +87 -0
- package/nitrogen/generated/shared/c++/RegionChangeEvent.hpp +80 -0
- package/nitrogen/generated/shared/c++/views/HybridNitroMapComponent.cpp +351 -0
- package/nitrogen/generated/shared/c++/views/HybridNitroMapComponent.hpp +141 -0
- package/nitrogen/generated/shared/json/NitroMapConfig.json +32 -0
- package/package.json +176 -0
- package/react-native.config.js +16 -0
- package/src/components/ImageMarker.tsx +254 -0
- package/src/components/NitroMap.tsx +433 -0
- package/src/components/PriceMarker.tsx +311 -0
- package/src/context/NitroMapContext.tsx +33 -0
- package/src/hooks/useNitroMarker.ts +198 -0
- package/src/index.tsx +62 -0
- package/src/modules/index.ts +6 -0
- package/src/modules/module.ts +45 -0
- package/src/specs/NitroMap.nitro.ts +292 -0
- package/src/specs/NitroMapConfig.nitro.ts +8 -0
- package/src/types/map.ts +166 -0
- package/src/types/marker.ts +267 -0
- package/src/utils/colors.ts +159 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
package com.margelo.nitro.nitromap
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.*
|
|
5
|
+
import android.util.Base64
|
|
6
|
+
import com.google.android.gms.maps.model.BitmapDescriptor
|
|
7
|
+
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
|
8
|
+
import java.net.URL
|
|
9
|
+
import kotlin.math.roundToInt
|
|
10
|
+
|
|
11
|
+
/** Factory for creating marker icons from MarkerData configuration */
|
|
12
|
+
object MarkerIconFactory {
|
|
13
|
+
|
|
14
|
+
private var reactContext: com.facebook.react.bridge.ReactContext? = null
|
|
15
|
+
|
|
16
|
+
/** Set the React context for view capture (call this from HybridNitroMap initialization) */
|
|
17
|
+
fun setReactContext(context: com.facebook.react.bridge.ReactContext?) {
|
|
18
|
+
reactContext = context
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fun createIcon(context: Context, markerData: MarkerData): BitmapDescriptor? {
|
|
22
|
+
return when (markerData.config.style) {
|
|
23
|
+
MarkerStyle.IMAGE -> createImageMarkerIcon(context, markerData.config.image)
|
|
24
|
+
MarkerStyle.PRICEMARKER ->
|
|
25
|
+
createPriceMarkerStyleIcon(context, markerData.config.priceMarker)
|
|
26
|
+
MarkerStyle.DEFAULT -> null
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private fun createPriceMarkerStyleIcon(
|
|
31
|
+
context: Context,
|
|
32
|
+
config: PriceMarkerStyle?
|
|
33
|
+
): BitmapDescriptor? {
|
|
34
|
+
config ?: return null
|
|
35
|
+
|
|
36
|
+
// Generate cache key (Flyweight pattern)
|
|
37
|
+
val cacheKey =
|
|
38
|
+
MarkerIconCache.priceMarkerKey(config.price, config.currency, config.selected)
|
|
39
|
+
|
|
40
|
+
// Check cache first
|
|
41
|
+
MarkerIconCache.getPriceMarker(cacheKey)?.let { cachedBitmap ->
|
|
42
|
+
return BitmapDescriptorFactory.fromBitmap(cachedBitmap)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
val density = context.resources.displayMetrics.density
|
|
46
|
+
val priceText = "${config.price} ${config.currency}"
|
|
47
|
+
val fontSize = (config.fontSize ?: 14.0) * density
|
|
48
|
+
val paddingH = (config.paddingHorizontal ?: 12.0) * density
|
|
49
|
+
val paddingV = (config.paddingVertical ?: 8.0) * density
|
|
50
|
+
|
|
51
|
+
val textPaint =
|
|
52
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
53
|
+
textSize = fontSize.toFloat()
|
|
54
|
+
typeface = Typeface.DEFAULT_BOLD
|
|
55
|
+
textAlign = Paint.Align.LEFT
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Set colors based on selection state
|
|
59
|
+
val bgColor =
|
|
60
|
+
if (config.selected) {
|
|
61
|
+
config.selectedBackgroundColor?.let { ColorUtils.fromVariant(it) }
|
|
62
|
+
?: Color.parseColor("#E53935") // Red for selected
|
|
63
|
+
} else {
|
|
64
|
+
config.backgroundColor?.let { ColorUtils.fromVariant(it) } ?: Color.WHITE
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
val textColor =
|
|
68
|
+
if (config.selected) {
|
|
69
|
+
config.selectedTextColor?.let { ColorUtils.fromVariant(it) } ?: Color.WHITE
|
|
70
|
+
} else {
|
|
71
|
+
config.textColor?.let { ColorUtils.fromVariant(it) } ?: Color.BLACK
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
textPaint.color = textColor
|
|
75
|
+
|
|
76
|
+
val textBounds = Rect()
|
|
77
|
+
textPaint.getTextBounds(priceText, 0, priceText.length, textBounds)
|
|
78
|
+
|
|
79
|
+
val arrowHeight = 8 * density
|
|
80
|
+
val width = textBounds.width() + paddingH * 2
|
|
81
|
+
val height = textBounds.height() + paddingV * 2 + arrowHeight
|
|
82
|
+
val cornerRadius = 8 * density
|
|
83
|
+
|
|
84
|
+
val bitmap =
|
|
85
|
+
Bitmap.createBitmap(
|
|
86
|
+
width.roundToInt(),
|
|
87
|
+
height.roundToInt(),
|
|
88
|
+
Bitmap.Config.ARGB_8888
|
|
89
|
+
)
|
|
90
|
+
val canvas = Canvas(bitmap)
|
|
91
|
+
|
|
92
|
+
val bgPaint =
|
|
93
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
94
|
+
color = bgColor
|
|
95
|
+
style = Paint.Style.FILL
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add shadow
|
|
99
|
+
val shadowPaint =
|
|
100
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
101
|
+
color = Color.BLACK
|
|
102
|
+
alpha = ((config.shadowOpacity ?: 0.2) * 255).toInt()
|
|
103
|
+
maskFilter = BlurMaskFilter((4 * density).toFloat(), BlurMaskFilter.Blur.NORMAL)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
val bubbleRect =
|
|
107
|
+
RectF(
|
|
108
|
+
(2 * density).toFloat(),
|
|
109
|
+
0f,
|
|
110
|
+
(width - 2 * density).toFloat(),
|
|
111
|
+
(height - arrowHeight).toFloat()
|
|
112
|
+
)
|
|
113
|
+
canvas.drawRoundRect(
|
|
114
|
+
bubbleRect.apply { offset(0f, (2 * density).toFloat()) },
|
|
115
|
+
cornerRadius.toFloat(),
|
|
116
|
+
cornerRadius.toFloat(),
|
|
117
|
+
shadowPaint
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
bubbleRect.offset(0f, (-2 * density).toFloat())
|
|
121
|
+
canvas.drawRoundRect(bubbleRect, cornerRadius.toFloat(), cornerRadius.toFloat(), bgPaint)
|
|
122
|
+
|
|
123
|
+
// Draw arrow
|
|
124
|
+
val path =
|
|
125
|
+
Path().apply {
|
|
126
|
+
moveTo((width / 2 - arrowHeight).toFloat(), (height - arrowHeight).toFloat())
|
|
127
|
+
lineTo((width / 2).toFloat(), height.toFloat())
|
|
128
|
+
lineTo((width / 2 + arrowHeight).toFloat(), (height - arrowHeight).toFloat())
|
|
129
|
+
close()
|
|
130
|
+
}
|
|
131
|
+
canvas.drawPath(path, bgPaint)
|
|
132
|
+
|
|
133
|
+
// Draw text
|
|
134
|
+
val textX = paddingH.toFloat()
|
|
135
|
+
val textY = paddingV.toFloat() + textBounds.height()
|
|
136
|
+
canvas.drawText(priceText, textX, textY, textPaint)
|
|
137
|
+
|
|
138
|
+
// Cache the bitmap for reuse
|
|
139
|
+
MarkerIconCache.putPriceMarker(cacheKey, bitmap)
|
|
140
|
+
|
|
141
|
+
return BitmapDescriptorFactory.fromBitmap(bitmap)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private fun createImageMarkerIcon(
|
|
145
|
+
context: Context,
|
|
146
|
+
config: ImageMarkerConfig?
|
|
147
|
+
): BitmapDescriptor? {
|
|
148
|
+
config ?: return null
|
|
149
|
+
|
|
150
|
+
val imageSource = config.imageBase64 ?: config.imageUrl ?: ""
|
|
151
|
+
|
|
152
|
+
// Generate cache key (Flyweight pattern)
|
|
153
|
+
val cacheKey =
|
|
154
|
+
MarkerIconCache.imageMarkerKey(
|
|
155
|
+
imageSource,
|
|
156
|
+
config.width,
|
|
157
|
+
config.height,
|
|
158
|
+
config.cornerRadius
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
// Check cache first
|
|
162
|
+
MarkerIconCache.getImageMarker(cacheKey)?.let { cachedBitmap ->
|
|
163
|
+
return BitmapDescriptorFactory.fromBitmap(cachedBitmap)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
val density = context.resources.displayMetrics.density
|
|
167
|
+
val width = (config.width * density).roundToInt()
|
|
168
|
+
val height = (config.height * density).roundToInt()
|
|
169
|
+
val cornerRadius = config.cornerRadius * density
|
|
170
|
+
val borderWidth = config.borderWidth * density
|
|
171
|
+
|
|
172
|
+
var sourceImage: Bitmap? = null
|
|
173
|
+
|
|
174
|
+
// Try to load image from base64
|
|
175
|
+
config.imageBase64?.let { base64 ->
|
|
176
|
+
try {
|
|
177
|
+
val bytes = Base64.decode(base64, Base64.DEFAULT)
|
|
178
|
+
sourceImage = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
|
|
179
|
+
} catch (e: Exception) {
|
|
180
|
+
e.printStackTrace()
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Try to load from URL (blocking - should be done on background thread in production)
|
|
185
|
+
if (sourceImage == null) {
|
|
186
|
+
config.imageUrl?.let { urlString ->
|
|
187
|
+
try {
|
|
188
|
+
val url = URL(urlString)
|
|
189
|
+
val connection = url.openConnection()
|
|
190
|
+
connection.connectTimeout = 5000
|
|
191
|
+
connection.readTimeout = 5000
|
|
192
|
+
val inputStream = connection.getInputStream()
|
|
193
|
+
sourceImage = BitmapFactory.decodeStream(inputStream)
|
|
194
|
+
inputStream.close()
|
|
195
|
+
} catch (e: Exception) {
|
|
196
|
+
e.printStackTrace()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
202
|
+
val canvas = Canvas(bitmap)
|
|
203
|
+
|
|
204
|
+
val clipPath =
|
|
205
|
+
Path().apply {
|
|
206
|
+
addRoundRect(
|
|
207
|
+
RectF(0f, 0f, width.toFloat(), height.toFloat()),
|
|
208
|
+
cornerRadius.toFloat(),
|
|
209
|
+
cornerRadius.toFloat(),
|
|
210
|
+
Path.Direction.CW
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
canvas.clipPath(clipPath)
|
|
214
|
+
|
|
215
|
+
// Draw image or placeholder
|
|
216
|
+
sourceImage?.let { img ->
|
|
217
|
+
val scaledBitmap = Bitmap.createScaledBitmap(img, width, height, true)
|
|
218
|
+
canvas.drawBitmap(scaledBitmap, 0f, 0f, null)
|
|
219
|
+
if (scaledBitmap != img) scaledBitmap.recycle()
|
|
220
|
+
}
|
|
221
|
+
?: run {
|
|
222
|
+
val placeholderPaint = Paint().apply { color = Color.LTGRAY }
|
|
223
|
+
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), placeholderPaint)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Draw border
|
|
227
|
+
if (borderWidth > 0) {
|
|
228
|
+
val borderPaint =
|
|
229
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
230
|
+
color = ColorUtils.fromColorValue(config.borderColor)
|
|
231
|
+
style = Paint.Style.STROKE
|
|
232
|
+
strokeWidth = borderWidth.toFloat()
|
|
233
|
+
}
|
|
234
|
+
canvas.drawRoundRect(
|
|
235
|
+
RectF(
|
|
236
|
+
borderWidth.toFloat() / 2,
|
|
237
|
+
borderWidth.toFloat() / 2,
|
|
238
|
+
width - borderWidth.toFloat() / 2,
|
|
239
|
+
height - borderWidth.toFloat() / 2
|
|
240
|
+
),
|
|
241
|
+
cornerRadius.toFloat(),
|
|
242
|
+
cornerRadius.toFloat(),
|
|
243
|
+
borderPaint
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Cache the bitmap for reuse
|
|
248
|
+
MarkerIconCache.putImageMarker(cacheKey, bitmap)
|
|
249
|
+
|
|
250
|
+
return BitmapDescriptorFactory.fromBitmap(bitmap)
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.margelo.nitro.nitromap
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
7
|
+
import com.facebook.react.uimanager.ViewManager
|
|
8
|
+
|
|
9
|
+
import com.margelo.nitro.nitromap.views.HybridNitroMapManager
|
|
10
|
+
|
|
11
|
+
class NitroMapPackage : BaseReactPackage() {
|
|
12
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
13
|
+
// Set context for HybridNitroMapConfig on first module access
|
|
14
|
+
HybridNitroMapConfig.setContext(reactContext)
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
19
|
+
return ReactModuleInfoProvider { HashMap() }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
23
|
+
// Set context for HybridNitroMapConfig
|
|
24
|
+
HybridNitroMapConfig.setContext(reactContext)
|
|
25
|
+
return listOf(HybridNitroMapManager())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
companion object {
|
|
29
|
+
init {
|
|
30
|
+
System.loadLibrary("nitromap")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
package com.margelo.nitro.nitromap.clustering
|
|
2
|
+
|
|
3
|
+
import com.google.android.gms.maps.model.LatLng
|
|
4
|
+
import com.google.android.gms.maps.model.LatLngBounds
|
|
5
|
+
import com.margelo.nitro.nitromap.ClusterConfig
|
|
6
|
+
import com.margelo.nitro.nitromap.MarkerData
|
|
7
|
+
import kotlin.math.*
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Marker point for clustering
|
|
11
|
+
*/
|
|
12
|
+
data class MarkerPoint(
|
|
13
|
+
val id: String,
|
|
14
|
+
val latitude: Double,
|
|
15
|
+
val longitude: Double
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Cluster result containing multiple markers
|
|
20
|
+
*/
|
|
21
|
+
data class Cluster(
|
|
22
|
+
val latitude: Double,
|
|
23
|
+
val longitude: Double,
|
|
24
|
+
val markerIds: List<String>,
|
|
25
|
+
val count: Int
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Full clustering result
|
|
30
|
+
*/
|
|
31
|
+
data class ClusterResult(
|
|
32
|
+
val clusters: List<Cluster>,
|
|
33
|
+
val singleMarkers: List<MarkerPoint>
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* High-performance clustering engine using QuadTree spatial indexing
|
|
38
|
+
* Kotlin port of C++ ClusterEngine
|
|
39
|
+
*/
|
|
40
|
+
class NitroClusterEngine {
|
|
41
|
+
|
|
42
|
+
// QuadTree for O(log n) spatial queries
|
|
43
|
+
private var quadTree: QuadTree? = null
|
|
44
|
+
|
|
45
|
+
// All markers stored by ID
|
|
46
|
+
private val markers = mutableMapOf<String, MarkerPoint>()
|
|
47
|
+
|
|
48
|
+
// Marker data cache for full marker info
|
|
49
|
+
private val markerDataCache = mutableMapOf<String, MarkerData>()
|
|
50
|
+
|
|
51
|
+
// Configuration
|
|
52
|
+
private var clusterRadius = 60.0
|
|
53
|
+
private var minClusterSize = 2
|
|
54
|
+
private var maxZoom = 20.0
|
|
55
|
+
|
|
56
|
+
// MARK: - Configuration
|
|
57
|
+
|
|
58
|
+
fun setClusterRadius(radius: Double) {
|
|
59
|
+
clusterRadius = radius
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fun setMinClusterSize(size: Int) {
|
|
63
|
+
minClusterSize = size
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fun setMaxZoom(zoom: Double) {
|
|
67
|
+
maxZoom = zoom
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fun updateConfig(config: ClusterConfig?) {
|
|
71
|
+
config?.let {
|
|
72
|
+
minClusterSize = it.minimumClusterSize.toInt()
|
|
73
|
+
maxZoom = it.maxZoom
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Marker Management
|
|
78
|
+
|
|
79
|
+
fun addMarker(markerData: MarkerData) {
|
|
80
|
+
val id = markerData.id
|
|
81
|
+
val point = MarkerPoint(
|
|
82
|
+
id = id,
|
|
83
|
+
latitude = markerData.coordinate.latitude,
|
|
84
|
+
longitude = markerData.coordinate.longitude
|
|
85
|
+
)
|
|
86
|
+
markers[id] = point
|
|
87
|
+
markerDataCache[id] = markerData
|
|
88
|
+
rebuildQuadTree()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fun addMarkers(markersList: List<MarkerData>) {
|
|
92
|
+
for (marker in markersList) {
|
|
93
|
+
val id = marker.id
|
|
94
|
+
val point = MarkerPoint(
|
|
95
|
+
id = id,
|
|
96
|
+
latitude = marker.coordinate.latitude,
|
|
97
|
+
longitude = marker.coordinate.longitude
|
|
98
|
+
)
|
|
99
|
+
markers[id] = point
|
|
100
|
+
markerDataCache[id] = marker
|
|
101
|
+
}
|
|
102
|
+
rebuildQuadTree()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fun removeMarker(id: String) {
|
|
106
|
+
markers.remove(id)
|
|
107
|
+
markerDataCache.remove(id)
|
|
108
|
+
rebuildQuadTree()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
fun clearMarkers() {
|
|
112
|
+
markers.clear()
|
|
113
|
+
markerDataCache.clear()
|
|
114
|
+
quadTree?.clear()
|
|
115
|
+
quadTree = null
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fun getMarkerCount(): Int = markers.size
|
|
119
|
+
|
|
120
|
+
fun getMarkerData(id: String): MarkerData? = markerDataCache[id]
|
|
121
|
+
|
|
122
|
+
// MARK: - Clustering
|
|
123
|
+
|
|
124
|
+
fun cluster(
|
|
125
|
+
bounds: LatLngBounds,
|
|
126
|
+
zoom: Float,
|
|
127
|
+
mapWidth: Int,
|
|
128
|
+
mapHeight: Int
|
|
129
|
+
): ClusterResult {
|
|
130
|
+
// At max zoom or beyond, don't cluster
|
|
131
|
+
if (zoom >= maxZoom) {
|
|
132
|
+
return ClusterResult(
|
|
133
|
+
clusters = emptyList(),
|
|
134
|
+
singleMarkers = markers.values.toList()
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
val tree = quadTree ?: return ClusterResult(emptyList(), markers.values.toList())
|
|
139
|
+
|
|
140
|
+
// Calculate cluster radius in coordinate space
|
|
141
|
+
val latSpan = bounds.northeast.latitude - bounds.southwest.latitude
|
|
142
|
+
val lngSpan = bounds.northeast.longitude - bounds.southwest.longitude
|
|
143
|
+
|
|
144
|
+
// Pixels to degrees conversion
|
|
145
|
+
val pixelsPerDegreeLat = if (latSpan > 0) mapHeight / latSpan else 1.0
|
|
146
|
+
val pixelsPerDegreeLng = if (lngSpan > 0) mapWidth / lngSpan else 1.0
|
|
147
|
+
|
|
148
|
+
// Cluster radius in degrees
|
|
149
|
+
val radiusLat = clusterRadius / pixelsPerDegreeLat
|
|
150
|
+
val radiusLng = clusterRadius / pixelsPerDegreeLng
|
|
151
|
+
val avgRadius = (radiusLat + radiusLng) / 2.0
|
|
152
|
+
|
|
153
|
+
// Grid-based clustering for O(n) performance
|
|
154
|
+
val gridSizeLat = radiusLat * 2
|
|
155
|
+
val gridSizeLng = radiusLng * 2
|
|
156
|
+
|
|
157
|
+
// Get visible markers
|
|
158
|
+
val visiblePoints = mutableListOf<QuadPoint>()
|
|
159
|
+
val range = BoundingBox(
|
|
160
|
+
bounds.southwest.longitude,
|
|
161
|
+
bounds.southwest.latitude,
|
|
162
|
+
bounds.northeast.longitude,
|
|
163
|
+
bounds.northeast.latitude
|
|
164
|
+
)
|
|
165
|
+
tree.query(range, visiblePoints)
|
|
166
|
+
|
|
167
|
+
// Track processed markers
|
|
168
|
+
val processed = mutableSetOf<String>()
|
|
169
|
+
val clusters = mutableListOf<Cluster>()
|
|
170
|
+
val singleMarkers = mutableListOf<MarkerPoint>()
|
|
171
|
+
|
|
172
|
+
for (point in visiblePoints) {
|
|
173
|
+
if (processed.contains(point.id)) continue
|
|
174
|
+
|
|
175
|
+
// Find nearby markers
|
|
176
|
+
val nearbyPoints = mutableListOf<QuadPoint>()
|
|
177
|
+
tree.queryRadius(point.x, point.y, avgRadius, nearbyPoints)
|
|
178
|
+
|
|
179
|
+
// Filter to unprocessed points
|
|
180
|
+
val unprocessedNearby = nearbyPoints.filter { !processed.contains(it.id) }
|
|
181
|
+
|
|
182
|
+
if (unprocessedNearby.size >= minClusterSize) {
|
|
183
|
+
// Create cluster
|
|
184
|
+
var sumLat = 0.0
|
|
185
|
+
var sumLng = 0.0
|
|
186
|
+
val markerIds = mutableListOf<String>()
|
|
187
|
+
|
|
188
|
+
for (nearby in unprocessedNearby) {
|
|
189
|
+
sumLng += nearby.x
|
|
190
|
+
sumLat += nearby.y
|
|
191
|
+
markerIds.add(nearby.id)
|
|
192
|
+
processed.add(nearby.id)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
val count = unprocessedNearby.size
|
|
196
|
+
clusters.add(
|
|
197
|
+
Cluster(
|
|
198
|
+
latitude = sumLat / count,
|
|
199
|
+
longitude = sumLng / count,
|
|
200
|
+
markerIds = markerIds,
|
|
201
|
+
count = count
|
|
202
|
+
)
|
|
203
|
+
)
|
|
204
|
+
} else {
|
|
205
|
+
// Single marker
|
|
206
|
+
processed.add(point.id)
|
|
207
|
+
markers[point.id]?.let { singleMarkers.add(it) }
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return ClusterResult(clusters, singleMarkers)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
private fun rebuildQuadTree() {
|
|
215
|
+
if (markers.isEmpty()) {
|
|
216
|
+
quadTree = null
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Find bounds
|
|
221
|
+
var minLat = Double.MAX_VALUE
|
|
222
|
+
var maxLat = -Double.MAX_VALUE
|
|
223
|
+
var minLng = Double.MAX_VALUE
|
|
224
|
+
var maxLng = -Double.MAX_VALUE
|
|
225
|
+
|
|
226
|
+
for (marker in markers.values) {
|
|
227
|
+
minLat = min(minLat, marker.latitude)
|
|
228
|
+
maxLat = max(maxLat, marker.latitude)
|
|
229
|
+
minLng = min(minLng, marker.longitude)
|
|
230
|
+
maxLng = max(maxLng, marker.longitude)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Add padding
|
|
234
|
+
val latPadding = (maxLat - minLat) * 0.1 + 0.001
|
|
235
|
+
val lngPadding = (maxLng - minLng) * 0.1 + 0.001
|
|
236
|
+
|
|
237
|
+
val bounds = BoundingBox(
|
|
238
|
+
minLng - lngPadding,
|
|
239
|
+
minLat - latPadding,
|
|
240
|
+
maxLng + lngPadding,
|
|
241
|
+
maxLat + latPadding
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
quadTree = QuadTree(bounds)
|
|
245
|
+
|
|
246
|
+
for (marker in markers.values) {
|
|
247
|
+
quadTree?.insert(
|
|
248
|
+
QuadPoint(marker.longitude, marker.latitude, marker.id)
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|