From f3eb6e71db9f6749b41000a283efa951311d7298 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Wed, 9 Oct 2024 22:55:59 +0100 Subject: [PATCH 1/9] adds parts data and better display mesh and base curve conversions --- .../Plugin/AutocadCommand.cs | 4 +- .../Bindings/Civil3dSendBinding.cs | 4 +- .../Civil3dConnectorModule.cs | 6 +- .../Send/Civil3dRootObjectBuilder.cs | 4 +- .../Geometry/SubDMeshToSpeckleConverter.cs | 4 +- .../Civil3dConversionSettings.cs | 2 +- .../Civil3dConversionSettingsFactory.cs | 2 +- ...er.cs => Civil3dRootToSpeckleConverter.cs} | 40 +++++- .../Civil3dToSpeckleUnitConverter.cs | 2 +- .../Helpers/BaseCurveExtractor.cs | 55 ++++++++ .../Helpers/DisplayValueExtractor.cs | 54 ++++++++ .../ServiceRegistration.cs | 6 +- ...Speckle.Converters.Civil3dShared.projitems | 7 +- .../CivilEntityToSpeckleTopLevelConverter.cs | 36 +++--- .../ToSpeckle/Parameters/PartDataExtractor.cs | 120 ++++++++++++++++++ .../GridSurfaceToSpeckleMeshRawConverter.cs | 71 +++++++++++ .../Raw/PropertySetToSpeckleRawConverter.cs | 2 +- .../TinSurfaceToSpeckleMeshRawConverter.cs | 67 ++++++++++ 18 files changed, 447 insertions(+), 39 deletions(-) rename Converters/Civil3d/Speckle.Converters.Civil3dShared/{Civil3dRootToHostConverter.cs => Civil3dRootToSpeckleConverter.cs} (61%) create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/DisplayValueExtractor.cs create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/TinSurfaceToSpeckleMeshRawConverter.cs diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs index 94111eb41..f7bd450f9 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs @@ -9,8 +9,8 @@ using Speckle.Connectors.Autocad.DependencyInjection; using Speckle.Converters.Autocad; #elif CIVIL3D -using Speckle.Converters.Civil3d; -using Speckle.Connectors.Civil3d.DependencyInjection; +using Speckle.Converters.Civil3dShared; +using Speckle.Connectors.Civil3dShared.DependencyInjection; #endif namespace Speckle.Connectors.Autocad.Plugin; diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs index d697acf20..a1aa571b0 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Bindings/Civil3dSendBinding.cs @@ -9,11 +9,11 @@ using Speckle.Connectors.DUI.Models; using Speckle.Connectors.DUI.Models.Card.SendFilter; using Speckle.Converters.Autocad; -using Speckle.Converters.Civil3d; +using Speckle.Converters.Civil3dShared; using Speckle.Converters.Common; using Speckle.Sdk; -namespace Speckle.Connectors.Civil3d.Bindings; +namespace Speckle.Connectors.Civil3dShared.Bindings; public sealed class Civil3dSendBinding : AutocadSendBaseBinding { diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs index 7c141f18a..408944574 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs @@ -2,13 +2,13 @@ using Microsoft.Extensions.DependencyInjection; using Speckle.Connectors.Autocad.DependencyInjection; using Speckle.Connectors.Autocad.Operations.Send; -using Speckle.Connectors.Civil3d.Bindings; -using Speckle.Connectors.Civil3d.Operations.Send; +using Speckle.Connectors.Civil3dShared.Bindings; +using Speckle.Connectors.Civil3dShared.Operations.Send; using Speckle.Connectors.Common.Builders; using Speckle.Connectors.DUI.Bindings; using Speckle.Sdk; -namespace Speckle.Connectors.Civil3d.DependencyInjection; +namespace Speckle.Connectors.Civil3dShared.DependencyInjection; public static class Civil3dConnectorModule { diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs index 679ae8e40..259a56826 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs @@ -7,7 +7,7 @@ using Speckle.Sdk.Logging; using Speckle.Sdk.Models.Collections; -namespace Speckle.Connectors.Civil3d.Operations.Send; +namespace Speckle.Connectors.Civil3dShared.Operations.Send; public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder { @@ -44,4 +44,6 @@ public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity en return (layer, autocadLayer); } + + // POC: probably will need to add Network definition proxies as well } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs index 212a9d93b..6e168f9a7 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Geometry/SubDMeshToSpeckleConverter.cs @@ -30,7 +30,9 @@ public SOG.Mesh RawConvert(ADB.SubDMesh target) var vertices = new List(target.Vertices.Count * 3); foreach (AG.Point3d vert in target.Vertices) { - vertices.AddRange(_pointConverter.Convert(vert).ToList()); + vertices.Add(vert.X); + vertices.Add(vert.Y); + vertices.Add(vert.Z); } // faces diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettings.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettings.cs index 71835b3dd..e15a58213 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettings.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettings.cs @@ -1,3 +1,3 @@ -namespace Speckle.Converters.Civil3d; +namespace Speckle.Converters.Civil3dShared; public record Civil3dConversionSettings(Document Document, string SpeckleUnits); diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettingsFactory.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettingsFactory.cs index b22adb63a..47ebb0934 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettingsFactory.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dConversionSettingsFactory.cs @@ -1,7 +1,7 @@ using Speckle.Converters.Common; using Speckle.InterfaceGenerator; -namespace Speckle.Converters.Civil3d; +namespace Speckle.Converters.Civil3dShared; [GenerateAutoInterface] public class Civil3dConversionSettingsFactory(IHostToSpeckleUnitConverter unitsConverter) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToHostConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs similarity index 61% rename from Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToHostConverter.cs rename to Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs index 858163ab9..3183feb6f 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToHostConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs @@ -1,23 +1,28 @@ using Autodesk.AutoCAD.DatabaseServices; +using Speckle.Converters.Civil3dShared.ToSpeckle; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; using Speckle.Converters.Common.Registration; +using Speckle.Sdk; using Speckle.Sdk.Models; -namespace Speckle.Converters.Civil3d; +namespace Speckle.Converters.Civil3dShared; -public class Civil3dRootToHostConverter : IRootToSpeckleConverter +public class Civil3dRootToSpeckleConverter : IRootToSpeckleConverter { private readonly IConverterManager _toSpeckle; private readonly IConverterSettingsStore _settingsStore; + private readonly PartDataExtractor _partDataExtractor; - public Civil3dRootToHostConverter( + public Civil3dRootToSpeckleConverter( IConverterManager toSpeckle, - IConverterSettingsStore settingsStore + IConverterSettingsStore settingsStore, + PartDataExtractor partDataExtractor ) { _toSpeckle = toSpeckle; _settingsStore = settingsStore; + _partDataExtractor = partDataExtractor; } public Base Convert(object target) @@ -31,15 +36,30 @@ public Base Convert(object target) Type type = dbObject.GetType(); object objectToConvert = dbObject; + Dictionary properties = new(); // check first for civil type objects + if (target is CDB.Entity civilEntity) { type = civilEntity.GetType(); objectToConvert = civilEntity; + + try + { + List>? partData = _partDataExtractor.GetPartData(civilEntity); + if (partData is not null) + { + properties.Add("Part Data", partData); + } + } + catch (Exception e) when (!e.IsFatal()) + { + //TODO: logger here + } } - var objectConverter = _toSpeckle.ResolveConverter(type); + var objectConverter = _toSpeckle.ResolveConverter(type, true); if (objectConverter == null) { @@ -52,9 +72,15 @@ public Base Convert(object target) { using (var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction()) { - var convertedObject = objectConverter.Convert(objectToConvert); + var result = objectConverter.Convert(objectToConvert); + + if (properties.Count > 0) + { + result["properties"] = properties; + } + tr.Commit(); - return convertedObject; + return result; } } } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dToSpeckleUnitConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dToSpeckleUnitConverter.cs index 1dc191f3a..bbcc6698d 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dToSpeckleUnitConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dToSpeckleUnitConverter.cs @@ -2,7 +2,7 @@ using Speckle.Sdk; using Speckle.Sdk.Common; -namespace Speckle.Converters.Civil3d; +namespace Speckle.Converters.Civil3dShared; public class Civil3dToSpeckleUnitConverter : IHostToSpeckleUnitConverter { diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs new file mode 100644 index 000000000..974bc49c6 --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs @@ -0,0 +1,55 @@ +using Autodesk.Civil.DatabaseServices; +using Microsoft.Extensions.Logging; +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; +using Speckle.Objects; + +namespace Speckle.Converters.Civil3dShared.Helpers; + +public sealed class BaseCurveExtractor +{ + private readonly ILogger _logger; + private readonly IConverterSettingsStore _converterSettings; + private readonly ITypedConverter _lineConverter; + private readonly ITypedConverter _arcConverter; + private readonly ITypedConverter _curveConverter; + + public BaseCurveExtractor( + ITypedConverter lineConverter, + ITypedConverter arcConverter, + ITypedConverter curveConverter, + ILogger logger, + IConverterSettingsStore converterSettings + ) + { + _lineConverter = lineConverter; + _arcConverter = arcConverter; + _curveConverter = curveConverter; + _logger = logger; + _converterSettings = converterSettings; + } + + public List GetBaseCurve(CDB.Entity entity) + { + List result = new(); + + switch (entity) + { + // rant: if this is a pipe, the BaseCurve prop is fake news && will return a DB.line with start and endpoints set to [0,0,0] & [0,0,1] + // do not use basecurve for pipes 😡 + case CDB.Pipe pipe: + ICurve pipeCurve = + pipe.SubEntityType == PipeSubEntityType.Straight + ? _lineConverter.Convert(new AG.LineSegment3d(pipe.StartPoint, pipe.EndPoint)) + : _arcConverter.Convert(pipe.Curve2d); + result.Add(pipeCurve); + break; + default: + ICurve baseCurve = _curveConverter.Convert(entity.BaseCurve); + result.Add(baseCurve); + break; + } + + return result; + } +} diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/DisplayValueExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/DisplayValueExtractor.cs new file mode 100644 index 000000000..0ab46cbb4 --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/DisplayValueExtractor.cs @@ -0,0 +1,54 @@ +using Microsoft.Extensions.Logging; +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Civil3dShared.Helpers; + +public sealed class DisplayValueExtractor +{ + private readonly ITypedConverter _solidConverter; + private readonly ITypedConverter _tinSurfaceConverter; + private readonly ITypedConverter _gridSurfaceConverter; + private readonly ILogger _logger; + private readonly IConverterSettingsStore _converterSettings; + + public DisplayValueExtractor( + ITypedConverter solidConverter, + ITypedConverter tinSurfaceConverter, + ITypedConverter gridSurfaceConverter, + ILogger logger, + IConverterSettingsStore converterSettings + ) + { + _solidConverter = solidConverter; + _tinSurfaceConverter = tinSurfaceConverter; + _gridSurfaceConverter = gridSurfaceConverter; + _logger = logger; + _converterSettings = converterSettings; + } + + public List GetDisplayValue(CDB.Entity entity) + { + List result = new(); + switch (entity) + { + // pipe networks: https://help.autodesk.com/view/CIV3D/2025/ENU/?guid=ade47b62-debf-f899-9b94-5645a620ab4f + case CDB.Part part: + SOG.Mesh partMesh = _solidConverter.Convert(part.Solid3dBody); + result.Add(partMesh); + break; + + // surfaces: https://help.autodesk.com/view/CIV3D/2025/ENU/?guid=d741aa49-e7da-9513-6b0b-226ebe3fa43f + // POC: volume surfaces not supported + case CDB.TinSurface tinSurface: + SOG.Mesh tinSurfaceMesh = _tinSurfaceConverter.Convert(tinSurface); + result.Add(tinSurfaceMesh); + break; + case CDB.GridSurface gridSurface: + SOG.Mesh gridSurfaceMesh = _gridSurfaceConverter.Convert(gridSurface); + result.Add(gridSurfaceMesh); + break; + } + return result; + } +} diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs index 0b001f819..2baff42cd 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs @@ -1,10 +1,10 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Speckle.Converters.Autocad; using Speckle.Converters.Common; using Speckle.Converters.Common.Registration; using Speckle.Sdk; -namespace Speckle.Converters.Civil3d; +namespace Speckle.Converters.Civil3dShared; public static class ServiceRegistration { @@ -16,7 +16,7 @@ public static void AddCivil3dConverters(this IServiceCollection serviceCollectio serviceCollection.AddMatchingInterfacesAsTransient(civil3dAssembly); serviceCollection.AddMatchingInterfacesAsTransient(autocadAssembly); // Register single root - serviceCollection.AddRootCommon(civil3dAssembly); + serviceCollection.AddRootCommon(civil3dAssembly); // register all application converters serviceCollection.AddApplicationConverters( diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems index fdde977ce..9f7ecbba4 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems @@ -11,11 +11,16 @@ - + + + + + + \ No newline at end of file diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs index 5f1807128..8ee3b8898 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs @@ -1,3 +1,4 @@ +using Speckle.Converters.Civil3dShared.Helpers; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; using Speckle.Objects; @@ -5,54 +6,59 @@ using Speckle.Sdk.Models; using AECPropDB = Autodesk.Aec.PropertyData.DatabaseServices; -namespace Speckle.Converters.Civil3d.ToSpeckle.BuiltElements; +namespace Speckle.Converters.Civil3dShared.ToSpeckle.BuiltElements; [NameAndRankValue(nameof(CDB.Entity), NameAndRankValueAttribute.SPECKLE_DEFAULT_RANK)] public class CivilEntityToSpeckleTopLevelConverter : IToSpeckleTopLevelConverter { private readonly ITypedConverter _pointConverter; - private readonly ITypedConverter _curveConverter; - private readonly ITypedConverter _solidConverter; private readonly ITypedConverter> _propertySetConverter; private readonly IConverterSettingsStore _settingsStore; + private readonly DisplayValueExtractor _displayValueExtractor; + private readonly BaseCurveExtractor _baseCurveExtractor; public CivilEntityToSpeckleTopLevelConverter( ITypedConverter pointConverter, - ITypedConverter curveConverter, - ITypedConverter solidConverter, ITypedConverter> propertySetConverter, - IConverterSettingsStore settingsStore + IConverterSettingsStore settingsStore, + DisplayValueExtractor displayValueExtractor, + BaseCurveExtractor baseCurveExtractor ) { _pointConverter = pointConverter; - _curveConverter = curveConverter; - _solidConverter = solidConverter; _propertySetConverter = propertySetConverter; _settingsStore = settingsStore; + _displayValueExtractor = displayValueExtractor; + _baseCurveExtractor = baseCurveExtractor; } public Base Convert(object target) => Convert((CDB.Entity)target); public Base Convert(CDB.Entity target) { - ICurve curve = _curveConverter.Convert(target.BaseCurve); - Base civilObject = new(); - civilObject["category"] = target.GetRXClass().AppName; + civilObject["category"] = target.GetType().ToString(); civilObject["name"] = target.Name; - civilObject["baseCurve"] = curve; civilObject["units"] = _settingsStore.Current.SpeckleUnits; - if (target is CDB.Part part) + // get basecurve + List baseCurves = _baseCurveExtractor.GetBaseCurve(target); + if (baseCurves.Count > 0) + { + civilObject["baseCurves"] = baseCurves; + } + + // extract display value + List display = _displayValueExtractor.GetDisplayValue(target); + if (display.Count > 0) { - // can get solid body info from part for display value - SOG.Mesh display = _solidConverter.Convert(part.Solid3dBody); civilObject["displayValue"] = display; } // POC: not setting property sets yet, need to determine connector parameter interoperability // POC: not setting part data yet, same reason as above + return civilObject; } } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs new file mode 100644 index 000000000..846c299b2 --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs @@ -0,0 +1,120 @@ +using Speckle.Converters.Common; + +namespace Speckle.Converters.Civil3dShared.ToSpeckle; + +/// +/// Extracts parameters out from an element. Expects to be scoped per operation. +/// +public class PartDataExtractor +{ + /// POC: Note that we're abusing dictionaries in here because we've yet to have a simple way to serialize non-base derived classes (or structs?) + private readonly IConverterSettingsStore _settingsStore; + + public PartDataExtractor(IConverterSettingsStore settingsStore) + { + _settingsStore = settingsStore; + } + + /// + /// Extracts part data out from an entity. Expects to be scoped per operation. + /// + /// + /// + public List>? GetPartData(CDB.Entity entity) + { + if (entity is CDB.Part part) + { + return ParsePartData(part.PartData); + } + + return null; + } + + private List> ParsePartData(CDB.PartDataRecord partData) + { + var result = new List>(); + + foreach (CDB.PartDataField field in partData.GetAllDataFields()) + { + var value = GetValue(field); + //var isNullOrEmpty = value == null || (value is string s && string.IsNullOrEmpty(s)); + + var fieldDictionary = new Dictionary() + { + ["value"] = value, + ["name"] = field.Name, + ["context"] = field.Context.ToString(), + ["units"] = field.Units + }; + + result.Add(fieldDictionary); + } + + return result; + } + + private object? GetValue(CDB.PartDataField field) + { + switch (field.DataType) + { + case CDB.PartCatalogDataType.Double: + return field.IsFromList + ? GetValueListGeneric(field.ValueList) + : field.IsFromRange + ? GetValueRangeGeneric(field.ValueRange) + : field.Value as double?; + case CDB.PartCatalogDataType.Int: + return field.IsFromList + ? GetValueListGeneric(field.ValueList) + : field.IsFromRange + ? GetValueRangeGeneric(field.ValueRange) + : field.Value as int?; + case CDB.PartCatalogDataType.Bool: + return field.IsFromList + ? GetValueListGeneric(field.ValueList) + : field.IsFromRange + ? GetValueRangeGeneric(field.ValueRange) + : field.Value as bool?; + default: + return field.IsFromList + ? GetValueListGeneric(field.ValueList) + : field.IsFromRange + ? GetValueRangeGeneric(field.ValueRange) + : field.Value.ToString(); + } + } + + private List? GetValueListGeneric(CDB.PartDataList list) + { + if (list == null || list.Count == 0) + { + return default; + } + + List result = new(); + for (int i = 0; i < list.Count; i++) + { + if (list[i] is TResult item) + { + result.Add(item); + } + } + + return result; + } + + private (TResult, TResult)? GetValueRangeGeneric(CDB.PartDataRange range) + { + if (range == null) + { + return default; + } + + if (range.RangeMin is TResult min && range.RangeMax is TResult max) + { + return (min, max); + } + + return default; + } +} diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs new file mode 100644 index 000000000..1c874940a --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/GridSurfaceToSpeckleMeshRawConverter.cs @@ -0,0 +1,71 @@ +using Autodesk.AutoCAD.Geometry; +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Civil3dShared.ToSpeckle.Raw; + +public class GridSurfaceToSpeckleMeshRawConverter : ITypedConverter +{ + private readonly IConverterSettingsStore _settingsStore; + + public GridSurfaceToSpeckleMeshRawConverter(IConverterSettingsStore settingsStore) + { + _settingsStore = settingsStore; + } + + public SOG.Mesh Convert(object target) => Convert((CDB.GridSurface)target); + + public SOG.Mesh Convert(CDB.GridSurface target) + { + List vertices = new(); + List faces = new(); + Dictionary indices = new(); + + int indexCounter = 0; + foreach (var cell in target.GetCells(false)) + { + try + { + Point3d[] cellVertices = + { + cell.BottomLeftVertex.Location, + cell.BottomRightVertex.Location, + cell.TopLeftVertex.Location, + cell.TopRightVertex.Location + }; + + foreach (Point3d p in cellVertices) + { + if (!indices.ContainsKey(p)) + { + vertices.Add(p.X); + vertices.Add(p.Y); + vertices.Add(p.Z); + indices.Add(p, indexCounter); + indexCounter++; + } + } + + faces.Add(4); + faces.Add(indices[cellVertices[0]]); + faces.Add(indices[cellVertices[1]]); + faces.Add(indices[cellVertices[2]]); + faces.Add(indices[cellVertices[3]]); + } + finally + { + cell.Dispose(); + } + } + + SOG.Mesh mesh = + new() + { + vertices = vertices, + faces = faces, + units = _settingsStore.Current.SpeckleUnits + }; + + return mesh; + } +} diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/PropertySetToSpeckleRawConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/PropertySetToSpeckleRawConverter.cs index c2517f70b..2317a00d9 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/PropertySetToSpeckleRawConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/PropertySetToSpeckleRawConverter.cs @@ -3,7 +3,7 @@ using Speckle.Objects.Other; using AECPropDB = Autodesk.Aec.PropertyData.DatabaseServices; -namespace Speckle.Converters.Civil3d.ToSpeckle.Raw; +namespace Speckle.Converters.Civil3dShared.ToSpeckle.Raw; public class PropertySetToSpeckleRawConverter : ITypedConverter> { diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/TinSurfaceToSpeckleMeshRawConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/TinSurfaceToSpeckleMeshRawConverter.cs new file mode 100644 index 000000000..aaf607bd9 --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Raw/TinSurfaceToSpeckleMeshRawConverter.cs @@ -0,0 +1,67 @@ +using Autodesk.AutoCAD.Geometry; +using Speckle.Converters.Common; +using Speckle.Converters.Common.Objects; + +namespace Speckle.Converters.Civil3dShared.ToSpeckle.Raw; + +public class TinSurfaceToSpeckleMeshRawConverter : ITypedConverter +{ + private readonly IConverterSettingsStore _settingsStore; + + public TinSurfaceToSpeckleMeshRawConverter(IConverterSettingsStore settingsStore) + { + _settingsStore = settingsStore; + } + + public SOG.Mesh Convert(object target) => Convert((CDB.TinSurface)target); + + public SOG.Mesh Convert(CDB.TinSurface target) + { + List vertices = new(); + List faces = new(); + Dictionary indices = new(); + + int indexCounter = 0; + foreach (var triangle in target.GetTriangles(false)) + { + try + { + Point3d[] triangleVertices = + { + triangle.Vertex1.Location, + triangle.Vertex2.Location, + triangle.Vertex3.Location + }; + foreach (Point3d p in triangleVertices) + { + if (!indices.ContainsKey(p)) + { + vertices.Add(p.X); + vertices.Add(p.Y); + vertices.Add(p.Z); + indices.Add(p, indexCounter); + indexCounter++; + } + } + faces.Add(3); + faces.Add(indices[triangleVertices[0]]); + faces.Add(indices[triangleVertices[1]]); + faces.Add(indices[triangleVertices[2]]); + } + finally + { + triangle.Dispose(); + } + } + + SOG.Mesh mesh = + new() + { + faces = faces, + vertices = vertices, + units = _settingsStore.Current.SpeckleUnits + }; + + return mesh; + } +} From 21a2765784767d1097d0c59fc5706e45e27c91c5 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Wed, 9 Oct 2024 23:12:40 +0100 Subject: [PATCH 2/9] fixes di issues --- .../ServiceRegistration.cs | 7 +++++++ .../ToSpeckle/Parameters/PartDataExtractor.cs | 8 +------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs index 2baff42cd..eb83d93c0 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs @@ -1,5 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using Speckle.Converters.Autocad; +using Speckle.Converters.Civil3dShared.Helpers; +using Speckle.Converters.Civil3dShared.ToSpeckle; using Speckle.Converters.Common; using Speckle.Converters.Common.Registration; using Speckle.Sdk; @@ -31,5 +33,10 @@ public static void AddCivil3dConverters(this IServiceCollection serviceCollectio IConverterSettingsStore, ConverterSettingsStore >(); + + // add other classes + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); } } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs index 846c299b2..d1dafe83a 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs @@ -1,5 +1,3 @@ -using Speckle.Converters.Common; - namespace Speckle.Converters.Civil3dShared.ToSpeckle; /// @@ -8,12 +6,8 @@ namespace Speckle.Converters.Civil3dShared.ToSpeckle; public class PartDataExtractor { /// POC: Note that we're abusing dictionaries in here because we've yet to have a simple way to serialize non-base derived classes (or structs?) - private readonly IConverterSettingsStore _settingsStore; - public PartDataExtractor(IConverterSettingsStore settingsStore) - { - _settingsStore = settingsStore; - } + public PartDataExtractor() { } /// /// Extracts part data out from an entity. Expects to be scoped per operation. From 90752b5488d946f9e8b3174c2270dde5c63598f4 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Wed, 9 Oct 2024 23:24:10 +0100 Subject: [PATCH 3/9] removes arc pipes for now --- .../Plugin/AutocadCommand.cs | 4 ++-- .../Helpers/BaseCurveExtractor.cs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs index f7bd450f9..f3c177540 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Plugin/AutocadCommand.cs @@ -31,7 +31,7 @@ public void Command() return; } - PaletteSet = new PaletteSet($"Speckle (Beta) for {AppUtils.App}", s_id) + PaletteSet = new PaletteSet($"Speckle (Beta) for {AppUtils.App.Name}", s_id) { Size = new Size(400, 500), DockEnabled = (DockSides)((int)DockSides.Left + (int)DockSides.Right) @@ -52,7 +52,7 @@ public void Command() var panelWebView = Container.GetRequiredService(); - PaletteSet.AddVisual($"Speckle (Beta) for {AppUtils.App} WebView", panelWebView); + PaletteSet.AddVisual($"Speckle (Beta) for {AppUtils.App.Name} WebView", panelWebView); FocusPalette(); } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs index 974bc49c6..d4c7a0c89 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs @@ -1,4 +1,3 @@ -using Autodesk.Civil.DatabaseServices; using Microsoft.Extensions.Logging; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; @@ -37,11 +36,12 @@ IConverterSettingsStore converterSettings { // rant: if this is a pipe, the BaseCurve prop is fake news && will return a DB.line with start and endpoints set to [0,0,0] & [0,0,1] // do not use basecurve for pipes 😡 + // currently not handling arc pipes due to lack of CircularArc2D converter, and also way to properly retrieve 2d arc curve case CDB.Pipe pipe: ICurve pipeCurve = - pipe.SubEntityType == PipeSubEntityType.Straight - ? _lineConverter.Convert(new AG.LineSegment3d(pipe.StartPoint, pipe.EndPoint)) - : _arcConverter.Convert(pipe.Curve2d); + //pipe.SubEntityType == PipeSubEntityType.Straight ? + _lineConverter.Convert(new AG.LineSegment3d(pipe.StartPoint, pipe.EndPoint)); + //: _arcConverter.Convert(pipe.Curve2d); result.Add(pipeCurve); break; default: From d6cc4cd974a68086fb34b2424c59125ad33688a1 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Wed, 9 Oct 2024 23:27:57 +0100 Subject: [PATCH 4/9] Update BaseCurveExtractor.cs --- .../Helpers/BaseCurveExtractor.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs index d4c7a0c89..c1f34c133 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs @@ -10,19 +10,20 @@ public sealed class BaseCurveExtractor private readonly ILogger _logger; private readonly IConverterSettingsStore _converterSettings; private readonly ITypedConverter _lineConverter; - private readonly ITypedConverter _arcConverter; + + //private readonly ITypedConverter _arcConverter; private readonly ITypedConverter _curveConverter; public BaseCurveExtractor( ITypedConverter lineConverter, - ITypedConverter arcConverter, + //ITypedConverter arcConverter, ITypedConverter curveConverter, ILogger logger, IConverterSettingsStore converterSettings ) { _lineConverter = lineConverter; - _arcConverter = arcConverter; + //_arcConverter = arcConverter; _curveConverter = curveConverter; _logger = logger; _converterSettings = converterSettings; From a32ecdb6f7df823dd0d99801e8556cf1cbe2f0e0 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Wed, 9 Oct 2024 23:36:37 +0100 Subject: [PATCH 5/9] Update PartDataExtractor.cs --- .../ToSpeckle/Parameters/PartDataExtractor.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs index d1dafe83a..22433bc07 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs @@ -14,7 +14,7 @@ public PartDataExtractor() { } /// /// /// - public List>? GetPartData(CDB.Entity entity) + public Dictionary? GetPartData(CDB.Entity entity) { if (entity is CDB.Part part) { @@ -24,9 +24,9 @@ public PartDataExtractor() { } return null; } - private List> ParsePartData(CDB.PartDataRecord partData) + private Dictionary ParsePartData(CDB.PartDataRecord partData) { - var result = new List>(); + var result = new Dictionary(); foreach (CDB.PartDataField field in partData.GetAllDataFields()) { @@ -41,7 +41,10 @@ public PartDataExtractor() { } ["units"] = field.Units }; - result.Add(fieldDictionary); + if (!result.ContainsKey(field.Name)) + { + result.Add(field.Name, fieldDictionary); + } } return result; From 8aae61ee77e4bca0da738295cac3c0e2dd519742 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Thu, 10 Oct 2024 17:11:24 +0100 Subject: [PATCH 6/9] adds property sets and defs --- .../Send/AutocadRootObjectBaseBuilder.cs | 5 + .../Send/Civil3dRootObjectBuilder.cs | 9 ++ .../Civil3dRootToSpeckleConverter.cs | 26 +++- .../GlobalUsings.cs | 1 + ...Speckle.Converters.Civil3dShared.projitems | 2 + .../CivilEntityToSpeckleTopLevelConverter.cs | 6 +- .../PropertySetDefinitionHandler.cs | 57 +++++++ .../Parameters/PropertySetExtractor.cs | 147 ++++++++++++++++++ .../Operations/ProxyKeys.cs | 3 +- 9 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs create mode 100644 Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs index 589cd11d3..63c4bdd7f 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs @@ -146,6 +146,11 @@ public virtual (Collection, LayerTableRecord?) CreateObjectCollection(Entity ent return (new(), null); } + public virtual void AddAdditionalProxiesToRoot(Collection rootCollection) + { + return; + } + private SendConversionResult ConvertAutocadEntity( Entity entity, string applicationId, diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs index 259a56826..ee4ce4a27 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/Operations/Send/Civil3dRootObjectBuilder.cs @@ -3,6 +3,8 @@ using Speckle.Connectors.Autocad.HostApp; using Speckle.Connectors.Autocad.Operations.Send; using Speckle.Connectors.Common.Caching; +using Speckle.Connectors.Common.Operations; +using Speckle.Converters.Civil3dShared.ToSpeckle; using Speckle.Converters.Common; using Speckle.Sdk.Logging; using Speckle.Sdk.Models.Collections; @@ -12,9 +14,11 @@ namespace Speckle.Connectors.Civil3dShared.Operations.Send; public sealed class Civil3dRootObjectBuilder : AutocadRootObjectBaseBuilder { private readonly AutocadLayerUnpacker _layerUnpacker; + private readonly PropertySetDefinitionHandler _propertySetDefinitionHandler; public Civil3dRootObjectBuilder( AutocadLayerUnpacker layerUnpacker, + PropertySetDefinitionHandler propertySetDefinitionHandler, IRootToSpeckleConverter converter, ISendConversionCache sendConversionCache, AutocadInstanceUnpacker instanceObjectManager, @@ -36,6 +40,7 @@ ISdkActivityFactory activityFactory ) { _layerUnpacker = layerUnpacker; + _propertySetDefinitionHandler = propertySetDefinitionHandler; } public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity entity, Transaction tr) @@ -46,4 +51,8 @@ public override (Collection, LayerTableRecord?) CreateObjectCollection(Entity en } // POC: probably will need to add Network definition proxies as well + public override void AddAdditionalProxiesToRoot(Collection rootObject) + { + rootObject[ProxyKeys.PROPERTYSET_DEFINITIONS] = _propertySetDefinitionHandler.Definitions; + } } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs index 3183feb6f..ac07bf2db 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Civil3dRootToSpeckleConverter.cs @@ -13,16 +13,19 @@ public class Civil3dRootToSpeckleConverter : IRootToSpeckleConverter private readonly IConverterManager _toSpeckle; private readonly IConverterSettingsStore _settingsStore; private readonly PartDataExtractor _partDataExtractor; + private readonly PropertySetExtractor _propertySetExtractor; public Civil3dRootToSpeckleConverter( IConverterManager toSpeckle, IConverterSettingsStore settingsStore, - PartDataExtractor partDataExtractor + PartDataExtractor partDataExtractor, + PropertySetExtractor propertySetExtractor ) { _toSpeckle = toSpeckle; _settingsStore = settingsStore; _partDataExtractor = partDataExtractor; + _propertySetExtractor = propertySetExtractor; } public Base Convert(object target) @@ -39,15 +42,16 @@ public Base Convert(object target) Dictionary properties = new(); // check first for civil type objects - if (target is CDB.Entity civilEntity) { type = civilEntity.GetType(); objectToConvert = civilEntity; + // TODO: refactor this into a property extractor class + // get part data try { - List>? partData = _partDataExtractor.GetPartData(civilEntity); + Dictionary? partData = _partDataExtractor.GetPartData(civilEntity); if (partData is not null) { properties.Add("Part Data", partData); @@ -57,6 +61,22 @@ public Base Convert(object target) { //TODO: logger here } + + // get property set data + try + { + Dictionary? propertySets = _propertySetExtractor.GetPropertySets(civilEntity); + if (propertySets is not null) + { + properties.Add("Property Sets", propertySets); + } + } + catch (Exception e) when (!e.IsFatal()) + { + //TODO: logger here + } + + // TODO: add XDATA here } var objectConverter = _toSpeckle.ResolveConverter(type, true); diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/GlobalUsings.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/GlobalUsings.cs index 84ef53636..a4bc49b0f 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/GlobalUsings.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/GlobalUsings.cs @@ -1,2 +1,3 @@ global using AAEC = Autodesk.Aec; +global using AAECPDB = Autodesk.Aec.PropertyData.DatabaseServices; global using CDB = Autodesk.Civil.DatabaseServices; diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems index 9f7ecbba4..ef7958f13 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems @@ -18,6 +18,8 @@ + + diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs index 8ee3b8898..453b7a4b1 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs @@ -37,7 +37,7 @@ BaseCurveExtractor baseCurveExtractor public Base Convert(CDB.Entity target) { Base civilObject = new(); - civilObject["category"] = target.GetType().ToString(); + civilObject["type"] = target.GetType().ToString(); civilObject["name"] = target.Name; civilObject["units"] = _settingsStore.Current.SpeckleUnits; @@ -55,10 +55,6 @@ public Base Convert(CDB.Entity target) civilObject["displayValue"] = display; } - // POC: not setting property sets yet, need to determine connector parameter interoperability - // POC: not setting part data yet, same reason as above - - return civilObject; } } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs new file mode 100644 index 000000000..80c1516e8 --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs @@ -0,0 +1,57 @@ +namespace Speckle.Converters.Civil3dShared.ToSpeckle; + +/// +/// Keeps track during a send conversion operation of the property set definitions used. +/// +public class PropertySetDefinitionHandler +{ + /// + /// Keeps track of all property set definitions used in the current send operation. This should be added to the properties dict on the root commit object post conversion. + /// + /// POC: Note that we're abusing dictionaries in here because we've yet to have a simple way to serialize non-base derived classes (or structs?) + /// POC: We're storing these by property set def name atm. There is a decent change different property sets can have the same name, need to validate this. + public Dictionary> Definitions { get; } = new(); + + /// + /// Extracts out and stores in the property set definition. + /// + /// The property set definition. Assumes this is opened for Read already. + /// + public (Dictionary propertyDefinitionNames, string name) HandleDefinition( + AAECPDB.PropertySetDefinition setDefinition + ) + { + Dictionary propertyDefinitionsDict = new(); // this is used to store on the property set definition + Dictionary propertyDefinitionNames = new(); // this is used to pass to the instance for property value retrieval + foreach (AAECPDB.PropertyDefinition propertyDefinition in setDefinition.Definitions) + { + string propertyName = propertyDefinition.Name; + propertyDefinitionNames[propertyDefinition.Id] = propertyName; + propertyDefinitionsDict[propertyName] = new Dictionary() + { + ["name"] = propertyName, + ["description"] = propertyDefinition.Description, + ["id"] = propertyDefinition.Id, + ["units"] = propertyDefinition.UnitType.GetTypeDisplayName(true), + ["isReadOnly"] = propertyDefinition.IsReadOnly, + ["dataType"] = propertyDefinition.DataType, + ["defaultValue"] = propertyDefinition.DefaultData + }; + } + + var name = setDefinition.Name; + + if (Definitions.ContainsKey(name)) + { + return (propertyDefinitionNames, name); + } + + Definitions[name] = new Dictionary() + { + ["name"] = name, + ["propertyDefinitions"] = propertyDefinitionsDict + }; + + return (propertyDefinitionNames, name); + } +} diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs new file mode 100644 index 000000000..064523a71 --- /dev/null +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs @@ -0,0 +1,147 @@ +using Microsoft.Extensions.Logging; +using Speckle.Converters.Common; +using Speckle.Sdk; + +namespace Speckle.Converters.Civil3dShared.ToSpeckle; + +/// +/// Extracts property sets out from a dbobject. Expects to be scoped per operation. +/// +public class PropertySetExtractor +{ + /// POC: Note that we're abusing dictionaries in here because we've yet to have a simple way to serialize non-base derived classes (or structs?) + private readonly PropertySetDefinitionHandler _propertySetDefinitionHandler; + private readonly IConverterSettingsStore _settingsStore; + private readonly ILogger _logger; + + public PropertySetExtractor( + PropertySetDefinitionHandler propertySetDefinitionHandler, + IConverterSettingsStore settingsStore, + ILogger logger + ) + { + _propertySetDefinitionHandler = propertySetDefinitionHandler; + _settingsStore = settingsStore; + _logger = logger; + } + + /// + /// Extracts property sets out from a dbObject. Expects to be scoped per operation. + /// + /// + /// + public Dictionary? GetPropertySets(ADB.DBObject dbObject) + { + ADB.ObjectIdCollection? propertySetIds = null; + + try + { + propertySetIds = AAECPDB.PropertyDataServices.GetPropertySets(dbObject); + } + catch (Exception e) when (!e.IsFatal()) + { + _logger.LogWarning(e, $"Failed to retrieve property sets on object {dbObject.Handle.Value}"); + } + + if (propertySetIds is null || propertySetIds.Count == 0) + { + return null; + } + + using (var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction()) + { + Dictionary propertySets = new(); + foreach (ADB.ObjectId id in propertySetIds) + { + AAECPDB.PropertySet propertySet = (AAECPDB.PropertySet)tr.GetObject(id, ADB.OpenMode.ForRead); + + // parse property sets within this transaction, since we'll need it for retrieving the definition as well + if (ParsePropertySet(propertySet, tr) is (string propertySetName, Dictionary propertySetValue)) + { + propertySets[propertySetName] = propertySetValue; + } + } + + tr.Commit(); + return propertySets; + } + } + + private (string, Dictionary)? ParsePropertySet(AAECPDB.PropertySet propertySet, ADB.Transaction tr) + { + try + { + // var isNullOrEmpty = value == null || (value is string s && string.IsNullOrEmpty(s)); + // POC: should add same check as in revit for sending null or empty values + + var setDefinition = (AAECPDB.PropertySetDefinition) + tr.GetObject(propertySet.PropertySetDefinition, ADB.OpenMode.ForRead); + + (Dictionary propertyDefinitionNames, string name) = _propertySetDefinitionHandler.HandleDefinition( + setDefinition + ); + + // get all property values in the propertyset + Dictionary properties = new(); + foreach (AAECPDB.PropertySetData data in propertySet.PropertySetData) + { + string dataName = propertyDefinitionNames.TryGetValue(data.Id, out string propertyDefinitionName) + ? propertyDefinitionName + : data.FieldBucketId; + + var value = GetValue(data); + + properties[dataName] = new Dictionary() + { + ["value"] = value, + ["name"] = dataName, + ["units"] = data.UnitType.GetTypeDisplayName(true) + }; + } + + // add property set to dict + Dictionary propertySetDict = + new() + { + ["name"] = name, + ["properties"] = properties, + ["definitionName"] = name + }; + + return (name, propertySetDict); + } + catch (Exception e) when (!e.IsFatal()) + { + _logger.LogWarning(e, $"Failed to convert property set {propertySet.Name}"); + } + + return null; + } + + private object? GetValue(AAECPDB.PropertySetData data) + { + object fieldData = data.GetData(data.UnitType); + + switch (data.DataType) + { + case AAEC.PropertyData.DataType.Integer: + return fieldData as int?; + case AAEC.PropertyData.DataType.Real: + return fieldData as double?; + case AAEC.PropertyData.DataType.TrueFalse: + return fieldData as bool?; + case AAEC.PropertyData.DataType.Graphic: // POC: not sure how to support atm + return null; + case AAEC.PropertyData.DataType.List: + return fieldData as List; + case AAEC.PropertyData.DataType.AutoIncrement: + return fieldData as int?; + case AAEC.PropertyData.DataType.AlphaIncrement: // POC: not sure what this is + return fieldData; + case AAEC.PropertyData.DataType.Text: + return fieldData as string; + default: + return fieldData; + } + } +} diff --git a/Sdk/Speckle.Connectors.Common/Operations/ProxyKeys.cs b/Sdk/Speckle.Connectors.Common/Operations/ProxyKeys.cs index f5ad1b9d3..a0abff694 100644 --- a/Sdk/Speckle.Connectors.Common/Operations/ProxyKeys.cs +++ b/Sdk/Speckle.Connectors.Common/Operations/ProxyKeys.cs @@ -1,4 +1,4 @@ -namespace Speckle.Connectors.Common.Operations; +namespace Speckle.Connectors.Common.Operations; public static class ProxyKeys { @@ -7,4 +7,5 @@ public static class ProxyKeys public const string INSTANCE_DEFINITION = "instanceDefinitionProxies"; public const string GROUP = "groupProxies"; public const string PARAMETER_DEFINITIONS = "parameterDefinitions"; + public const string PROPERTYSET_DEFINITIONS = "propertySetDefinitions"; } From b34818380aaa40ac918891dbc755abeb4d957964 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Thu, 10 Oct 2024 18:54:18 +0100 Subject: [PATCH 7/9] additional bug fixes --- .../Send/AutocadRootObjectBaseBuilder.cs | 3 +++ .../Civil3dConnectorModule.cs | 4 ++++ .../Raw/DBCurveToSpeckleRawConverter.cs | 6 +++--- .../ServiceRegistration.cs | 2 ++ .../ToSpeckle/Parameters/PartDataExtractor.cs | 6 ++++-- .../Parameters/PropertySetDefinitionHandler.cs | 16 +++++++++++++--- .../ToSpeckle/Parameters/PropertySetExtractor.cs | 14 +++++++++----- 7 files changed, 38 insertions(+), 13 deletions(-) diff --git a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs index 63c4bdd7f..f4862e3d7 100644 --- a/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs +++ b/Connectors/Autocad/Speckle.Connectors.AutocadShared/Operations/Send/AutocadRootObjectBaseBuilder.cs @@ -137,6 +137,9 @@ CancellationToken ct // 5 - Unpack the color proxies root[ProxyKeys.COLOR] = _colorUnpacker.UnpackColors(atomicObjects, usedAcadLayers); + // add any additional properties (most likely from verticals) + AddAdditionalProxiesToRoot(root); + return new RootObjectBuilderResult(root, results); } } diff --git a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs index 408944574..e43b04302 100644 --- a/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs +++ b/Connectors/Autocad/Speckle.Connectors.Civil3dShared/DependencyInjection/Civil3dConnectorModule.cs @@ -6,6 +6,7 @@ using Speckle.Connectors.Civil3dShared.Operations.Send; using Speckle.Connectors.Common.Builders; using Speckle.Connectors.DUI.Bindings; +using Speckle.Converters.Civil3dShared.ToSpeckle; using Speckle.Sdk; namespace Speckle.Connectors.Civil3dShared.DependencyInjection; @@ -23,5 +24,8 @@ public static void AddCivil3d(this IServiceCollection serviceCollection) // automatically detects the Class:IClass interface pattern to register all generated interfaces serviceCollection.AddMatchingInterfacesAsTransient(Assembly.GetExecutingAssembly()); + + // additional classes + serviceCollection.AddScoped(); } } diff --git a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCurveToSpeckleRawConverter.cs b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCurveToSpeckleRawConverter.cs index 789d6db00..d12177389 100644 --- a/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCurveToSpeckleRawConverter.cs +++ b/Converters/Autocad/Speckle.Converters.AutocadShared/ToSpeckle/Raw/DBCurveToSpeckleRawConverter.cs @@ -53,9 +53,9 @@ public Objects.ICurve Convert(ADB.Curve target) => target switch { ADB.Line line => _lineConverter.Convert(line), - //ADB.Polyline polyline => _polylineConverter.Convert(polyline), - //ADB.Polyline2d polyline2d => _polyline2dConverter.Convert(polyline2d), - //ADB.Polyline3d polyline3d => _polyline3dConverter.Convert(polyline3d), + ADB.Polyline polyline => _polylineConverter.Convert(polyline), + ADB.Polyline2d polyline2d => _polyline2dConverter.Convert(polyline2d), + ADB.Polyline3d polyline3d => _polyline3dConverter.Convert(polyline3d), ADB.Arc arc => _arcConverter.Convert(arc), ADB.Circle circle => _circleConverter.Convert(circle), ADB.Ellipse ellipse => _ellipseConverter.Convert(ellipse), diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs index eb83d93c0..063280a5f 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ServiceRegistration.cs @@ -38,5 +38,7 @@ public static void AddCivil3dConverters(this IServiceCollection serviceCollectio serviceCollection.AddScoped(); serviceCollection.AddScoped(); serviceCollection.AddScoped(); + serviceCollection.AddScoped(); + serviceCollection.AddScoped(); } } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs index 22433bc07..f3b1f2fe7 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs @@ -38,6 +38,8 @@ public PartDataExtractor() { } ["value"] = value, ["name"] = field.Name, ["context"] = field.Context.ToString(), + ["isFromRange"] = field.IsFromRange, + ["isReadOnly"] = field.IsReadOnly, ["units"] = field.Units }; @@ -100,7 +102,7 @@ public PartDataExtractor() { } return result; } - private (TResult, TResult)? GetValueRangeGeneric(CDB.PartDataRange range) + private List? GetValueRangeGeneric(CDB.PartDataRange range) { if (range == null) { @@ -109,7 +111,7 @@ public PartDataExtractor() { } if (range.RangeMin is TResult min && range.RangeMax is TResult max) { - return (min, max); + return new() { min, max }; } return default; diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs index 80c1516e8..73f210461 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs @@ -1,3 +1,5 @@ +using Speckle.Sdk; + namespace Speckle.Converters.Civil3dShared.ToSpeckle; /// @@ -27,16 +29,24 @@ AAECPDB.PropertySetDefinition setDefinition { string propertyName = propertyDefinition.Name; propertyDefinitionNames[propertyDefinition.Id] = propertyName; - propertyDefinitionsDict[propertyName] = new Dictionary() + var propertyDict = new Dictionary() { ["name"] = propertyName, ["description"] = propertyDefinition.Description, ["id"] = propertyDefinition.Id, - ["units"] = propertyDefinition.UnitType.GetTypeDisplayName(true), ["isReadOnly"] = propertyDefinition.IsReadOnly, - ["dataType"] = propertyDefinition.DataType, + ["dataType"] = propertyDefinition.DataType.ToString(), ["defaultValue"] = propertyDefinition.DefaultData }; + + try + { + // accessing unit type prop can be expected to throw if it's not applicable to the definition + propertyDict["units"] = propertyDefinition.UnitType.GetTypeDisplayName(true); + } + catch (Exception e) when (!e.IsFatal()) { } + + propertyDefinitionsDict[propertyName] = propertyDict; } var name = setDefinition.Name; diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs index 064523a71..6c56bae7b 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs @@ -91,12 +91,16 @@ ILogger logger var value = GetValue(data); - properties[dataName] = new Dictionary() + var propertyValueDict = new Dictionary() { ["value"] = value, ["name"] = dataName }; + + try { - ["value"] = value, - ["name"] = dataName, - ["units"] = data.UnitType.GetTypeDisplayName(true) - }; + // accessing unit type prop can be expected to throw if it's not applicable to the definition + propertyValueDict["units"] = data.UnitType.GetTypeDisplayName(true); + } + catch (Exception e) when (!e.IsFatal()) { } + + properties[dataName] = propertyValueDict; } // add property set to dict From 893ffb81cccc9dd12aeb4a82aa4a40141635ae09 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Thu, 10 Oct 2024 19:18:33 +0100 Subject: [PATCH 8/9] renames parameters folder to properties --- .../ToSpeckle/{Parameters => Properties}/PartDataExtractor.cs | 0 .../{Parameters => Properties}/PropertySetDefinitionHandler.cs | 0 .../ToSpeckle/{Parameters => Properties}/PropertySetExtractor.cs | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/{Parameters => Properties}/PartDataExtractor.cs (100%) rename Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/{Parameters => Properties}/PropertySetDefinitionHandler.cs (100%) rename Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/{Parameters => Properties}/PropertySetExtractor.cs (100%) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/PartDataExtractor.cs similarity index 100% rename from Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PartDataExtractor.cs rename to Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/PartDataExtractor.cs diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/PropertySetDefinitionHandler.cs similarity index 100% rename from Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetDefinitionHandler.cs rename to Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/PropertySetDefinitionHandler.cs diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/PropertySetExtractor.cs similarity index 100% rename from Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Parameters/PropertySetExtractor.cs rename to Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/PropertySetExtractor.cs From b77170e71405bd13b83d8a2a3314b1d133955925 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Thu, 10 Oct 2024 23:22:07 +0100 Subject: [PATCH 9/9] Update Speckle.Converters.Civil3dShared.projitems --- .../Speckle.Converters.Civil3dShared.projitems | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems index ef7958f13..6d7ec1d66 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Speckle.Converters.Civil3dShared.projitems @@ -18,9 +18,9 @@ - - - + + +