expo-arcgis 0.1.2 → 0.1.3
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/android/src/main/java/expo/modules/arcgis/DynamicEntityLayerRef.kt +30 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisExtrasModule.kt +15 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisGeometryModule.kt +2 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisModule.kt +7 -2
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisSceneView.kt +20 -0
- package/android/src/main/java/expo/modules/arcgis/GeometryEngineFunctions.kt +68 -0
- package/android/src/main/java/expo/modules/arcgis/GeoprocessingFunctions.kt +25 -0
- package/android/src/main/java/expo/modules/arcgis/GraphicsOverlayRef.kt +7 -0
- package/android/src/main/java/expo/modules/arcgis/OfflineFunctions.kt +19 -0
- package/build/DynamicEntityLayer.d.ts +4 -1
- package/build/DynamicEntityLayer.d.ts.map +1 -1
- package/build/DynamicEntityLayer.js +8 -1
- package/build/DynamicEntityLayer.js.map +1 -1
- package/build/ExpoArcgis.types.d.ts +133 -1
- package/build/ExpoArcgis.types.d.ts.map +1 -1
- package/build/ExpoArcgis.types.js.map +1 -1
- package/build/ExpoArcgisExtrasModule.d.ts +7 -1
- package/build/ExpoArcgisExtrasModule.d.ts.map +1 -1
- package/build/ExpoArcgisExtrasModule.js.map +1 -1
- package/build/ExpoArcgisGeometryModule.d.ts +3 -1
- package/build/ExpoArcgisGeometryModule.d.ts.map +1 -1
- package/build/ExpoArcgisGeometryModule.js.map +1 -1
- package/build/ExpoArcgisModule.d.ts +2 -1
- package/build/ExpoArcgisModule.d.ts.map +1 -1
- package/build/ExpoArcgisModule.js.map +1 -1
- package/build/auth.d.ts +14 -0
- package/build/auth.d.ts.map +1 -1
- package/build/auth.js +17 -0
- package/build/auth.js.map +1 -1
- package/build/geometryEngine.d.ts +13 -1
- package/build/geometryEngine.d.ts.map +1 -1
- package/build/geometryEngine.js +12 -0
- package/build/geometryEngine.js.map +1 -1
- package/build/index.d.ts +1 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/offline.d.ts +7 -1
- package/build/offline.d.ts.map +1 -1
- package/build/offline.js +7 -0
- package/build/offline.js.map +1 -1
- package/ios/DynamicEntityLayerRef.swift +46 -0
- package/ios/ExpoArcgisExtrasModule.swift +19 -0
- package/ios/ExpoArcgisGeometryModule.swift +2 -0
- package/ios/ExpoArcgisModule.swift +4 -0
- package/ios/ExpoArcgisSceneView.swift +24 -0
- package/ios/GeometryEngineFunctions.swift +83 -0
- package/ios/GeoprocessingFunctions.swift +20 -0
- package/ios/GraphicsOverlayRef.swift +4 -0
- package/ios/OfflineFunctions.swift +14 -0
- package/package.json +1 -1
- package/src/DynamicEntityLayer.tsx +12 -1
- package/src/ExpoArcgis.types.ts +136 -2
- package/src/ExpoArcgisExtrasModule.ts +17 -0
- package/src/ExpoArcgisGeometryModule.ts +4 -0
- package/src/ExpoArcgisModule.ts +2 -0
- package/src/auth.ts +23 -0
- package/src/geometryEngine.ts +18 -0
- package/src/index.ts +1 -0
- package/src/offline.ts +14 -0
|
@@ -39,6 +39,18 @@ class DynamicEntityLayerRef(appContext: AppContext, props: Map<String, Any?>) :
|
|
|
39
39
|
emit("onConnectionStatusChange", mapOf("status" to connectionStatusString(status)))
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
// Emit entity-received events (new/updated observation arrived for an entity).
|
|
43
|
+
scope.launch {
|
|
44
|
+
dataSource.dynamicEntityReceivedEvent.collect { info ->
|
|
45
|
+
emit("onDynamicEntityChange", dynamicEntityPayload("received", info.dynamicEntity))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Emit entity-purged events (entity evicted by purge rules).
|
|
49
|
+
scope.launch {
|
|
50
|
+
dataSource.dynamicEntityPurgedEvent.collect { info ->
|
|
51
|
+
emit("onDynamicEntityChange", dynamicEntityPayload("purged", info.dynamicEntity))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
42
54
|
}
|
|
43
55
|
|
|
44
56
|
/** Pushes an observation into a custom data source (no-op for a stream service). */
|
|
@@ -97,6 +109,24 @@ fun connectionStatusString(status: ConnectionStatus): String = when (status) {
|
|
|
97
109
|
is ConnectionStatus.Failed -> "failed"
|
|
98
110
|
}
|
|
99
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Builds a compact payload for the `onDynamicEntityChange` event.
|
|
114
|
+
* Only `received` and `purged` change types are emitted (observation-only updates are
|
|
115
|
+
* captured within `dynamicEntityReceivedEvent` which fires per-entity arrival, not per
|
|
116
|
+
* observation, so the event rate is bounded to entity lifecycle changes).
|
|
117
|
+
* Geometry is serialized only when present; attributes are passed as-is (the map returned
|
|
118
|
+
* by the SDK is a shallow snapshot of the current entity attributes).
|
|
119
|
+
*/
|
|
120
|
+
private fun dynamicEntityPayload(changeType: String, entity: com.arcgismaps.realtime.DynamicEntity): Map<String, Any?> {
|
|
121
|
+
val payload = mutableMapOf<String, Any?>(
|
|
122
|
+
"changeType" to changeType,
|
|
123
|
+
"entityId" to entity.id,
|
|
124
|
+
"attributes" to entity.attributes.toMap(),
|
|
125
|
+
)
|
|
126
|
+
entity.geometry?.let { payload["geometry"] = dictFromGeometry(it) }
|
|
127
|
+
return payload
|
|
128
|
+
}
|
|
129
|
+
|
|
100
130
|
/** Builds the real-time data source: a custom feed (push from JS) or a stream service. */
|
|
101
131
|
private fun buildDataSource(
|
|
102
132
|
props: Map<String, Any?>,
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package expo.modules.arcgis
|
|
2
2
|
|
|
3
|
+
import com.arcgismaps.ArcGISEnvironment
|
|
4
|
+
import com.arcgismaps.httpcore.authentication.TokenCredential
|
|
3
5
|
import expo.modules.kotlin.functions.Coroutine
|
|
4
6
|
import expo.modules.kotlin.modules.Module
|
|
5
7
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
@@ -71,6 +73,19 @@ class ExpoArcgisExtrasModule : Module() {
|
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
// Per-service token credential — mint a token for a specific URL and add it to the store.
|
|
77
|
+
AsyncFunction("setServiceCredential") Coroutine { serviceUrl: String, username: String, password: String, tokenExpirationMinutes: Int? ->
|
|
78
|
+
val credential = TokenCredential.create(serviceUrl, username, password, tokenExpirationMinutes)
|
|
79
|
+
.getOrThrow()
|
|
80
|
+
ArcGISEnvironment.authenticationManager.arcGISCredentialStore.add(credential, serviceUrl)
|
|
81
|
+
.getOrThrow()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Tile-cache size estimation — quick estimate before committing to a download.
|
|
85
|
+
AsyncFunction("estimateTileCacheSize") Coroutine { tileServiceUrl: String, areaOfInterest: Map<String, Any?>, options: Map<String, Any?>? ->
|
|
86
|
+
estimateTileCacheSize(tileServiceUrl, areaOfInterest, options)
|
|
87
|
+
}
|
|
88
|
+
|
|
74
89
|
// Turn-by-turn navigation — solve a route and track device locations against it.
|
|
75
90
|
AsyncFunction("createRouteTracker") Coroutine { stops: List<Map<String, Any?>>, params: Map<String, Any?> ->
|
|
76
91
|
createRouteTracker(appContext, stops, params)
|
|
@@ -59,6 +59,8 @@ class ExpoArcgisGeometryModule : Module() {
|
|
|
59
59
|
Function("geMove", ::geMove)
|
|
60
60
|
Function("geRotate", ::geRotate)
|
|
61
61
|
Function("geScale", ::geScale)
|
|
62
|
+
Function("geEllipseGeodesic", ::geEllipseGeodesic)
|
|
63
|
+
Function("geSectorGeodesic", ::geSectorGeodesic)
|
|
62
64
|
|
|
63
65
|
// CoordinateFormatter — point <-> notation strings, exposed as the JS `coordinateFormatter` namespace.
|
|
64
66
|
Function("cfToLatLong", ::cfToLatLong)
|
|
@@ -234,12 +234,13 @@ class ExpoArcgisModule : Module() {
|
|
|
234
234
|
Function("applyProps") { ref: OgcFeatureLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
// Real-time DynamicEntityLayer (stream service) — emits onConnectionStatusChange
|
|
237
|
+
// Real-time DynamicEntityLayer (stream service) — emits onConnectionStatusChange +
|
|
238
|
+
// onDynamicEntityChange (received/purged entity events).
|
|
238
239
|
Class(DynamicEntityLayerRef::class) {
|
|
239
240
|
Constructor { props: Map<String, Any?> ->
|
|
240
241
|
DynamicEntityLayerRef(appContext, props).also { it.applyProps(props) }
|
|
241
242
|
}
|
|
242
|
-
Events("onConnectionStatusChange")
|
|
243
|
+
Events("onConnectionStatusChange", "onDynamicEntityChange")
|
|
243
244
|
Function("applyProps") { ref: DynamicEntityLayerRef, changed: Map<String, Any?> ->
|
|
244
245
|
ref.applyProps(changed)
|
|
245
246
|
}
|
|
@@ -405,6 +406,10 @@ class ExpoArcgisModule : Module() {
|
|
|
405
406
|
view.setCamera(camera)
|
|
406
407
|
}
|
|
407
408
|
|
|
409
|
+
Prop("cameraController") { view: ExpoArcgisSceneView, value: Map<String, Any?>? ->
|
|
410
|
+
view.setCameraController(value)
|
|
411
|
+
}
|
|
412
|
+
|
|
408
413
|
Prop("sunLighting") { view: ExpoArcgisSceneView, value: String? ->
|
|
409
414
|
view.setSunLighting(value)
|
|
410
415
|
}
|
|
@@ -9,7 +9,9 @@ import com.arcgismaps.geometry.Point
|
|
|
9
9
|
import com.arcgismaps.geometry.SpatialReference
|
|
10
10
|
import com.arcgismaps.mapping.view.AtmosphereEffect
|
|
11
11
|
import com.arcgismaps.mapping.view.Camera
|
|
12
|
+
import com.arcgismaps.mapping.view.GlobeCameraController
|
|
12
13
|
import com.arcgismaps.mapping.view.LightingMode
|
|
14
|
+
import com.arcgismaps.mapping.view.OrbitLocationCameraController
|
|
13
15
|
import com.arcgismaps.mapping.view.SceneView
|
|
14
16
|
import com.arcgismaps.mapping.view.ScreenCoordinate
|
|
15
17
|
import expo.modules.kotlin.AppContext
|
|
@@ -147,6 +149,24 @@ class ExpoArcgisSceneView(context: Context, appContext: AppContext) : ExpoView(c
|
|
|
147
149
|
scope.launch { sceneView.setViewpointCameraAnimated(camera, 0.5f) }
|
|
148
150
|
}
|
|
149
151
|
|
|
152
|
+
/** Sets or clears the scene's camera controller (orbit/globe). `null` restores the SDK default. */
|
|
153
|
+
fun setCameraController(c: Map<String, Any?>?) {
|
|
154
|
+
sceneView.cameraController = when (c?.get("type") as? String) {
|
|
155
|
+
"orbitLocation" -> {
|
|
156
|
+
val target = c["target"] as? Map<*, *>
|
|
157
|
+
val x = (target?.get("x") as? Number)?.toDouble() ?: 0.0
|
|
158
|
+
val y = (target?.get("y") as? Number)?.toDouble() ?: 0.0
|
|
159
|
+
val z = (target?.get("z") as? Number)?.toDouble()
|
|
160
|
+
val point = if (z != null) Point(x, y, z, SpatialReference.wgs84())
|
|
161
|
+
else Point(x, y, SpatialReference.wgs84())
|
|
162
|
+
val distance = (c["distance"] as? Number)?.toDouble() ?: 1500.0
|
|
163
|
+
OrbitLocationCameraController(point, distance)
|
|
164
|
+
}
|
|
165
|
+
"globe" -> GlobeCameraController()
|
|
166
|
+
else -> GlobeCameraController() // null/absent → restore SDK default (GlobeCameraController)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
150
170
|
/** Sun lighting mode (shadows). */
|
|
151
171
|
fun setSunLighting(s: String?) {
|
|
152
172
|
sceneView.sunLighting = when (s) {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package expo.modules.arcgis
|
|
2
2
|
|
|
3
3
|
import com.arcgismaps.geometry.Envelope
|
|
4
|
+
import com.arcgismaps.geometry.GeodesicEllipseParameters
|
|
5
|
+
import com.arcgismaps.geometry.GeodesicSectorParameters
|
|
4
6
|
import com.arcgismaps.geometry.Geometry
|
|
5
7
|
import com.arcgismaps.geometry.GeometryEngine
|
|
6
8
|
import com.arcgismaps.geometry.Multipart
|
|
@@ -256,3 +258,69 @@ internal fun geScale(
|
|
|
256
258
|
else GeometryEngine.scale(geometry, factorX, factorY),
|
|
257
259
|
)
|
|
258
260
|
}
|
|
261
|
+
|
|
262
|
+
// region Geodesic construction
|
|
263
|
+
|
|
264
|
+
internal fun geEllipseGeodesic(params: Map<String, Any?>): Map<String, Any?>? {
|
|
265
|
+
val centerDict = params["center"] as? Map<String, Any?> ?: return null
|
|
266
|
+
val center = parsePoint(centerDict) ?: return null
|
|
267
|
+
|
|
268
|
+
val semiAxis1Length = (params["semiAxis1Length"] as? Number)?.toDouble() ?: 0.0
|
|
269
|
+
val semiAxis2Length = (params["semiAxis2Length"] as? Number)?.toDouble() ?: 0.0
|
|
270
|
+
val axisDirection = (params["axisDirection"] as? Number)?.toDouble() ?: 0.0
|
|
271
|
+
val angUnit = angularUnit(params["angularUnit"] as? String)
|
|
272
|
+
val linUnit = linearUnit(params["linearUnit"] as? String)
|
|
273
|
+
val maxSegLen = (params["maxSegmentLength"] as? Number)?.toDouble() ?: 0.0
|
|
274
|
+
val maxPtCount = (params["maxPointCount"] as? Number)?.toLong() ?: 10L
|
|
275
|
+
val geoType = params["geometryType"] as? String
|
|
276
|
+
|
|
277
|
+
val p: GeodesicEllipseParameters = when (geoType) {
|
|
278
|
+
"polyline" -> GeodesicEllipseParameters.Companion.createForPolyline()
|
|
279
|
+
"multipoint" -> GeodesicEllipseParameters.Companion.createForMultipoint()
|
|
280
|
+
else -> GeodesicEllipseParameters.Companion.createForPolygon()
|
|
281
|
+
}
|
|
282
|
+
p.center = center
|
|
283
|
+
p.semiAxis1Length = semiAxis1Length
|
|
284
|
+
p.semiAxis2Length = semiAxis2Length
|
|
285
|
+
p.axisDirection = axisDirection
|
|
286
|
+
p.angularUnit = angUnit
|
|
287
|
+
p.linearUnit = linUnit
|
|
288
|
+
p.maxSegmentLength = maxSegLen
|
|
289
|
+
p.maxPointCount = maxPtCount
|
|
290
|
+
|
|
291
|
+
return encode(GeometryEngine.ellipseGeodesicOrNull(p))
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
internal fun geSectorGeodesic(params: Map<String, Any?>): Map<String, Any?>? {
|
|
295
|
+
val centerDict = params["center"] as? Map<String, Any?> ?: return null
|
|
296
|
+
val center = parsePoint(centerDict) ?: return null
|
|
297
|
+
|
|
298
|
+
val semiAxis1Length = (params["semiAxis1Length"] as? Number)?.toDouble() ?: 0.0
|
|
299
|
+
val semiAxis2Length = (params["semiAxis2Length"] as? Number)?.toDouble() ?: 0.0
|
|
300
|
+
val axisDirection = (params["axisDirection"] as? Number)?.toDouble() ?: 0.0
|
|
301
|
+
val sectorAngle = (params["sectorAngle"] as? Number)?.toDouble() ?: 0.0
|
|
302
|
+
val startDirection = (params["startDirection"] as? Number)?.toDouble() ?: 0.0
|
|
303
|
+
val angUnit = angularUnit(params["angularUnit"] as? String)
|
|
304
|
+
val linUnit = linearUnit(params["linearUnit"] as? String)
|
|
305
|
+
val maxSegLen = (params["maxSegmentLength"] as? Number)?.toDouble() ?: 0.0
|
|
306
|
+
val maxPtCount = (params["maxPointCount"] as? Number)?.toLong() ?: 10L
|
|
307
|
+
val geoType = params["geometryType"] as? String
|
|
308
|
+
|
|
309
|
+
val p: GeodesicSectorParameters = when (geoType) {
|
|
310
|
+
"polyline" -> GeodesicSectorParameters.Companion.createForPolyline()
|
|
311
|
+
"multipoint" -> GeodesicSectorParameters.Companion.createForMultipoint()
|
|
312
|
+
else -> GeodesicSectorParameters.Companion.createForPolygon()
|
|
313
|
+
}
|
|
314
|
+
p.center = center
|
|
315
|
+
p.semiAxis1Length = semiAxis1Length
|
|
316
|
+
p.semiAxis2Length = semiAxis2Length
|
|
317
|
+
p.axisDirection = axisDirection
|
|
318
|
+
p.sectorAngle = sectorAngle
|
|
319
|
+
p.startDirection = startDirection
|
|
320
|
+
p.angularUnit = angUnit
|
|
321
|
+
p.linearUnit = linUnit
|
|
322
|
+
p.maxSegmentLength = maxSegLen
|
|
323
|
+
p.maxPointCount = maxPtCount
|
|
324
|
+
|
|
325
|
+
return encode(GeometryEngine.sectorGeodesicOrNull(p))
|
|
326
|
+
}
|
|
@@ -4,12 +4,15 @@ import com.arcgismaps.data.FeatureCollectionTable
|
|
|
4
4
|
import com.arcgismaps.mapping.view.Graphic
|
|
5
5
|
import com.arcgismaps.tasks.geoprocessing.GeoprocessingTask
|
|
6
6
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingBoolean
|
|
7
|
+
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingDataFile
|
|
7
8
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingDate
|
|
8
9
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingDouble
|
|
9
10
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingFeatures
|
|
10
11
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingLinearUnit
|
|
11
12
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingLong
|
|
13
|
+
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingMultiValue
|
|
12
14
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingParameter
|
|
15
|
+
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingParameterType
|
|
13
16
|
import com.arcgismaps.tasks.geoprocessing.geoprocessingparameters.GeoprocessingString
|
|
14
17
|
import expo.modules.kotlin.AppContext
|
|
15
18
|
import java.time.Instant
|
|
@@ -60,6 +63,28 @@ private fun buildGeoprocessingParameter(d: Map<*, *>): GeoprocessingParameter? =
|
|
|
60
63
|
?.map { Graphic().apply { geometry = it } } ?: emptyList()
|
|
61
64
|
GeoprocessingFeatures(FeatureCollectionTable(graphics, emptyList()))
|
|
62
65
|
}
|
|
66
|
+
"multiValue" -> {
|
|
67
|
+
// JS numbers → GeoprocessingDouble, JS strings → GeoprocessingString.
|
|
68
|
+
val rawValues = d["values"] as? List<*> ?: emptyList<Any>()
|
|
69
|
+
val elements: List<GeoprocessingParameter> = rawValues.mapNotNull { v ->
|
|
70
|
+
when (v) {
|
|
71
|
+
is Number -> GeoprocessingDouble(v.toDouble())
|
|
72
|
+
is String -> GeoprocessingString(v)
|
|
73
|
+
else -> null
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Use the element type of the first item to determine the multiValue's parameterType;
|
|
77
|
+
// fall back to GeoprocessingParameterType.GeoprocessingString when the list is empty.
|
|
78
|
+
val paramType = if (elements.firstOrNull() is GeoprocessingDouble)
|
|
79
|
+
GeoprocessingParameterType.GeoprocessingDouble
|
|
80
|
+
else
|
|
81
|
+
GeoprocessingParameterType.GeoprocessingString
|
|
82
|
+
GeoprocessingMultiValue(paramType, elements)
|
|
83
|
+
}
|
|
84
|
+
"dataFile" -> {
|
|
85
|
+
val url = d["url"] as? String ?: return null
|
|
86
|
+
GeoprocessingDataFile.Companion.createWithUrl(url)
|
|
87
|
+
}
|
|
63
88
|
else -> null
|
|
64
89
|
}
|
|
65
90
|
|
|
@@ -8,6 +8,7 @@ import com.arcgismaps.mapping.reduction.ClusteringFeatureReduction
|
|
|
8
8
|
import com.arcgismaps.mapping.reduction.FeatureReduction
|
|
9
9
|
import com.arcgismaps.mapping.symbology.ClassBreak
|
|
10
10
|
import com.arcgismaps.mapping.symbology.ClassBreaksRenderer
|
|
11
|
+
import com.arcgismaps.mapping.symbology.CompositeSymbol
|
|
11
12
|
import com.arcgismaps.mapping.symbology.HorizontalAlignment
|
|
12
13
|
import com.arcgismaps.mapping.symbology.Renderer
|
|
13
14
|
import com.arcgismaps.mapping.symbology.SceneSymbolAnchorPosition
|
|
@@ -213,6 +214,12 @@ private fun buildSymbol(s: Map<*, *>): Symbol? = when (s["type"]) {
|
|
|
213
214
|
}
|
|
214
215
|
composite
|
|
215
216
|
}
|
|
217
|
+
"composite" -> {
|
|
218
|
+
val symbolList = (s["symbols"] as? List<*> ?: emptyList<Any>()).mapNotNull { item ->
|
|
219
|
+
(item as? Map<*, *>)?.let(::buildSymbol)
|
|
220
|
+
}
|
|
221
|
+
CompositeSymbol(symbolList)
|
|
222
|
+
}
|
|
216
223
|
else -> null
|
|
217
224
|
}
|
|
218
225
|
|
|
@@ -10,6 +10,7 @@ import com.arcgismaps.mapping.MobileMapPackage
|
|
|
10
10
|
import com.arcgismaps.tasks.offlinemaptask.OfflineMapSyncTask
|
|
11
11
|
import com.arcgismaps.tasks.offlinemaptask.OfflineMapTask
|
|
12
12
|
import com.arcgismaps.tasks.tilecache.ExportTileCacheTask
|
|
13
|
+
import com.arcgismaps.tasks.tilecache.EstimateTileCacheSizeJob
|
|
13
14
|
import expo.modules.kotlin.AppContext
|
|
14
15
|
import java.io.File
|
|
15
16
|
|
|
@@ -151,6 +152,24 @@ internal suspend fun exportTileCache(
|
|
|
151
152
|
}
|
|
152
153
|
}
|
|
153
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Estimates the on-disk file size and tile count for an [exportTileCache] download WITHOUT
|
|
157
|
+
* downloading. Runs the [EstimateTileCacheSizeJob] to completion and returns `{fileSize, tileCount}`.
|
|
158
|
+
*/
|
|
159
|
+
internal suspend fun estimateTileCacheSize(
|
|
160
|
+
tileServiceUrl: String,
|
|
161
|
+
areaOfInterest: Map<String, Any?>,
|
|
162
|
+
@Suppress("UNUSED_PARAMETER") options: Map<String, Any?>?,
|
|
163
|
+
): Map<String, Any?> {
|
|
164
|
+
val area = geometryFromDict(areaOfInterest) ?: throw IllegalArgumentException("Invalid area of interest")
|
|
165
|
+
val task = ExportTileCacheTask(tileServiceUrl)
|
|
166
|
+
val parameters = task.createDefaultExportTileCacheParameters(area, 0.0, 0.0).getOrThrow()
|
|
167
|
+
val job = task.createEstimateTileCacheSizeJob(parameters)
|
|
168
|
+
job.start()
|
|
169
|
+
val estimate = job.result().getOrThrow()
|
|
170
|
+
return mapOf("fileSize" to estimate.fileSize, "tileCount" to estimate.tileCount)
|
|
171
|
+
}
|
|
172
|
+
|
|
154
173
|
internal suspend fun exportVectorTiles(
|
|
155
174
|
appContext: AppContext,
|
|
156
175
|
baseDir: File?,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConnectionStatus, DynamicEntityLayerHandle } from './ExpoArcgis.types';
|
|
1
|
+
import type { ConnectionStatus, DynamicEntityChange, DynamicEntityLayerHandle } from './ExpoArcgis.types';
|
|
2
2
|
/**
|
|
3
3
|
* Declarative real-time `DynamicEntityLayer`. Adds itself to the nearest `<Map>` / `<Scene>`, shows
|
|
4
4
|
* live moving entities from a `streamServiceUrl` (or a `customSource` you feed via the ref), reports
|
|
@@ -14,5 +14,8 @@ export declare const DynamicEntityLayer: import("react").ForwardRefExoticCompone
|
|
|
14
14
|
geometry?: import("./ExpoArcgis.types").Geometry;
|
|
15
15
|
};
|
|
16
16
|
onConnectionStatusChange?: (status: ConnectionStatus) => void;
|
|
17
|
+
onDynamicEntityChange?: (event: {
|
|
18
|
+
nativeEvent: DynamicEntityChange;
|
|
19
|
+
}) => void;
|
|
17
20
|
} & import("react").RefAttributes<DynamicEntityLayerHandle>>;
|
|
18
21
|
//# sourceMappingURL=DynamicEntityLayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynamicEntityLayer.d.ts","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EAEzB,MAAM,oBAAoB,CAAC;AAO5B;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;
|
|
1
|
+
{"version":3,"file":"DynamicEntityLayer.d.ts","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EAEzB,MAAM,oBAAoB,CAAC;AAO5B;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;mBAwDszqB,CAAC;gBAAkB,CAAC;;;;;;4DADx2qB,CAAC"}
|
|
@@ -10,7 +10,7 @@ import { getPropsDiffs } from './utils/getPropsDiffs';
|
|
|
10
10
|
* connection state through `onConnectionStatusChange`, and exposes `queryDynamicEntities` /
|
|
11
11
|
* `pushObservation` through a `ref`.
|
|
12
12
|
*/
|
|
13
|
-
export const DynamicEntityLayer = forwardRef(function DynamicEntityLayer({ onConnectionStatusChange, ...layerProps }, handle) {
|
|
13
|
+
export const DynamicEntityLayer = forwardRef(function DynamicEntityLayer({ onConnectionStatusChange, onDynamicEntityChange, ...layerProps }, handle) {
|
|
14
14
|
const model = useGeoModel();
|
|
15
15
|
const ref = useRef(undefined);
|
|
16
16
|
if (!ref.current) {
|
|
@@ -33,6 +33,13 @@ export const DynamicEntityLayer = forwardRef(function DynamicEntityLayer({ onCon
|
|
|
33
33
|
const sub = ref.current.addListener('onConnectionStatusChange', (event) => onConnectionStatusChange(event.status));
|
|
34
34
|
return () => sub.remove();
|
|
35
35
|
}, [onConnectionStatusChange]);
|
|
36
|
+
// The entity-change callback is wired as an event listener.
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!onDynamicEntityChange)
|
|
39
|
+
return;
|
|
40
|
+
const sub = ref.current.addListener('onDynamicEntityChange', (event) => onDynamicEntityChange({ nativeEvent: event }));
|
|
41
|
+
return () => sub.remove();
|
|
42
|
+
}, [onDynamicEntityChange]);
|
|
36
43
|
useUpdateEffect(() => {
|
|
37
44
|
const diffs = getPropsDiffs(prev, layerProps);
|
|
38
45
|
if (diffs.length === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DynamicEntityLayer.js","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DynamicEntityLayer.js","sourceRoot":"","sources":["../src/DynamicEntityLayer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';\n\nimport type {\n ConnectionStatus,\n DynamicEntityChange,\n DynamicEntityLayerHandle,\n DynamicEntityLayerProps,\n} from './ExpoArcgis.types';\nimport ExpoArcgisModule, { type DynamicEntityLayerRef } from './ExpoArcgisModule';\nimport { useGeoModel } from './contexts';\nimport { usePrevious } from './hooks/usePrevious';\nimport { useUpdateEffect } from './hooks/useUpdateEffect';\nimport { getPropsDiffs } from './utils/getPropsDiffs';\n\n/**\n * Declarative real-time `DynamicEntityLayer`. Adds itself to the nearest `<Map>` / `<Scene>`, shows\n * live moving entities from a `streamServiceUrl` (or a `customSource` you feed via the ref), reports\n * connection state through `onConnectionStatusChange`, and exposes `queryDynamicEntities` /\n * `pushObservation` through a `ref`.\n */\nexport const DynamicEntityLayer = forwardRef<DynamicEntityLayerHandle, DynamicEntityLayerProps>(\n function DynamicEntityLayer({ onConnectionStatusChange, onDynamicEntityChange, ...layerProps }, handle) {\n const model = useGeoModel();\n const ref = useRef<DynamicEntityLayerRef | undefined>(undefined);\n if (!ref.current) {\n ref.current = new ExpoArcgisModule.DynamicEntityLayerRef(layerProps);\n }\n\n const prev = usePrevious(layerProps);\n\n useEffect(() => {\n const layer = ref.current!;\n model.addLayer(layer);\n return () => {\n model.removeLayer(layer);\n layer.release();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // The connection-status callback is wired as an event listener (functions can't cross as props).\n useEffect(() => {\n if (!onConnectionStatusChange) return;\n const sub = ref.current!.addListener(\n 'onConnectionStatusChange',\n (event: { status: ConnectionStatus }) => onConnectionStatusChange(event.status)\n );\n return () => sub.remove();\n }, [onConnectionStatusChange]);\n\n // The entity-change callback is wired as an event listener.\n useEffect(() => {\n if (!onDynamicEntityChange) return;\n const sub = ref.current!.addListener(\n 'onDynamicEntityChange',\n (event: DynamicEntityChange) => onDynamicEntityChange({ nativeEvent: event })\n );\n return () => sub.remove();\n }, [onDynamicEntityChange]);\n\n useUpdateEffect(() => {\n const diffs = getPropsDiffs(prev, layerProps);\n if (diffs.length === 0) return;\n const changed: Record<string, unknown> = {};\n diffs.forEach((key) => {\n changed[key as string] = (layerProps as Record<string, unknown>)[key as string];\n });\n ref.current?.applyProps(changed);\n }, [layerProps]);\n\n // The native ref exposes queryDynamicEntities / pushObservation — hand it over directly.\n useImperativeHandle(handle, () => ref.current!, []);\n\n return null;\n }\n);\n"]}
|
|
@@ -522,6 +522,27 @@ export type OgcFeatureLayerProps = LayerProps & {
|
|
|
522
522
|
};
|
|
523
523
|
/** Connection state of a real-time `DynamicEntityDataSource`. Mirrors `ConnectionStatus`. */
|
|
524
524
|
export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'failed';
|
|
525
|
+
/**
|
|
526
|
+
* The kind of entity lifecycle event emitted by `onDynamicEntityChange`.
|
|
527
|
+
* - `received` — a new or updated entity observation arrived (fires once per entity, not per
|
|
528
|
+
* observation, so attribute-only updates within the same entity are collapsed).
|
|
529
|
+
* - `purged` — the entity was evicted by the data source's purge rules.
|
|
530
|
+
*/
|
|
531
|
+
export type DynamicEntityChangeType = 'received' | 'purged';
|
|
532
|
+
/**
|
|
533
|
+
* Payload for the `<DynamicEntityLayer onDynamicEntityChange>` event.
|
|
534
|
+
* Contains the entity's current attribute snapshot and geometry at the time of the event.
|
|
535
|
+
*/
|
|
536
|
+
export type DynamicEntityChange = {
|
|
537
|
+
/** Whether the entity arrived/updated (`received`) or was evicted (`purged`). */
|
|
538
|
+
changeType: DynamicEntityChangeType;
|
|
539
|
+
/** The entity's unique numeric id (from the data source's `entityIDField`). */
|
|
540
|
+
entityId: number;
|
|
541
|
+
/** The entity's current attribute values (snapshot at event time). */
|
|
542
|
+
attributes: Record<string, unknown>;
|
|
543
|
+
/** The entity's current geometry, or `undefined` when unavailable. */
|
|
544
|
+
geometry?: Geometry;
|
|
545
|
+
};
|
|
525
546
|
/** Track display options for a `<DynamicEntityLayer>` (history of past observations). */
|
|
526
547
|
export type TrackDisplay = {
|
|
527
548
|
/** How many past observations to keep per track. */
|
|
@@ -557,6 +578,14 @@ export type DynamicEntityLayerProps = LayerProps & {
|
|
|
557
578
|
};
|
|
558
579
|
/** Fired as the data source connects / disconnects. */
|
|
559
580
|
onConnectionStatusChange?: (status: ConnectionStatus) => void;
|
|
581
|
+
/**
|
|
582
|
+
* Fired when a dynamic entity is received (new/updated) or purged. High-frequency on busy
|
|
583
|
+
* stream services — only entity lifecycle events are emitted (one per entity arrival or purge),
|
|
584
|
+
* not per-observation attribute updates.
|
|
585
|
+
*/
|
|
586
|
+
onDynamicEntityChange?: (event: {
|
|
587
|
+
nativeEvent: DynamicEntityChange;
|
|
588
|
+
}) => void;
|
|
560
589
|
};
|
|
561
590
|
/** A live dynamic entity returned by `queryDynamicEntities`. */
|
|
562
591
|
export type DynamicEntityInfo = {
|
|
@@ -659,6 +688,54 @@ export type AreaUnit = 'squareMeters' | 'squareKilometers' | 'squareFeet' | 'squ
|
|
|
659
688
|
export type GeodeticCurveType = 'geodesic' | 'loxodrome' | 'greatElliptic' | 'normalSection' | 'shapePreserving';
|
|
660
689
|
/** Join style for `geometryEngine.offset`. Defaults to `mitered`. */
|
|
661
690
|
export type GeometryOffsetType = 'mitered' | 'bevelled' | 'rounded' | 'squared';
|
|
691
|
+
/**
|
|
692
|
+
* Angular unit for geodesic ellipse / sector construction. Defaults to `degrees`.
|
|
693
|
+
* Maps to the native `AngularUnit`.
|
|
694
|
+
*/
|
|
695
|
+
export type AngularUnit = 'degrees' | 'radians';
|
|
696
|
+
/**
|
|
697
|
+
* Output geometry type for `geometryEngine.ellipseGeodesic` / `sectorGeodesic`.
|
|
698
|
+
* Defaults to `polygon`. Maps to the native `GeometryType`.
|
|
699
|
+
*/
|
|
700
|
+
export type GeodesicGeometryType = 'polygon' | 'polyline' | 'multipoint';
|
|
701
|
+
/**
|
|
702
|
+
* Parameters for `geometryEngine.ellipseGeodesic`. Mirrors the native
|
|
703
|
+
* `GeodesicEllipseParameters` (Swift) / `com.arcgismaps.geometry.GeodesicEllipseParameters` (Kotlin).
|
|
704
|
+
*/
|
|
705
|
+
export type GeodesicEllipseParams = {
|
|
706
|
+
/** Center point of the ellipse. */
|
|
707
|
+
center: PointGeometry;
|
|
708
|
+
/** Length of the semi-major axis. */
|
|
709
|
+
semiAxis1Length: number;
|
|
710
|
+
/** Length of the semi-minor axis. */
|
|
711
|
+
semiAxis2Length: number;
|
|
712
|
+
/**
|
|
713
|
+
* Direction of the major axis, in `angularUnit` clockwise from north. Defaults to `0`.
|
|
714
|
+
*/
|
|
715
|
+
axisDirection?: number;
|
|
716
|
+
/** Unit for `axisDirection`. Defaults to `degrees`. */
|
|
717
|
+
angularUnit?: AngularUnit;
|
|
718
|
+
/** Unit for `semiAxis1Length` / `semiAxis2Length`. Defaults to `meters`. */
|
|
719
|
+
linearUnit?: LinearUnit;
|
|
720
|
+
/**
|
|
721
|
+
* Maximum segment length on the output geometry. `0` / omitted lets the SDK choose.
|
|
722
|
+
*/
|
|
723
|
+
maxSegmentLength?: number;
|
|
724
|
+
/** Maximum number of vertices on the output geometry. Defaults to `10` (SDK default). */
|
|
725
|
+
maxPointCount?: number;
|
|
726
|
+
/** Output geometry type. Defaults to `polygon`. */
|
|
727
|
+
geometryType?: GeodesicGeometryType;
|
|
728
|
+
};
|
|
729
|
+
/**
|
|
730
|
+
* Parameters for `geometryEngine.sectorGeodesic`. Extends `GeodesicEllipseParams` with
|
|
731
|
+
* the sector angle and start direction. Mirrors the native `GeodesicSectorParameters`.
|
|
732
|
+
*/
|
|
733
|
+
export type GeodesicSectorParams = GeodesicEllipseParams & {
|
|
734
|
+
/** The angular size of the sector, in `angularUnit`. */
|
|
735
|
+
sectorAngle: number;
|
|
736
|
+
/** The direction from which the sector opens, in `angularUnit` clockwise from north. */
|
|
737
|
+
startDirection: number;
|
|
738
|
+
};
|
|
662
739
|
/** Result of `geometryEngine.geodesicDistance` — distance plus the two azimuths (degrees). */
|
|
663
740
|
export type GeodeticDistanceResult = {
|
|
664
741
|
distance: number;
|
|
@@ -925,6 +1002,16 @@ export type GeoprocessingInput = {
|
|
|
925
1002
|
} | {
|
|
926
1003
|
type: 'features';
|
|
927
1004
|
geometries: Geometry[];
|
|
1005
|
+
}
|
|
1006
|
+
/** An array of homogeneous strings or numbers — maps to `GeoprocessingMultiValue`. */
|
|
1007
|
+
| {
|
|
1008
|
+
type: 'multiValue';
|
|
1009
|
+
values: (string | number)[];
|
|
1010
|
+
}
|
|
1011
|
+
/** A remote file input (URL) — maps to `GeoprocessingDataFile`. */
|
|
1012
|
+
| {
|
|
1013
|
+
type: 'dataFile';
|
|
1014
|
+
url: string;
|
|
928
1015
|
};
|
|
929
1016
|
/** Result of `geoprocessor.execute`. Mirrors the native `GeoprocessingResult`. */
|
|
930
1017
|
export type GeoprocessingResult = {
|
|
@@ -1049,6 +1136,13 @@ export type OfflineTileResult = {
|
|
|
1049
1136
|
/** Local filesystem path of the downloaded tile package (`.tpkx` / `.vtpk`). */
|
|
1050
1137
|
path: string;
|
|
1051
1138
|
};
|
|
1139
|
+
/** Result of `offline.estimateTileCacheSize` — an estimate of the download footprint. */
|
|
1140
|
+
export type TileCacheSizeEstimate = {
|
|
1141
|
+
/** Estimated on-disk size of the tile cache in bytes. */
|
|
1142
|
+
fileSize: number;
|
|
1143
|
+
/** Estimated number of tiles in the tile cache. */
|
|
1144
|
+
tileCount: number;
|
|
1145
|
+
};
|
|
1052
1146
|
/** The kind of geometry a `<GeometryEditor>` sketches. */
|
|
1053
1147
|
export type GeometryEditorType = 'point' | 'multipoint' | 'polyline' | 'polygon' | 'envelope';
|
|
1054
1148
|
/**
|
|
@@ -1198,8 +1292,26 @@ export type DistanceCompositeSceneSymbol = {
|
|
|
1198
1292
|
type: 'distance-composite-scene';
|
|
1199
1293
|
ranges: DistanceSymbolRange[];
|
|
1200
1294
|
};
|
|
1295
|
+
/**
|
|
1296
|
+
* A composite symbol that overlays multiple symbols stacked on top of each other.
|
|
1297
|
+
* Useful for combining a marker with a label, or layering two markers for a ring effect.
|
|
1298
|
+
* Mirrors the native `CompositeSymbol`.
|
|
1299
|
+
*
|
|
1300
|
+
* @example
|
|
1301
|
+
* ```ts
|
|
1302
|
+
* { type: 'composite', symbols: [
|
|
1303
|
+
* { type: 'simple-marker', color: '#fff', size: 18 },
|
|
1304
|
+
* { type: 'simple-marker', color: '#e63946', size: 10 },
|
|
1305
|
+
* ] }
|
|
1306
|
+
* ```
|
|
1307
|
+
*/
|
|
1308
|
+
export type CompositeSymbolType = {
|
|
1309
|
+
type: 'composite';
|
|
1310
|
+
/** The symbols to stack, drawn in order (first = bottom, last = top). */
|
|
1311
|
+
symbols: Symbol[];
|
|
1312
|
+
};
|
|
1201
1313
|
/** Any symbol usable by a `<Graphic>`. Mirrors the native `Symbol` hierarchy. */
|
|
1202
|
-
export type Symbol = SimpleMarkerSymbol | SimpleLineSymbol | SimpleFillSymbol | TextSymbol | SimpleMarkerSceneSymbol | PictureMarkerSymbol | PictureFillSymbol | DistanceCompositeSceneSymbol;
|
|
1314
|
+
export type Symbol = SimpleMarkerSymbol | SimpleLineSymbol | SimpleFillSymbol | TextSymbol | SimpleMarkerSceneSymbol | PictureMarkerSymbol | PictureFillSymbol | DistanceCompositeSceneSymbol | CompositeSymbolType;
|
|
1203
1315
|
/** A renderer that draws every feature/graphic with the same `symbol`. */
|
|
1204
1316
|
export type SimpleRenderer = {
|
|
1205
1317
|
type: 'simple';
|
|
@@ -1307,11 +1419,31 @@ export type SceneProps = {
|
|
|
1307
1419
|
export type SunLighting = 'off' | 'light' | 'lightAndShadows';
|
|
1308
1420
|
/** Atmosphere rendering for a 3D scene view. */
|
|
1309
1421
|
export type AtmosphereEffect = 'off' | 'horizonOnly' | 'realistic';
|
|
1422
|
+
/**
|
|
1423
|
+
* Camera controller for a `<SceneView>`.
|
|
1424
|
+
* - `orbitLocation` — orbits around a fixed target point (`OrbitLocationCameraController`).
|
|
1425
|
+
* - `globe` — free globe navigation (`GlobeCameraController`).
|
|
1426
|
+
*/
|
|
1427
|
+
export type CameraController = {
|
|
1428
|
+
type: 'orbitLocation';
|
|
1429
|
+
/** The point the camera orbits around (WGS84 longitude/latitude, optional altitude). */
|
|
1430
|
+
target: Point;
|
|
1431
|
+
/** Initial camera distance from the target, in meters. */
|
|
1432
|
+
distance: number;
|
|
1433
|
+
} | {
|
|
1434
|
+
type: 'globe';
|
|
1435
|
+
};
|
|
1310
1436
|
/** Props for the `<SceneView>` host component. */
|
|
1311
1437
|
export type SceneViewProps = {
|
|
1312
1438
|
style?: StyleProp<ViewStyle>;
|
|
1313
1439
|
/** Animates the view to this 3D camera whenever the value changes (runtime camera control). */
|
|
1314
1440
|
camera?: Camera;
|
|
1441
|
+
/**
|
|
1442
|
+
* Swaps the scene's camera-control mode. Omit (or pass `null`) to use the SDK default.
|
|
1443
|
+
* - `{ type: 'orbitLocation', target, distance }` — orbit around a fixed point.
|
|
1444
|
+
* - `{ type: 'globe' }` — free globe navigation.
|
|
1445
|
+
*/
|
|
1446
|
+
cameraController?: CameraController | null;
|
|
1315
1447
|
/** Sun lighting mode (shadows). Defaults to `off`. */
|
|
1316
1448
|
sunLighting?: SunLighting;
|
|
1317
1449
|
/** Atmosphere rendering. Defaults to `horizonOnly`. */
|