From c2caeb59009a974ee5c5b858a4cf94da91c01172 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Thu, 10 Oct 2024 16:56:50 +0100 Subject: [PATCH 1/7] fix: CNX-567 --- .../TopLevel/FootPrintRoofToSpeckleTopLevelConverter.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/FootPrintRoofToSpeckleTopLevelConverter.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/FootPrintRoofToSpeckleTopLevelConverter.cs index 85e8f7dbb..3234b6c7f 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/FootPrintRoofToSpeckleTopLevelConverter.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/TopLevel/FootPrintRoofToSpeckleTopLevelConverter.cs @@ -55,10 +55,6 @@ public override RevitFootprintRoof Convert(FootPrintRoof target) out var topLevel ); - //POC: CNX-9403 can be null if the sides have different slopes. - //We currently don't validate the success or failure of this TryGet as it's not necessary, but will be once we start the above ticket. - _parameterValueExtractor.TryGetValueAsDouble(target, DB.BuiltInParameter.ROOF_SLOPE, out var slope); - var elementType = (ElementType)target.Document.GetElement(target.GetTypeId()); List displayValue = _displayValueExtractor.GetDisplayValue(target); @@ -69,7 +65,6 @@ out var topLevel family = elementType.FamilyName, level = _levelConverter.Convert(baseLevel), cutOffLevel = topLevel is not null ? _levelConverter.Convert(topLevel) : null, - slope = slope, displayValue = displayValue, units = _converterSettings.Current.SpeckleUnits }; From a95e7cc225f4b5fab6d800ac7393f02816c166e1 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Thu, 10 Oct 2024 17:41:37 +0100 Subject: [PATCH 2/7] fix: CNX-556 --- .../Parameters/ParameterExtractor.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs index 15310fae7..17fa028ad 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs @@ -71,6 +71,12 @@ ILogger logger return CreateParameterDictionary(instanceParameterDictionary, typeParameterDictionary); } + /// + /// Internal utility to create the default parameter structure we expect all elements to have. + /// + /// + /// + /// private Dictionary CreateParameterDictionary( Dictionary> instanceParams, Dictionary>? typeParams @@ -90,16 +96,24 @@ ILogger logger { try { + var (internalDefinitionName, humanReadableName, groupName, units) = + _parameterDefinitionHandler.HandleDefinition(parameter); + + // NOTE: ids don't really have much meaning; if we discover the opposite, we can bring them back. See [CNX-556: All ID Parameters are send as Name](https://linear.app/speckle/issue/CNX-556/all-id-parameters-are-send-as-name) + if (internalDefinitionName.Contains("_ID")) + { + continue; + } + var value = GetValue(parameter); + var isNullOrEmpty = value == null || (value is string s && string.IsNullOrEmpty(s)); + if (!_settingsStore.Current.SendParameterNullOrEmptyStrings && isNullOrEmpty) { continue; } - var (internalDefinitionName, humanReadableName, groupName, units) = - _parameterDefinitionHandler.HandleDefinition(parameter); - var param = new Dictionary() { ["value"] = value, @@ -107,7 +121,7 @@ ILogger logger ["internalDefinitionName"] = internalDefinitionName }; - if (units is string paramUnits) + if (units is not null) { param["units"] = units; } From 0d584bb0ac7c806751cbaca460f398096594671f Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Thu, 10 Oct 2024 18:12:06 +0100 Subject: [PATCH 3/7] fix: CNX-559 --- .../ToSpeckle/Parameters/ParameterExtractor.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs index 17fa028ad..09aada6a1 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs @@ -163,10 +163,16 @@ ILogger logger : parameter.AsValueString(); case DB.StorageType.ElementId: var elId = parameter.AsElementId()!; + if (elId == DB.ElementId.InvalidElementId) + { + return null; + } + if (_elementNameCache.TryGetValue(elId, out string? value)) { return value; } + var docElement = _settingsStore.Current.Document.GetElement(elId); var docElementName = docElement?.Name ?? elId.ToString(); _elementNameCache[parameter.AsElementId()] = docElementName; From 491490c559bfc8b68690d4e97363279c8eb0710a Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 11 Oct 2024 13:14:21 +0100 Subject: [PATCH 4/7] fix: CNX-565 and CNX-564 --- .../Parameters/ParameterExtractor.cs | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs index 09aada6a1..0c2451e0d 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs @@ -114,6 +114,22 @@ ILogger logger continue; } + if (value is (string typeName, string familyName)) // element type dilemma + { + if (internalDefinitionName == "ELEM_FAMILY_PARAM") + { + value = familyName; + } + else if (internalDefinitionName == "ELEM_TYPE_PARAM") + { + value = typeName; + } + else + { + value = familyName + " " + typeName; + } + } + var param = new Dictionary() { ["value"] = value, @@ -149,7 +165,7 @@ ILogger logger return dict; } - private readonly Dictionary _elementNameCache = new(); + private readonly Dictionary _elementNameCache = new(); private object? GetValue(DB.Parameter parameter) { @@ -168,13 +184,22 @@ ILogger logger return null; } - if (_elementNameCache.TryGetValue(elId, out string? value)) + if (_elementNameCache.TryGetValue(elId, out object? value)) { return value; } var docElement = _settingsStore.Current.Document.GetElement(elId); - var docElementName = docElement?.Name ?? elId.ToString(); + object? docElementName; + if (docElement is DB.ElementType elementType) + { + docElementName = (elementType.Name, elementType.FamilyName); // new[] { elementType.Name, elementType.FamilyName }; + } + else + { + docElementName = docElement?.Name ?? null; + } + _elementNameCache[parameter.AsElementId()] = docElementName; return docElementName; case DB.StorageType.String: From 51550c96a6dbb3b151f2b9f2056e6e77266f2508 Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 11 Oct 2024 13:59:44 +0100 Subject: [PATCH 5/7] feat: adds support for assembly structure (CNX-570) (extracting material thickness and composition) --- .../Parameters/ParameterExtractor.cs | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs index 0c2451e0d..b15cbb165 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs @@ -65,7 +65,31 @@ ILogger logger return CreateParameterDictionary(instanceParameterDictionary, null); } - typeParameterDictionary = ParseParameterSet(type.Parameters); + typeParameterDictionary = ParseParameterSet(type.Parameters); // NOTE: type parameters should be ideally proxied out for a better data layout. + if (type is DB.HostObjAttributes hostObjectAttr) + { + var factor = _scalingServiceToSpeckle.ScaleLength(1); + + var structureDictionary = new Dictionary(); + var structure = hostObjectAttr.GetCompoundStructure(); + var layers = structure.GetLayers(); + foreach (var layer in layers) + { + if (_settingsStore.Current.Document.GetElement(layer.MaterialId) is DB.Material material) + { + structureDictionary[material.Name] = new Dictionary() + { + ["material"] = material.Name, + ["function"] = layer.Function.ToString(), + ["thickness"] = layer.Width * factor, + ["units"] = _settingsStore.Current.SpeckleUnits + }; + } + } + + typeParameterDictionary["Structure"] = structureDictionary; + } + _typeParameterCache[typeId] = typeParameterDictionary; return CreateParameterDictionary(instanceParameterDictionary, typeParameterDictionary); @@ -114,9 +138,9 @@ ILogger logger continue; } - if (value is (string typeName, string familyName)) // element type dilemma + if (value is (string typeName, string familyName)) // element type: same element, different expected values depending on the param definition { - if (internalDefinitionName == "ELEM_FAMILY_PARAM") + if (internalDefinitionName == "ELEM_FAMILY_PARAM") // Probably should be using the BUILTINPARAM whatever { value = familyName; } @@ -191,9 +215,12 @@ ILogger logger var docElement = _settingsStore.Current.Document.GetElement(elId); object? docElementName; + + // Note: for element types, different params point at the same element. We're getting the right value out in the parent function + // based on what the actual built in param name is. if (docElement is DB.ElementType elementType) { - docElementName = (elementType.Name, elementType.FamilyName); // new[] { elementType.Name, elementType.FamilyName }; + docElementName = (elementType.Name, elementType.FamilyName); } else { From 9804acd10c6b00260f3bcbe5dace96e60720bfbd Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 11 Oct 2024 14:14:23 +0100 Subject: [PATCH 6/7] feat: makes material quantities a map (used to a be a list) tbh, this just makes it easier to show in the frontend - but worthwhile for now --- .../RevitRootToSpeckleConverter.cs | 4 ++-- .../ToSpeckle/Raw/MaterialQuantitiesToSpeckle.cs | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToSpeckleConverter.cs b/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToSpeckleConverter.cs index 120f81c37..71e0772af 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToSpeckleConverter.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/RevitRootToSpeckleConverter.cs @@ -13,7 +13,7 @@ namespace Speckle.Converters.RevitShared; public class RevitRootToSpeckleConverter : IRootToSpeckleConverter { private readonly IConverterManager _toSpeckle; - private readonly ITypedConverter>> _materialQuantityConverter; + private readonly ITypedConverter> _materialQuantityConverter; private readonly IConverterSettingsStore _converterSettings; private readonly ParameterExtractor _parameterExtractor; private readonly ILogger _logger; @@ -22,7 +22,7 @@ public class RevitRootToSpeckleConverter : IRootToSpeckleConverter public RevitRootToSpeckleConverter( IConverterManager toSpeckle, - ITypedConverter>> materialQuantityConverter, + ITypedConverter> materialQuantityConverter, IConverterSettingsStore converterSettings, ParameterExtractor parameterExtractor, ILogger logger diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/MaterialQuantitiesToSpeckle.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/MaterialQuantitiesToSpeckle.cs index 0953be5a0..6defa25b0 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/MaterialQuantitiesToSpeckle.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Raw/MaterialQuantitiesToSpeckle.cs @@ -11,7 +11,7 @@ namespace Speckle.Converters.RevitShared.ToSpeckle; /// Lighter converter for material quantities. It basically returns a For each material quantity available on the target element, it will return a dictionary containing: area, volume, units, material name, material class and material category. /// POC: we need to validate this with user needs. It currently does not include material parameters or any other more complex props to ensure speedy sending of data and a lighter payload. We're though keen to re-add more data provided we can validate it. /// -public class MaterialQuantitiesToSpeckleLite : ITypedConverter>> +public class MaterialQuantitiesToSpeckleLite : ITypedConverter> { private readonly ScalingServiceToSpeckle _scalingService; private readonly IConverterSettingsStore _converterSettings; @@ -30,10 +30,9 @@ IConverterSettingsStore converterSettings /// /// /// - public List> Convert(DB.Element target) + public Dictionary Convert(DB.Element target) { - List> quantities = new(); - + Dictionary quantities = new(); if (target.Category.HasMaterialQuantities) { foreach (DB.ElementId matId in target.GetMaterialIds(false)) @@ -55,7 +54,7 @@ public List> Convert(DB.Element target) materialQuantity["materialName"] = material.Name; materialQuantity["materialCategory"] = material.MaterialCategory; materialQuantity["materialClass"] = material.MaterialClass; - quantities.Add(materialQuantity); + quantities[material.Name] = materialQuantity; } } } From 650022ee10c511bc490579261cd1f80639f15cbd Mon Sep 17 00:00:00 2001 From: Dimitrie Stefanescu Date: Fri, 11 Oct 2024 14:27:00 +0100 Subject: [PATCH 7/7] chore: adds comment --- .../ToSpeckle/Parameters/ParameterExtractor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs index b15cbb165..6f93643b4 100644 --- a/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs +++ b/Converters/Revit/Speckle.Converters.RevitShared/ToSpeckle/Parameters/ParameterExtractor.cs @@ -68,8 +68,8 @@ ILogger logger typeParameterDictionary = ParseParameterSet(type.Parameters); // NOTE: type parameters should be ideally proxied out for a better data layout. if (type is DB.HostObjAttributes hostObjectAttr) { + // NOTE: this could be paired up and merged with material quantities - they're pretty much the same :/ var factor = _scalingServiceToSpeckle.ScaleLength(1); - var structureDictionary = new Dictionary(); var structure = hostObjectAttr.GetCompoundStructure(); var layers = structure.GetLayers();