From 6e56c3c190921d945fbfbce14cf8fe4c6d7e2610 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Wed, 16 Oct 2024 16:57:49 +0100 Subject: [PATCH] feat(civil3d): adds subassembly and parcel props (#305) * adds general and class properties extractors * Update Speckle.Converters.Civil3dShared.projitems * adds class properties for catchments * adds catchment group proxies * catchment proxy bug fix * adds site props * Update ClassPropertiesExtractor.cs * Update ClassPropertiesExtractor.cs * adds network, structure, and pipes * registers pipe network * adds alignment basecurves and properties * adds profiles to alignments * adds corridors * fixes di and other corridor bugs * parses corridor solid property sets * Update CorridorHandler.cs * Update CorridorHandler.cs * adds body raw converter to autocad * adds calculated info * adds subassembly props * adds subassemblies, and parcels * adds volume surface stats * removes unnecessary * resolve merge conflict * handles name exception from some entity types * Update DBBodyToSpeckleRawConverter.cs --- .../Helpers/BaseCurveExtractor.cs | 2 + .../CivilEntityToSpeckleTopLevelConverter.cs | 32 +++++- .../Properties/ClassPropertiesExtractor.cs | 29 ++--- .../Properties/GeneralPropertiesExtractor.cs | 106 ++++++++++++++++-- 4 files changed, 147 insertions(+), 22 deletions(-) diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs index f8ee35255..c48fd3c98 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/Helpers/BaseCurveExtractor.cs @@ -52,6 +52,8 @@ public sealed class BaseCurveExtractor case CDB.Alignment alignment: return GetAlignmentBaseCurves(alignment); + case CDB.Parcel parcel: + return new() { _curveConverter.Convert(parcel.BaseCurve) }; // for any entities that don't use their basecurve prop default: return null; diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs index 25243105c..fbb57679c 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/BuiltElements/CivilEntityToSpeckleTopLevelConverter.cs @@ -3,6 +3,7 @@ using Speckle.Converters.Civil3dShared.Helpers; using Speckle.Converters.Common; using Speckle.Converters.Common.Objects; using Speckle.Objects; +using Speckle.Sdk; using Speckle.Sdk.Models; namespace Speckle.Converters.Civil3dShared.ToSpeckle.BuiltElements; @@ -35,11 +36,18 @@ public class CivilEntityToSpeckleTopLevelConverter : IToSpeckleTopLevelConverter public Base Convert(CDB.Entity target) { + string name = target.DisplayName; + try + { + name = target.Name; // this will throw for some entities like labels + } + catch (Exception e) when (!e.IsFatal()) { } + Base civilObject = new() { ["type"] = target.GetType().ToString().Split('.').Last(), - ["name"] = target.Name, + ["name"] = name, ["units"] = _settingsStore.Current.SpeckleUnits, applicationId = target.GetSpeckleApplicationId() }; @@ -79,7 +87,12 @@ public class CivilEntityToSpeckleTopLevelConverter : IToSpeckleTopLevelConverter case CDB.Corridor corridor: children = _corridorHandler.GetCorridorChildren(corridor); break; + + case CDB.Site site: + children = GetSiteChildren(site); + break; } + if (children is not null) { civilObject["@elements"] = children; @@ -88,6 +101,23 @@ public class CivilEntityToSpeckleTopLevelConverter : IToSpeckleTopLevelConverter return civilObject; } + private List? GetSiteChildren(CDB.Site site) + { + List parcels = new(); + + using (var tr = _settingsStore.Current.Document.Database.TransactionManager.StartTransaction()) + { + foreach (ADB.ObjectId parcelId in site.GetParcelIds()) + { + var parcel = (CDB.Parcel)tr.GetObject(parcelId, ADB.OpenMode.ForRead); + parcels.Add(Convert(parcel)); + } + + tr.Commit(); + } + return parcels.Count > 0 ? parcels : null; + } + private List? GetAlignmentChildren(CDB.Alignment alignment) { List profiles = new(); diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/ClassPropertiesExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/ClassPropertiesExtractor.cs index bfe72bccd..da40f1f6e 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/ClassPropertiesExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/ClassPropertiesExtractor.cs @@ -46,6 +46,8 @@ public class ClassPropertiesExtractor return ExtractCatchmentProperties(catchment); case CDB.Site site: return ExtractSiteProperties(site); + case CDB.Parcel parcel: + return ExtractParcelProperties(parcel); // pipe networks case CDB.Pipe pipe: @@ -59,28 +61,29 @@ public class ClassPropertiesExtractor case CDB.Profile profile: return ExtractProfileProperties(profile); + // assemblies + case CDB.Subassembly subassembly: + return ExtractSubassemblyProperties(subassembly); + default: return null; } } - // For more info on how points are used: https://help.autodesk.com/view/CIV3D/2024/ENU/?guid=GUID-CBABE972-D690-49AE-A7DE-60F2E1B0675D - private Dictionary ExtractPointProperties(CDB.Point point) + private Dictionary ExtractParcelProperties(CDB.Parcel parcel) { - Dictionary pointProperties = - new() - { - ["elevation"] = point.Elevation, - ["station"] = point.Station, - ["isLoopPoint"] = point.IsLoopPoint - }; + return new() { ["number"] = parcel.Number, ["taxId"] = parcel.TaxId }; + } - if (point.Codes.Count > 0) + private Dictionary ExtractSubassemblyProperties(CDB.Subassembly subassembly) + { + Dictionary subassemblyProperties = new(); + if (subassembly.HasSide) { - pointProperties["codes"] = point.Codes.ToList(); + subassemblyProperties["side"] = subassembly.Side; } - return pointProperties; + return subassemblyProperties; } private Dictionary ExtractProfileProperties(CDB.Profile profile) @@ -224,12 +227,10 @@ public class ClassPropertiesExtractor ["area"] = catchment.Area, ["area2d"] = catchment.Area2d, ["boundary"] = boundary, - ["exclusionary"] = catchment.Exclusionary, ["hydrologicalSoilGroup"] = catchment.HydrologicalSoilGroup.ToString(), ["imperviousArea"] = catchment.ImperviousArea, ["manningsCoefficient"] = catchment.ManningsCoefficient, ["perimeter2d"] = catchment.Perimeter2d, - ["runoffCoefficient"] = catchment.RunoffCoefficient, ["timeOfConcentration"] = catchment.TimeOfConcentration }; } diff --git a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/GeneralPropertiesExtractor.cs b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/GeneralPropertiesExtractor.cs index 2dcbc4b4e..cdcc17b45 100644 --- a/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/GeneralPropertiesExtractor.cs +++ b/Converters/Civil3d/Speckle.Converters.Civil3dShared/ToSpeckle/Properties/GeneralPropertiesExtractor.cs @@ -1,4 +1,5 @@ using System.Reflection; +using Autodesk.Civil.Runtime; using Speckle.Converters.Civil3dShared.Extensions; namespace Speckle.Converters.Civil3dShared.ToSpeckle; @@ -19,6 +20,10 @@ public class GeneralPropertiesExtractor { switch (entity) { + // catchment -> properties -> Catchment Properties + case CDB.Catchment catchment: + return ExtractCatchmentProperties(catchment); + // surface -> properties -> statistics -> general, extended, and tin/grid properties case CDB.Surface surface: return ExtractSurfaceProperties(surface); @@ -32,20 +37,96 @@ public class GeneralPropertiesExtractor case CDB.Corridor corridor: return ExtractCorridorProperties(corridor); - //case CDB.Assembly assembly: - //return ExtractAssemblyProperties(assembly); - - //case CDB.Subassembly subassembly: - //return ExtractSubassemblyProperties(subassembly); + // subassembly -> properties -> parameters, codes + case CDB.Subassembly subassembly: + return ExtractSubassemblyProperties(subassembly); default: return null; } } - //private Dictionary ExtractSubassemblyProperties(CDB.Subassembly subassembly) { } + private Dictionary ExtractCatchmentProperties(CDB.Catchment catchment) + { + Dictionary generalPropertiesDict = new(); - //private Dictionary ExtractAssemblyProperties(CDB.Assembly assembly) { } + // get catchment properties props + Dictionary catchmentPropertiesDict = new(); + + Dictionary hydrologicalProps = new() { ["runoffCoefficient"] = catchment.RunoffCoefficient }; + catchmentPropertiesDict["Hydrological Properties"] = hydrologicalProps; + + Dictionary sheetFlow = + new() + { + ["sheetFlowSegments"] = catchment.SheetFlowSegments, + ["sheetFlowTravelTime"] = catchment.SheetFlowTravelTime + }; + catchmentPropertiesDict["Sheet Flow"] = sheetFlow; + + Dictionary shallowConcentratedFlow = + new() + { + ["shallowFlowSegments"] = catchment.ShallowFlowSegments, + ["shallowFlowTravelTime"] = catchment.ShallowFlowTravelTime + }; + catchmentPropertiesDict["Shallow Concentrated Flow"] = shallowConcentratedFlow; + + Dictionary channelFlow = + new() + { + ["channelFlowSegments"] = catchment.ChannelFlowSegments, + ["channelFlowTravelTime"] = catchment.ChannelFlowTravelTime + }; + catchmentPropertiesDict["Channel Flow"] = channelFlow; + + Dictionary timeOfConcentration = + new() + { + ["timeOfConcentration"] = catchment.TimeOfConcentration, + ["timeOfConcentrationCalculationMethod"] = catchment.TimeOfConcentrationCalculationMethod, + ["hydrologicallyMostDistantPoint"] = catchment.HydrologicallyMostDistantPoint.ToArray(), + ["hydrologicallyMostDistantLength"] = catchment.HydrologicallyMostDistantLength + }; + catchmentPropertiesDict["Time of Concentration"] = timeOfConcentration; + + if (catchmentPropertiesDict.Count > 0) + { + generalPropertiesDict["Catchment Properties"] = catchmentPropertiesDict; + } + + return generalPropertiesDict; + } + + private Dictionary ExtractSubassemblyProperties(CDB.Subassembly subassembly) + { + Dictionary generalPropertiesDict = new(); + + // get parameters props + Dictionary parametersDict = new(); + foreach (ParamBool p in subassembly.ParamsBool) + { + parametersDict[p.DisplayName] = p.Value; + } + foreach (ParamDouble p in subassembly.ParamsDouble) + { + parametersDict[p.DisplayName] = p.Value; + } + foreach (ParamString p in subassembly.ParamsString) + { + parametersDict[p.DisplayName] = p.Value; + } + foreach (ParamLong p in subassembly.ParamsLong) + { + parametersDict[p.DisplayName] = p.Value; + } + if (parametersDict.Count > 0) + { + generalPropertiesDict["Parameters"] = parametersDict; + } + + return generalPropertiesDict; + } private void ProcessCorridorFeaturelinePoints( CDB.CorridorFeatureLine featureline, @@ -252,6 +333,9 @@ public class GeneralPropertiesExtractor break; case CDB.TinVolumeSurface tinVolumeSurface: statisticsDict["TIN"] = ExtractPropertiesGeneric(tinVolumeSurface.GetTinProperties()); + statisticsDict["Volume"] = ExtractPropertiesGeneric( + tinVolumeSurface.GetVolumeProperties() + ); break; case CDB.GridSurface gridSurface: statisticsDict["Grid"] = ExtractPropertiesGeneric(gridSurface.GetGridProperties()); @@ -260,6 +344,9 @@ public class GeneralPropertiesExtractor statisticsDict["Grid"] = ExtractPropertiesGeneric( gridVolumeSurface.GetGridProperties() ); + statisticsDict["Volume"] = ExtractPropertiesGeneric( + gridVolumeSurface.GetVolumeProperties() + ); break; } @@ -278,6 +365,11 @@ public class GeneralPropertiesExtractor foreach (PropertyInfo? property in properties) { var value = property.GetValue(obj); + if (value is ADB.ObjectId id) + { + value = id.GetSpeckleApplicationId(); + } + propertiesDict[property.Name] = value; }