expo-arcgis 0.1.0 โ 0.1.2
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 +7 -3
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisExtrasModule.kt +87 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisGeometryModule.kt +81 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisMapView.kt +16 -0
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisModule.kt +14 -32
- package/android/src/main/java/expo/modules/arcgis/ExpoArcgisSceneView.kt +16 -0
- package/android/src/main/java/expo/modules/arcgis/GeocoderFunctions.kt +13 -3
- package/android/src/main/java/expo/modules/arcgis/GeometryEngineFunctions.kt +35 -0
- package/android/src/main/java/expo/modules/arcgis/GraphicsOverlayRef.kt +25 -0
- package/android/src/main/java/expo/modules/arcgis/LayerRef.kt +244 -7
- package/android/src/main/java/expo/modules/arcgis/QueryCodec.kt +21 -0
- package/android/src/main/java/expo/modules/arcgis/RouterFunctions.kt +61 -0
- package/android/src/main/java/expo/modules/arcgis/UtilityNetworkRef.kt +24 -0
- package/build/DynamicEntityLayer.d.ts.map +1 -1
- package/build/ExpoArcgis.types.d.ts +252 -8
- package/build/ExpoArcgis.types.d.ts.map +1 -1
- package/build/ExpoArcgis.types.js.map +1 -1
- package/build/ExpoArcgisExtrasModule.d.ts +16 -0
- package/build/ExpoArcgisExtrasModule.d.ts.map +1 -0
- package/build/ExpoArcgisExtrasModule.js +3 -0
- package/build/ExpoArcgisExtrasModule.js.map +1 -0
- package/build/ExpoArcgisGeometryModule.d.ts +18 -2
- package/build/ExpoArcgisGeometryModule.d.ts.map +1 -1
- package/build/ExpoArcgisGeometryModule.js.map +1 -1
- package/build/ExpoArcgisModule.d.ts +23 -4
- package/build/ExpoArcgisModule.d.ts.map +1 -1
- package/build/ExpoArcgisModule.js.map +1 -1
- package/build/FeatureLayer.d.ts.map +1 -1
- package/build/FeatureLayer.js +2 -2
- package/build/FeatureLayer.js.map +1 -1
- package/build/GroupLayer.d.ts +9 -0
- package/build/GroupLayer.d.ts.map +1 -0
- package/build/GroupLayer.js +44 -0
- package/build/GroupLayer.js.map +1 -0
- package/build/auth.d.ts +25 -0
- package/build/auth.d.ts.map +1 -1
- package/build/auth.js +30 -0
- package/build/auth.js.map +1 -1
- package/build/geometryEngine.d.ts +12 -0
- 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 +5 -2
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -2
- package/build/index.js.map +1 -1
- package/build/layers.d.ts +19 -1
- package/build/layers.d.ts.map +1 -1
- package/build/layers.js +21 -0
- package/build/layers.js.map +1 -1
- package/build/router.d.ts +6 -1
- package/build/router.d.ts.map +1 -1
- package/build/router.js +6 -0
- package/build/router.js.map +1 -1
- package/expo-module.config.json +6 -2
- package/ios/ExpoArcgisExtrasModule.swift +85 -0
- package/ios/ExpoArcgisGeometryModule.swift +94 -0
- package/ios/ExpoArcgisMapView.swift +15 -0
- package/ios/ExpoArcgisModule.swift +14 -34
- package/ios/ExpoArcgisSceneView.swift +15 -0
- package/ios/GeocoderFunctions.swift +9 -1
- package/ios/GeometryEngineFunctions.swift +39 -0
- package/ios/GraphicsOverlayRef.swift +20 -0
- package/ios/LayerRef.swift +244 -7
- package/ios/QueryCodec.swift +21 -1
- package/ios/RouterFunctions.swift +57 -0
- package/ios/UtilityNetworkRef.swift +21 -0
- package/package.json +2 -2
- package/src/ExpoArcgis.types.ts +259 -8
- package/src/ExpoArcgisExtrasModule.ts +22 -0
- package/src/ExpoArcgisGeometryModule.ts +31 -1
- package/src/ExpoArcgisModule.ts +29 -3
- package/src/FeatureLayer.tsx +3 -2
- package/src/GroupLayer.tsx +52 -0
- package/src/auth.ts +32 -0
- package/src/geometryEngine.ts +22 -0
- package/src/index.ts +10 -0
- package/src/layers.tsx +49 -0
- package/src/router.ts +16 -1
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ SDK-faithful component API to JS/TS โ `<MapView>` / `<SceneView>` with layers,
|
|
|
6
6
|
editing, query, analysis, geocoding, routing, geoprocessing, utility networks, offline, real-time and
|
|
7
7
|
authentication.
|
|
8
8
|
|
|
9
|
+
๐ **[Documentation & samples โ](https://alex-krassavin.github.io/expo-arcgis)**
|
|
10
|
+
|
|
9
11
|
> **Status โ early / pre-1.0.** The full surface below is implemented and **compile-verified** on both
|
|
10
12
|
> platforms (TypeScript ยท Android `compileDebugKotlin` ยท iOS pod build). On-device **runtime** validation
|
|
11
13
|
> (rendering, network calls, device sensors) should be done in your own app. The API may still change
|
|
@@ -16,14 +18,14 @@ authentication.
|
|
|
16
18
|
| Area | What's covered |
|
|
17
19
|
|---|---|
|
|
18
20
|
| **2D / 3D** | `<MapView>` + `<Map>`; `<SceneView>` + `<Scene>` (surface, camera, web scenes, light/shadows) |
|
|
19
|
-
| **Layers** | Feature, Tile, MapImage, Vector-tile, Raster, WMS, WMTS, KML, Scene, IntegratedMesh, PointCloud, OGC 3D Tiles, WebTiled, OpenStreetMap,
|
|
21
|
+
| **Layers** | Feature, Tile, MapImage, Vector-tile, Raster, WMS, WMTS, KML, Scene, IntegratedMesh, PointCloud, OGC 3D Tiles, WebTiled, OpenStreetMap, WFS, OGC API Features, DynamicEntity (stream), Annotation, Dimension, BuildingScene (3D), OrientedImagery, SubtypeFeature, **Group** (container), **FeatureCollection** (in-memory), **GeoPackage** (local `.gpkg`) |
|
|
20
22
|
| **Graphics** | `<GraphicsOverlay>` + `<Graphic>`, symbols (simple marker/line/fill, text, 3D scene symbol, picture-marker), renderers (simple / unique-value / class-breaks), labels, clustering |
|
|
21
23
|
| **Geometry** | `geometryEngine` (buffer, project, distance, intersect, โฆ), `coordinateFormatter`, codec for all geometry types |
|
|
22
24
|
| **Query** | feature query / count / extent / statistics on a `<FeatureLayer>` ref; `identify` on a view ref |
|
|
23
25
|
| **Editing** | add / update / delete features, `<GeometryEditor>` (tools), feature templates |
|
|
24
26
|
| **Location** | device location, simulated location data source, `onLocationChange` |
|
|
25
27
|
| **Geocoding** | `geocoder.geocode` / `reverseGeocode` / `suggest`, offline `.loc` locators |
|
|
26
|
-
| **Routing** | `router.solveRoute` / directions, travel modes, point barriers, curb approach |
|
|
28
|
+
| **Routing** | `router.solveRoute` / directions, travel modes, point barriers, curb approach; `router.createRouteTracker` turn-by-turn navigation |
|
|
27
29
|
| **Analysis (3D)** | `<AnalysisOverlay>` + `<Viewshed>` / `<LineOfSight>` / `<DistanceMeasurement>` |
|
|
28
30
|
| **Geoprocessing** | `geoprocessor.execute` โ `JobRef` (progress + cancel), typed parameters |
|
|
29
31
|
| **Utility network** | `<UtilityNetwork>` load + trace, named configs, associations, `describeNetwork` |
|
|
@@ -122,7 +124,9 @@ const [hit] = await geocoder.geocode('Los Angeles');
|
|
|
122
124
|
- **Views & models** โ `MapSettings`, `Map`, `Scene`, `MapView`, `SceneView`
|
|
123
125
|
- **Layers** โ `FeatureLayer`, `TileLayer`, `MapImageLayer`, `SceneLayer`, `VectorTileLayer`,
|
|
124
126
|
`IntegratedMeshLayer`, `PointCloudLayer`, `Ogc3DTilesLayer`, `WebTiledLayer`, `OpenStreetMapLayer`,
|
|
125
|
-
`WmsLayer`, `WmtsLayer`, `RasterLayer`, `KmlLayer`, `WfsLayer`, `OgcFeatureLayer`, `DynamicEntityLayer
|
|
127
|
+
`WmsLayer`, `WmtsLayer`, `RasterLayer`, `KmlLayer`, `WfsLayer`, `OgcFeatureLayer`, `DynamicEntityLayer`,
|
|
128
|
+
`AnnotationLayer`, `DimensionLayer`, `BuildingSceneLayer`, `OrientedImageryLayer`, `SubtypeFeatureLayer`,
|
|
129
|
+
`GroupLayer`, `FeatureCollectionLayer`, `GeoPackageLayer`
|
|
126
130
|
- **Graphics & analysis** โ `GraphicsOverlay`, `Graphic`, `AnalysisOverlay`, `Viewshed`, `LineOfSight`,
|
|
127
131
|
`DistanceMeasurement`, `GeometryEditor`, `UtilityNetwork`
|
|
128
132
|
- **Namespaces** โ `geometryEngine`, `coordinateFormatter`, `geocoder`, `router`, `geoprocessor`, `offline`
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
package expo.modules.arcgis
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.functions.Coroutine
|
|
4
|
+
import expo.modules.kotlin.modules.Module
|
|
5
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Third native module, hosting the heavier operational-layer SharedObject classes (currently
|
|
9
|
+
* [FeatureLayerRef]), exposed to JS as `ExpoArcgisExtras`. Split out of [ExpoArcgisGeometryModule]
|
|
10
|
+
* so that no module's `definition()` exceeds the JVM 64 KB method-size limit. SharedObjects are
|
|
11
|
+
* global, so a ref constructed here attaches to a `<MapView>` from the main module fine.
|
|
12
|
+
*/
|
|
13
|
+
class ExpoArcgisExtrasModule : Module() {
|
|
14
|
+
override fun definition() = ModuleDefinition {
|
|
15
|
+
Name("ExpoArcgisExtras")
|
|
16
|
+
|
|
17
|
+
Class(FeatureLayerRef::class) {
|
|
18
|
+
Constructor { props: Map<String, Any?> ->
|
|
19
|
+
FeatureLayerRef(appContext, props).also { it.applyProps(props) }
|
|
20
|
+
}
|
|
21
|
+
Function("applyProps") { ref: FeatureLayerRef, changed: Map<String, Any?> ->
|
|
22
|
+
ref.applyProps(changed)
|
|
23
|
+
}
|
|
24
|
+
AsyncFunction("queryFeatures") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?>? ->
|
|
25
|
+
ref.queryFeatures(query)
|
|
26
|
+
}
|
|
27
|
+
AsyncFunction("queryFeatureCount") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?>? ->
|
|
28
|
+
ref.queryFeatureCount(query)
|
|
29
|
+
}
|
|
30
|
+
AsyncFunction("queryExtent") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?>? ->
|
|
31
|
+
ref.queryExtent(query)
|
|
32
|
+
}
|
|
33
|
+
AsyncFunction("queryStatistics") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?> ->
|
|
34
|
+
ref.queryStatistics(query)
|
|
35
|
+
}
|
|
36
|
+
AsyncFunction("queryFeatureTemplates") Coroutine { ref: FeatureLayerRef ->
|
|
37
|
+
ref.queryFeatureTemplates()
|
|
38
|
+
}
|
|
39
|
+
AsyncFunction("addFeature") Coroutine { ref: FeatureLayerRef, attributes: Map<String, Any?>, geometry: Map<String, Any?>?, apply: Boolean? ->
|
|
40
|
+
ref.addFeature(attributes, geometry, apply)
|
|
41
|
+
}
|
|
42
|
+
AsyncFunction("updateFeature") Coroutine { ref: FeatureLayerRef, objectId: Long, changes: Map<String, Any?>, apply: Boolean? ->
|
|
43
|
+
ref.updateFeature(objectId, changes, apply)
|
|
44
|
+
}
|
|
45
|
+
AsyncFunction("deleteFeature") Coroutine { ref: FeatureLayerRef, objectId: Long, apply: Boolean? ->
|
|
46
|
+
ref.deleteFeature(objectId, apply)
|
|
47
|
+
}
|
|
48
|
+
AsyncFunction("applyEdits") Coroutine { ref: FeatureLayerRef ->
|
|
49
|
+
ref.applyEdits()
|
|
50
|
+
}
|
|
51
|
+
AsyncFunction("undoLocalEdits") Coroutine { ref: FeatureLayerRef ->
|
|
52
|
+
ref.undoLocalEdits()
|
|
53
|
+
}
|
|
54
|
+
AsyncFunction("queryRelatedFeatures") Coroutine { ref: FeatureLayerRef, objectId: Long ->
|
|
55
|
+
ref.queryRelatedFeatures(objectId)
|
|
56
|
+
}
|
|
57
|
+
AsyncFunction("queryAttachments") Coroutine { ref: FeatureLayerRef, objectId: Long ->
|
|
58
|
+
ref.queryAttachments(objectId)
|
|
59
|
+
}
|
|
60
|
+
AsyncFunction("addAttachment") Coroutine { ref: FeatureLayerRef, objectId: Long, name: String, contentType: String, dataBase64: String ->
|
|
61
|
+
ref.addAttachment(objectId, name, contentType, dataBase64)
|
|
62
|
+
}
|
|
63
|
+
AsyncFunction("fetchAttachment") Coroutine { ref: FeatureLayerRef, objectId: Long, attachmentId: Long ->
|
|
64
|
+
ref.fetchAttachment(objectId, attachmentId)
|
|
65
|
+
}
|
|
66
|
+
AsyncFunction("deleteAttachment") Coroutine { ref: FeatureLayerRef, objectId: Long, attachmentId: Long ->
|
|
67
|
+
ref.deleteAttachment(objectId, attachmentId)
|
|
68
|
+
}
|
|
69
|
+
AsyncFunction("updateAttachment") Coroutine { ref: FeatureLayerRef, objectId: Long, attachmentId: Long, name: String, contentType: String, dataBase64: String ->
|
|
70
|
+
ref.updateAttachment(objectId, attachmentId, name, contentType, dataBase64)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Turn-by-turn navigation โ solve a route and track device locations against it.
|
|
75
|
+
AsyncFunction("createRouteTracker") Coroutine { stops: List<Map<String, Any?>>, params: Map<String, Any?> ->
|
|
76
|
+
createRouteTracker(appContext, stops, params)
|
|
77
|
+
}
|
|
78
|
+
Class(RouteTrackerRef::class) {
|
|
79
|
+
AsyncFunction("trackLocation") Coroutine { ref: RouteTrackerRef, location: Map<String, Any?> ->
|
|
80
|
+
ref.trackLocation(location)
|
|
81
|
+
}
|
|
82
|
+
AsyncFunction("switchToNextDestination") Coroutine { ref: RouteTrackerRef ->
|
|
83
|
+
ref.switchToNextDestination()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package expo.modules.arcgis
|
|
2
2
|
|
|
3
|
+
import com.arcgismaps.ArcGISEnvironment
|
|
4
|
+
import com.arcgismaps.httpcore.authentication.ArcGISCredentialStore
|
|
3
5
|
import expo.modules.kotlin.functions.Coroutine
|
|
4
6
|
import expo.modules.kotlin.modules.Module
|
|
5
7
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
@@ -30,6 +32,12 @@ class ExpoArcgisGeometryModule : Module() {
|
|
|
30
32
|
Function("geClip", ::geClip)
|
|
31
33
|
Function("geCut", ::geCut)
|
|
32
34
|
Function("geConvexHull", ::geConvexHull)
|
|
35
|
+
Function("geLabelPoint", ::geLabelPoint)
|
|
36
|
+
Function("geNormalizeCentralMeridian", ::geNormalizeCentralMeridian)
|
|
37
|
+
Function("geReshape", ::geReshape)
|
|
38
|
+
Function("geIntersections", ::geIntersections)
|
|
39
|
+
Function("geExtend", ::geExtend)
|
|
40
|
+
Function("geAutoComplete", ::geAutoComplete)
|
|
33
41
|
Function("geBoundary", ::geBoundary)
|
|
34
42
|
Function("geSimplify", ::geSimplify)
|
|
35
43
|
Function("geDensify", ::geDensify)
|
|
@@ -90,6 +98,79 @@ class ExpoArcgisGeometryModule : Module() {
|
|
|
90
98
|
AsyncFunction("cancel") Coroutine { ref: JobRef -> ref.cancel() }
|
|
91
99
|
}
|
|
92
100
|
|
|
101
|
+
// Extended operational layers from a service URL โ registered here (not in the main module) to
|
|
102
|
+
// keep ExpoArcgisModule's definition under the JVM 64 KB method limit. SharedObjects are global,
|
|
103
|
+
// so a layer constructed via this module attaches to a `<MapView>` from the main module fine.
|
|
104
|
+
Class(AnnotationLayerRef::class) {
|
|
105
|
+
Constructor { props: Map<String, Any?> ->
|
|
106
|
+
AnnotationLayerRef(appContext, props["url"] as? String ?: "").also { it.applyProps(props) }
|
|
107
|
+
}
|
|
108
|
+
Function("applyProps") { ref: AnnotationLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
109
|
+
}
|
|
110
|
+
Class(DimensionLayerRef::class) {
|
|
111
|
+
Constructor { props: Map<String, Any?> ->
|
|
112
|
+
DimensionLayerRef(appContext, props["url"] as? String ?: "").also { it.applyProps(props) }
|
|
113
|
+
}
|
|
114
|
+
Function("applyProps") { ref: DimensionLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
115
|
+
}
|
|
116
|
+
Class(BuildingSceneLayerRef::class) {
|
|
117
|
+
Constructor { props: Map<String, Any?> ->
|
|
118
|
+
BuildingSceneLayerRef(appContext, props["url"] as? String ?: "").also { it.applyProps(props) }
|
|
119
|
+
}
|
|
120
|
+
Function("applyProps") { ref: BuildingSceneLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
121
|
+
}
|
|
122
|
+
Class(OrientedImageryLayerRef::class) {
|
|
123
|
+
Constructor { props: Map<String, Any?> ->
|
|
124
|
+
OrientedImageryLayerRef(appContext, props["url"] as? String ?: "").also { it.applyProps(props) }
|
|
125
|
+
}
|
|
126
|
+
Function("applyProps") { ref: OrientedImageryLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
127
|
+
}
|
|
128
|
+
Class(SubtypeFeatureLayerRef::class) {
|
|
129
|
+
Constructor { props: Map<String, Any?> ->
|
|
130
|
+
SubtypeFeatureLayerRef(appContext, props["url"] as? String ?: "").also { it.applyProps(props) }
|
|
131
|
+
}
|
|
132
|
+
Function("applyProps") { ref: SubtypeFeatureLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
133
|
+
}
|
|
134
|
+
// GroupLayer โ a container layer that hosts its own child layers (addLayer/removeLayer).
|
|
135
|
+
Class(GroupLayerRef::class) {
|
|
136
|
+
Constructor { props: Map<String, Any?> ->
|
|
137
|
+
GroupLayerRef(appContext).also { it.applyProps(props) }
|
|
138
|
+
}
|
|
139
|
+
Function("applyProps") { ref: GroupLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
140
|
+
Function("addLayer") { ref: GroupLayerRef, layer: LayerRef -> ref.addLayer(layer) }
|
|
141
|
+
Function("removeLayer") { ref: GroupLayerRef, layer: LayerRef -> ref.removeLayer(layer) }
|
|
142
|
+
}
|
|
143
|
+
// FeatureLayerRef moved to the third module (ExpoArcgisExtras) to keep this module's
|
|
144
|
+
// definition() under the 64 KB limit. SharedObjects are global, so it stays cross-module.
|
|
145
|
+
// In-memory FeatureCollectionLayer โ built from a client-side schema + features (no service).
|
|
146
|
+
Class(FeatureCollectionLayerRef::class) {
|
|
147
|
+
Constructor { props: Map<String, Any?> ->
|
|
148
|
+
FeatureCollectionLayerRef(appContext, props).also { it.applyProps(props) }
|
|
149
|
+
}
|
|
150
|
+
Function("applyProps") { ref: FeatureCollectionLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
151
|
+
}
|
|
152
|
+
// GeoPackage layer โ async-loads a local .gpkg, picks the feature table, wraps it in a FeatureLayer.
|
|
153
|
+
Class(GeoPackageLayerRef::class) {
|
|
154
|
+
Constructor { props: Map<String, Any?> ->
|
|
155
|
+
GeoPackageLayerRef(
|
|
156
|
+
appContext,
|
|
157
|
+
props["path"] as? String ?: "",
|
|
158
|
+
props["tableName"] as? String,
|
|
159
|
+
).also { it.applyProps(props) }
|
|
160
|
+
}
|
|
161
|
+
Function("applyProps") { ref: GeoPackageLayerRef, changed: Map<String, Any?> -> ref.applyProps(changed) }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Auth โ persistent credential store (survives app restarts via Android encrypted storage).
|
|
165
|
+
// Registered here (not in the main module) because the main module is at the JVM 64 KB limit.
|
|
166
|
+
AsyncFunction("enablePersistentCredentialStore") Coroutine { ->
|
|
167
|
+
val store = ArcGISCredentialStore.createWithPersistence().getOrThrow()
|
|
168
|
+
ArcGISEnvironment.authenticationManager.arcGISCredentialStore = store
|
|
169
|
+
}
|
|
170
|
+
AsyncFunction("clearCredentialStore") Coroutine { ->
|
|
171
|
+
ArcGISEnvironment.authenticationManager.arcGISCredentialStore.removeAll()
|
|
172
|
+
}
|
|
173
|
+
|
|
93
174
|
// Offline โ take maps/data offline, exposed as the JS `offline` namespace.
|
|
94
175
|
AsyncFunction("generateOfflineMap") Coroutine { portalItemId: String, areaOfInterest: Map<String, Any?>, downloadName: String ->
|
|
95
176
|
generateOfflineMap(appContext, appContext.reactContext?.filesDir, portalItemId, areaOfInterest, downloadName)
|
|
@@ -196,6 +196,22 @@ class ExpoArcgisMapView(context: Context, appContext: AppContext) : ExpoView(con
|
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/** Identifies popups under a screen point โ evaluates each and returns `{ title, fields }`. */
|
|
200
|
+
fun identifyPopups(screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise) {
|
|
201
|
+
val x = (screenPoint["x"] as? Number)?.toDouble() ?: 0.0
|
|
202
|
+
val y = (screenPoint["y"] as? Number)?.toDouble() ?: 0.0
|
|
203
|
+
val tolerance = (options?.get("tolerance") as? Number)?.toDouble() ?: 12.0
|
|
204
|
+
val maxResults = (options?.get("maxResults") as? Number)?.toInt() ?: 1
|
|
205
|
+
scope.launch {
|
|
206
|
+
try {
|
|
207
|
+
val results = mapView.identifyLayers(ScreenCoordinate(x, y), tolerance, false, maxResults).getOrThrow()
|
|
208
|
+
promise.resolve(serializePopups(results))
|
|
209
|
+
} catch (e: Exception) {
|
|
210
|
+
promise.reject("IDENTIFY_ERROR", e.message ?: "Identify failed", e)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
199
215
|
/** Retries loading the map (Loadable pattern) โ useful after a network outage. Re-emits the result. */
|
|
200
216
|
fun retryLoad(promise: Promise) {
|
|
201
217
|
val map = mapView.map ?: run { promise.resolve(null); return }
|
|
@@ -96,38 +96,8 @@ class ExpoArcgisModule : Module() {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// Operational layers โ SharedObjects the JS <FeatureLayer>/<TileLayer> construct.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
FeatureLayerRef(appContext, props).also { it.applyProps(props) }
|
|
102
|
-
}
|
|
103
|
-
Function("applyProps") { ref: FeatureLayerRef, changed: Map<String, Any?> ->
|
|
104
|
-
ref.applyProps(changed)
|
|
105
|
-
}
|
|
106
|
-
AsyncFunction("queryFeatures") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?>? ->
|
|
107
|
-
ref.queryFeatures(query)
|
|
108
|
-
}
|
|
109
|
-
AsyncFunction("queryFeatureCount") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?>? ->
|
|
110
|
-
ref.queryFeatureCount(query)
|
|
111
|
-
}
|
|
112
|
-
AsyncFunction("queryExtent") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?>? ->
|
|
113
|
-
ref.queryExtent(query)
|
|
114
|
-
}
|
|
115
|
-
AsyncFunction("queryStatistics") Coroutine { ref: FeatureLayerRef, query: Map<String, Any?> ->
|
|
116
|
-
ref.queryStatistics(query)
|
|
117
|
-
}
|
|
118
|
-
AsyncFunction("queryFeatureTemplates") Coroutine { ref: FeatureLayerRef ->
|
|
119
|
-
ref.queryFeatureTemplates()
|
|
120
|
-
}
|
|
121
|
-
AsyncFunction("addFeature") Coroutine { ref: FeatureLayerRef, attributes: Map<String, Any?>, geometry: Map<String, Any?>? ->
|
|
122
|
-
ref.addFeature(attributes, geometry)
|
|
123
|
-
}
|
|
124
|
-
AsyncFunction("updateFeature") Coroutine { ref: FeatureLayerRef, objectId: Long, changes: Map<String, Any?> ->
|
|
125
|
-
ref.updateFeature(objectId, changes)
|
|
126
|
-
}
|
|
127
|
-
AsyncFunction("deleteFeature") Coroutine { ref: FeatureLayerRef, objectId: Long ->
|
|
128
|
-
ref.deleteFeature(objectId)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
99
|
+
// FeatureLayerRef is registered on the ExpoArcgisGeometry module to keep this module's
|
|
100
|
+
// definition() under the Android JVM 64 KB method-size limit (SharedObjects cross modules).
|
|
131
101
|
|
|
132
102
|
Class(TiledLayerRef::class) {
|
|
133
103
|
Constructor { props: Map<String, Any?> ->
|
|
@@ -358,6 +328,10 @@ class ExpoArcgisModule : Module() {
|
|
|
358
328
|
AsyncFunction("associations") Coroutine { ref: UtilityNetworkRef, tableName: String, whereClause: String ->
|
|
359
329
|
ref.associations(tableName, whereClause)
|
|
360
330
|
}
|
|
331
|
+
AsyncFunction("getState") Coroutine { ref: UtilityNetworkRef -> ref.getState() }
|
|
332
|
+
Function("validateNetworkTopology") { ref: UtilityNetworkRef, extent: Map<String, Any?> ->
|
|
333
|
+
ref.validateNetworkTopology(extent)
|
|
334
|
+
}
|
|
361
335
|
}
|
|
362
336
|
|
|
363
337
|
// Interactive GeometryEditor โ bound to a <MapView> for sketching; emits onGeometryChange.
|
|
@@ -401,6 +375,10 @@ class ExpoArcgisModule : Module() {
|
|
|
401
375
|
view.identify(screenPoint, options, promise)
|
|
402
376
|
}
|
|
403
377
|
|
|
378
|
+
AsyncFunction("identifyPopups") { view: ExpoArcgisMapView, screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise ->
|
|
379
|
+
view.identifyPopups(screenPoint, options, promise)
|
|
380
|
+
}
|
|
381
|
+
|
|
404
382
|
AsyncFunction("retryLoad") { view: ExpoArcgisMapView, promise: Promise ->
|
|
405
383
|
view.retryLoad(promise)
|
|
406
384
|
}
|
|
@@ -446,6 +424,10 @@ class ExpoArcgisModule : Module() {
|
|
|
446
424
|
AsyncFunction("identify") { view: ExpoArcgisSceneView, screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise ->
|
|
447
425
|
view.identify(screenPoint, options, promise)
|
|
448
426
|
}
|
|
427
|
+
|
|
428
|
+
AsyncFunction("identifyPopups") { view: ExpoArcgisSceneView, screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise ->
|
|
429
|
+
view.identifyPopups(screenPoint, options, promise)
|
|
430
|
+
}
|
|
449
431
|
}
|
|
450
432
|
}
|
|
451
433
|
}
|
|
@@ -101,6 +101,22 @@ class ExpoArcgisSceneView(context: Context, appContext: AppContext) : ExpoView(c
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
/** Identifies popups under a screen point โ evaluates each and returns `{ title, fields }`. */
|
|
105
|
+
fun identifyPopups(screenPoint: Map<String, Any?>, options: Map<String, Any?>?, promise: Promise) {
|
|
106
|
+
val x = (screenPoint["x"] as? Number)?.toDouble() ?: 0.0
|
|
107
|
+
val y = (screenPoint["y"] as? Number)?.toDouble() ?: 0.0
|
|
108
|
+
val tolerance = (options?.get("tolerance") as? Number)?.toDouble() ?: 12.0
|
|
109
|
+
val maxResults = (options?.get("maxResults") as? Number)?.toInt() ?: 1
|
|
110
|
+
scope.launch {
|
|
111
|
+
try {
|
|
112
|
+
val results = sceneView.identifyLayers(ScreenCoordinate(x, y), tolerance, false, maxResults).getOrThrow()
|
|
113
|
+
promise.resolve(serializePopups(results))
|
|
114
|
+
} catch (e: Exception) {
|
|
115
|
+
promise.reject("IDENTIFY_ERROR", e.message ?: "Identify failed", e)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
104
120
|
/** Retries loading the scene (Loadable pattern) โ useful after a network outage. Re-emits the result. */
|
|
105
121
|
fun retryLoad(promise: Promise) {
|
|
106
122
|
val scene = sceneView.scene ?: run { promise.resolve(null); return }
|
|
@@ -25,9 +25,19 @@ private fun locatorTask(params: Map<String, Any?>): LocatorTask {
|
|
|
25
25
|
return locators.getOrPut(url) { LocatorTask(url) }
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
internal suspend fun geocode(searchText: String, params: Map<String, Any?>): List<Map<String, Any?>>
|
|
29
|
-
locatorTask(params)
|
|
30
|
-
|
|
28
|
+
internal suspend fun geocode(searchText: String, params: Map<String, Any?>): List<Map<String, Any?>> {
|
|
29
|
+
val locator = locatorTask(params)
|
|
30
|
+
val parameters = buildGeocodeParameters(params)
|
|
31
|
+
@Suppress("UNCHECKED_CAST")
|
|
32
|
+
val searchValues = (params["searchValues"] as? Map<*, *>)
|
|
33
|
+
?.mapNotNull { (k, v) -> if (k is String && v is String) k to v else null }
|
|
34
|
+
?.toMap()
|
|
35
|
+
return if (!searchValues.isNullOrEmpty()) {
|
|
36
|
+
locator.geocode(searchValues, parameters).getOrThrow()
|
|
37
|
+
} else {
|
|
38
|
+
locator.geocode(searchText, parameters).getOrThrow()
|
|
39
|
+
}.map { serializeGeocodeResult(it) }
|
|
40
|
+
}
|
|
31
41
|
|
|
32
42
|
internal suspend fun reverseGeocode(point: Map<String, Any?>, params: Map<String, Any?>): List<Map<String, Any?>> {
|
|
33
43
|
val location = geometryFromDict(point) as? Point ?: return emptyList()
|
|
@@ -3,7 +3,9 @@ package expo.modules.arcgis
|
|
|
3
3
|
import com.arcgismaps.geometry.Envelope
|
|
4
4
|
import com.arcgismaps.geometry.Geometry
|
|
5
5
|
import com.arcgismaps.geometry.GeometryEngine
|
|
6
|
+
import com.arcgismaps.geometry.Multipart
|
|
6
7
|
import com.arcgismaps.geometry.Point
|
|
8
|
+
import com.arcgismaps.geometry.Polygon
|
|
7
9
|
import com.arcgismaps.geometry.Polyline
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -104,6 +106,39 @@ internal fun geCut(g: Map<String, Any?>, cutter: Map<String, Any?>): List<Map<St
|
|
|
104
106
|
internal fun geConvexHull(g: Map<String, Any?>): Map<String, Any?>? =
|
|
105
107
|
parseGeo(g)?.let { encode(GeometryEngine.convexHullOrNull(it)) }
|
|
106
108
|
|
|
109
|
+
internal fun geLabelPoint(g: Map<String, Any?>): Map<String, Any?>? =
|
|
110
|
+
(parseGeo(g) as? Polygon)?.let { encode(GeometryEngine.labelPointOrNull(it)) }
|
|
111
|
+
|
|
112
|
+
internal fun geNormalizeCentralMeridian(g: Map<String, Any?>): Map<String, Any?>? =
|
|
113
|
+
parseGeo(g)?.let { encode(GeometryEngine.normalizeCentralMeridian(it)) }
|
|
114
|
+
|
|
115
|
+
internal fun geReshape(g: Map<String, Any?>, reshaper: Map<String, Any?>): Map<String, Any?>? {
|
|
116
|
+
val multipart = parseGeo(g) as? Multipart ?: return null
|
|
117
|
+
val line = parseGeo(reshaper) as? Polyline ?: return null
|
|
118
|
+
return encode(GeometryEngine.reshape(multipart, line))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
internal fun geIntersections(a: Map<String, Any?>, b: Map<String, Any?>): List<Map<String, Any?>> {
|
|
122
|
+
val g1 = parseGeo(a) ?: return emptyList()
|
|
123
|
+
val g2 = parseGeo(b) ?: return emptyList()
|
|
124
|
+
return GeometryEngine.tryIntersections(g1, g2).mapNotNull { encode(it) }
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
internal fun geExtend(p: Map<String, Any?>, extender: Map<String, Any?>): Map<String, Any?>? {
|
|
128
|
+
val polyline = parseGeo(p) as? Polyline ?: return null
|
|
129
|
+
val ext = parseGeo(extender) as? Polyline ?: return null
|
|
130
|
+
return encode(GeometryEngine.extend(polyline, ext, emptySet()))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
internal fun geAutoComplete(
|
|
134
|
+
existing: List<Map<String, Any?>>,
|
|
135
|
+
boundaries: List<Map<String, Any?>>,
|
|
136
|
+
): List<Map<String, Any?>> {
|
|
137
|
+
val polygons = existing.mapNotNull { parseGeo(it) as? Polygon }
|
|
138
|
+
val lines = boundaries.mapNotNull { parseGeo(it) as? Polyline }
|
|
139
|
+
return GeometryEngine.tryAutoComplete(polygons, lines).mapNotNull { encode(it) }
|
|
140
|
+
}
|
|
141
|
+
|
|
107
142
|
internal fun geBoundary(g: Map<String, Any?>): Map<String, Any?>? =
|
|
108
143
|
parseGeo(g)?.let { encode(GeometryEngine.boundaryOrNull(it)) }
|
|
109
144
|
|
|
@@ -15,8 +15,11 @@ import com.arcgismaps.mapping.symbology.SimpleFillSymbol
|
|
|
15
15
|
import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle
|
|
16
16
|
import com.arcgismaps.mapping.symbology.SimpleLineSymbol
|
|
17
17
|
import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle
|
|
18
|
+
import com.arcgismaps.mapping.symbology.DistanceCompositeSceneSymbol
|
|
19
|
+
import com.arcgismaps.mapping.symbology.DistanceSymbolRange
|
|
18
20
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSceneSymbol
|
|
19
21
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSceneSymbolStyle
|
|
22
|
+
import com.arcgismaps.mapping.symbology.PictureFillSymbol
|
|
20
23
|
import com.arcgismaps.mapping.symbology.PictureMarkerSymbol
|
|
21
24
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol
|
|
22
25
|
import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle
|
|
@@ -188,6 +191,28 @@ private fun buildSymbol(s: Map<*, *>): Symbol? = when (s["type"]) {
|
|
|
188
191
|
(s["height"] as? Number)?.toFloat()?.let { height = it }
|
|
189
192
|
}
|
|
190
193
|
}
|
|
194
|
+
"picture-fill" -> (s["url"] as? String)?.let { url ->
|
|
195
|
+
PictureFillSymbol(url).apply {
|
|
196
|
+
(s["width"] as? Number)?.toFloat()?.let { width = it }
|
|
197
|
+
(s["height"] as? Number)?.toFloat()?.let { height = it }
|
|
198
|
+
outline = outlineOf(s["outline"])
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
"distance-composite-scene" -> {
|
|
202
|
+
val composite = DistanceCompositeSceneSymbol()
|
|
203
|
+
val rangeList = s["ranges"] as? List<*> ?: emptyList<Any>()
|
|
204
|
+
for (rd in rangeList) {
|
|
205
|
+
val rdMap = rd as? Map<*, *> ?: continue
|
|
206
|
+
val sym = (rdMap["symbol"] as? Map<*, *>)?.let(::buildSymbol) ?: continue
|
|
207
|
+
val range = DistanceSymbolRange(
|
|
208
|
+
sym,
|
|
209
|
+
(rdMap["minDistance"] as? Number)?.toDouble(),
|
|
210
|
+
(rdMap["maxDistance"] as? Number)?.toDouble(),
|
|
211
|
+
)
|
|
212
|
+
composite.ranges.add(range)
|
|
213
|
+
}
|
|
214
|
+
composite
|
|
215
|
+
}
|
|
191
216
|
else -> null
|
|
192
217
|
}
|
|
193
218
|
|