diff --git a/All.sln b/All.sln index 3fffc2325d..5e80640bb0 100644 --- a/All.sln +++ b/All.sln @@ -3044,8 +3044,6 @@ Global {11F7D41B-AFCA-4D29-BC08-285A14BF3A3B} = {2E00592E-558D-492D-88F9-3ECEE4C0C7DA} {804E065F-914C-414A-AF84-009312C3CFF6} = {1FE3C60E-7865-40A5-9794-55ECB64F6489} {9ADD1B7A-6401-4202-8613-F668E2FBC0A4} = {804E065F-914C-414A-AF84-009312C3CFF6} - {631C295A-7CCF-4B42-8686-7034E31469E7} = {804E065F-914C-414A-AF84-009312C3CFF6} - {D940853C-003A-482C-BDB0-665367F274A0} = {804E065F-914C-414A-AF84-009312C3CFF6} {7420652C-3046-4F38-BE64-9B9E69D76FA2} = {FD4D6594-D81E-456F-8F2E-35B09E04A755} {3973D572-5E24-476F-B058-8022D826B793} = {326ECEE0-D009-4A65-B24C-00FA343D8B99} {7B02BACC-D9B6-4FFE-A450-7ECB5F71F209} = {C73C19B5-72A3-4C63-8D56-0A7E7DB46CA5} @@ -3056,6 +3054,8 @@ Global {70DEAA13-6DC8-44A0-B287-9E806A8054F1} = {890F3257-FCC2-4ED8-9180-22B3641B494C} {F06E4C37-4076-4272-9CA6-FB505E02CD31} = {BE521908-7944-46F3-98BF-B47D34509934} {DDBBA313-69A6-40DE-AB3A-79EE5BF32A7E} = {743489BF-1941-43D5-8AF9-35C56D0DCC34} + {631C295A-7CCF-4B42-8686-7034E31469E7} = {804E065F-914C-414A-AF84-009312C3CFF6} + {D940853C-003A-482C-BDB0-665367F274A0} = {804E065F-914C-414A-AF84-009312C3CFF6} {C9C28F31-1367-438C-83B0-049C3B3A3E3B} = {804E065F-914C-414A-AF84-009312C3CFF6} {06082BAA-98E8-49B1-9D33-252B126A0561} = {804E065F-914C-414A-AF84-009312C3CFF6} EndGlobalSection diff --git a/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs index 649691a526..961ceb1576 100644 --- a/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs +++ b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Bindings/BasicConnectorBinding.cs @@ -1,7 +1,9 @@ using System.Reflection; +using ArcGIS.Core.Data; using ArcGIS.Desktop.Framework.Threading.Tasks; using ArcGIS.Desktop.Mapping; using Speckle.Connectors.ArcGIS.HostApp; +using Speckle.Connectors.ArcGIS.Utils; using Speckle.Connectors.DUI.Bindings; using Speckle.Connectors.DUI.Bridge; using Speckle.Connectors.DUI.Models; @@ -58,7 +60,8 @@ public BasicConnectorBinding(DocumentModelStore store, ArcGISSettings settings, public void RemoveModel(ModelCard model) => _store.RemoveModel(model); - public void HighlightObjects(List objectIds) => HighlightObjectsOnView(objectIds); + public void HighlightObjects(List objectIds) => + HighlightObjectsOnView(objectIds.Select(x => new ObjectID(x)).ToList()); public void HighlightModel(string modelCardId) { @@ -69,16 +72,16 @@ public void HighlightModel(string modelCardId) return; } - var objectIds = new List(); + var objectIds = new List(); if (model is SenderModelCard senderModelCard) { - objectIds = senderModelCard.SendFilter.NotNull().GetObjectIds(); + objectIds = senderModelCard.SendFilter.NotNull().GetObjectIds().Select(x => new ObjectID(x)).ToList(); } if (model is ReceiverModelCard receiverModelCard) { - objectIds = receiverModelCard.BakedObjectIds.NotNull(); + objectIds = receiverModelCard.BakedObjectIds.NotNull().Select(x => new ObjectID(x)).ToList(); } if (objectIds is null) @@ -88,42 +91,42 @@ public void HighlightModel(string modelCardId) HighlightObjectsOnView(objectIds); } - private async void HighlightObjectsOnView(List objectIds) + private async void HighlightObjectsOnView(List objectIds) { MapView mapView = MapView.Active; await QueuedTask .Run(() => { - List mapMembers = GetMapMembers(objectIds, mapView); + List mapMembersFeatures = GetMapMembers(objectIds, mapView); ClearSelectionInTOC(); ClearSelection(); - SelectMapMembersInTOC(mapMembers); - SelectMapMembers(mapMembers); + SelectMapMembersInTOC(mapMembersFeatures); + SelectMapMembersAndFeatures(mapMembersFeatures); mapView.ZoomToSelected(); }) .ConfigureAwait(false); } - private List GetMapMembers(List objectIds, MapView mapView) + private List GetMapMembers(List objectIds, MapView mapView) { - List mapMembers = new(); + // find the layer on the map (from the objectID) and add the featureID is available + List mapMembersFeatures = new(); - foreach (string objectId in objectIds) + foreach (ObjectID objectId in objectIds) { - MapMember mapMember = mapView.Map.FindLayer(objectId); + MapMember mapMember = mapView.Map.FindLayer(objectId.MappedLayerURI, true); if (mapMember is null) { - mapMember = mapView.Map.FindStandaloneTable(objectId); + mapMember = mapView.Map.FindStandaloneTable(objectId.MappedLayerURI); } - if (mapMember is null) + if (mapMember is not null) { - continue; + MapMemberFeature mapMembersFeat = new(mapMember, objectId.FeatureId); + mapMembersFeatures.Add(mapMembersFeat); } - mapMembers.Add(mapMember); } - - return mapMembers; + return mapMembersFeatures; } private void ClearSelection() @@ -143,24 +146,39 @@ private void ClearSelectionInTOC() MapView.Active.ClearTOCSelection(); } - private void SelectMapMembers(List mapMembers) + private void SelectMapMembersAndFeatures(List mapMembersFeatures) { - foreach (var member in mapMembers) + foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures) { + MapMember member = mapMemberFeat.MapMember; if (member is FeatureLayer layer) { - layer.Select(); + if (mapMemberFeat.FeatureId == null) + { + // select full layer if featureID not specified + layer.Select(); + } + else + { + // query features by ID + var objectIDfield = layer.GetFeatureClass().GetDefinition().GetObjectIDField(); + + // FeatureID range starts from 0, but auto-assigned IDs in the layer start from 1 + QueryFilter anotherQueryFilter = new() { WhereClause = $"{objectIDfield} = {mapMemberFeat.FeatureId + 1}" }; + using (Selection onlyOneSelection = layer.Select(anotherQueryFilter, SelectionCombinationMethod.New)) { } + } } } } - private void SelectMapMembersInTOC(List mapMembers) + private void SelectMapMembersInTOC(List mapMembersFeatures) { List layers = new(); List tables = new(); - foreach (MapMember member in mapMembers) + foreach (MapMemberFeature mapMemberFeat in mapMembersFeatures) { + MapMember member = mapMemberFeat.MapMember; if (member is Layer layer) { if (member is not GroupLayer) // group layer selection clears other layers selection diff --git a/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/HostObjectBuilder.cs b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/HostObjectBuilder.cs index 3e22f2d85d..953a6b2abb 100644 --- a/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/HostObjectBuilder.cs +++ b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Operations/Receive/HostObjectBuilder.cs @@ -11,6 +11,7 @@ using Speckle.Core.Models.GraphTraversal; using Speckle.Converters.ArcGIS3; using RasterLayer = Objects.GIS.RasterLayer; +using Speckle.Connectors.ArcGIS.Utils; namespace Speckle.Connectors.ArcGIS.Operations.Receive; @@ -116,21 +117,33 @@ CancellationToken cancellationToken else if (trackerItem.DatasetId == null) { results.Add( - new(Status.ERROR, trackerItem.Base, null, null, new ArgumentException("Unknown error: Dataset not created")) + new( + Status.ERROR, + trackerItem.Base, + null, + null, + new ArgumentException($"Unknown error: Dataset not created for {trackerItem.Base.speckle_type}") + ) ); } else if (bakedMapMembers.TryGetValue(trackerItem.DatasetId, out MapMember? value)) { + // add layer and layer URI to tracker + trackerItem.AddConvertedMapMember(value); + trackerItem.AddLayerURI(value.URI); + conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further // only add a report item AddResultsFromTracker(trackerItem, results); } else { - // add layer and layer URI to tracker + // add layer to Map MapMember mapMember = AddDatasetsToMap(trackerItem, createdLayerGroups); + + // add layer and layer URI to tracker trackerItem.AddConvertedMapMember(mapMember); trackerItem.AddLayerURI(mapMember.URI); - conversionTracker[item.Key] = trackerItem; + conversionTracker[item.Key] = trackerItem; // not necessary atm, but needed if we use conversionTracker further // add layer URI to bakedIds bakedObjectIds.Add(trackerItem.MappedLayerURI == null ? "" : trackerItem.MappedLayerURI); @@ -151,24 +164,45 @@ CancellationToken cancellationToken private void AddResultsFromTracker(ObjectConversionTracker trackerItem, List results) { - // prioritize individual hostAppGeometry type, if available: - if (trackerItem.HostAppGeom != null) - { - results.Add( - new(Status.SUCCESS, trackerItem.Base, trackerItem.MappedLayerURI, trackerItem.HostAppGeom.GetType().ToString()) - ); - } - else + if (trackerItem.MappedLayerURI == null) // should not happen { results.Add( new( - Status.SUCCESS, + Status.ERROR, trackerItem.Base, - trackerItem.MappedLayerURI, - trackerItem.HostAppMapMember?.GetType().ToString() + null, + null, + new ArgumentException($"Created Layer URI not found for {trackerItem.Base.speckle_type}") ) ); } + else + { + // encode layer ID and ID of its feature in 1 object represented as string + ObjectID objectId = new(trackerItem.MappedLayerURI, trackerItem.DatasetRow); + if (trackerItem.HostAppGeom != null) // individual hostAppGeometry + { + results.Add( + new( + Status.SUCCESS, + trackerItem.Base, + objectId.ObjectIdToString(), + trackerItem.HostAppGeom.GetType().ToString() + ) + ); + } + else // hostApp Layers + { + results.Add( + new( + Status.SUCCESS, + trackerItem.Base, + objectId.ObjectIdToString(), + trackerItem.HostAppMapMember?.GetType().ToString() + ) + ); + } + } } private MapMember AddDatasetsToMap( diff --git a/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Utils/MapMemberFeature.cs b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Utils/MapMemberFeature.cs new file mode 100644 index 0000000000..026e5165dc --- /dev/null +++ b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Utils/MapMemberFeature.cs @@ -0,0 +1,16 @@ +using ArcGIS.Desktop.Mapping; + +namespace Speckle.Connectors.ArcGIS.Utils; + +// bind together a layer object on the map, and auto-assigned ID if the specific feature +public readonly struct MapMemberFeature +{ + public int? FeatureId { get; } // unique feature id (start from 0) of a feature in the layer + public MapMember MapMember { get; } // layer object on the Map + + public MapMemberFeature(MapMember mapMember, int? featureId) + { + MapMember = mapMember; + FeatureId = featureId; + } +} diff --git a/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Utils/ObjectID.cs b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Utils/ObjectID.cs new file mode 100644 index 0000000000..8374181c5b --- /dev/null +++ b/DUI3-DX/Connectors/ArcGIS/Speckle.Connectors.ArcGIS3/Utils/ObjectID.cs @@ -0,0 +1,38 @@ +namespace Speckle.Connectors.ArcGIS.Utils; + +// this struct is needed to be able to parse single-string value into IDs of both a layer, and it's individual feature +public struct ObjectID +{ + private const string FEATURE_ID_SEPARATOR = "__speckleFeatureId__"; + public string MappedLayerURI { get; } // unique ID of the layer on the map + public int? FeatureId { get; } // unique feature id (start from 0) of a feature in the layer + + public ObjectID(string encodedId) + { + List stringParts = encodedId.Split(FEATURE_ID_SEPARATOR).ToList(); + MappedLayerURI = stringParts[0]; + FeatureId = null; + if (stringParts.Count > 1) + { + FeatureId = Convert.ToInt32(stringParts[1]); + } + } + + public ObjectID(string layerId, int? featureId) + { + MappedLayerURI = layerId; + FeatureId = featureId; + } + + public readonly string ObjectIdToString() + { + if (FeatureId == null) + { + return $"{MappedLayerURI}"; + } + else + { + return $"{MappedLayerURI}{FEATURE_ID_SEPARATOR}{FeatureId}"; + } + } +} diff --git a/DUI3-DX/Connectors/Autocad/Directory.Packages.props b/DUI3-DX/Connectors/Autocad/Directory.Packages.props deleted file mode 100644 index 568fea5f0f..0000000000 --- a/DUI3-DX/Connectors/Autocad/Directory.Packages.props +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/DUI3-DX/Connectors/Autocad/Speckle.Connectors.Autocad2023/Speckle.Connectors.Autocad2023.csproj b/DUI3-DX/Connectors/Autocad/Speckle.Connectors.Autocad2023/Speckle.Connectors.Autocad2023.csproj index b0f4587d7f..e3913f6c11 100644 --- a/DUI3-DX/Connectors/Autocad/Speckle.Connectors.Autocad2023/Speckle.Connectors.Autocad2023.csproj +++ b/DUI3-DX/Connectors/Autocad/Speckle.Connectors.Autocad2023/Speckle.Connectors.Autocad2023.csproj @@ -19,8 +19,7 @@ - - + diff --git a/DUI3-DX/Connectors/Rhino/Speckle.Connectors.Rhino7/Speckle.Connectors.Rhino7.csproj b/DUI3-DX/Connectors/Rhino/Speckle.Connectors.Rhino7/Speckle.Connectors.Rhino7.csproj index dbea907d5c..ef4a884995 100644 --- a/DUI3-DX/Connectors/Rhino/Speckle.Connectors.Rhino7/Speckle.Connectors.Rhino7.csproj +++ b/DUI3-DX/Connectors/Rhino/Speckle.Connectors.Rhino7/Speckle.Connectors.Rhino7.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/Raw/PointToSpeckleConverter.cs b/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/Raw/PointToSpeckleConverter.cs index e77591ee3f..46ffb8f937 100644 --- a/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/Raw/PointToSpeckleConverter.cs +++ b/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/ToSpeckle/Raw/PointToSpeckleConverter.cs @@ -23,7 +23,7 @@ is not MapPoint reprojectedPt ) { throw new SpeckleConversionException( - $"Conversion to Spatial Reference {_contextStack.Current.Document.Map.SpatialReference} failed" + $"Conversion to Spatial Reference {_contextStack.Current.Document.Map.SpatialReference.Name} failed" ); } return new(reprojectedPt.X, reprojectedPt.Y, reprojectedPt.Z, _contextStack.Current.SpeckleUnits); diff --git a/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Utils/FeatureClassUtils.cs b/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Utils/FeatureClassUtils.cs index c80b8473f1..6e3a587b45 100644 --- a/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Utils/FeatureClassUtils.cs +++ b/DUI3-DX/Converters/ArcGIS/Speckle.Converters.ArcGIS3/Utils/FeatureClassUtils.cs @@ -122,7 +122,11 @@ public ACG.GeometryType GetLayerGeometryType(VectorLayer target) GISLayerGeometryType.POLYLINE => ACG.GeometryType.Polyline, GISLayerGeometryType.MULTIPATCH => ACG.GeometryType.Multipatch, GISLayerGeometryType.POLYGON3D => ACG.GeometryType.Multipatch, - _ => throw new ArgumentOutOfRangeException(nameof(target)), + _ + => throw new ArgumentOutOfRangeException( + nameof(target), + $"Geometry type '{originalGeomType}' is not recognized." + ), }; } } diff --git a/DUI3-DX/Converters/Autocad/2023/Directory.Packages.props b/DUI3-DX/Converters/Autocad/2023/Directory.Packages.props deleted file mode 100644 index 568fea5f0f..0000000000 --- a/DUI3-DX/Converters/Autocad/2023/Directory.Packages.props +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/DUI3-DX/Converters/Autocad/2023/Speckle.Converters.Autocad2023/Speckle.Converters.Autocad2023.csproj b/DUI3-DX/Converters/Autocad/2023/Speckle.Converters.Autocad2023/Speckle.Converters.Autocad2023.csproj index 753a408e8e..2fc9b23da0 100644 --- a/DUI3-DX/Converters/Autocad/2023/Speckle.Converters.Autocad2023/Speckle.Converters.Autocad2023.csproj +++ b/DUI3-DX/Converters/Autocad/2023/Speckle.Converters.Autocad2023/Speckle.Converters.Autocad2023.csproj @@ -6,7 +6,7 @@ - + diff --git a/DUI3-DX/Converters/Autocad/2024/Directory.Packages.props b/DUI3-DX/Converters/Autocad/2024/Directory.Packages.props deleted file mode 100644 index 27e149ab85..0000000000 --- a/DUI3-DX/Converters/Autocad/2024/Directory.Packages.props +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024.DependencyInjection/packages.lock.json b/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024.DependencyInjection/packages.lock.json index fe9923d926..bb0e3cfe08 100644 --- a/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024.DependencyInjection/packages.lock.json +++ b/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024.DependencyInjection/packages.lock.json @@ -396,7 +396,7 @@ }, "Speckle.AutoCAD.API": { "type": "CentralTransitive", - "requested": "[2024.0.0, )", + "requested": "[2023.0.0, )", "resolved": "2024.0.0", "contentHash": "pZZ5uI+NXhZaQnsqRkgp/rywqBAjDObDJ9XNFGJvemT5k2OthDpHzlK/mKxz8QDCYie7uImQ8dv3uWj2QUFDPw==" }, diff --git a/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024/Speckle.Converters.Autocad2024.csproj b/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024/Speckle.Converters.Autocad2024.csproj index 8aad1ab7d5..05f9613b37 100644 --- a/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024/Speckle.Converters.Autocad2024.csproj +++ b/DUI3-DX/Converters/Autocad/2024/Speckle.Converters.Autocad2024/Speckle.Converters.Autocad2024.csproj @@ -6,7 +6,7 @@ - + diff --git a/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023/Speckle.Converters.Revit2023.csproj b/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023/Speckle.Converters.Revit2023.csproj index 985086abd5..4b7de6a4df 100644 --- a/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023/Speckle.Converters.Revit2023.csproj +++ b/DUI3-DX/Converters/Revit/Speckle.Converters.Revit2023/Speckle.Converters.Revit2023.csproj @@ -8,7 +8,7 @@ - + diff --git a/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7.DependencyInjection/Speckle.Converters.Rhino7.DependencyInjection.csproj b/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7.DependencyInjection/Speckle.Converters.Rhino7.DependencyInjection.csproj index 78870eeb41..f92549ccd3 100644 --- a/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7.DependencyInjection/Speckle.Converters.Rhino7.DependencyInjection.csproj +++ b/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7.DependencyInjection/Speckle.Converters.Rhino7.DependencyInjection.csproj @@ -11,6 +11,6 @@ - + diff --git a/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7/Speckle.Converters.Rhino7.csproj b/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7/Speckle.Converters.Rhino7.csproj index bf1bdbd6de..19094744c9 100644 --- a/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7/Speckle.Converters.Rhino7.csproj +++ b/DUI3-DX/Converters/Rhino/Speckle.Converters.Rhino7/Speckle.Converters.Rhino7.csproj @@ -5,7 +5,7 @@ - + diff --git a/DUI3-DX/Directory.Packages.props b/DUI3-DX/Directory.Packages.props index f8e92452ff..217c4a191b 100644 --- a/DUI3-DX/Directory.Packages.props +++ b/DUI3-DX/Directory.Packages.props @@ -14,11 +14,12 @@ - - + + +