From 7c3b5b2a95023d17c50a5557eca874a9a3a5aa45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinhagen?= Date: Thu, 9 Jan 2025 12:59:25 +0100 Subject: [PATCH] CNX-619 Revit Analytical Panel (#3645) * 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 * 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) * 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. * 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) * RVT 22 Scaling Updates Testing on Revit 2022 - ETABS connection * Default Fallback Assign at least something to Element2D * Fixed shared project case sensitivity * IDE0005 --------- Co-authored-by: Jedd Morgan <45512892+JR-Morgan@users.noreply.github.com> --- .../PartialClasses/Geometry/ConvertArea.cs | 35 +++- .../Properties/Convert2DProperty.cs | 15 ++ .../Properties/Convert2DPropertyFloor.cs | 19 ++ .../Properties/Convert2DPropertyWall.cs | 17 +- .../ConverterRevitShared.projitems | 1 + .../PartialClasses/ConvertAnalyticalStick.cs | 155 --------------- .../ConvertAnalyticalSurface.cs | 54 +++--- .../ConvertStructuralMaterial.cs | 177 ++++++++++++++++++ .../PartialClasses/Units.cs | 29 +++ .../Structural/Properties/Property2D.cs | 1 + Objects/Objects/Structural/PropertyType.cs | 2 +- 11 files changed, 310 insertions(+), 195 deletions(-) create mode 100644 Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs diff --git a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs index 06676f0016..3f7e58b7da 100644 --- a/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs +++ b/Objects/Converters/ConverterCSI/ConverterCSIShared/PartialClasses/Geometry/ConvertArea.cs @@ -210,8 +210,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}\"" @@ -297,7 +297,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(); @@ -308,30 +308,45 @@ 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()) { SpeckleLog.Logger.Error(ex, "Unable to create property2d"); - // something failed... replace the type + isPropertyHandled = false; } } - isExactMatch = false; - if (propNames.Any()) + /* 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 + { + 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..304a010ea9 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,20 @@ void setProperties(CSIProperty2D property2D, string matProp, double thickeness, return; } + private string Property2DToNative(Property2D property2D) + { + // Walls are typically shells (axially loaded) + if (property2D.type == Structural.PropertyType2D.Wall || property2D.type == Structural.PropertyType2D.Shell) + { + return WallPropertyToNative(property2D); + } + // Floors are typically plates (loaded in bending and shear) + 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/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) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevitShared.projitems index a42188f2c0..c4a8165555 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 528c81afa7..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; @@ -650,158 +649,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/ConvertAnalyticalSurface.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertAnalyticalSurface.cs index b7a30a37a5..3b408b2bbe 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; @@ -232,21 +233,18 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalModelSurface revitSurface speckleElement2D.topology = outlineBuilder.GetOutline().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) { @@ -255,7 +253,7 @@ private Element2D AnalyticalSurfaceToSpeckle(AnalyticalModelSurface revitSurface 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); @@ -263,13 +261,16 @@ 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.type = memberType; prop.thickness = thickness; + prop.units = ModelUnits; speckleElement2D.property = prop; GetAllRevitParamsAndIds(speckleElement2D, revitSurface); + speckleElement2D.displayValue = GetElementDisplayValue( + revitSurface.Document.GetElement(revitSurface.GetElementId()) + ); return speckleElement2D; } @@ -369,47 +370,46 @@ 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 = 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.analysisType = Structural.AnalysisType2D.Shell; - prop.thickness = thickness; + prop.name = structuralElement.Name; // NOTE: This is typically "" for analytical surfaces + prop.type = memberType; + 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/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs new file mode 100644 index 0000000000..4a43f6c43b --- /dev/null +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertStructuralMaterial.cs @@ -0,0 +1,177 @@ +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 = ScaleToSpeckle(materialAsset.ConcreteCompression, RevitStressTypeId); + 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 = ScaleToSpeckle(materialAsset.MinimumYieldStress, RevitStressTypeId); + steelMaterial.ultimateStrength = ScaleToSpeckle(materialAsset.MinimumTensileStrength, RevitStressTypeId); + } + + 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"] = 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; + break; + default: + var defaultMaterial = new Objects.Structural.Materials.StructuralMaterial { name = name, }; + speckleMaterial = defaultMaterial; + break; + } + + // TODO: support non-isotropic materials + if (materialAsset != null) + { + // 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; + } + + 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/Units.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs index 7ad9d6bb29..24b81121b6 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/Units.cs @@ -36,6 +36,20 @@ 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 +180,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/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; } } 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