From 0ceceb25c99eb7c0729dea4578b39ee1ae2f283e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn?= Date: Fri, 18 Oct 2024 15:24:41 +0200 Subject: [PATCH 1/8] File Added: ConvertStructuralMaterial Separated methods pertaining to StructuralMaterial outside of the ConvertAnalyticalStick.cs file. Didn't make sense that these functions were in the ConvertAnalyticalStick.cs when the ConvertAnalyticalSurface.cs referenced them --- .../ConverterRevitShared.projitems | 1 + .../PartialClasses/ConvertAnalyticalStick.cs | 154 ----------------- .../ConvertStructuralMaterial.cs | 162 ++++++++++++++++++ 3 files changed, 163 insertions(+), 154 deletions(-) create mode 100644 Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems index a42188f2c0..c50b605cd8 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems @@ -56,6 +56,7 @@ + diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs index 2da7027efe..268ec7fb41 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs @@ -629,158 +629,4 @@ private void SetStructuralSectionProps(StructuralSection revitSection, SectionPr //speckleSection["webToeOfFillet"] = u.WebToeOfFillet * scaleFactor; // this is in inches (or mm?) so it needs a different scaleFactor } } - - private StructuralMaterial GetStructuralMaterial(Material material) - { - if (material == null) - { - return null; - } - - StructuralAsset materialAsset = null; - string name = null; - if (material.StructuralAssetId != ElementId.InvalidElementId) - { - materialAsset = ( - (PropertySetElement)material.Document.GetElement(material.StructuralAssetId) - ).GetStructuralAsset(); - - name = material.Document.GetElement(material.StructuralAssetId)?.Name; - } - var materialName = material.MaterialClass; - var materialType = GetMaterialType(materialName); - - var speckleMaterial = GetStructuralMaterial(materialType, materialAsset, name); - speckleMaterial.applicationId = material.UniqueId; - - return speckleMaterial; - } - - private StructuralMaterial GetStructuralMaterial( - StructuralMaterialType materialType, - StructuralAsset materialAsset, - string name - ) - { - Structural.Materials.StructuralMaterial speckleMaterial = null; - - if (materialType == StructuralMaterialType.Undefined && materialAsset != null) - { - materialType = GetMaterialType(materialAsset); - } - - name ??= materialType.ToString(); - switch (materialType) - { - case StructuralMaterialType.Concrete: - var concreteMaterial = new Concrete { name = name, materialType = Structural.MaterialType.Concrete, }; - - if (materialAsset != null) - { - concreteMaterial.compressiveStrength = materialAsset.ConcreteCompression; // Newtons per foot meter - concreteMaterial.lightweight = materialAsset.Lightweight; - } - - speckleMaterial = concreteMaterial; - break; - case StructuralMaterialType.Steel: - var steelMaterial = new Steel - { - name = name, - materialType = Structural.MaterialType.Steel, - designCode = null, - codeYear = null, - maxStrain = 0, - dampingRatio = 0, - }; - - if (materialAsset != null) - { - steelMaterial.grade = materialAsset.Name; - steelMaterial.yieldStrength = materialAsset.MinimumYieldStress; // Newtons per foot meter - steelMaterial.ultimateStrength = materialAsset.MinimumTensileStrength; // Newtons per foot meter - } - - speckleMaterial = steelMaterial; - break; - case StructuralMaterialType.Wood: - var timberMaterial = new Timber - { - name = name, - materialType = Structural.MaterialType.Timber, - designCode = null, - codeYear = null, - dampingRatio = 0 - }; - - if (materialAsset != null) - { - timberMaterial.grade = materialAsset.WoodGrade; - timberMaterial.species = materialAsset.WoodSpecies; - timberMaterial["bendingStrength"] = materialAsset.WoodBendingStrength; - timberMaterial["parallelCompressionStrength"] = materialAsset.WoodParallelCompressionStrength; - timberMaterial["parallelShearStrength"] = materialAsset.WoodParallelShearStrength; - timberMaterial["perpendicularCompressionStrength"] = materialAsset.WoodPerpendicularCompressionStrength; - timberMaterial["perpendicularShearStrength"] = materialAsset.WoodPerpendicularShearStrength; - } - - speckleMaterial = timberMaterial; - break; - default: - var defaultMaterial = new Objects.Structural.Materials.StructuralMaterial { name = name, }; - speckleMaterial = defaultMaterial; - break; - } - - // TODO: support non-isotropic materials - if (materialAsset != null) - { - // some of these are actually the dumbest units I've ever heard of - speckleMaterial.elasticModulus = materialAsset.YoungModulus.X; // Newtons per foot meter - speckleMaterial.poissonsRatio = materialAsset.PoissonRatio.X; // Unitless - speckleMaterial.shearModulus = materialAsset.ShearModulus.X; // Newtons per foot meter - speckleMaterial.density = materialAsset.Density; // kilograms per cubed feet - speckleMaterial.thermalExpansivity = materialAsset.ThermalExpansionCoefficient.X; // inverse Kelvin - } - - return speckleMaterial; - } - - private StructuralMaterialType GetMaterialType(string materialName) - { - StructuralMaterialType materialType = StructuralMaterialType.Undefined; - switch (materialName.ToLower()) - { - case "concrete": - materialType = StructuralMaterialType.Concrete; - break; - case "steel": - materialType = StructuralMaterialType.Steel; - break; - case "wood": - materialType = StructuralMaterialType.Wood; - break; - } - - return materialType; - } - - private StructuralMaterialType GetMaterialType(StructuralAsset materialAsset) - { - StructuralMaterialType materialType = StructuralMaterialType.Undefined; - switch (materialAsset?.StructuralAssetClass) - { - case StructuralAssetClass.Metal: - materialType = StructuralMaterialType.Steel; - break; - case StructuralAssetClass.Concrete: - materialType = StructuralMaterialType.Concrete; - break; - case StructuralAssetClass.Wood: - materialType = StructuralMaterialType.Wood; - break; - } - - return materialType; - } } diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs new file mode 100644 index 0000000000..01a96c5b54 --- /dev/null +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs @@ -0,0 +1,162 @@ +using Autodesk.Revit.DB; +using Autodesk.Revit.DB.Structure; +using Objects.Structural.Materials; + +namespace Objects.Converter.Revit; + +public partial class ConverterRevit +{ + private StructuralMaterial GetStructuralMaterial(Material material) + { + if (material == null) + { + return null; + } + + StructuralAsset materialAsset = null; + string name = null; + if (material.StructuralAssetId != ElementId.InvalidElementId) + { + materialAsset = ( + (PropertySetElement)material.Document.GetElement(material.StructuralAssetId) + ).GetStructuralAsset(); + + name = material.Document.GetElement(material.StructuralAssetId)?.Name; + } + var materialName = material.MaterialClass; + var materialType = GetMaterialType(materialName); + + var speckleMaterial = GetStructuralMaterial(materialType, materialAsset, name); + speckleMaterial.applicationId = material.UniqueId; + + return speckleMaterial; + } + + private StructuralMaterial GetStructuralMaterial( + StructuralMaterialType materialType, + StructuralAsset materialAsset, + string name + ) + { + Structural.Materials.StructuralMaterial speckleMaterial = null; + + if (materialType == StructuralMaterialType.Undefined && materialAsset != null) + { + materialType = GetMaterialType(materialAsset); + } + + name ??= materialType.ToString(); + switch (materialType) + { + case StructuralMaterialType.Concrete: + var concreteMaterial = new Concrete { name = name, materialType = Structural.MaterialType.Concrete, }; + + if (materialAsset != null) + { + concreteMaterial.compressiveStrength = materialAsset.ConcreteCompression; // Newtons per foot meter + concreteMaterial.lightweight = materialAsset.Lightweight; + } + + speckleMaterial = concreteMaterial; + break; + case StructuralMaterialType.Steel: + var steelMaterial = new Steel + { + name = name, + materialType = Structural.MaterialType.Steel, + designCode = null, + codeYear = null, + maxStrain = 0, + dampingRatio = 0, + }; + + if (materialAsset != null) + { + steelMaterial.grade = materialAsset.Name; + steelMaterial.yieldStrength = materialAsset.MinimumYieldStress; // Newtons per foot meter + steelMaterial.ultimateStrength = materialAsset.MinimumTensileStrength; // Newtons per foot meter + } + + speckleMaterial = steelMaterial; + break; + case StructuralMaterialType.Wood: + var timberMaterial = new Timber + { + name = name, + materialType = Structural.MaterialType.Timber, + designCode = null, + codeYear = null, + dampingRatio = 0 + }; + + if (materialAsset != null) + { + timberMaterial.grade = materialAsset.WoodGrade; + timberMaterial.species = materialAsset.WoodSpecies; + timberMaterial["bendingStrength"] = materialAsset.WoodBendingStrength; + timberMaterial["parallelCompressionStrength"] = materialAsset.WoodParallelCompressionStrength; + timberMaterial["parallelShearStrength"] = materialAsset.WoodParallelShearStrength; + timberMaterial["perpendicularCompressionStrength"] = materialAsset.WoodPerpendicularCompressionStrength; + timberMaterial["perpendicularShearStrength"] = materialAsset.WoodPerpendicularShearStrength; + } + + speckleMaterial = timberMaterial; + break; + default: + var defaultMaterial = new Objects.Structural.Materials.StructuralMaterial { name = name, }; + speckleMaterial = defaultMaterial; + break; + } + + // TODO: support non-isotropic materials + if (materialAsset != null) + { + // some of these are actually the dumbest units I've ever heard of + speckleMaterial.elasticModulus = materialAsset.YoungModulus.X; // Newtons per foot meter + speckleMaterial.poissonsRatio = materialAsset.PoissonRatio.X; // Unitless + speckleMaterial.shearModulus = materialAsset.ShearModulus.X; // Newtons per foot meter + speckleMaterial.density = materialAsset.Density; // kilograms per cubed feet + speckleMaterial.thermalExpansivity = materialAsset.ThermalExpansionCoefficient.X; // inverse Kelvin + } + + return speckleMaterial; + } + + private StructuralMaterialType GetMaterialType(string materialName) + { + StructuralMaterialType materialType = StructuralMaterialType.Undefined; + switch (materialName.ToLower()) + { + case "concrete": + materialType = StructuralMaterialType.Concrete; + break; + case "steel": + materialType = StructuralMaterialType.Steel; + break; + case "wood": + materialType = StructuralMaterialType.Wood; + break; + } + + return materialType; + } + + private StructuralMaterialType GetMaterialType(StructuralAsset materialAsset) + { + StructuralMaterialType materialType = StructuralMaterialType.Undefined; + switch (materialAsset?.StructuralAssetClass) + { + case StructuralAssetClass.Metal: + materialType = StructuralMaterialType.Steel; + break; + case StructuralAssetClass.Concrete: + materialType = StructuralMaterialType.Concrete; + break; + case StructuralAssetClass.Wood: + materialType = StructuralMaterialType.Wood; + break; + } + + return materialType; + } +} From 9aac9c872e39c3f4240e2610a881bae0d3be987a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn?= Date: Fri, 18 Oct 2024 17:07:33 +0200 Subject: [PATCH 2/8] ScaleToSpeckle Material properties were sent as revit internal units. Inconsistent with the Revit model / project units. These can't be used for connection applications (e.g. receiving analytical elements in ETABS) --- .../ConvertAnalyticalSurface.cs | 12 +++--- .../ConvertStructuralMaterial.cs | 43 +++++++++++++------ .../PartialClasses/Units.cs | 23 ++++++++++ Objects/Objects/Structural/PropertyType.cs | 2 +- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs index 52a8c5f97a..1a27b43534 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs @@ -4,6 +4,7 @@ using Autodesk.Revit.DB.Structure; using Objects.BuiltElements.Revit; using Objects.Geometry; +using Objects.Structural; using Objects.Structural.Geometry; using Objects.Structural.Properties; using Speckle.Core.Models; @@ -268,7 +269,7 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalModelSurface revitSurface prop.name = revitSurface.Document.GetElement(revitSurface.GetElementId()).Name; //prop.type = memberType; //prop.analysisType = Structural.AnalysisType2D.Shell; - prop.thickness = thickness; + prop.thickness = ScaleToSpeckle(thickness); speckleElement2D.property = prop; @@ -389,28 +390,27 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalPanel revitSurface) // Material DB.Material structMaterial = null; double thickness = 0; - var memberType = MemberType2D.Generic2D; + var memberType = PropertyType2D.Plate; // NOTE: a floor is typically classified as a plate since subjected to bending and shear stresses. Standard to have this as default. if (structuralElement.StructuralRole is AnalyticalStructuralRole.StructuralRoleFloor) { structMaterial = structuralElement.Document.GetElement(structuralElement.MaterialId) as DB.Material; thickness = structuralElement.Thickness; - memberType = MemberType2D.Slab; } else if (structuralElement.StructuralRole is AnalyticalStructuralRole.StructuralRoleWall) { structMaterial = structuralElement.Document.GetElement(structuralElement.MaterialId) as DB.Material; thickness = structuralElement.Thickness; - memberType = MemberType2D.Wall; + memberType = PropertyType2D.Shell; // NOTE: A wall is typically classified as shell since subjected to axial stresses } var speckleMaterial = GetStructuralMaterial(structMaterial); prop.material = speckleMaterial; prop.name = structuralElement.Name; - //prop.type = memberType; + prop.type = memberType; //prop.analysisType = Structural.AnalysisType2D.Shell; - prop.thickness = thickness; + prop.thickness = ScaleToSpeckle(thickness); // NOTE: This function overload takes RevitLengthTypeId by default speckleElement2D.property = prop; diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs index 01a96c5b54..4a43f6c43b 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs @@ -53,7 +53,7 @@ string name if (materialAsset != null) { - concreteMaterial.compressiveStrength = materialAsset.ConcreteCompression; // Newtons per foot meter + concreteMaterial.compressiveStrength = ScaleToSpeckle(materialAsset.ConcreteCompression, RevitStressTypeId); concreteMaterial.lightweight = materialAsset.Lightweight; } @@ -73,8 +73,8 @@ string name if (materialAsset != null) { steelMaterial.grade = materialAsset.Name; - steelMaterial.yieldStrength = materialAsset.MinimumYieldStress; // Newtons per foot meter - steelMaterial.ultimateStrength = materialAsset.MinimumTensileStrength; // Newtons per foot meter + steelMaterial.yieldStrength = ScaleToSpeckle(materialAsset.MinimumYieldStress, RevitStressTypeId); + steelMaterial.ultimateStrength = ScaleToSpeckle(materialAsset.MinimumTensileStrength, RevitStressTypeId); } speckleMaterial = steelMaterial; @@ -93,11 +93,23 @@ string name { timberMaterial.grade = materialAsset.WoodGrade; timberMaterial.species = materialAsset.WoodSpecies; - timberMaterial["bendingStrength"] = materialAsset.WoodBendingStrength; - timberMaterial["parallelCompressionStrength"] = materialAsset.WoodParallelCompressionStrength; - timberMaterial["parallelShearStrength"] = materialAsset.WoodParallelShearStrength; - timberMaterial["perpendicularCompressionStrength"] = materialAsset.WoodPerpendicularCompressionStrength; - timberMaterial["perpendicularShearStrength"] = materialAsset.WoodPerpendicularShearStrength; + timberMaterial["bendingStrength"] = ScaleToSpeckle(materialAsset.WoodBendingStrength, RevitStressTypeId); + timberMaterial["parallelCompressionStrength"] = ScaleToSpeckle( + materialAsset.WoodParallelCompressionStrength, + RevitStressTypeId + ); + timberMaterial["parallelShearStrength"] = ScaleToSpeckle( + materialAsset.WoodParallelShearStrength, + RevitStressTypeId + ); + timberMaterial["perpendicularCompressionStrength"] = ScaleToSpeckle( + materialAsset.WoodPerpendicularCompressionStrength, + RevitStressTypeId + ); + timberMaterial["perpendicularShearStrength"] = ScaleToSpeckle( + materialAsset.WoodPerpendicularShearStrength, + RevitStressTypeId + ); } speckleMaterial = timberMaterial; @@ -111,12 +123,15 @@ string name // TODO: support non-isotropic materials if (materialAsset != null) { - // some of these are actually the dumbest units I've ever heard of - speckleMaterial.elasticModulus = materialAsset.YoungModulus.X; // Newtons per foot meter - speckleMaterial.poissonsRatio = materialAsset.PoissonRatio.X; // Unitless - speckleMaterial.shearModulus = materialAsset.ShearModulus.X; // Newtons per foot meter - speckleMaterial.density = materialAsset.Density; // kilograms per cubed feet - speckleMaterial.thermalExpansivity = materialAsset.ThermalExpansionCoefficient.X; // inverse Kelvin + // NOTE: Convert all internal units to project units + speckleMaterial.elasticModulus = ScaleToSpeckle(materialAsset.YoungModulus.X, RevitStressTypeId); + speckleMaterial.poissonsRatio = materialAsset.PoissonRatio.X; + speckleMaterial.shearModulus = ScaleToSpeckle(materialAsset.ShearModulus.X, RevitStressTypeId); + speckleMaterial.density = ScaleToSpeckle(materialAsset.Density, RevitMassDensityTypeId); + speckleMaterial.thermalExpansivity = ScaleToSpeckle( + materialAsset.ThermalExpansionCoefficient.X, + RevitThermalExpansionTypeId + ); } return speckleMaterial; diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs index 1572b80614..0ea242f57e 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs @@ -36,6 +36,14 @@ public DisplayUnitType RevitLengthTypeId return _revitUnitsTypeId; } } + public DisplayUnitType RevitMassDensityTypeId + { get { return Doc.GetUnits().GetFormatOptions(UnitType.UT_MassDensity).DisplayUnits; } } + + public DisplayUnitType RevitStressTypeId + { get { return Doc.GetUnits().GetFormatOptions(UnitType.UT_Stress).DisplayUnits; } } + + public DisplayUnitType RevitThermalExpansionTypeId + { get { return Doc.GetUnits().GetFormatOptions(UnitType.UT_ThermalExpansion).DisplayUnits; } } /// /// Converts Speckle length values to internal ones @@ -166,6 +174,21 @@ public ForgeTypeId RevitLengthTypeId } } + public ForgeTypeId RevitMassDensityTypeId + { + get { return Doc.GetUnits().GetFormatOptions(SpecTypeId.MassDensity).GetUnitTypeId(); } + } + + public ForgeTypeId RevitStressTypeId + { + get { return Doc.GetUnits().GetFormatOptions(SpecTypeId.Stress).GetUnitTypeId(); } + } + + public ForgeTypeId RevitThermalExpansionTypeId + { + get { return Doc.GetUnits().GetFormatOptions(SpecTypeId.ThermalExpansionCoefficient).GetUnitTypeId(); } + } + public static double ScaleToNative(double value, string units) { if (string.IsNullOrEmpty(units)) diff --git a/Objects/Objects/Structural/PropertyType.cs b/Objects/Objects/Structural/PropertyType.cs index b17f28a335..e0190ac7bd 100644 --- a/Objects/Objects/Structural/PropertyType.cs +++ b/Objects/Objects/Structural/PropertyType.cs @@ -7,7 +7,7 @@ public enum PropertyType2D Plate, Shell, Curved, - Wall, + Wall, // NOTE: Shell and wall duplicates? Where do these come from? Strain, Axi, Load From 3de7c29dcb01479fbbe2394e5c15192a7059cd32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn?= Date: Mon, 21 Oct 2024 16:28:01 +0200 Subject: [PATCH 3/8] ETABS Receive Property2D ETABS currently only created properties for Element2Ds with a CSIProperty2D, but what about Property2D? These should also be received without us defaulting to the "Slab1" ETABS section. --- .../ConnectorETABS/ConnectorETABS.csproj | 2 +- .../PartialClasses/Geometry/ConvertArea.cs | 33 +++++++++++++------ .../Properties/Convert2DProperty.cs | 13 ++++++++ .../Properties/Convert2DPropertyFloor.cs | 19 +++++++++++ .../ConvertAnalyticalSurface.cs | 32 +++++++++--------- .../Structural/Properties/Property2D.cs | 1 + 6 files changed, 73 insertions(+), 27 deletions(-) diff --git a/ConnectorCSI/ConnectorETABS/ConnectorETABS.csproj b/ConnectorCSI/ConnectorETABS/ConnectorETABS.csproj index 8c7a43b05e..603552b6b2 100644 --- a/ConnectorCSI/ConnectorETABS/ConnectorETABS.csproj +++ b/ConnectorCSI/ConnectorETABS/ConnectorETABS.csproj @@ -4,7 +4,7 @@ SpeckleConnectorCSI net48 Program - C:\Program Files\Computers and Structures\ETABS 19\ETABS.exe + C:\Program Files\Computers and Structures\ETABS 21\ETABS.exe x64 ConnectorETABS ConnectorETABS diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs index 85bf8ea782..8b9a6ced13 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs @@ -212,8 +212,8 @@ public void AreaToNative(Element2D area, ApplicationObject appObj) throw new ConversionException($"There is already a frame object named {area.name} in the model"); } - var propName = CreateOrGetProp(area.property, out bool isExactMatch); - if (!isExactMatch) + var propName = CreateOrGetProp(area.property, out bool isPropertyHandled); + if (!isPropertyHandled) { appObj.Update( logItem: $"Area section for object could not be created and was replaced with section named \"{propName}\"" @@ -299,7 +299,7 @@ private string CreateAreaFromPoints(IEnumerable points, string propName) return name; } - private string? CreateOrGetProp(Property2D property, out bool isExactMatch) + private string? CreateOrGetProp(Property2D property, out bool isPropertyHandled) { int numberNames = 0; string[] propNames = Array.Empty(); @@ -310,30 +310,43 @@ private string CreateAreaFromPoints(IEnumerable points, string propName) throw new ConversionException("Failed to retrieve the names of all defined area properties"); } - isExactMatch = true; + isPropertyHandled = true; + // Use the property if it already exists in the analytical model if (propNames.Contains(property?.name)) { return property.name; } - if (property is CSIProperty2D prop2D) + // Create detailed property if it is of type CSI and doesn't exist in the analytical model + if (property is CSIProperty2D csiProp2D) { try { - return Property2DToNative(prop2D); + return Property2DToNative(csiProp2D); } catch (Exception ex) when (!ex.IsFatal()) { + // Should we not change the out of isPropertyHandled here?? SpeckleLog.Logger.Error(ex, "Unable to create property2d"); - // something failed... replace the type } } - isExactMatch = false; - if (propNames.Any()) + // Create the property with information we can use if it is a Property2D (i.e. thickness) + if (property is Property2D structuralProp2D && !string.IsNullOrEmpty(structuralProp2D.name)) + { + try + { + return Property2DToNative(structuralProp2D); + } + catch (Exception ex) when (!ex.IsFatal()) + { + SpeckleLog.Logger.Error(ex, "Unable to create property2d"); + } + } + isPropertyHandled = false; + if (propNames.Length == 0) { - // TODO: support creating of Property2D return propNames.First(); } diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs index 7a34d510f3..85f07703df 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs @@ -1,6 +1,7 @@ using CSiAPIv1; using Objects.Structural.CSI.Analysis; using Objects.Structural.CSI.Properties; +using Objects.Structural.Properties; namespace Objects.Converter.CSI; @@ -14,6 +15,18 @@ void setProperties(CSIProperty2D property2D, string matProp, double thickeness, return; } + private string Property2DToNative(Property2D property2D) + { + if (property2D.type.ToString() == "Plate") + { + return FloorPropertyToNative(property2D); + } + else + { + return FloorPropertyToNative(property2D); + } + } + private string Property2DToNative(CSIProperty2D property2D) { if (property2D.type2D == CSIPropertyType2D.Wall) diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyFloor.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyFloor.cs index 65524ab3e2..83c9717785 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyFloor.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyFloor.cs @@ -1,6 +1,7 @@ using System; using CSiAPIv1; using Objects.Structural.CSI.Properties; +using Objects.Structural.Properties; using Speckle.Core.Kits; namespace Objects.Converter.CSI; @@ -118,6 +119,24 @@ private string FloorSlabPropertyToNative(CSIProperty2D property2D) return property2D.name; } + // A Property2D can be created with the basic information we have i.e. thickness and material. No need to default to "Slab1" + public string FloorPropertyToNative(Property2D property2D) + { + var materialName = MaterialToNative(property2D.material); + int success = Model.PropArea.SetSlab( + property2D.name, + eSlabType.Slab, + eShellType.ShellThin, + materialName, + ScaleToNative(property2D.thickness, property2D.units) + ); + if (success != 0) + { + throw new ConversionException("Failed to set slab property"); + } + return property2D.name; + } + public string FloorPropertyToNative(CSIProperty2D property2D) { if (property2D.deckType != Structural.CSI.Analysis.DeckType.Null) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs index 1a27b43534..5bc7e40000 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs @@ -373,21 +373,9 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalPanel revitSurface) } speckleElement2D.topology = edgeNodes; - var analyticalToPhysicalManager = AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager( - Doc - ); - if (analyticalToPhysicalManager.HasAssociation(revitSurface.Id)) - { - var physicalElementId = analyticalToPhysicalManager.GetAssociatedElementId(revitSurface.Id); - var physicalElement = Doc.GetElement(physicalElementId); - speckleElement2D.displayValue = GetElementDisplayValue(physicalElement); - } - - speckleElement2D.openings = GetOpenings(revitSurface); + // Property and Material var prop = new Property2D(); - - // Material DB.Material structMaterial = null; double thickness = 0; var memberType = PropertyType2D.Plate; // NOTE: a floor is typically classified as a plate since subjected to bending and shear stresses. Standard to have this as default. @@ -407,12 +395,24 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalPanel revitSurface) var speckleMaterial = GetStructuralMaterial(structMaterial); prop.material = speckleMaterial; - prop.name = structuralElement.Name; + prop.name = structuralElement.Name; // NOTE: This is typically "" for analytical surfaces prop.type = memberType; - //prop.analysisType = Structural.AnalysisType2D.Shell; - prop.thickness = ScaleToSpeckle(thickness); // NOTE: This function overload takes RevitLengthTypeId by default + prop.thickness = ScaleToSpeckle(thickness); + prop.units = ModelUnits; + + var analyticalToPhysicalManager = AnalyticalToPhysicalAssociationManager.GetAnalyticalToPhysicalAssociationManager( + Doc + ); + if (analyticalToPhysicalManager.HasAssociation(revitSurface.Id)) + { + var physicalElementId = analyticalToPhysicalManager.GetAssociatedElementId(revitSurface.Id); + var physicalElement = Doc.GetElement(physicalElementId); + speckleElement2D.displayValue = GetElementDisplayValue(physicalElement); + prop.name = physicalElement.Name; // Rather use the name of the associated physical type (better than an empty string) + } speckleElement2D.property = prop; + speckleElement2D.openings = GetOpenings(revitSurface); GetAllRevitParamsAndIds(speckleElement2D, revitSurface); diff --git a/Objects/Objects/Structural/Properties/Property2D.cs b/Objects/Objects/Structural/Properties/Property2D.cs index 157f692a46..66130ec774 100644 --- a/Objects/Objects/Structural/Properties/Property2D.cs +++ b/Objects/Objects/Structural/Properties/Property2D.cs @@ -39,4 +39,5 @@ public Property2D(string name, StructuralMaterial? material, PropertyType2D type public double modifierBending { get; set; } public double modifierShear { get; set; } public double modifierVolume { get; set; } + public string units { get; set; } } From 099d8f5da769cc3cc3a38abce8e83110011ecf9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn?= Date: Mon, 21 Oct 2024 17:11:16 +0200 Subject: [PATCH 4/8] ETABS Receive Wall Property Walls were previously assigned with slab sections which is incorrect. The WallPropertyToNative() was implemented (previously raised a ConversionNotSupportedException for some reason) --- .../PartialClasses/Geometry/ConvertArea.cs | 4 +++- .../Properties/Convert2DProperty.cs | 6 ++++-- .../Properties/Convert2DPropertyWall.cs | 17 +++++++++++++++-- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs index 8b9a6ced13..dc95adf3f7 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs @@ -332,7 +332,9 @@ private string CreateAreaFromPoints(IEnumerable points, string propName) } } - // Create the property with information we can use if it is a Property2D (i.e. thickness) + /* Create the property with information we can use if it is a Property2D (i.e. thickness) + * Furthermore, a property can only be created if it has a name (hence the two conditionals). + * Name is inherited from the physical association in Revit (i.e. it comes from the type name of the family) */ if (property is Property2D structuralProp2D && !string.IsNullOrEmpty(structuralProp2D.name)) { try diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs index 85f07703df..304a010ea9 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DProperty.cs @@ -17,10 +17,12 @@ void setProperties(CSIProperty2D property2D, string matProp, double thickeness, private string Property2DToNative(Property2D property2D) { - if (property2D.type.ToString() == "Plate") + // Walls are typically shells (axially loaded) + if (property2D.type == Structural.PropertyType2D.Wall || property2D.type == Structural.PropertyType2D.Shell) { - return FloorPropertyToNative(property2D); + return WallPropertyToNative(property2D); } + // Floors are typically plates (loaded in bending and shear) else { return FloorPropertyToNative(property2D); diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyWall.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyWall.cs index d471b05ab8..53e30e8bb7 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyWall.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Properties/Convert2DPropertyWall.cs @@ -1,14 +1,27 @@ using CSiAPIv1; using Objects.Structural.CSI.Properties; +using Objects.Structural.Properties; using Speckle.Core.Kits; namespace Objects.Converter.CSI; public partial class ConverterCSI { - public string WallPropertyToNative(CSIProperty2D Wall) + public string WallPropertyToNative(Property2D property2D) { - throw new ConversionNotSupportedException("Wall properties are not currently supported on receive"); + var materialName = MaterialToNative(property2D.material); + int success = Model.PropArea.SetWall( + property2D.name, + eWallPropType.Specified, + eShellType.ShellThin, // Lateral stability analysis typically has walls as thin shells + materialName, + ScaleToNative(property2D.thickness, property2D.units) + ); + if (success != 0) + { + throw new ConversionException("Failed to set wall property"); + } + return property2D.name; } public CSIProperty2D WallPropertyToSpeckle(string property) From 084d9bce080e20303037a65d32a6113b64d3b0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn?= Date: Mon, 21 Oct 2024 20:39:43 +0200 Subject: [PATCH 5/8] RVT 22 Scaling Updates Testing on Revit 2022 - ETABS connection --- .../PartialClasses/Geometry/ConvertArea.cs | 2 +- .../PartialClasses/ConvertAnalyticalSurface.cs | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs index dc95adf3f7..6b9cc73bf9 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs @@ -327,8 +327,8 @@ private string CreateAreaFromPoints(IEnumerable points, string propName) } catch (Exception ex) when (!ex.IsFatal()) { - // Should we not change the out of isPropertyHandled here?? SpeckleLog.Logger.Error(ex, "Unable to create property2d"); + isPropertyHandled = false; } } diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs index 5bc7e40000..ac11358007 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs @@ -238,28 +238,25 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalModelSurface revitSurface .Select(p => new Node(p)) .ToList(); - speckleElement2D.displayValue = GetElementDisplayValue(revitSurface); - var prop = new Property2D(); // Material DB.Material structMaterial = null; double thickness = 0; - var memberType = MemberType2D.Generic2D; + var memberType = PropertyType2D.Plate; // NOTE: a floor is typically classified as a plate since subjected to bending and shear stresses. Standard to have this as default. if (structuralElement is DB.Floor) { var floor = structuralElement as DB.Floor; structMaterial = floor.Document.GetElement(floor.FloorType.StructuralMaterialId) as DB.Material; thickness = GetParamValue(structuralElement, BuiltInParameter.STRUCTURAL_FLOOR_CORE_THICKNESS); - memberType = MemberType2D.Slab; } else if (structuralElement is DB.Wall) { var wall = structuralElement as DB.Wall; structMaterial = wall.Document.GetElement(wall.WallType.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM).AsElementId()) as DB.Material; thickness = ScaleToSpeckle(wall.WallType.Width); - memberType = MemberType2D.Wall; + memberType = PropertyType2D.Shell; // NOTE: A wall is typically classified as shell since subjected to axial stresses } var speckleMaterial = GetStructuralMaterial(structMaterial); @@ -267,13 +264,14 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalModelSurface revitSurface prop.material = speckleMaterial; prop.name = revitSurface.Document.GetElement(revitSurface.GetElementId()).Name; - //prop.type = memberType; - //prop.analysisType = Structural.AnalysisType2D.Shell; - prop.thickness = ScaleToSpeckle(thickness); + prop.type = memberType; + prop.thickness = thickness; + prop.units = ModelUnits; speckleElement2D.property = prop; GetAllRevitParamsAndIds(speckleElement2D, revitSurface); + speckleElement2D.displayValue = GetElementDisplayValue(revitSurface.Document.GetElement(revitSurface.GetElementId())); return speckleElement2D; } From fb1437f6e0ab7971ae703fcc3b8cb5a52111d9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn?= Date: Tue, 26 Nov 2024 12:40:02 +0100 Subject: [PATCH 6/8] Default Fallback Assign at least something to Element2D --- .../ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs index 6b9cc73bf9..5e4640cb67 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs @@ -347,7 +347,7 @@ private string CreateAreaFromPoints(IEnumerable points, string propName) } } isPropertyHandled = false; - if (propNames.Length == 0) + if (propNames.Length > 0) { return propNames.First(); } From 750ab154e37e067db76529a364b726b4c1aad2a1 Mon Sep 17 00:00:00 2001 From: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:36:56 +0000 Subject: [PATCH 7/8] Fixed shared project case sensitivity --- .../ConverterRevitShared/ConverterRevitShared.projitems | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems index c50b605cd8..c4a8165555 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems @@ -56,7 +56,7 @@ - + From b2c645bcd871b8b55c348300430562ded205ab02 Mon Sep 17 00:00:00 2001 From: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:35:45 +0000 Subject: [PATCH 8/8] IDE0005 --- .../PartialClasses/ConvertAnalyticalStick.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs index 8e4e7ab76e..dd5ca22b43 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalStick.cs @@ -6,7 +6,6 @@ using Objects.BuiltElements; using Objects.BuiltElements.Revit; using Objects.Structural.Geometry; -using Objects.Structural.Materials; using Objects.Structural.Properties; using Objects.Structural.Properties.Profiles; using Speckle.Core.Models;