From cd30370654dab2741d6479d5d8aae18933cd283b Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Tue, 10 Feb 2026 13:16:27 +0000 Subject: [PATCH] feat(autocad/civil): add reference point behavior (#1126) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * adds reference point transform to publish * only send reference point if not identity * first pass at adding reference point transform to publish * fixes transform matrix * fixes autocad to system matrix conversion * fixes text transforms * removes bboxs * removes to internal reference point (send only for now) * fix nullability * adds instance handling * adds converter settings to civil * refactors instance unpacker and polyline to speckle conversion * fixes blocks and some polyline receive conversions * removes transform on root * feat(autocad): adds event tracking for change of ucs/wcs settings (#1164) * feat: track ucs changes and invalidate cache * chore: redundant qualifier * fixes polyline conversions time to cry * fix(autocad): fixes polyline2d conversion with non-standard normals (#1169) * fix: polyline2d like polyline * refactor: coordinate system extension * refactor: extension for pt3d to ocs * renames reference point methods * moves logic to reference point converter * Update AutocadPolycurveToHostConverter.cs (#1175) --------- Co-authored-by: Björn Steinhagen <88777268+bjoernsteinhagen@users.noreply.github.com> Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com> Co-authored-by: bimgeek Co-authored-by: Mucahit Bilal GOKER <51519350+bimgeek@users.noreply.github.com> --- .../Bindings/AutocadSendBaseBinding.cs | 70 ++++++++++++++- .../HostApp/AutocadInstanceUnpacker.cs | 10 +-- .../HostApp/AutocadMaterialUnpacker.cs | 12 +++ .../Send/AutocadRootObjectBaseBuilder.cs | 68 +++++++++++++-- .../Send/AutocadRootObjectBuilder.cs | 3 + .../Send/Civil3dRootObjectBuilder.cs | 3 + .../Operations/Send/RhinoRootObjectBuilder.cs | 2 +- .../AutocadConversionSettings.cs | 4 +- .../AutocadConversionSettingsFactory.cs | 12 ++- .../Extensions/ListExtensions.cs | 42 +++------ .../Helpers/ReferencePointHelper.cs | 42 +++++++++ .../Helpers/TransformHelper.cs | 73 ++++++++++++++++ .../IReferencePointConverter.cs | 33 +++++++ .../ReferencePointConverter.cs | 74 ++++++++++++++++ .../ServiceRegistration.cs | 2 + ...Speckle.Converters.AutocadShared.projitems | 15 +++- .../AutocadPolycurveToHostConverter.cs | 32 ++++++- ...adPolycurveToHostPolyline2dRawConverter.cs | 14 +-- ...ocadPolycurveToHostPolylineRawConverter.cs | 14 +-- .../PolyfaceMeshToSpeckleConverter.cs | 27 ++---- .../Geometry/Polyline2dToSpeckleConverter.cs | 42 ++++----- .../Geometry/Polyline3dToSpeckleConverter.cs | 32 +++---- .../Geometry/PolylineToSpeckleConverter.cs | 27 +++--- .../Geometry/SubDMeshToSpeckleConverter.cs | 79 ++--------------- .../Raw/BrepToSpeckleRawConverter.cs | 9 +- .../Raw/CircularArc2dToSpeckleRawConverter.cs | 27 ++---- .../Raw/DBArcToSpeckleRawConverter.cs | 5 -- .../Raw/DBCircleToSpeckleRawConverter.cs | 7 +- .../Raw/DBCurveToSpeckleRawConverter.cs | 6 +- .../Raw/DBEllipseToSpeckleRawConverter.cs | 26 +++--- .../Raw/DBLineToSpeckleRawConverter.cs | 6 +- .../Raw/DBSplineToSpeckleRawConverter.cs | 16 ++-- .../Raw/DBSubDMeshToSpeckleRawConverter.cs | 86 +++++++++++++++++++ .../Raw/DBTextToSpeckleRawConverter.cs | 28 ++++-- .../DoublesToSpecklePolylineRawConverter.cs | 32 +++++++ .../Raw/MTextToSpeckleRawConverter.cs | 30 +++++-- .../Raw/PlaneToSpeckleRawConverter.cs | 11 ++- .../Raw/Point2dToSpeckleRawConverter.cs | 26 ++++++ .../Raw/Point3dToSpeckleRawConverter.cs | 25 ++++++ .../Raw/PointToSpeckleRawConverter.cs | 16 ---- .../Raw/Vector3dToSpeckleRawConverter.cs | 25 ++++++ .../Raw/VectorToSpeckleRawConverter.cs | 17 ---- .../ServiceRegistration.cs | 1 + ...gnmentSubentityArcToSpeckleRawConverter.cs | 27 ++---- ...nmentSubentityLineToSpeckleRawConverter.cs | 26 ++---- ...entSubentitySpiralToSpeckleRawConverter.cs | 10 ++- .../GridSurfaceToSpeckleMeshRawConverter.cs | 17 ++-- .../Point3dCollectionToSpeckleRawConverter.cs | 10 ++- .../TinSurfaceToSpeckleMeshRawConverter.cs | 10 ++- .../Instances/IInstanceObjectsManager.cs | 3 +- .../Instances/InstanceObjectsManager.cs | 9 +- .../Instances/UnpackResult.cs | 1 + 52 files changed, 866 insertions(+), 378 deletions(-) create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/ReferencePointHelper.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/TransformHelper.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/IReferencePointConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ReferencePointConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSubDMeshToSpeckleRawConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DoublesToSpecklePolylineRawConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point2dToSpeckleRawConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point3dToSpeckleRawConverter.cs delete mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PointToSpeckleRawConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Vector3dToSpeckleRawConverter.cs delete mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/VectorToSpeckleRawConverter.cs diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs index f30544012..9c23996ed 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadSendBaseBinding.cs @@ -1,6 +1,7 @@ using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; using Autodesk.AutoCAD.DatabaseServices; +using Autodesk.AutoCAD.Geometry; using Speckle.Connectors.Autocad.HostApp.Extensions; using Speckle.Connectors.Common.Caching; using Speckle.Connectors.Common.Cancellation; @@ -40,6 +41,9 @@ public abstract class AutocadSendBaseBinding : ISendBinding /// private ConcurrentBag ChangedObjectIds { get; set; } = new(); + private readonly List _docSubsTracker = new(); + private readonly Dictionary _docUcsTracker = new(); + protected AutocadSendBaseBinding( DocumentModelStore store, IBrowserBridge parent, @@ -71,6 +75,10 @@ public abstract class AutocadSendBaseBinding : ISendBinding // catches the case when autocad just opens up with a blank new doc SubscribeToObjectChanges(Application.DocumentManager.CurrentDocument); } + + Application.SystemVariableChanged += (_, e) => + _topLevelExceptionHandler.CatchUnhandled(() => OnSystemVariableChanged(e)); + // Since ids of the objects generates from same seed, we should clear the cache always whenever doc swapped. _store.DocumentChanged += (_, _) => { @@ -78,8 +86,6 @@ public abstract class AutocadSendBaseBinding : ISendBinding }; } - private readonly List _docSubsTracker = new(); - private void SubscribeToObjectChanges(Document doc) { if (doc == null || doc.Database == null || _docSubsTracker.Contains(doc.Name)) @@ -88,11 +94,58 @@ public abstract class AutocadSendBaseBinding : ISendBinding } _docSubsTracker.Add(doc.Name); + _docUcsTracker[doc.Name] = doc.Editor.CurrentUserCoordinateSystem; + doc.Database.ObjectAppended += (_, e) => OnObjectChanged(e.DBObject); doc.Database.ObjectErased += (_, e) => OnObjectChanged(e.DBObject); doc.Database.ObjectModified += (_, e) => OnObjectChanged(e.DBObject); } + /// + /// Handles system variable changes to detect UCS modifications. + /// When UCS changes, clears the conversion cache and expires all sender model cards. + /// + private void OnSystemVariableChanged(Autodesk.AutoCAD.ApplicationServices.SystemVariableChangedEventArgs e) + { + // check if this is a UCS-defining system variable + string varName = e.Name.ToUpperInvariant(); + bool isUcsChange = varName == "UCSNAME" || varName == "UCSORG" || varName == "UCSXDIR" || varName == "UCSYDIR"; + + if (!isUcsChange) + { + return; + } + + // get the currently active document + Document doc = Application.DocumentManager.MdiActiveDocument; + if (doc == null) + { + return; + } + + var currentUcs = doc.Editor.CurrentUserCoordinateSystem; + + // first time tracking this document's UCS + if (!_docUcsTracker.TryGetValue(doc.Name, out Matrix3d storedUcs)) + { + _docUcsTracker[doc.Name] = currentUcs; + return; + } + + // ucs hasn't actually changed (multiple variables fire for single UCS change) + if (currentUcs.IsEqualTo(storedUcs)) + { + return; + } + + // ucs has changed - all cached conversions invalid + _sendConversionCache.ClearCache(); + _docUcsTracker[doc.Name] = currentUcs; + + // expire all sender model cards + _idleManager.SubscribeToIdle(nameof(ExpireAllSenders), async () => await ExpireAllSenders()); + } + private void OnObjectChanged(DBObject dbObject) => _topLevelExceptionHandler.CatchUnhandled(() => OnChangeChangedObjectIds(dbObject)); @@ -123,6 +176,19 @@ public abstract class AutocadSendBaseBinding : ISendBinding ChangedObjectIds = new(); } + /// + /// Expires all sender model cards when a global change occurs (like UCS change). + /// + private async Task ExpireAllSenders() + { + var senders = _store.GetSenders(); + var expiredSenderIds = senders.Select(s => s.ModelCardId.NotNull()).ToList(); + if (expiredSenderIds.Count > 0) + { + await Commands.SetModelsExpired(expiredSenderIds); + } + } + public List GetSendFilters() => _sendFilters; public List GetSendSettings() => []; diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceUnpacker.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceUnpacker.cs index d38ebca41..3b9611c84 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceUnpacker.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadInstanceUnpacker.cs @@ -3,9 +3,9 @@ using Microsoft.Extensions.Logging; using Speckle.Connectors.Autocad.HostApp.Extensions; using Speckle.Connectors.Autocad.Operations.Send; using Speckle.Connectors.Common.Instances; +using Speckle.Converters.Autocad.Helpers; using Speckle.Converters.AutocadShared.ToSpeckle; using Speckle.Converters.Common; -using Speckle.DoubleNumerics; using Speckle.Sdk; using Speckle.Sdk.Models.Instances; @@ -46,6 +46,7 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker { UnpackInstance(blockReference, 0, transaction); } + _instanceObjectsManager.AddAtomicObject(obj.ApplicationId, obj); } return _instanceObjectsManager.GetUnpackResult(); @@ -66,13 +67,14 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker ? instance.AnonymousBlockTableRecord : instance.BlockTableRecord; + // transforms on instances are always stored in WCS InstanceProxy instanceProxy = new() { applicationId = instanceId, definitionId = definitionId.ToString(), maxDepth = depth, - transform = GetMatrix(instance.BlockTransform.ToArray()), + transform = TransformHelper.ConvertToInstanceMatrix4x4(instance.BlockTransform), units = _unitsConverter.ConvertOrThrow(Application.DocumentManager.CurrentDocument.Database.Insunits) }; @@ -173,6 +175,7 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker UnpackInstance(blockReference, depth + 1, transaction); } + _instanceObjectsManager.AddAtomicDefinitionObjectId(appId); _instanceObjectsManager.AddAtomicObject(appId, new(obj, appId)); } @@ -183,7 +186,4 @@ public class AutocadInstanceUnpacker : IInstanceUnpacker _logger.LogError(ex, "Failed unpacking Autocad instance"); } } - - private Matrix4x4 GetMatrix(double[] t) => - new(t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); } diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialUnpacker.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialUnpacker.cs index 9b1f843b3..0f87df9a5 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialUnpacker.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/HostApp/AutocadMaterialUnpacker.cs @@ -51,6 +51,12 @@ public class AutocadMaterialUnpacker if (transaction.GetObject(entity.MaterialId, OpenMode.ForRead) is Material material) { + // skip default material + if (material.Name == "Global") + { + continue; + } + string materialId = material.GetSpeckleApplicationId(); if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value)) { @@ -77,6 +83,12 @@ public class AutocadMaterialUnpacker { if (transaction.GetObject(layer.MaterialId, OpenMode.ForRead) is Material material) { + // skip default material + if (material.Name == "Global") + { + continue; + } + string materialId = material.GetSpeckleApplicationId(); string layerId = layer.GetSpeckleApplicationId(); // Do not use handle directly, see note in the 'GetSpeckleApplicationId' method if (materialProxies.TryGetValue(materialId, out RenderMaterialProxy? value)) diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs index 0434dcc35..20b5660d2 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using Autodesk.AutoCAD.DatabaseServices; +using Autodesk.AutoCAD.Geometry; using Microsoft.Extensions.Logging; using Speckle.Connectors.Autocad.HostApp; using Speckle.Connectors.Common.Builders; @@ -7,6 +8,8 @@ using Speckle.Connectors.Common.Caching; using Speckle.Connectors.Common.Conversion; using Speckle.Connectors.Common.Extensions; using Speckle.Connectors.Common.Operations; +using Speckle.Converters.Autocad; +using Speckle.Converters.Autocad.Helpers; using Speckle.Converters.Common; using Speckle.Sdk; using Speckle.Sdk.Logging; @@ -19,6 +22,7 @@ namespace Speckle.Connectors.Autocad.Operations.Send; public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder { private readonly IRootToSpeckleConverter _converter; + private readonly IConverterSettingsStore _converterSettings; private readonly string[] _documentPathSeparator = ["\\"]; private readonly ISendConversionCache _sendConversionCache; private readonly AutocadInstanceUnpacker _instanceUnpacker; @@ -30,6 +34,7 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder converterSettings, ISendConversionCache sendConversionCache, AutocadInstanceUnpacker instanceObjectManager, AutocadMaterialUnpacker materialUnpacker, @@ -40,6 +45,7 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder usedAcadLayers = new(); // Keeps track of autocad layers used, so we can pass them on later to the material and color unpacker. List results = new(); int count = 0; + + // 4 - Convert atomic objects foreach (var (entity, applicationId) in atomicObjects) { cancellationToken.ThrowIfCancellationRequested(); @@ -104,9 +128,28 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder currentSettings with { ReferencePointTransform = null })) + { + result = ConvertAutocadEntity(entity, applicationId, objectCollection, instanceProxies, projectId); + } + } + else // this is a selected atomic object (not part of definition) + { + result = ConvertAutocadEntity( + entity, + applicationId, + objectCollection, + instanceProxies, + projectId, + referenceTransform // set this for top level instance proxies to use if needed + ); + } + results.Add(result); onOperationProgressed.Report(new("Converting", (double)++count / atomicObjects.Count)); } @@ -115,10 +158,10 @@ public abstract class AutocadRootObjectBaseBuilder : IRootObjectBuilder instanceProxies, - string projectId + string projectId, + Matrix3d? transform = null ) { string sourceType = entity.GetType().ToString(); try { Base converted; - if (entity is BlockReference && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy)) + if (entity is BlockReference br && instanceProxies.TryGetValue(applicationId, out InstanceProxy? instanceProxy)) { + // modify transform by reference point this if it is top level + if (instanceProxy.maxDepth == 0 && transform is Matrix3d validTransform) + { + instanceProxy.transform = TransformHelper.ConvertToInstanceMatrix4x4( + br.BlockTransform.PreMultiplyBy(validTransform) + ); + } + converted = instanceProxy; } else if (_sendConversionCache.TryGetValue(projectId, applicationId, out ObjectReference? value)) diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBuilder.cs index 7278ecae6..a356d6960 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBuilder.cs @@ -2,6 +2,7 @@ using Autodesk.AutoCAD.DatabaseServices; using Microsoft.Extensions.Logging; using Speckle.Connectors.Autocad.HostApp; using Speckle.Connectors.Common.Caching; +using Speckle.Converters.Autocad; using Speckle.Converters.Common; using Speckle.Sdk.Logging; using Speckle.Sdk.Models.Collections; @@ -15,6 +16,7 @@ public sealed class AutocadRootObjectBuilder : AutocadRootObjectBaseBuilder public AutocadRootObjectBuilder( AutocadLayerUnpacker layerUnpacker, IRootToSpeckleConverter converter, + IConverterSettingsStore converterSettings, ISendConversionCache sendConversionCache, AutocadInstanceUnpacker instanceObjectManager, AutocadMaterialUnpacker materialUnpacker, @@ -25,6 +27,7 @@ public sealed class AutocadRootObjectBuilder : AutocadRootObjectBaseBuilder ) : base( converter, + converterSettings, sendConversionCache, instanceObjectManager, materialUnpacker, diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs index 9f17bd7e0..c1a629415 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs @@ -4,6 +4,7 @@ using Speckle.Connectors.Autocad.HostApp; using Speckle.Connectors.Autocad.Operations.Send; using Speckle.Connectors.Common.Caching; using Speckle.Connectors.Common.Operations; +using Speckle.Converters.Autocad; using Speckle.Converters.Civil3dShared.ToSpeckle; using Speckle.Converters.Common; using Speckle.Sdk.Logging; @@ -20,6 +21,7 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder AutocadLayerUnpacker layerUnpacker, PropertySetDefinitionHandler propertySetDefinitionHandler, IRootToSpeckleConverter converter, + IConverterSettingsStore converterSettings, ISendConversionCache sendConversionCache, AutocadInstanceUnpacker instanceObjectManager, AutocadMaterialUnpacker materialUnpacker, @@ -30,6 +32,7 @@ public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder ) : base( converter, + converterSettings, sendConversionCache, instanceObjectManager, materialUnpacker, diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs index 491c06c12..8394ec6c5 100644 --- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs +++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/Operations/Send/RhinoRootObjectBuilder.cs @@ -86,7 +86,7 @@ public class RhinoRootObjectBuilder : IRootObjectBuilder unpackResults = _instanceUnpacker.UnpackSelection(rhinoObjects); } - var (atomicObjects, instanceProxies, instanceDefinitionProxies) = unpackResults; + var (atomicObjects, atomicDefinitionObjectIds, instanceProxies, instanceDefinitionProxies) = unpackResults; // POC: we should formalise this, sooner or later - or somehow fix it a bit more rootObjectCollection[ProxyKeys.INSTANCE_DEFINITION] = instanceDefinitionProxies; // this won't work re traversal on receive diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettings.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettings.cs index 093f92e9b..7add8edff 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettings.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettings.cs @@ -1,3 +1,3 @@ -namespace Speckle.Converters.Autocad; +namespace Speckle.Converters.Autocad; -public record AutocadConversionSettings(Document Document, string SpeckleUnits); +public record AutocadConversionSettings(Document Document, AG.Matrix3d? ReferencePointTransform, string SpeckleUnits); diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettingsFactory.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettingsFactory.cs index 08b4d4a68..433139174 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettingsFactory.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/AutocadConversionSettingsFactory.cs @@ -1,4 +1,4 @@ -using Speckle.Converters.Common; +using Speckle.Converters.Common; using Speckle.InterfaceGenerator; namespace Speckle.Converters.Autocad; @@ -7,6 +7,12 @@ namespace Speckle.Converters.Autocad; public class AutocadConversionSettingsFactory(IHostToSpeckleUnitConverter unitsConverter) : IAutocadConversionSettingsFactory { - public AutocadConversionSettings Create(Document document) => - new(document, unitsConverter.ConvertOrThrow(document.Database.Insunits)); + public AutocadConversionSettings Create(Document document) + { + AG.Matrix3d? m = + document.Editor.CurrentUserCoordinateSystem == AG.Matrix3d.Identity + ? null + : document.Editor.CurrentUserCoordinateSystem; + return new(document, m, unitsConverter.ConvertOrThrow(document.Database.Insunits)); + } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/Extensions/ListExtensions.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/Extensions/ListExtensions.cs index 99595f357..add433011 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/Extensions/ListExtensions.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/Extensions/ListExtensions.cs @@ -2,34 +2,6 @@ namespace Speckle.Converters.Autocad.Extensions; public static class ListExtensions { - public static SOG.Polyline ConvertToSpecklePolyline(this List pointList, string speckleUnits) - { - // throw if list is malformed - if (pointList.Count % 3 != 0) - { - throw new ArgumentException("Point list of xyz values is malformed", nameof(pointList)); - } - - return new() { value = pointList, units = speckleUnits }; - } - - public static List ConvertToPoint2d(this List pointList, double conversionFactor = 1) - { - // throw if list is malformed - if (pointList.Count % 2 != 0) - { - throw new ArgumentException("Point list of xy values is malformed", nameof(pointList)); - } - - List points2d = new(pointList.Count / 2); - for (int i = 1; i < pointList.Count; i += 2) - { - points2d.Add(new AG.Point2d(pointList[i - 1] * conversionFactor, pointList[i] * conversionFactor)); - } - - return points2d; - } - public static List ConvertToPoint3d(this List pointList, double conversionFactor = 1) { // throw if list is malformed @@ -52,4 +24,18 @@ public static class ListExtensions return points3d; } + + /// + /// Converts a list of doubles to Point3d objects and transforms them to OCS (Object Coordinate System) + /// based on the provided normal vector + /// + public static List ConvertToPoint3dInOcs( + this List pointList, + AG.Vector3d normal, + double conversionFactor = 1 + ) + { + AG.Matrix3d matrixOcs = AG.Matrix3d.WorldToPlane(normal); + return pointList.ConvertToPoint3d(conversionFactor).Select(p => p.TransformBy(matrixOcs)).ToList(); + } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/ReferencePointHelper.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/ReferencePointHelper.cs new file mode 100644 index 000000000..c0b34a98b --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/ReferencePointHelper.cs @@ -0,0 +1,42 @@ +namespace Speckle.Converters.Autocad.Helpers; + +/// +/// Helper class for working with reference points +/// +public static class ReferencePointHelper +{ + public const string REFERENCE_POINT_TRANSFORM_KEY = "referencePointTransform"; + + /// + /// Changes Autocad Matrix3d Transform to a double array. + /// Uses a 16-element column-major matrix representation. See https://speckle.guide/dev/objects.html + /// + public static Dictionary CreateTransformDataForRootObject(AG.Matrix3d transform) + { + return new Dictionary + { + { + "transform", // TODO: it would also be nice to include the key-value pair for reference point type as a string + new[] + { + transform.CoordinateSystem3d.Xaxis.X, + transform.CoordinateSystem3d.Xaxis.Y, + transform.CoordinateSystem3d.Xaxis.Z, + 0, + transform.CoordinateSystem3d.Yaxis.X, + transform.CoordinateSystem3d.Yaxis.Y, + transform.CoordinateSystem3d.Yaxis.Z, + 0, + transform.CoordinateSystem3d.Zaxis.X, + transform.CoordinateSystem3d.Zaxis.Y, + transform.CoordinateSystem3d.Zaxis.Z, + 0, + transform.CoordinateSystem3d.Origin.X, + transform.CoordinateSystem3d.Origin.Y, + transform.CoordinateSystem3d.Origin.Z, + 1 + } + } + }; + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/TransformHelper.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/TransformHelper.cs new file mode 100644 index 000000000..9a2d48237 --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/Helpers/TransformHelper.cs @@ -0,0 +1,73 @@ +using Speckle.DoubleNumerics; + +namespace Speckle.Converters.Autocad.Helpers; + +/// +/// Helper class for working with transforms +/// +public static class TransformHelper +{ + /// + /// Converts an AutoCAD matrix3d to a row-dominant Speckle Matrix4x4 + /// + /// + /// + /// + /// Use for System Numerics operations, eg matrix and vector multiplication + /// + public static Matrix4x4 ConvertToMatrix4x4(AG.Matrix3d m) => + new( + m[0, 0], + m[1, 0], + m[2, 0], + m[3, 0], + m[0, 1], + m[1, 1], + m[2, 1], + m[3, 1], + m[0, 2], + m[1, 2], + m[2, 2], + m[3, 2], + m[0, 3], + m[1, 3], + m[2, 3], + m[3, 3] + ); + + /// + /// Speckle Instances use a transform that is column-dominant, not row dominant. + /// + /// + /// + /// Use only for Speckle Instance object transforms. + public static Matrix4x4 ConvertToInstanceMatrix4x4(AG.Matrix3d m) => + new( + m[0, 0], + m[0, 1], + m[0, 2], + m[0, 3], + m[1, 0], + m[1, 1], + m[1, 2], + m[1, 3], + m[2, 0], + m[2, 1], + m[2, 2], + m[2, 3], + m[3, 0], + m[3, 1], + m[3, 2], + m[3, 3] + ); + + /// + /// Get the transform matrix from an entity's OCS to the WCS + /// + /// + /// + /// + /// Use this method for certain properties or methods on entities that return values in OCS + /// + public static AG.Matrix3d GetTransformFromOCSToWCS(AG.Vector3d normal) => AG.Matrix3d.WorldToPlane(normal); +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/IReferencePointConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/IReferencePointConverter.cs new file mode 100644 index 000000000..d114b5ced --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/IReferencePointConverter.cs @@ -0,0 +1,33 @@ +namespace Speckle.Converters.Autocad; + +public interface IReferencePointConverter +{ + /// + /// Converts a list of doubles representing point3ds in WCS coordinates to the current active coordinate system + /// + /// + /// + List ConvertWCSDoublesToExternalCoordinates(List d); + + /// + /// Converts a Point in WCS coordinates to the current active coordinate system + /// + /// + /// + AG.Point3d ConvertWCSPointToExternalCoordinates(AG.Point3d p); + + /// + /// Converts a Vector in WCS coordinates to the current active coordinate system + /// + /// + /// + AG.Vector3d ConvertWCSVectorToExternalCoordinates(AG.Vector3d v); + + /// + /// Converts an elevation in OCS coordinates to the current active coordinate system + /// + /// elevation in OCS + /// OCS plane normal in WCS + /// + double ConvertOCSElevationDoubleToExternalCoordinates(double e, AG.Vector3d normal); +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ReferencePointConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ReferencePointConverter.cs new file mode 100644 index 000000000..33fef2814 --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ReferencePointConverter.cs @@ -0,0 +1,74 @@ +using Speckle.Converters.Autocad.Helpers; +using Speckle.Converters.Common; +using Speckle.DoubleNumerics; + +namespace Speckle.Converters.Autocad; + +/// +/// POC: reference point functionality needs to be revisited (we are currently baking in these transforms into all geometry using the point and vector converters, and losing the transform). +/// This converter uses the transform from the converter settings (from the current doc) +/// +public class ReferencePointConverter(IConverterSettingsStore converterSettings) + : IReferencePointConverter +{ + public List ConvertWCSDoublesToExternalCoordinates(List d) + { + if (d.Count % 3 != 0) + { + throw new ArgumentException("Point list of xyz values is malformed", nameof(d)); + } + + if (converterSettings.Current.ReferencePointTransform is AG.Matrix3d m) + { + Matrix4x4 transform = TransformHelper.ConvertToMatrix4x4(m.Inverse()); + + var transformed = new List(d.Count); + + for (int i = 0; i < d.Count; i += 3) + { + Vector3 p = Vector3.Transform(new(d[i], d[i + 1], d[i + 2]), transform); + + transformed.Add(p.X); + transformed.Add(p.Y); + transformed.Add(p.Z); + } + + return transformed; + } + + return d; + } + + public AG.Point3d ConvertWCSPointToExternalCoordinates(AG.Point3d p) + { + if (converterSettings.Current.ReferencePointTransform is AG.Matrix3d transform) + { + return p.TransformBy(transform.Inverse()); + } + + return p; + } + + public AG.Vector3d ConvertWCSVectorToExternalCoordinates(AG.Vector3d v) + { + if (converterSettings.Current.ReferencePointTransform is AG.Matrix3d transform) + { + return v.TransformBy(transform.Inverse()); + } + + return v; + } + + public double ConvertOCSElevationDoubleToExternalCoordinates(double elevation, AG.Vector3d normal) + { + // get a point on the plane in WCS + AG.Point3d wcsPoint = AG.Point3d.Origin + normal * elevation; + + // transform to external coords + AG.Point3d extPoint = ConvertWCSPointToExternalCoordinates(wcsPoint); + AG.Vector3d extNormal = ConvertWCSVectorToExternalCoordinates(normal); + + // calculate elevation as perpendicular distance in external coords + return extPoint.GetAsVector().DotProduct(extNormal); + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ServiceRegistration.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ServiceRegistration.cs index e748b49a4..adc447336 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ServiceRegistration.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ServiceRegistration.cs @@ -26,6 +26,8 @@ public static class ServiceRegistration >(); serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly()); + serviceCollection.AddScoped(); + // add other classes serviceCollection.AddScoped(); serviceCollection.AddScoped(); diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems b/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems index cfe3ceade..2808e48d3 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems @@ -1,4 +1,4 @@ - + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) @@ -16,6 +16,10 @@ + + + + @@ -54,6 +58,7 @@ + @@ -62,6 +67,7 @@ + @@ -80,7 +86,6 @@ - @@ -88,9 +93,11 @@ - + + + - + diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Geometry/AutocadPolycurveToHostConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Geometry/AutocadPolycurveToHostConverter.cs index 65a3028b5..96df3782b 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Geometry/AutocadPolycurveToHostConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Geometry/AutocadPolycurveToHostConverter.cs @@ -11,16 +11,19 @@ public class AutocadPolycurveToHostConverter : IToHostTopLevelConverter private readonly ITypedConverter _polylineConverter; private readonly ITypedConverter _polyline2dConverter; private readonly ITypedConverter _polyline3dConverter; + private readonly ITypedConverter> _polycurveConverter; public AutocadPolycurveToHostConverter( ITypedConverter polylineConverter, ITypedConverter polyline2dConverter, - ITypedConverter polyline3dConverter + ITypedConverter polyline3dConverter, + ITypedConverter> polycurveConverter ) { _polylineConverter = polylineConverter; _polyline2dConverter = polyline2dConverter; _polyline3dConverter = polyline3dConverter; + _polycurveConverter = polycurveConverter; } public object Convert(Base target) @@ -30,7 +33,7 @@ public class AutocadPolycurveToHostConverter : IToHostTopLevelConverter switch (polycurve.polyType) { case SOG.Autocad.AutocadPolyType.Light: - return _polylineConverter.Convert(polycurve); + return Has2DValue(polycurve) ? _polycurveConverter.Convert(polycurve) : _polylineConverter.Convert(polycurve); case SOG.Autocad.AutocadPolyType.Simple2d: case SOG.Autocad.AutocadPolyType.FitCurve2d: @@ -47,4 +50,29 @@ public class AutocadPolycurveToHostConverter : IToHostTopLevelConverter throw new ValidationException("Unknown poly type for AutocadPolycurve"); } } + + // Method for backwards compatibility: polylines from 3.10 and before had point2d values in OCS instead of point3d values in WCS/UCS + private bool Has2DValue(SOG.Autocad.AutocadPolycurve polycurve) + { + int pointListCount = polycurve.value.Count; + if (pointListCount % 3 == 0 && pointListCount % 2 != 0) + { + return false; + } + + if (pointListCount % 2 != 0) + { + throw new ValidationException( + "Polycurve value list was deformed, could not translate into 2d or 3d coordinates." + ); + } + + int segmentVertexCount = polycurve.closed ? polycurve.segments.Count : polycurve.segments.Count + 1; + if (pointListCount / 2 == segmentVertexCount) + { + return true; + } + + return false; + } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolyline2dRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolyline2dRawConverter.cs index b3ad64154..6c986d336 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolyline2dRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolyline2dRawConverter.cs @@ -26,33 +26,33 @@ public class AutocadPolycurveToHostPolyline2dRawConverter // check for normal if (target.normal is not SOG.Vector normal) { - throw new System.ArgumentException($"Autocad polycurve of type {target.polyType} did not have a normal"); + throw new ArgumentException($"Autocad polycurve of type {target.polyType} did not have a normal"); } // check for elevation if (target.elevation is not double elevation) { - throw new System.ArgumentException($"Autocad polycurve of type {target.polyType} did not have an elevation"); + throw new ArgumentException($"Autocad polycurve of type {target.polyType} did not have an elevation"); } - // get vertices + // convert the normal, get vertices and transform them to ocs + var convertedNormal = _vectorConverter.Convert(normal); double f = Units.GetConversionFactor(target.units, _settingsStore.Current.SpeckleUnits); - List points = target.value.ConvertToPoint3d(f); + List points = target.value.ConvertToPoint3dInOcs(convertedNormal, f); // check for invalid bulges if (target.bulges is null || target.bulges.Count < points.Count) { - throw new System.ArgumentException($"Autocad polycurve of type {target.polyType} had null or malformed bulges"); + throw new ArgumentException($"Autocad polycurve of type {target.polyType} had null or malformed bulges"); } // check for invalid tangents if (target.tangents is null || target.tangents.Count < points.Count) { - throw new System.ArgumentException($"Autocad polycurve of type {target.polyType} had null or malformed tangents"); + throw new ArgumentException($"Autocad polycurve of type {target.polyType} had null or malformed tangents"); } // create the polyline2d using the empty constructor - AG.Vector3d convertedNormal = _vectorConverter.Convert(normal); double convertedElevation = elevation * f; ADB.Polyline2d polyline = new() diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolylineRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolylineRawConverter.cs index dff137087..e05430e6f 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolylineRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToHost/Raw/AutocadPolycurveToHostPolylineRawConverter.cs @@ -24,26 +24,26 @@ public class AutocadPolycurveToHostPolylineRawConverter : ITypedConverter points2d = target.value.ConvertToPoint2d(f); + List points3d = target.value.ConvertToPoint3dInOcs(normal, f); ADB.Polyline polyline = new() { - Normal = _vectorConverter.Convert(target.normal), + Normal = normal, Elevation = (double)target.elevation * f, Closed = target.closed }; - for (int i = 0; i < points2d.Count; i++) + for (int i = 0; i < points3d.Count; i++) { var bulge = target.bulges is null ? 0 : target.bulges[i]; - polyline.AddVertexAt(i, points2d[i], bulge, 0, 0); + polyline.AddVertexAt(i, new(points3d[i].X, points3d[i].Y), bulge, 0, 0); } return polyline; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolyfaceMeshToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolyfaceMeshToSpeckleConverter.cs index a8d23bbef..679498076 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolyfaceMeshToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolyfaceMeshToSpeckleConverter.cs @@ -1,4 +1,3 @@ -using Autodesk.AutoCAD.Geometry; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; using Speckle.Sdk.Models; @@ -14,18 +13,15 @@ namespace Speckle.Converters.Autocad.Geometry; [NameAndRankValue(typeof(ADB.PolyFaceMesh), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)] public class DBPolyfaceMeshToSpeckleConverter : IToSpeckleTopLevelConverter { - private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _boxConverter; + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; public DBPolyfaceMeshToSpeckleConverter( - ITypedConverter pointConverter, - ITypedConverter boxConverter, + IReferencePointConverter referencePointConverter, IConverterSettingsStore settingsStore ) { - _pointConverter = pointConverter; - _boxConverter = boxConverter; + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -33,7 +29,7 @@ public class DBPolyfaceMeshToSpeckleConverter : IToSpeckleTopLevelConverter public SOG.Mesh RawConvert(ADB.PolyFaceMesh target) { - List dbVertices = new(); + List vertices = new(); List faces = new(); List faceVisibility = new(); List colors = new(); @@ -45,7 +41,9 @@ public class DBPolyfaceMeshToSpeckleConverter : IToSpeckleTopLevelConverter switch (obj) { case ADB.PolyFaceMeshVertex o: - dbVertices.Add(o.Position); + vertices.Add(o.Position.X); + vertices.Add(o.Position.Y); + vertices.Add(o.Position.Z); colors.Add(o.Color.ColorValue.ToArgb()); break; case ADB.FaceRecord o: @@ -84,22 +82,13 @@ public class DBPolyfaceMeshToSpeckleConverter : IToSpeckleTopLevelConverter tr.Commit(); } - List vertices = new(dbVertices.Count * 3); - foreach (Point3d vert in dbVertices) - { - vertices.AddRange(_pointConverter.Convert(vert).ToList()); - } - - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); - SOG.Mesh speckleMesh = new() { - vertices = vertices, + vertices = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(vertices), // transform by reference point faces = faces, colors = colors, units = _settingsStore.Current.SpeckleUnits, - bbox = bbox, ["faceVisibility"] = faceVisibility }; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline2dToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline2dToSpeckleConverter.cs index e6cdfe890..1b73a5a50 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline2dToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline2dToSpeckleConverter.cs @@ -19,30 +19,30 @@ public class Polyline2dToSpeckleConverter : IToSpeckleTopLevelConverter, ITypedConverter { + private readonly ITypedConverter, SOG.Polyline> _doublesConverter; private readonly ITypedConverter _arcConverter; private readonly ITypedConverter _lineConverter; - private readonly ITypedConverter _polylineConverter; private readonly ITypedConverter _splineConverter; private readonly ITypedConverter _vectorConverter; - private readonly ITypedConverter _boxConverter; + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; public Polyline2dToSpeckleConverter( + ITypedConverter, SOG.Polyline> doublesConverter, ITypedConverter arcConverter, ITypedConverter lineConverter, - ITypedConverter polylineConverter, ITypedConverter splineConverter, ITypedConverter vectorConverter, - ITypedConverter boxConverter, + IReferencePointConverter referencePointConverter, IConverterSettingsStore settingsStore ) { + _doublesConverter = doublesConverter; _arcConverter = arcConverter; _lineConverter = lineConverter; - _polylineConverter = polylineConverter; _splineConverter = splineConverter; _vectorConverter = vectorConverter; - _boxConverter = boxConverter; + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -85,11 +85,13 @@ public class Polyline2dToSpeckleConverter for (int i = 0; i < vertices.Count; i++) { - ADB.Vertex2d vertex = vertices[i]; + ADB.Vertex2d vertex = vertices[i]; // this is in OCS // get vertex value in the Global Coordinate System (GCS). - // NOTE: for some reason, the z value of the position for rotated polyline2ds doesn't seem to match the exploded segment endpoint values - value.AddRange(vertex.Position.ToArray()); + AG.Point3d vertexGCS = target.VertexPosition(vertex); + value.Add(vertexGCS.X); + value.Add(vertexGCS.Y); + value.Add(vertexGCS.Z); // get the bulge and tangent bulges.Add(vertex.Bulge); @@ -160,31 +162,31 @@ public class Polyline2dToSpeckleConverter if (isSpline) { SOG.Curve spline = _splineConverter.Convert(target.Spline); - SOG.Polyline displayValue = segmentValues.ConvertToSpecklePolyline(_settingsStore.Current.SpeckleUnits); - if (displayValue != null) - { - spline.displayValue = displayValue; - } - + spline.displayValue = _doublesConverter.Convert(segmentValues); segments.Add(spline); } - SOG.Vector normal = _vectorConverter.Convert(target.Normal); - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); + SOG.Vector normal = _vectorConverter.Convert(target.Normal); // wcs + + // get the elevation transformed by ucs + double elevation = _referencePointConverter.ConvertOCSElevationDoubleToExternalCoordinates( + target.Elevation, + target.Normal + ); + SOG.Autocad.AutocadPolycurve polycurve = new() { segments = segments, - value = value, + value = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(value), // convert with reference point bulges = bulges, tangents = tangents, normal = normal, - elevation = target.Elevation, + elevation = elevation, polyType = polyType, closed = target.Closed, length = target.Length, area = target.Area, - bbox = bbox, units = _settingsStore.Current.SpeckleUnits }; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline3dToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline3dToSpeckleConverter.cs index 76218142d..43a8e00ab 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline3dToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/Polyline3dToSpeckleConverter.cs @@ -18,21 +18,21 @@ public class Polyline3dToSpeckleConverter : IToSpeckleTopLevelConverter, ITypedConverter { - private readonly ITypedConverter _pointConverter; + private readonly ITypedConverter, SOG.Polyline> _doublesConverter; private readonly ITypedConverter _splineConverter; - private readonly ITypedConverter _boxConverter; + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; public Polyline3dToSpeckleConverter( - ITypedConverter pointConverter, + ITypedConverter, SOG.Polyline> doublesConverter, ITypedConverter splineConverter, - ITypedConverter boxConverter, + IReferencePointConverter referencePointConverter, IConverterSettingsStore settingsStore ) { - _pointConverter = pointConverter; + _doublesConverter = doublesConverter; _splineConverter = splineConverter; - _boxConverter = boxConverter; + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -56,7 +56,6 @@ public class Polyline3dToSpeckleConverter } // get all vertex data except control vertices - List value = new(); List vertices = target .GetSubEntities( ADB.OpenMode.ForRead, @@ -64,10 +63,13 @@ public class Polyline3dToSpeckleConverter ) .Where(e => e.VertexType != ADB.Vertex3dType.FitVertex) // Do not collect fit vertex points, they are not used for creation .ToList(); + List value = new(vertices.Count * 3); for (int i = 0; i < vertices.Count; i++) { // vertex value is in the Global Coordinate System (GCS). - value.AddRange(vertices[i].Position.ToArray()); + value.Add(vertices[i].Position.X); + value.Add(vertices[i].Position.Y); + value.Add(vertices[i].Position.Z); } List segments = new(); @@ -94,18 +96,15 @@ public class Polyline3dToSpeckleConverter } } - SOG.Polyline displayValue = segmentValues.ConvertToSpecklePolyline(_settingsStore.Current.SpeckleUnits); - if (displayValue != null) - { - spline.displayValue = displayValue; - } + // set displayValue of spline + spline.displayValue = _doublesConverter.Convert(segmentValues); segments.Add(spline); } // for simple polyline3ds just get the polyline segment from the value else { - SOG.Polyline polyline = value.ConvertToSpecklePolyline(_settingsStore.Current.SpeckleUnits); + SOG.Polyline polyline = _doublesConverter.Convert(value); if (target.Closed) { polyline.closed = true; @@ -114,8 +113,6 @@ public class Polyline3dToSpeckleConverter segments.Add(polyline); } - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); - SOG.Autocad.AutocadPolycurve polycurve = new() { @@ -123,11 +120,10 @@ public class Polyline3dToSpeckleConverter bulges = null, tangents = null, normal = null, - value = value, + value = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(value), // convert with reference point polyType = polyType, closed = target.Closed, length = target.Length, - bbox = bbox, units = _settingsStore.Current.SpeckleUnits }; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolylineToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolylineToSpeckleConverter.cs index da89a945b..6ad5630bd 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolylineToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/PolylineToSpeckleConverter.cs @@ -17,22 +17,23 @@ public class PolylineToSpeckleConverter { private readonly ITypedConverter _lineConverter; private readonly ITypedConverter _arcConverter; + private readonly ITypedConverter _vectorConverter; - private readonly ITypedConverter _boxConverter; + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; public PolylineToSpeckleConverter( ITypedConverter lineConverter, ITypedConverter arcConverter, ITypedConverter vectorConverter, - ITypedConverter boxConverter, + IReferencePointConverter referencePointConverter, IConverterSettingsStore settingsStore ) { _lineConverter = lineConverter; _arcConverter = arcConverter; _vectorConverter = vectorConverter; - _boxConverter = boxConverter; + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -45,9 +46,11 @@ public class PolylineToSpeckleConverter List segments = new(); for (int i = 0; i < target.NumberOfVertices; i++) { - // get vertex value in the Object Coordinate System (OCS) - AG.Point2d vertex = target.GetPoint2dAt(i); - value.AddRange(vertex.ToArray()); + // get vertex value in the World Coordinate System (WCS) + AG.Point3d vertex = target.GetPoint3dAt(i); + value.Add(vertex.X); + value.Add(vertex.Y); + value.Add(vertex.Z); // get the bulge bulges.Add(target.GetBulgeAt(i)); @@ -71,22 +74,26 @@ public class PolylineToSpeckleConverter } SOG.Vector normal = _vectorConverter.Convert(target.Normal); - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); + + // get the elevation transformed by ucs + double elevation = _referencePointConverter.ConvertOCSElevationDoubleToExternalCoordinates( + target.Elevation, + target.Normal + ); SOG.Autocad.AutocadPolycurve polycurve = new() { segments = segments, - value = value, + value = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(value), // convert with reference point bulges = bulges, normal = normal, tangents = null, - elevation = target.Elevation, + elevation = elevation, polyType = SOG.Autocad.AutocadPolyType.Light, closed = target.Closed, length = target.Length, area = target.Area, - bbox = bbox, units = _settingsStore.Current.SpeckleUnits }; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs index 608c31243..8514f4c93 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs @@ -1,85 +1,20 @@ using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; -using Speckle.Sdk; using Speckle.Sdk.Models; -namespace Speckle.Converters.Autocad.Geometry; +namespace Speckle.Converters.Autocad.ToSpeckle.Geometry; [NameAndRankValue(typeof(ADB.SubDMesh), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)] -public class DBSubDMeshToSpeckleConverter : IToSpeckleTopLevelConverter +public class SubDMeshToSpeckleConverter : IToSpeckleTopLevelConverter { - private readonly IConverterSettingsStore _settingsStore; + private readonly ITypedConverter _subDMeshConverter; - public DBSubDMeshToSpeckleConverter(IConverterSettingsStore settingsStore) + public SubDMeshToSpeckleConverter(ITypedConverter subDMeshConverter) { - _settingsStore = settingsStore; + _subDMeshConverter = subDMeshConverter; } - public Base Convert(object target) => RawConvert((ADB.SubDMesh)target); + public Base Convert(object target) => Convert((ADB.SubDMesh)target); - public SOG.Mesh RawConvert(ADB.SubDMesh target) - { - //vertices - var vertices = new List(target.Vertices.Count * 3); - foreach (AG.Point3d vert in target.Vertices) - { - vertices.Add(vert.X); - vertices.Add(vert.Y); - vertices.Add(vert.Z); - } - - // faces - var faces = new List(); - int[] faceArr = target.FaceArray.ToArray(); // contains vertex indices - int edgeCount = 0; - for (int i = 0; i < faceArr.Length; i = i + edgeCount + 1) - { - List faceVertices = new(); - edgeCount = faceArr[i]; - for (int j = i + 1; j <= i + edgeCount; j++) - { - faceVertices.Add(faceArr[j]); - } - - if (edgeCount == 4) // quad face - { - faces.AddRange(new List { 4, faceVertices[0], faceVertices[1], faceVertices[2], faceVertices[3] }); - } - else // triangle face - { - faces.AddRange(new List { 3, faceVertices[0], faceVertices[1], faceVertices[2] }); - } - } - - // colors - var colors = target - .VertexColorArray.Select(o => - System - .Drawing.Color.FromArgb( - System.Convert.ToInt32(o.Red), - System.Convert.ToInt32(o.Green), - System.Convert.ToInt32(o.Blue) - ) - .ToArgb() - ) - .ToList(); - - SOG.Mesh speckleMesh = - new() - { - vertices = vertices, - faces = faces, - colors = colors, - units = _settingsStore.Current.SpeckleUnits, - area = target.ComputeSurfaceArea() - }; - - try - { - speckleMesh.volume = target.ComputeVolume(); - } - catch (Exception e) when (!e.IsFatal()) { } // for non-volumetric meshes - - return speckleMesh; - } + public SOG.Mesh Convert(ADB.SubDMesh target) => _subDMeshConverter.Convert(target); } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs index b97ed7727..fda77d849 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs @@ -7,10 +7,15 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class BrepToSpeckleRawConverter : ITypedConverter { + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; - public BrepToSpeckleRawConverter(IConverterSettingsStore settingsStore) + public BrepToSpeckleRawConverter( + IReferencePointConverter referencePointConverter, + IConverterSettingsStore settingsStore + ) { + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -65,7 +70,7 @@ public class BrepToSpeckleRawConverter : ITypedConverter new() { faces = faces, - vertices = vertices, + vertices = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(vertices), // transform by reference point units = _settingsStore.Current.SpeckleUnits, area = target.GetSurfaceArea() }; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/CircularArc2dToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/CircularArc2dToSpeckleRawConverter.cs index 5b16e80f6..39c474736 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/CircularArc2dToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/CircularArc2dToSpeckleRawConverter.cs @@ -5,14 +5,17 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class CircularArc2dToSpeckleRawConverter : ITypedConverter { + private readonly ITypedConverter _pointConverter; private readonly ITypedConverter _planeConverter; private readonly IConverterSettingsStore _settingsStore; public CircularArc2dToSpeckleRawConverter( + ITypedConverter pointConverter, ITypedConverter planeConverter, IConverterSettingsStore settingsStore ) { + _pointConverter = pointConverter; _planeConverter = planeConverter; _settingsStore = settingsStore; } @@ -35,27 +38,9 @@ public class CircularArc2dToSpeckleRawConverter : ITypedConverter { private readonly ITypedConverter _pointConverter; private readonly ITypedConverter _planeConverter; - private readonly ITypedConverter _boxConverter; private readonly IConverterSettingsStore _settingsStore; public DBArcToSpeckleRawConverter( ITypedConverter pointConverter, ITypedConverter planeConverter, - ITypedConverter boxConverter, IConverterSettingsStore settingsStore ) { _pointConverter = pointConverter; _planeConverter = planeConverter; - _boxConverter = boxConverter; _settingsStore = settingsStore; } @@ -33,7 +30,6 @@ public class DBArcToSpeckleRawConverter : ITypedConverter SOG.Point end = _pointConverter.Convert(target.EndPoint); SOG.Point mid = _pointConverter.Convert(target.GetPointAtDist(target.Length / 2.0)); SOP.Interval domain = new() { start = target.StartParam, end = target.EndParam }; - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); SOG.Arc arc = new() @@ -43,7 +39,6 @@ public class DBArcToSpeckleRawConverter : ITypedConverter endPoint = end, midPoint = mid, domain = domain, - bbox = bbox, units = _settingsStore.Current.SpeckleUnits }; diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCircleToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCircleToSpeckleRawConverter.cs index 7d63f6ee8..b84bd4e9b 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCircleToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCircleToSpeckleRawConverter.cs @@ -7,17 +7,14 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class DBCircleToSpeckleRawConverter : ITypedConverter { private readonly ITypedConverter _planeConverter; - private readonly ITypedConverter _boxConverter; private readonly IConverterSettingsStore _settingsStore; public DBCircleToSpeckleRawConverter( ITypedConverter planeConverter, - ITypedConverter boxConverter, IConverterSettingsStore settingsStore ) { _planeConverter = planeConverter; - _boxConverter = boxConverter; _settingsStore = settingsStore; } @@ -26,14 +23,12 @@ public class DBCircleToSpeckleRawConverter : ITypedConverter _circleConverter; private readonly ITypedConverter _ellipseConverter; private readonly ITypedConverter _splineConverter; - private readonly IConverterSettingsStore _settingsStore; public DBCurveToSpeckleRawConverter( ITypedConverter lineConverter, @@ -25,8 +23,7 @@ public class DBCurveToSpeckleRawConverter : ITypedConverter arcConverter, ITypedConverter circleConverter, ITypedConverter ellipseConverter, - ITypedConverter splineConverter, - IConverterSettingsStore settingsStore + ITypedConverter splineConverter ) { _lineConverter = lineConverter; @@ -37,7 +34,6 @@ public class DBCurveToSpeckleRawConverter : ITypedConverter diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBEllipseToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBEllipseToSpeckleRawConverter.cs index 39acc0a66..9dc8ac5bd 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBEllipseToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBEllipseToSpeckleRawConverter.cs @@ -6,18 +6,18 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class DBEllipseToSpeckleRawConverter : ITypedConverter { - private readonly ITypedConverter _planeConverter; - private readonly ITypedConverter _boxConverter; + private readonly ITypedConverter _pointConverter; + private readonly ITypedConverter _vectorConverter; private readonly IConverterSettingsStore _settingsStore; public DBEllipseToSpeckleRawConverter( - ITypedConverter planeConverter, - ITypedConverter boxConverter, + ITypedConverter pointConverter, + ITypedConverter vectorConverter, IConverterSettingsStore settingsStore ) { - _planeConverter = planeConverter; - _boxConverter = boxConverter; + _pointConverter = pointConverter; + _vectorConverter = vectorConverter; _settingsStore = settingsStore; } @@ -25,8 +25,15 @@ public class DBEllipseToSpeckleRawConverter : ITypedConverter { private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _boxConverter; private readonly IConverterSettingsStore _settingsStore; public DBLineToSpeckleRawConverter( ITypedConverter pointConverter, - ITypedConverter boxConverter, IConverterSettingsStore settingsStore ) { _pointConverter = pointConverter; - _boxConverter = boxConverter; _settingsStore = settingsStore; } @@ -28,8 +25,7 @@ public class DBLineToSpeckleRawConverter : ITypedConverter { start = _pointConverter.Convert(target.StartPoint), end = _pointConverter.Convert(target.EndPoint), - units = _settingsStore.Current.SpeckleUnits, domain = new SOP.Interval { start = 0, end = target.Length }, - bbox = _boxConverter.Convert(target.GeometricExtents) + units = _settingsStore.Current.SpeckleUnits }; } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSplineToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSplineToSpeckleRawConverter.cs index 608da74b8..41d5bb5dc 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSplineToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSplineToSpeckleRawConverter.cs @@ -8,18 +8,21 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class DBSplineToSpeckleRawConverter : ITypedConverter { + private readonly ITypedConverter, SOG.Polyline> _doublesConverter; private readonly ITypedConverter _intervalConverter; - private readonly ITypedConverter _boxConverter; + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; public DBSplineToSpeckleRawConverter( + ITypedConverter, SOG.Polyline> doublesConverter, ITypedConverter intervalConverter, - ITypedConverter boxConverter, + IReferencePointConverter referencePointConverter, IConverterSettingsStore settingsStore ) { + _doublesConverter = doublesConverter; _intervalConverter = intervalConverter; - _boxConverter = boxConverter; + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -44,11 +47,11 @@ public class DBSplineToSpeckleRawConverter : ITypedConverter points = new(); foreach (Point3d point in data.GetControlPoints().OfType()) { - points.Add(point); + points.Add(_referencePointConverter.ConvertWCSPointToExternalCoordinates(point)); } // NOTE: for closed periodic splines, autocad does not track last #degree points. @@ -108,7 +111,6 @@ public class DBSplineToSpeckleRawConverter : ITypedConverter +{ + private readonly IReferencePointConverter _referencePointConverter; + private readonly IConverterSettingsStore _settingsStore; + + public DBSubDMeshToSpeckleRawConverter( + IReferencePointConverter referencePointConverter, + IConverterSettingsStore settingsStore + ) + { + _referencePointConverter = referencePointConverter; + _settingsStore = settingsStore; + } + + public SOG.Mesh Convert(ADB.SubDMesh target) + { + // vertices + List vertices = new(target.Vertices.Count * 3); + foreach (AG.Point3d vert in target.Vertices) + { + vertices.Add(vert.X); + vertices.Add(vert.Y); + vertices.Add(vert.Z); + } + + // faces + List faces = new(); + int[] faceArr = target.FaceArray.ToArray(); // contains vertex indices + int edgeCount = 0; + for (int i = 0; i < faceArr.Length; i = i + edgeCount + 1) + { + List faceVertices = new(); + edgeCount = faceArr[i]; + for (int j = i + 1; j <= i + edgeCount; j++) + { + faceVertices.Add(faceArr[j]); + } + + if (edgeCount == 4) // quad face + { + faces.AddRange(new List { 4, faceVertices[0], faceVertices[1], faceVertices[2], faceVertices[3] }); + } + else // triangle face + { + faces.AddRange(new List { 3, faceVertices[0], faceVertices[1], faceVertices[2] }); + } + } + + // colors + var colors = target + .VertexColorArray.Select(o => + System + .Drawing.Color.FromArgb( + System.Convert.ToInt32(o.Red), + System.Convert.ToInt32(o.Green), + System.Convert.ToInt32(o.Blue) + ) + .ToArgb() + ) + .ToList(); + + SOG.Mesh speckleMesh = + new() + { + vertices = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(vertices), // transform with reference point + faces = faces, + colors = colors, + units = _settingsStore.Current.SpeckleUnits, + area = target.ComputeSurfaceArea() + }; + + try + { + speckleMesh.volume = target.ComputeVolume(); + } + catch (Exception e) when (!e.IsFatal()) { } // for non-volumetric meshes + + return speckleMesh; + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBTextToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBTextToSpeckleRawConverter.cs index e245808f3..f14fb7e41 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBTextToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBTextToSpeckleRawConverter.cs @@ -1,3 +1,4 @@ +using Speckle.Converters.Autocad.Helpers; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; using Speckle.Objects.Annotation; @@ -7,17 +8,17 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class DBTextToSpeckleRawConverter : ITypedConverter { private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _planeConverter; + private readonly ITypedConverter _vectorConverter; private readonly IConverterSettingsStore _settingsStore; public DBTextToSpeckleRawConverter( ITypedConverter pointConverter, - ITypedConverter planeConverter, + ITypedConverter vectorConverter, IConverterSettingsStore settingsStore ) { _pointConverter = pointConverter; - _planeConverter = planeConverter; + _vectorConverter = vectorConverter; _settingsStore = settingsStore; } @@ -41,15 +42,24 @@ public class DBTextToSpeckleRawConverter : ITypedConverter units = _settingsStore.Current.SpeckleUnits }; + // For DBText, the following properties are stored in: + // - Position: WCS + // - Normal: WCS + // - Rotation: OCS -> WCS https://help.autodesk.com/view/OARX/2020/ENU/?guid=OARX-ManagedRefGuide-Autodesk_AutoCAD_DatabaseServices_DBText_Rotation private SOG.Plane GetTextPlane(ADB.DBText target) { - AG.Plane plane = new(target.Position, target.Normal); + // Rotation prop is in OCS: calculate the x and y axis based in WCS + AG.Matrix3d transform = TransformHelper.GetTransformFromOCSToWCS(target.Normal).Inverse(); + AG.Vector3d xDir = AG.Vector3d.XAxis.RotateBy(target.Rotation, target.Normal).TransformBy(transform); + AG.Vector3d yDir = AG.Vector3d.YAxis.RotateBy(target.Rotation, target.Normal).TransformBy(transform); - if (target.Rotation != 0) + return new() { - plane.RotateBy(target.Rotation, target.Normal, target.Position); - } - - return _planeConverter.Convert(plane); + origin = _pointConverter.Convert(target.Position), + normal = _vectorConverter.Convert(target.Normal), + xdir = _vectorConverter.Convert(xDir), + ydir = _vectorConverter.Convert(yDir), + units = _settingsStore.Current.SpeckleUnits, + }; } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DoublesToSpecklePolylineRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DoublesToSpecklePolylineRawConverter.cs new file mode 100644 index 000000000..c041ff39d --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DoublesToSpecklePolylineRawConverter.cs @@ -0,0 +1,32 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Autocad.ToSpeckle.Raw; + +public class DoublesToSpeckleRawConverter : ITypedConverter, SOG.Polyline> +{ + private readonly IReferencePointConverter _referencePointConverter; + private readonly IConverterSettingsStore _settingsStore; + + public DoublesToSpeckleRawConverter( + IConverterSettingsStore settingsStore, + IReferencePointConverter referencePointConverter + ) + { + _settingsStore = settingsStore; + _referencePointConverter = referencePointConverter; + } + + public SOG.Polyline Convert(List target) + { + // throw if list is malformed + if (target.Count % 3 != 0) + { + throw new ArgumentException("Point list of xyz values is malformed", nameof(target)); + } + + List value = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(target); + + return new() { value = value, units = _settingsStore.Current.SpeckleUnits }; + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/MTextToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/MTextToSpeckleRawConverter.cs index d4a55addc..e163f39c0 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/MTextToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/MTextToSpeckleRawConverter.cs @@ -6,17 +6,17 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class MTextToSpeckleRawConverter : ITypedConverter { private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _planeConverter; + private readonly ITypedConverter _vectorConverter; private readonly IConverterSettingsStore _settingsStore; public MTextToSpeckleRawConverter( ITypedConverter pointConverter, - ITypedConverter planeConverter, + ITypedConverter vectorConverter, IConverterSettingsStore settingsStore ) { _pointConverter = pointConverter; - _planeConverter = planeConverter; + _vectorConverter = vectorConverter; _settingsStore = settingsStore; } @@ -38,16 +38,28 @@ public class MTextToSpeckleRawConverter : ITypedConverter units = _settingsStore.Current.SpeckleUnits }; + // For MText, the following properties are stored in: + // - Position: WCS + // - Normal: WCS?? + // - Rotation: OCS -> UCS?? https://help.autodesk.com/view/OARX/2020/ENU/?guid=OARX-ManagedRefGuide-Autodesk_AutoCAD_DatabaseServices_MText_Rotation + // "Accesses the angle between the X axis of the OCS for the normal vector of the current AutoCAD editor's UCS + // and the projection of the MText object's direction vector onto the plane of the AutoCAD editor's current UCS." + // - Direction: WCS + // "Note that the direction vector need not be orthogonal to the normal vector." <- do not use FML private SOG.Plane GetTextPlane(ADB.MText target) { - AG.Plane plane = new(target.Location, target.Normal); + // Rotation prop is in UCS already: do NOT use vector converter or it will transform again! + AG.Vector3d xDir = AG.Vector3d.XAxis.RotateBy(target.Rotation, target.Normal); + AG.Vector3d yDir = AG.Vector3d.YAxis.RotateBy(target.Rotation, target.Normal); - if (target.Rotation != 0) + return new() { - plane.RotateBy(target.Rotation, target.Normal, target.Location); - } - - return _planeConverter.Convert(plane); + origin = _pointConverter.Convert(target.Location), + normal = _vectorConverter.Convert(target.Normal), + xdir = new(xDir.X, xDir.Y, xDir.Z, _settingsStore.Current.SpeckleUnits), + ydir = new(yDir.X, yDir.Y, yDir.Z, _settingsStore.Current.SpeckleUnits), + units = _settingsStore.Current.SpeckleUnits, + }; } /// diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PlaneToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PlaneToSpeckleRawConverter.cs index 6a24731ed..1b1377d1e 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PlaneToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PlaneToSpeckleRawConverter.cs @@ -23,13 +23,16 @@ public class PlaneToSpeckleRawConverter : ITypedConverter public Base Convert(object target) => Convert((AG.Plane)target); - public SOG.Plane Convert(AG.Plane target) => - new() + public SOG.Plane Convert(AG.Plane target) + { + AG.CoordinateSystem3d cs = target.GetCoordinateSystem(); // TODO: validate if this returns the coordinate system in GCS or already transformed + return new() { origin = _pointConverter.Convert(target.PointOnPlane), normal = _vectorConverter.Convert(target.Normal), - xdir = _vectorConverter.Convert(target.GetCoordinateSystem().Xaxis), - ydir = _vectorConverter.Convert(target.GetCoordinateSystem().Yaxis), + xdir = _vectorConverter.Convert(cs.Xaxis), + ydir = _vectorConverter.Convert(cs.Yaxis), units = _settingsStore.Current.SpeckleUnits, }; + } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point2dToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point2dToSpeckleRawConverter.cs new file mode 100644 index 000000000..dd450d2b2 --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point2dToSpeckleRawConverter.cs @@ -0,0 +1,26 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Autocad.ToSpeckle.Raw; + +public class Point2dToSpeckleRawConverter : ITypedConverter +{ + private readonly IConverterSettingsStore _settingsStore; + private readonly IReferencePointConverter _referencePointConverter; + + public Point2dToSpeckleRawConverter( + IConverterSettingsStore settingsStore, + IReferencePointConverter referencePointConverter + ) + { + _settingsStore = settingsStore; + _referencePointConverter = referencePointConverter; + } + + public SOG.Point Convert(AG.Point2d target) + { + var extPt = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(new(3) { target.X, target.Y, 0 }); + + return new(extPt[0], extPt[1], extPt[2], _settingsStore.Current.SpeckleUnits); + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point3dToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point3dToSpeckleRawConverter.cs new file mode 100644 index 000000000..10118ea7e --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Point3dToSpeckleRawConverter.cs @@ -0,0 +1,25 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Autocad.ToSpeckle.Raw; + +public class Point3dToSpeckleRawConverter : ITypedConverter +{ + private readonly IConverterSettingsStore _settingsStore; + private readonly IReferencePointConverter _referencePointConverter; + + public Point3dToSpeckleRawConverter( + IConverterSettingsStore settingsStore, + IReferencePointConverter referencePointConverter + ) + { + _settingsStore = settingsStore; + _referencePointConverter = referencePointConverter; + } + + public SOG.Point Convert(AG.Point3d target) + { + AG.Point3d extPt = _referencePointConverter.ConvertWCSPointToExternalCoordinates(target); + return new(extPt.X, extPt.Y, extPt.Z, _settingsStore.Current.SpeckleUnits); + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PointToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PointToSpeckleRawConverter.cs deleted file mode 100644 index a1e71fc87..000000000 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/PointToSpeckleRawConverter.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Speckle.Converters.Common; -using Speckle.Converters.Common.Objects; - -namespace Speckle.Converters.Autocad.ToSpeckle.Raw; - -public class PointToSpeckleRawConverter : ITypedConverter -{ - private readonly IConverterSettingsStore _settingsStore; - - public PointToSpeckleRawConverter(IConverterSettingsStore settingsStore) - { - _settingsStore = settingsStore; - } - - public SOG.Point Convert(AG.Point3d target) => new(target.X, target.Y, target.Z, _settingsStore.Current.SpeckleUnits); -} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Vector3dToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Vector3dToSpeckleRawConverter.cs new file mode 100644 index 000000000..817bcbcea --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/Vector3dToSpeckleRawConverter.cs @@ -0,0 +1,25 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Autocad.ToSpeckle.Raw; + +public class Vector3dToSpeckleRawConverter : ITypedConverter +{ + private readonly IConverterSettingsStore _settingsStore; + private readonly IReferencePointConverter _referencePointConverter; + + public Vector3dToSpeckleRawConverter( + IConverterSettingsStore settingsStore, + IReferencePointConverter referencePointConverter + ) + { + _settingsStore = settingsStore; + _referencePointConverter = referencePointConverter; + } + + public SOG.Vector Convert(AG.Vector3d target) + { + AG.Vector3d extVector = _referencePointConverter.ConvertWCSVectorToExternalCoordinates(target); + return new(extVector.X, extVector.Y, extVector.Z, _settingsStore.Current.SpeckleUnits); + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/VectorToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/VectorToSpeckleRawConverter.cs deleted file mode 100644 index 6c9dddf68..000000000 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/VectorToSpeckleRawConverter.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Speckle.Converters.Common; -using Speckle.Converters.Common.Objects; - -namespace Speckle.Converters.Autocad.ToSpeckle.Raw; - -public class VectorToSpeckleRawConverter : ITypedConverter -{ - private readonly IConverterSettingsStore _settingsStore; - - public VectorToSpeckleRawConverter(IConverterSettingsStore settingsStore) - { - _settingsStore = settingsStore; - } - - public SOG.Vector Convert(AG.Vector3d target) => - new(target.X, target.Y, target.Z, _settingsStore.Current.SpeckleUnits); -} diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs index ef33264a0..bfcd4cfa1 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs @@ -34,6 +34,7 @@ public static class ServiceRegistration IConverterSettingsStore, ConverterSettingsStore >(); + serviceCollection.AddScoped(); // add other classes serviceCollection.AddScoped(); // for civil diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentityArcToSpeckleRawConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentityArcToSpeckleRawConverter.cs index 1bb7a4a4e..ca00e4bc4 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentityArcToSpeckleRawConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentityArcToSpeckleRawConverter.cs @@ -6,14 +6,17 @@ namespace Speckle.Converters.Civil3dShared.ToSpeckle.Raw; public class AlignmentSubentityArcToSpeckleRawConverter : ITypedConverter { + private readonly ITypedConverter _pointConverter; private readonly ITypedConverter _planeConverter; private readonly IConverterSettingsStore _settingsStore; public AlignmentSubentityArcToSpeckleRawConverter( + ITypedConverter pointConverter, ITypedConverter planeConverter, IConverterSettingsStore settingsStore ) { + _pointConverter = pointConverter; _planeConverter = planeConverter; _settingsStore = settingsStore; } @@ -53,27 +56,9 @@ public class AlignmentSubentityArcToSpeckleRawConverter : ITypedConverter { private readonly IConverterSettingsStore _settingsStore; + private readonly ITypedConverter _pointConverter; - public AlignmentSubentityLineToSpeckleRawConverter(IConverterSettingsStore settingsStore) + public AlignmentSubentityLineToSpeckleRawConverter( + IConverterSettingsStore settingsStore, + ITypedConverter pointConverter + ) { _settingsStore = settingsStore; + _pointConverter = pointConverter; } public SOG.Line Convert(object target) => Convert((CDB.AlignmentSubEntityLine)target); public SOG.Line Convert(CDB.AlignmentSubEntityLine target) { - SOG.Point start = - new() - { - x = target.StartPoint.X, - y = target.StartPoint.Y, - z = 0, - units = _settingsStore.Current.SpeckleUnits - }; - - SOG.Point end = - new() - { - x = target.EndPoint.X, - y = target.EndPoint.Y, - z = 0, - units = _settingsStore.Current.SpeckleUnits - }; + SOG.Point start = _pointConverter.Convert(target.StartPoint); + SOG.Point end = _pointConverter.Convert(target.EndPoint); SOG.Line line = new() diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentitySpiralToSpeckleRawConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentitySpiralToSpeckleRawConverter.cs index 2a7f70b8a..0ec8a653b 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentitySpiralToSpeckleRawConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/AlignmentSubentitySpiralToSpeckleRawConverter.cs @@ -1,3 +1,4 @@ +using Speckle.Converters.Autocad; using Speckle.Converters.Civil3dShared.Helpers; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; @@ -7,10 +8,15 @@ namespace Speckle.Converters.Civil3dShared.ToSpeckle.Raw; public class AlignmentSubentitySpiralToSpeckleRawConverter : ITypedConverter<(CDB.AlignmentSubEntitySpiral, CDB.Alignment), SOG.Polyline> { + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; - public AlignmentSubentitySpiralToSpeckleRawConverter(IConverterSettingsStore settingsStore) + public AlignmentSubentitySpiralToSpeckleRawConverter( + IReferencePointConverter referencePointConverter, + IConverterSettingsStore settingsStore + ) { + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -45,7 +51,7 @@ public class AlignmentSubentitySpiralToSpeckleRawConverter SOG.Polyline polyline = new() { - value = polylineValue, + value = _referencePointConverter.ConvertWCSDoublesToExternalCoordinates(polylineValue), // convert by ref point transform units = units, closed = spiral.StartPoint == spiral.EndPoint }; diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs index 87f1637e1..de0bd426f 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs @@ -1,4 +1,4 @@ -using Autodesk.AutoCAD.Geometry; +using Speckle.Converters.Autocad; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; @@ -6,10 +6,15 @@ namespace Speckle.Converters.Civil3dShared.ToSpeckle.Raw; public class GridSurfaceToSpeckleMeshRawConverter : ITypedConverter { + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; - public GridSurfaceToSpeckleMeshRawConverter(IConverterSettingsStore settingsStore) + public GridSurfaceToSpeckleMeshRawConverter( + IReferencePointConverter referencePointConverter, + IConverterSettingsStore settingsStore + ) { + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -19,14 +24,14 @@ public class GridSurfaceToSpeckleMeshRawConverter : ITypedConverter vertices = new(); List faces = new(); - Dictionary indices = new(); + Dictionary indices = new(); int indexCounter = 0; foreach (var cell in target.GetCells(false)) { try { - Point3d[] cellVertices = + AG.Point3d[] cellVertices = { cell.BottomLeftVertex.Location, cell.BottomRightVertex.Location, @@ -34,7 +39,7 @@ public class GridSurfaceToSpeckleMeshRawConverter : ITypedConverter { + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; - public Point3dCollectionToSpeckleRawConverter(IConverterSettingsStore settingsStore) + public Point3dCollectionToSpeckleRawConverter( + IReferencePointConverter referencePointConverter, + IConverterSettingsStore settingsStore + ) { + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -33,7 +39,7 @@ public class Point3dCollectionToSpeckleRawConverter : ITypedConverter { + private readonly IReferencePointConverter _referencePointConverter; private readonly IConverterSettingsStore _settingsStore; - public TinSurfaceToSpeckleMeshRawConverter(IConverterSettingsStore settingsStore) + public TinSurfaceToSpeckleMeshRawConverter( + IReferencePointConverter referencePointConverter, + IConverterSettingsStore settingsStore + ) { + _referencePointConverter = referencePointConverter; _settingsStore = settingsStore; } @@ -60,7 +66,7 @@ public class TinSurfaceToSpeckleMeshRawConverter : ITypedConverter void AddInstanceProxy(string objectId, InstanceProxy instanceProxy); void AddDefinitionProxy(string objectId, InstanceDefinitionProxy instanceDefinitionProxy); void AddAtomicObject(string objectId, THostObjectType obj); + void AddAtomicDefinitionObjectId(string objectId); void AddInstanceProxiesByDefinitionId(string definitionId, List instanceProxies); UnpackResult GetUnpackResult(); bool TryGetInstanceProxiesFromDefinitionId( diff --git a/Sdk/Speckle.Connectors.Common/Instances/InstanceObjectsManager.cs b/Sdk/Speckle.Connectors.Common/Instances/InstanceObjectsManager.cs index 2af8cb20e..b67ba455f 100644 --- a/Sdk/Speckle.Connectors.Common/Instances/InstanceObjectsManager.cs +++ b/Sdk/Speckle.Connectors.Common/Instances/InstanceObjectsManager.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using Speckle.Sdk.Models.Instances; namespace Speckle.Connectors.Common.Instances; @@ -10,6 +10,7 @@ public class InstanceObjectsManager private readonly Dictionary> _instanceProxiesByDefinitionId = new(); private readonly Dictionary _definitionProxies = new(); private readonly Dictionary _flatAtomicObjects = new(); + private readonly HashSet _flatAtomicDefinitionObjectIds = new(); public void AddInstanceProxy(string objectId, InstanceProxy instanceProxy) => _instanceProxies[objectId] = instanceProxy; @@ -19,11 +20,13 @@ public class InstanceObjectsManager public void AddAtomicObject(string objectId, THostObjectType obj) => _flatAtomicObjects[objectId] = obj; + public void AddAtomicDefinitionObjectId(string objectId) => _flatAtomicDefinitionObjectIds.Add(objectId); + public void AddInstanceProxiesByDefinitionId(string definitionId, List instanceProxies) => _instanceProxiesByDefinitionId[definitionId] = instanceProxies; public UnpackResult GetUnpackResult() => - new(GetAtomicObjects(), GetInstanceProxies(), GetDefinitionProxies()); + new(GetAtomicObjects(), GetAtomicDefinitionObjectIds(), GetInstanceProxies(), GetDefinitionProxies()); public bool TryGetInstanceProxiesFromDefinitionId( string definitionId, @@ -58,6 +61,8 @@ public class InstanceObjectsManager private List GetAtomicObjects() => _flatAtomicObjects.Values.ToList(); + private HashSet GetAtomicDefinitionObjectIds() => _flatAtomicDefinitionObjectIds; + private List GetDefinitionProxies() => _definitionProxies.Values.ToList(); private Dictionary GetInstanceProxies() => _instanceProxies; diff --git a/Sdk/Speckle.Connectors.Common/Instances/UnpackResult.cs b/Sdk/Speckle.Connectors.Common/Instances/UnpackResult.cs index 6d311c785..26246a81d 100644 --- a/Sdk/Speckle.Connectors.Common/Instances/UnpackResult.cs +++ b/Sdk/Speckle.Connectors.Common/Instances/UnpackResult.cs @@ -4,6 +4,7 @@ namespace Speckle.Connectors.Common.Instances; public record UnpackResult( List AtomicObjects, + HashSet AtomicDefinitionObjectIds, Dictionary InstanceProxies, List InstanceDefinitionProxies );