From f53e52bbfef8e76cd57bd7065ac843f6112ca909 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Tue, 3 Dec 2024 13:39:41 +0000 Subject: [PATCH] feat(autocad): adds surface and region converters (#428) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * adds surface and region converter also adds brep raw converter and refactors existing converters to avoid duplicate logic * Update Speckle.Connectors.sln --------- Co-authored-by: Oğuzhan Koral <45078678+oguzhankoral@users.noreply.github.com> --- .../Bindings/AutocadBasicConnectorBinding.cs | 1 + ...Speckle.Converters.AutocadShared.projitems | 3 + .../Geometry/RegionToSpeckleConverter.cs | 33 ++++++++ .../Geometry/SubDMeshToSpeckleConverter.cs | 22 ++--- .../Geometry/SurfaceToSpeckleConverter.cs | 30 +++++++ .../Raw/BrepToSpeckleRawConverter.cs | 82 +++++++++++++++++++ .../Raw/DBBodyToSpeckleRawConverter.cs | 71 +--------------- .../Raw/DBSolid3dToSpeckleRawConverter.cs | 65 +-------------- 8 files changed, 166 insertions(+), 141 deletions(-) create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/RegionToSpeckleConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SurfaceToSpeckleConverter.cs create mode 100644 Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs index 01427f425..5a976f0fc 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Bindings/AutocadBasicConnectorBinding.cs @@ -165,6 +165,7 @@ await Parent { // Note: we're swallowing exeptions here because of a weird case when receiving blocks, we would have // acad api throw an error on accessing entity.GeometricExtents. + // may also throw Autodesk.AutoCAD.Runtime.Exception for invalid extents on objects like rays and xlines } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems b/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems index b4966066f..30fd7c666 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/Speckle.Converters.AutocadShared.projitems @@ -41,7 +41,10 @@ + + + diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/RegionToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/RegionToSpeckleConverter.cs new file mode 100644 index 000000000..4723e50ac --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/RegionToSpeckleConverter.cs @@ -0,0 +1,33 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; +using Speckle.Sdk.Common.Exceptions; +using Speckle.Sdk.Models; + +namespace Speckle.Converters.Autocad.Geometry; + +[NameAndRankValue(nameof(ADB.Region), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)] +public class RegionToSpeckleConverter : IToSpeckleTopLevelConverter, ITypedConverter +{ + private readonly ITypedConverter _brepConverter; + + public RegionToSpeckleConverter(ITypedConverter brepConverter) + { + _brepConverter = brepConverter; + } + + public Base Convert(object target) => Convert((ADB.Region)target); + + public SOG.Mesh Convert(ADB.Region target) + { + using ABR.Brep brep = new(target); + if (brep.IsNull) + { + throw new ConversionException("Could not retrieve brep from the region."); + } + + SOG.Mesh mesh = _brepConverter.Convert(brep); + mesh.area = target.Area; + + return mesh; + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs index 6e168f9a7..996b0e1db 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs @@ -1,5 +1,6 @@ using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; +using Speckle.Sdk; using Speckle.Sdk.Models; namespace Speckle.Converters.Autocad.Geometry; @@ -7,18 +8,10 @@ namespace Speckle.Converters.Autocad.Geometry; [NameAndRankValue(nameof(ADB.SubDMesh), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)] public class DBSubDMeshToSpeckleConverter : IToSpeckleTopLevelConverter { - private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _boxConverter; private readonly IConverterSettingsStore _settingsStore; - public DBSubDMeshToSpeckleConverter( - ITypedConverter pointConverter, - ITypedConverter boxConverter, - IConverterSettingsStore settingsStore - ) + public DBSubDMeshToSpeckleConverter(IConverterSettingsStore settingsStore) { - _pointConverter = pointConverter; - _boxConverter = boxConverter; _settingsStore = settingsStore; } @@ -71,9 +64,6 @@ public SOG.Mesh RawConvert(ADB.SubDMesh target) ) .ToList(); - // bbox - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); - SOG.Mesh speckleMesh = new() { @@ -81,9 +71,15 @@ public SOG.Mesh RawConvert(ADB.SubDMesh target) faces = faces, colors = colors, units = _settingsStore.Current.SpeckleUnits, - bbox = bbox + 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/Geometry/SurfaceToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SurfaceToSpeckleConverter.cs new file mode 100644 index 000000000..e15d5f3e1 --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SurfaceToSpeckleConverter.cs @@ -0,0 +1,30 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; +using Speckle.Sdk.Common.Exceptions; +using Speckle.Sdk.Models; + +namespace Speckle.Converters.Autocad.Geometry; + +[NameAndRankValue(nameof(ADB.Surface), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)] +public class SurfaceToSpeckleConverter : IToSpeckleTopLevelConverter, ITypedConverter +{ + private readonly ITypedConverter _brepConverter; + + public SurfaceToSpeckleConverter(ITypedConverter brepConverter) + { + _brepConverter = brepConverter; + } + + public Base Convert(object target) => Convert((ADB.Surface)target); + + public SOG.Mesh Convert(ADB.Surface target) + { + using ABR.Brep brep = new(target); + if (brep.IsNull) + { + throw new ConversionException("Could not retrieve brep from the plane surface."); + } + + return _brepConverter.Convert(brep); + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs new file mode 100644 index 000000000..b97ed7727 --- /dev/null +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/BrepToSpeckleRawConverter.cs @@ -0,0 +1,82 @@ +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; +using Speckle.Sdk; +using Speckle.Sdk.Common.Exceptions; + +namespace Speckle.Converters.Autocad.ToSpeckle.Raw; + +public class BrepToSpeckleRawConverter : ITypedConverter +{ + private readonly IConverterSettingsStore _settingsStore; + + public BrepToSpeckleRawConverter(IConverterSettingsStore settingsStore) + { + _settingsStore = settingsStore; + } + + public SOG.Mesh Convert(ABR.Brep target) + { + if (target.IsNull) + { + throw new ConversionException("Brep was null."); + } + + List faces = new(); + List vertices = new(); + int vertexCount = 0; + + using (var control = new ABR.Mesh2dControl()) + { + // These settings may need adjusting + control.MaxSubdivisions = 10000; + + // create mesh filters + using (var filter = new ABR.Mesh2dFilter()) + { + filter.Insert(target, control); + using (ABR.Mesh2d m = new(filter)) + { + foreach (ABR.Element2d? e in m.Element2ds) + { + // add number of vertices for this face + int nodeCount = e.Nodes.Count(); + faces.Add(nodeCount); + + foreach (var n in e.Nodes) + { + // add index of current vertex to face + faces.Add(vertexCount); + vertexCount++; + + // add vertex coords + vertices.Add(n.Point.X); + vertices.Add(n.Point.Y); + vertices.Add(n.Point.Z); + n.Dispose(); + } + + e.Dispose(); + } + } + } + + // create speckle mesh + SOG.Mesh mesh = + new() + { + faces = faces, + vertices = vertices, + units = _settingsStore.Current.SpeckleUnits, + area = target.GetSurfaceArea() + }; + + try + { + mesh.volume = target.GetVolume(); + } + catch (ABR.Exception e) when (!e.IsFatal()) { } // exceptions can be thrown for non-volumetric breps + + return mesh; + } + } +} diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBBodyToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBBodyToSpeckleRawConverter.cs index 39eb631eb..af31c3469 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBBodyToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBBodyToSpeckleRawConverter.cs @@ -1,6 +1,4 @@ -using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; -using Speckle.Sdk; using Speckle.Sdk.Common.Exceptions; using Speckle.Sdk.Models; @@ -8,19 +6,11 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class DBBodyToSpeckleRawConverter : ITypedConverter { - private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _boxConverter; - private readonly IConverterSettingsStore _settingsStore; + private readonly ITypedConverter _brepConverter; - public DBBodyToSpeckleRawConverter( - ITypedConverter pointConverter, - ITypedConverter boxConverter, - IConverterSettingsStore settingsStore - ) + public DBBodyToSpeckleRawConverter(ITypedConverter brepConverter) { - _pointConverter = pointConverter; - _boxConverter = boxConverter; - _settingsStore = settingsStore; + _brepConverter = brepConverter; } public Base Convert(object target) => Convert((ADB.Body)target); @@ -33,59 +23,6 @@ public SOG.Mesh Convert(ADB.Body target) throw new ConversionException("Could not retrieve brep from the body."); } - var vertices = new List(); - var faces = new List(); - - // create mesh from solid with mesh filter - using ABR.Mesh2dControl control = new(); - control.MaxSubdivisions = 10000; // POC: these settings may need adjusting - using ABR.Mesh2dFilter filter = new(); - filter.Insert(brep, control); - using ABR.Mesh2d m = new(filter); - foreach (ABR.Element2d e in m.Element2ds) - { - // get vertices - List faceIndices = new(); - foreach (ABR.Node n in e.Nodes) - { - faceIndices.Add(vertices.Count); - vertices.Add(n.Point); - n.Dispose(); - } - - // get faces - List faceList = new() { e.Nodes.Count() }; - for (int i = 0; i < e.Nodes.Count(); i++) - { - faceList.Add(faceIndices[i]); - } - - faces.AddRange(faceList); - - e.Dispose(); - } - - // mesh props - var convertedVertices = vertices.SelectMany(o => _pointConverter.Convert(o).ToList()).ToList(); - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); - - // create speckle mesh - SOG.Mesh mesh = - new() - { - vertices = convertedVertices, - faces = faces, - area = brep.GetSurfaceArea(), - units = _settingsStore.Current.SpeckleUnits, - bbox = bbox - }; - - try - { - mesh.volume = brep.GetVolume(); - } - catch (Autodesk.AutoCAD.BoundaryRepresentation.Exception e) when (!e.IsFatal()) { } - - return mesh; + return _brepConverter.Convert(brep); } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSolid3dToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSolid3dToSpeckleRawConverter.cs index 80ca83be0..6aecd0554 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSolid3dToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBSolid3dToSpeckleRawConverter.cs @@ -1,4 +1,3 @@ -using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; using Speckle.Sdk.Common.Exceptions; using Speckle.Sdk.Models; @@ -7,19 +6,11 @@ namespace Speckle.Converters.Autocad.ToSpeckle.Raw; public class Solid3dToSpeckleRawConverter : ITypedConverter { - private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _boxConverter; - private readonly IConverterSettingsStore _settingsStore; + private readonly ITypedConverter _brepConverter; - public Solid3dToSpeckleRawConverter( - ITypedConverter pointConverter, - ITypedConverter boxConverter, - IConverterSettingsStore settingsStore - ) + public Solid3dToSpeckleRawConverter(ITypedConverter brepConverter) { - _pointConverter = pointConverter; - _boxConverter = boxConverter; - _settingsStore = settingsStore; + _brepConverter = brepConverter; } public Base Convert(object target) => Convert((ADB.Solid3d)target); @@ -32,55 +23,7 @@ public SOG.Mesh Convert(ADB.Solid3d target) throw new ValidationException("Could not retrieve brep from the solid3d."); } - var vertices = new List(); - var faces = new List(); - - // create mesh from solid with mesh filter - using ABR.Mesh2dControl control = new(); - control.MaxSubdivisions = 10000; // POC: these settings may need adjusting - using ABR.Mesh2dFilter filter = new(); - filter.Insert(brep, control); - using ABR.Mesh2d m = new(filter); - foreach (ABR.Element2d e in m.Element2ds) - { - // get vertices - List faceIndices = new(); - foreach (ABR.Node n in e.Nodes) - { - faceIndices.Add(vertices.Count); - vertices.Add(n.Point); - n.Dispose(); - } - - // get faces - List faceList = new() { e.Nodes.Count() }; - for (int i = 0; i < e.Nodes.Count(); i++) - { - faceList.Add(faceIndices[i]); - } - - faces.AddRange(faceList); - - e.Dispose(); - } - - // mesh props - var convertedVertices = vertices.SelectMany(o => _pointConverter.Convert(o).ToList()).ToList(); - double volume = target.MassProperties.Volume; - double area = target.Area; - SOG.Box bbox = _boxConverter.Convert(target.GeometricExtents); - - // create speckle mesh - SOG.Mesh mesh = - new() - { - vertices = convertedVertices, - faces = faces, - units = _settingsStore.Current.SpeckleUnits, - bbox = bbox, - area = area, - volume = volume - }; + SOG.Mesh mesh = _brepConverter.Convert(brep); return mesh; }