Hello,
I need to load some FeatureLayers and FeatureTables stored in a Geodatbase saved on the device, to my scene,
but when I try to add them to my scene I have an Exception that says "Object is already owned", but I have cleared
the collections before trying add and I don't understand why I have this error.
My code to load the data is:
try {
var geoDb = Geodatabase(fullPath)
geoDb.addDoneLoadingListener {
try {
if(geoDb.loadStatus == LoadStatus.LOADED){
for(geoDbFeatureTable in geoDb.geodatabaseFeatureTables){
val featureLayer = FeatureLayer(geoDbFeatureTable)
//featureTables.add(geoDbFeature)
//val featureLayer = FeatureLayer(geoDbFeature)
featureTables.add(geoDbFeatureTable)
try{
FeatureLayerUtils().setGraphicLayer(featureLayer, layer)
featureLayers.add(featureLayer)
}
catch (e: InterruptedException){
Log.e("LOGERROR", "Error identifying resuts: " + e.message)
}
catch (e : ExecutionException){
Log.e("LOGERROR", "Error identifying results: " + e.message)
}
// Aggiornamento del Bounding Box
FeatureLayerUtils().updateBoundingBox(featureLayer, layer, arSceneView.originCamera.location)
featureLayer.sceneProperties.altitudeOffset = layer.defaultObjectY.toDouble()
featureLayer.sceneProperties.surfacePlacement = LayerSceneProperties.SurfacePlacement.RELATIVE
featureLayer.isVisible = layer.visible
featureLayersPair[layer] = featureLayer
featureLayers.add(featureLayer)
layerBoundingBoxPair[layer] = FeatureLayerUtils().createBoundingBox(arSceneView.originCamera.location, layer.maxDistanceFromOrigin.toDouble())
}
try {
arSceneView.sceneView.scene.tables.clear()
arSceneView.sceneView.scene.operationalLayers.clear()
arSceneView.sceneView.scene.tables.addAll(featureTables)
arSceneView.sceneView.scene.operationalLayers.addAll(featureLayers)
viewModel.setTables(featureLayers)
val tablesToFilter: Spinner = binding.assets.findViewById(R.id.tablesToFilter)
tablesToFilter.adapter = AssetSpinnerAdapter(applicationContext, featureLayers)
val featureLayer: FeatureLayer = featureLayers[0]
viewModel.setTableFilters(FeatureLayerUtils().getFeatureLayerStringFields(featureLayer))
val fieldFilters: Spinner = binding.assets.findViewById(R.id.fieldFilters)
val editTextSearchAsset: EditText = binding.assets.findViewById(R.id.editTextSearchAsset)
if (viewModel.uiState.value.tableFilters.isEmpty()) {
fieldFilters.visibility = View.GONE
editTextSearchAsset.visibility = View.GONE
} else {
fieldFilters.adapter = AssetFilterSpinnerAdapter(applicationContext, viewModel.uiState.value.tableFilters)
fieldFilters.visibility = View.VISIBLE
editTextSearchAsset.visibility = View.VISIBLE
}
}
catch (e : Exception){
Log.d(TAG, "Error: " + e.message)
}
}
}
catch (e : Exception){
Log.d(TAG, "Error")
}
}
geoDb.loadAsync()
}
catch (e : Error){
Log.d(TAG, "Error")
}
Thanks yo all for the support!
For performance reasons, where objects have a strong dependent relationship (e.g. a FeatureLayer is dependent on (or "owns") a FeatureTable), that is limited to a single "owner" at a time.
It looks like you do not need this line:
arSceneView.sceneView.scene.tables.addAll(featureTables)
You are taking the feature tables that you have already created feature layers for (i.e. each FeatureTable is already "owned" by a FeatureLayer) and trying to add them to the Scene's tables collection. This will try to set the Scene as the table's owner, but the layer is already the owner.
The scene's tables property is for standalone tables that are not used by a layer (perhaps they're related to features and/or don't have geometry).
Hi Nicholas,
thank you!
I have made some changes in the loading method and now I have this:
var geoDb = Geodatabase(fullPath)
geoDb.addDoneLoadingListener {
try {
if(geoDb.loadStatus == LoadStatus.LOADED){
val fLayers = geoDb.geodatabaseFeatureTables.map { featureTable -> FeatureLayer(featureTable) }
arSceneView.sceneView.scene.operationalLayers.addAll(fLayers)
}
}
catch (e : Exception){
Log.d(TAG, "Error")
}
}
geoDb.loadAsync()
but on the map I don't see anything.
The geodatabase is generated from a FeatureService that show some polygon on the map and if I load from remote I see al polygons, but loading from GeoDatabase not show anything.
To generate my Geodatabase from the remote service I use this code:
val generateGeoBdJob = geoDbSyncTask.generateGeodatabase(generatedParams, geoDBPath)
generateGeoBdJob.addStatusChangedListener{
if(generateGeoBdJob.status == Job.Status.SUCCEEDED)
{
Log.d(TAG, "Local Data successfully created for $serviceName on internal storage")
//response.add("Local Data successfully created for $serviceName on internal storage")
val result = generateGeoBdJob.result
if(result != null)
{
val geoDBPath = result.path
Log.d("TAG", "Current path of Geo Database: $geoDBPath")
// TODO: Show a message to the user
}
}
else if(generateGeoBdJob.status == Job.Status.FAILED)
{
val message : String = "Local Data for $serviceName not created."
Log.d(TAG, message)
}
// Remove this job from list
geoDbJobList.remove(generateGeoBdJob)
// Check if this job is the last in the list and hide the loader
if(geoDbJobList.isEmpty())
{
stopLoading()
}
}
generateGeoBdJob.start()