diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISColorUnpacker.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISColorUnpacker.cs index 1f9046db3..06d700ae1 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISColorUnpacker.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/HostApp/ArcGISColorUnpacker.cs @@ -1,5 +1,4 @@ using ArcGIS.Desktop.Mapping; -using Speckle.Converters.ArcGIS3.Extensions; using Speckle.Sdk.Models.Proxies; namespace Speckle.Connectors.ArcGIS.HostApp; @@ -121,10 +120,8 @@ public void StoreRenderer(ADM.LasDatasetLayer lasLayer) /// POC: logic probably can be combined with ProcessFeatureLayerColor. /// /// - public void ProcessLasLayerColor(ACD.Analyst3D.LasPoint point) + public void ProcessLasLayerColor(ACD.Analyst3D.LasPoint point, string pointApplicationId) { - string pointApplicationId = point.GetSpeckleApplicationId(); - // get the color from the renderer and point AC.CIM.CIMColor? color; switch (StoredTinRenderer) @@ -180,10 +177,8 @@ ACD.Analyst3D.LasPoint point /// /// /// - public void ProcessFeatureLayerColor(ACD.Row row) + public void ProcessFeatureLayerColor(ACD.Row row, string rowApplicationId) { - string rowApplicationId = row.GetSpeckleApplicationId(); - // if stored color is not null, this means the renderer was a simple renderer that applies to the entire layer, and was already created. // just add the row application id to the color proxy. if (StoredColor is int existingColorProxyId) diff --git a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs index cfd59211c..8b77cee0d 100644 --- a/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs +++ b/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Send/ArcGISRootObjectBuilder.cs @@ -1,3 +1,4 @@ +using ArcGIS.Core.Data.Raster; using ArcGIS.Core.Geometry; using ArcGIS.Desktop.Framework.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -12,6 +13,7 @@ using Speckle.Converters.ArcGIS3; using Speckle.Converters.Common; using Speckle.Sdk; +using Speckle.Sdk.Common.Exceptions; using Speckle.Sdk.Logging; using Speckle.Sdk.Models; using Speckle.Sdk.Models.Collections; @@ -212,11 +214,15 @@ await QueuedTask // Same IDisposable issue appears to happen on Row class too. Docs say it should always be disposed of manually by the caller. using (ACD.Row row = rowCursor.Current) { + // get application id. test for subtypes before defaulting to base type. Base converted = _rootToSpeckleConverter.Convert(row); + string applicationId = GetSpeckleApplicationId(featureLayer, row); + converted.applicationId = applicationId; + convertedObjects.Add(converted); // process the object color - _colorUnpacker.ProcessFeatureLayerColor(row); + _colorUnpacker.ProcessFeatureLayerColor(row, applicationId); } } } @@ -233,7 +239,10 @@ private async Task> ConvertRasterLayerObjectsAsync(ADM.RasterLayer ra await QueuedTask .Run(() => { - Base converted = _rootToSpeckleConverter.Convert(rasterLayer.GetRaster()); + Raster raster = rasterLayer.GetRaster(); + Base converted = _rootToSpeckleConverter.Convert(raster); + string applicationId = GetSpeckleApplicationId(rasterLayer, raster); + converted.applicationId = applicationId; convertedObjects.Add(converted); }) .ConfigureAwait(false); @@ -262,10 +271,12 @@ await QueuedTask using (ACD.Analyst3D.LasPoint pt = ptCursor.Current) { Base converted = _rootToSpeckleConverter.Convert(pt); + string applicationId = GetSpeckleApplicationId(lasDatasetLayer, pt); + converted.applicationId = applicationId; convertedObjects.Add(converted); // process the object color - _colorUnpacker.ProcessLasLayerColor(pt); + _colorUnpacker.ProcessLasLayerColor(pt, applicationId); } } } @@ -274,9 +285,29 @@ await QueuedTask } catch (ACD.Exceptions.TinException ex) { - throw new SpeckleException($"3D analyst extension is not enabled for .las layer operations", ex); + throw new SpeckleException("3D analyst extension is not enabled for .las layer operations", ex); } return convertedObjects; } + + /// + /// Retrieves the Speckle application id for Features as a concatenation of the layer URI (applicationId) + /// and the row OID (index of row in layer) or point OID for LasDatasets. + /// + /// Throws when this is *not* called on MCT. Use QueuedTask.Run. + public string GetSpeckleApplicationId(ADM.Layer layer, AC.CoreObjectsBase coreObject) + { + if (coreObject is ACD.Row row) + { + return $"{layer.URI}_{row.GetObjectID()}"; + } + + if (coreObject is ACD.Analyst3D.LasPoint point) + { + return $"{layer.URI}_{point.PointID}"; + } + + throw new ConversionNotSupportedException($"Conversion not supported for objects of type '{coreObject.GetType()}'"); + } } diff --git a/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Extensions/SpeckleApplicationIdExtensions.cs b/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Extensions/SpeckleApplicationIdExtensions.cs deleted file mode 100644 index 10a0f2aae..000000000 --- a/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Extensions/SpeckleApplicationIdExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Speckle.Converters.ArcGIS3.Extensions; - -public static class SpeckleApplicationIdExtensions -{ - /// - /// Retrieves the Speckle application id for rows as a concatenation of the handle (generated from layer) and the row OID (index of row in layer) - /// - /// Throws when this is *not* called on MCT. Use QueuedTask.Run. - public static string GetSpeckleApplicationId(this ACD.Row row) => $"{row.Handle}_{row.GetObjectID()}"; - - /// - /// Retrieves the Speckle application id for las points as a concatenation of the handle (generated from layer) and the point OID (record number of point in las layer) - /// - /// Throws when this is *not* called on MCT. Use QueuedTask.Run. - public static string GetSpeckleApplicationId(this ACD.Analyst3D.LasPoint point) => $"{point.Handle}_{point.PointID}"; - - /// - /// Retrieves the Speckle application id for core objects bases as the handle (generated from layer) - /// - public static string GetSpeckleApplicationId(this AC.CoreObjectsBase coreObject) => $"{coreObject.Handle}"; -} diff --git a/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Speckle.Converters.ArcGIS3.csproj b/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Speckle.Converters.ArcGIS3.csproj index 579e00a68..adbee8c0b 100644 --- a/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Speckle.Converters.ArcGIS3.csproj +++ b/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Speckle.Converters.ArcGIS3.csproj @@ -15,4 +15,8 @@ + + + + diff --git a/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/TopLevel/CoreObjectsBaseToSpeckleTopLevelConverter.cs b/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/TopLevel/CoreObjectsBaseToSpeckleTopLevelConverter.cs index 66fc4973d..2bb4a2032 100644 --- a/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/TopLevel/CoreObjectsBaseToSpeckleTopLevelConverter.cs +++ b/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/TopLevel/CoreObjectsBaseToSpeckleTopLevelConverter.cs @@ -1,4 +1,3 @@ -using Speckle.Converters.ArcGIS3.Extensions; using Speckle.Converters.ArcGIS3.ToSpeckle.Helpers; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; @@ -37,13 +36,6 @@ private ArcgisObject Convert(AC.CoreObjectsBase target) // get properties Dictionary properties = _propertiesExtractor.GetProperties(target); - // get application id. test for subtypes before defaulting to base type. - string applicationId = target is ACD.Row row - ? row.GetSpeckleApplicationId() - : target is ACD.Analyst3D.LasPoint point - ? point.GetSpeckleApplicationId() - : target.GetSpeckleApplicationId(); - ArcgisObject result = new() { @@ -52,7 +44,7 @@ private ArcgisObject Convert(AC.CoreObjectsBase target) displayValue = display, properties = properties, units = _settingsStore.Current.SpeckleUnits, - applicationId = applicationId + applicationId = "" }; return result;