diff --git a/Physical_Engine/Create/Floor.cs b/Physical_Engine/Create/Floor.cs index f3d336745..60d2b7e75 100644 --- a/Physical_Engine/Create/Floor.cs +++ b/Physical_Engine/Create/Floor.cs @@ -21,7 +21,6 @@ */ using System.ComponentModel; - using BH.oM.Physical.Constructions; using BH.oM.Base.Attributes; using BH.oM.Physical.Elements; @@ -47,7 +46,6 @@ public static partial class Create public static Floor Floor(oM.Geometry.ISurface location, IConstruction construction, List openings = null, Offset offset = Offset.Undefined, string name = "") { openings = openings ?? new List(); - return new Floor { Location = location, @@ -58,6 +56,8 @@ public static Floor Floor(oM.Geometry.ISurface location, IConstruction construct }; } + /***************************************************/ + [Description("Creates physical floor based on given construction and external edges.")] [Input("construction", "Construction of the floor.")] [Input("edges", "External edges of the floor (Profile - planar closed curve).")] @@ -74,35 +74,35 @@ public static Floor Floor(Construction construction, ICurve edges) [Input("edges", "External edges of the floor (Profile - planar closed curve).")] [Input("internalEdges", "Internal edges of openings.")] [Output("floor", "A physical floor.")] - public static Floor Floor(Construction construction, ICurve edges, IEnumerable internalEdges) + public static Floor Floor(Construction construction, ICurve edges, IEnumerable internalEdges = null) { if (construction == null || edges == null) { - Base.Compute.RecordError("Physical Roof could not be created because some input data are null."); + Base.Compute.RecordError("Physical Floor could not be created because some input data are null."); return null; } - List aInternalCurveList = null; - if (internalEdges != null && internalEdges.Count() > 0) - aInternalCurveList = internalEdges.ToList().ConvertAll(x => x as ICurve); - - PlanarSurface aPlanarSurface = Geometry.Create.PlanarSurface(edges, aInternalCurveList); - if (aPlanarSurface == null) + //Create the location for the floor + PlanarSurface location = Geometry.Create.PlanarSurface(edges); + if (location == null) { - Base.Compute.RecordError("Physical Roof could not be created because invalid geometry of edges."); + Base.Compute.RecordError("Physical Floor could not be created because of invalid geometry of edges."); return null; } - return new Floor() + //Create the openings + List openings = new List(); + + if (internalEdges != null && internalEdges.Count() > 0) { - Construction = construction, - Location = aPlanarSurface - }; - } + foreach (ICurve openingCurve in internalEdges) + if (openingCurve != null) + openings.Add(new Void { Location = Geometry.Create.PlanarSurface(openingCurve) }); + } + return Floor(location, construction, openings); + } + /***************************************************/ } -} - - - +} \ No newline at end of file diff --git a/Physical_Engine/Create/Wall.cs b/Physical_Engine/Create/Wall.cs index 3b982c027..0a7ee81ed 100644 --- a/Physical_Engine/Create/Wall.cs +++ b/Physical_Engine/Create/Wall.cs @@ -20,15 +20,9 @@ * along with this code. If not, see . */ -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; - using BH.oM.Physical.Constructions; -using BH.oM.Physical.Materials; - using BH.oM.Base.Attributes; using System.ComponentModel; using BH.oM.Physical.Elements; @@ -61,15 +55,15 @@ public static Wall Wall(IConstruction construction, ICurve bottomEdge, double he Base.Compute.RecordError("Physical Wall could not be created because bottom edge cannot be closed curve."); return null; } - + ICurve aICurve = bottomEdge.ITranslate(Geometry.Create.Vector(0, 0, height)).IFlip(); Line aLine_1 = Geometry.Create.Line(bottomEdge.IEndPoint(), aICurve.IStartPoint()); Line aLine_2 = Geometry.Create.Line(aICurve.IEndPoint(), bottomEdge.IStartPoint()); - PolyCurve aPolyCurve = Geometry.Create.PolyCurve(new ICurve[] { bottomEdge, aLine_1, aICurve, aLine_2 }); + PolyCurve aPolyCurve = Geometry.Create.PolyCurve(new ICurve[]{bottomEdge, aLine_1, aICurve, aLine_2}); - return new Wall() + return new Wall { Construction = construction, Location = Geometry.Create.PlanarSurface(aPolyCurve) @@ -87,7 +81,7 @@ public static Wall Wall(IConstruction construction, ICurve bottomEdge, double he [Output("Wall", "The created physical Wall.")] public static Wall Wall(Line line, double height, IConstruction construction, Offset offset = Offset.Undefined, string name = "") { - if(line == null) + if (line == null) { BH.Engine.Base.Compute.RecordError("Cannot create a Physical.Wall from a null line."); return null; @@ -107,8 +101,7 @@ public static Wall Wall(Line line, double height, IConstruction construction, Of { Location = Geometry.Create.PlanarSurface(boundary), Construction = construction, - Offset = offset, - Name = name + Offset = offset, Name = name }; } @@ -119,7 +112,7 @@ public static Wall Wall(Line line, double height, IConstruction construction, Of [Input("edges", "External edges of the wall (Profile - planar closed curve).")] [Input("internalEdges", "Internal edges of wall (profile).")] [Output("wall", "A physical wall.")] - public static Wall Wall(IConstruction construction, ICurve edges, IEnumerable internalEdges) + public static Wall Wall(IConstruction construction, ICurve edges, IEnumerable internalEdges = null) { if (construction == null || edges == null) { @@ -127,18 +120,25 @@ public static Wall Wall(IConstruction construction, ICurve edges, IEnumerable openings = new List(); + + if (internalEdges != null && internalEdges.Count() > 0) { - Construction = construction, - Location = aPlanarSurface - }; + foreach (ICurve openingCurve in internalEdges) + if (openingCurve != null) + openings.Add(new oM.Physical.Elements.Void() { Location = Geometry.Create.PlanarSurface(openingCurve) }); + } + + return Wall(location, construction, openings); } /***************************************************/ @@ -153,7 +153,6 @@ public static Wall Wall(IConstruction construction, ICurve edges, IEnumerable openings = null, Offset offset = Offset.Undefined, string name = "") { openings = openings ?? new List(); - return new Wall { Location = location, @@ -174,10 +173,7 @@ public static Wall Wall(IConstruction construction, ICurve edges) { return Wall(construction, edges, null); } - + /***************************************************/ } -} - - - +} \ No newline at end of file diff --git a/Physical_Engine/Query/MaterialComposition.cs b/Physical_Engine/Query/MaterialComposition.cs index ef9528474..b8bc90e60 100644 --- a/Physical_Engine/Query/MaterialComposition.cs +++ b/Physical_Engine/Query/MaterialComposition.cs @@ -26,7 +26,6 @@ using System.ComponentModel; using BH.oM.Base.Attributes; using BH.oM.Physical.Elements; - using BH.Engine.Base; using BH.oM.Physical.Materials; using BH.oM.Physical.FramingProperties; @@ -41,12 +40,12 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - [Description("Gets all the Materials a IFramingElement is composed of and in which ratios")] - [Input("framingElement", "The IFramingElement to get the MaterialComposition from")] - [Output("materialComposition", "The kind of matter the IFramingElement is composed of and in which ratios")] + [Description("Gets all the Materials a IFramingElement is composed of and in which ratios.")] + [Input("framingElement", "The IFramingElement to get the MaterialComposition from.")] + [Output("materialComposition", "The kind of matter the IFramingElement is composed of and in which ratios.")] public static MaterialComposition MaterialComposition(this IFramingElement framingElement) { - if(framingElement == null) + if (framingElement == null) { BH.Engine.Base.Compute.RecordError("Cannot query the material composition of a null framing element."); return null; @@ -57,17 +56,18 @@ public static MaterialComposition MaterialComposition(this IFramingElement frami Engine.Base.Compute.RecordError("The MaterialComposition could not be queried as no Property has been assigned to the IFramingElement."); return null; } + return framingElement.Property.IMaterialComposition(); } /***************************************************/ - [Description("Gets all the Materials a ISurface is composed of and in which ratios")] - [Input("surface", "The ISurface to get the MaterialComposition from")] - [Output("materialComposition", "The kind of matter the ISurface is composed of and in which ratios")] + [Description("Gets all the Materials a ISurface is composed of and in which ratios.")] + [Input("surface", "The ISurface to get the MaterialComposition from.")] + [Output("materialComposition", "The kind of matter the ISurface is composed of and in which ratios.")] public static MaterialComposition MaterialComposition(this ISurface surface) { - if(surface == null) + if (surface == null) { BH.Engine.Base.Compute.RecordError("Cannot query the material composition of a null surface."); return null; @@ -78,14 +78,15 @@ public static MaterialComposition MaterialComposition(this ISurface surface) Engine.Base.Compute.RecordError("The MaterialComposition could not be queried as no IConstruction has been assigned to the ISurface."); return null; } + return surface.Construction.IMaterialComposition(); } /***************************************************/ - [Description("Gets all the Materials an IOpening is composed of and in which ratios")] - [Input("opening", "The IOpening to get the MaterialComposition from")] - [Output("materialComposition", "The kind of matter the IOpening is composed of and in which ratios")] + [Description("Gets all the Materials an IOpening is composed of and in which ratios.")] + [Input("opening", "The IOpening to get the MaterialComposition from.")] + [Output("materialComposition", "The kind of matter the IOpening is composed of and in which ratios.")] public static MaterialComposition MaterialComposition(this IOpening opening) { MaterialComposition materialComposition = null; @@ -122,9 +123,9 @@ public static MaterialComposition MaterialComposition(this IOpening opening) /***************************************************/ - [Description("Gets all the Materials a SolidBulk is composed of and in which ratios")] - [Input("solidBulk", "The SolidBulk to get the MaterialComposition from")] - [Output("materialComposition", "The kind of matter the SolidBulk is composed of and in which ratios", typeof(Ratio))] + [Description("Gets all the Materials a SolidBulk is composed of and in which ratios.")] + [Input("solidBulk", "The SolidBulk to get the MaterialComposition from.")] + [Output("materialComposition", "The kind of matter the SolidBulk is composed of and in which ratios.", typeof(Ratio))] public static MaterialComposition MaterialComposition(this SolidBulk solidBulk) { if (solidBulk == null) @@ -137,14 +138,15 @@ public static MaterialComposition MaterialComposition(this SolidBulk solidBulk) Engine.Base.Compute.RecordError("The SolidBulk MaterialComposition could not be queried as no Materials have been assigned to at least one of the layers of the Construction."); return null; } + return solidBulk.MaterialComposition; } /***************************************************/ - [Description("Gets all the Materials a ExplicitBulk is composed of and in which ratios")] - [Input("explicitBulk", "The ExplicitBulk to get the MaterialComposition from")] - [Output("materialComposition", "The kind of matter the ExplicitBulk is composed of and in which ratios", typeof(Ratio))] + [Description("Gets all the Materials a ExplicitBulk is composed of and in which ratios.")] + [Input("explicitBulk", "The ExplicitBulk to get the MaterialComposition from.")] + [Output("materialComposition", "The kind of matter the ExplicitBulk is composed of and in which ratios.", typeof(Ratio))] public static MaterialComposition MaterialComposition(this ExplicitBulk explicitBulk) { if (explicitBulk == null) @@ -157,6 +159,7 @@ public static MaterialComposition MaterialComposition(this ExplicitBulk explicit Engine.Base.Compute.RecordError("The ExplicitBulk MaterialComposition could not be queried as no Materials have been assigned to at least one of the layers of the Construction."); return null; } + return explicitBulk.MaterialComposition; } @@ -164,6 +167,9 @@ public static MaterialComposition MaterialComposition(this ExplicitBulk explicit /**** IConstruction Methods ****/ /******************************************************/ + [Description("Gets all the Materials a ExplicitBulk is composed of and in which ratios.")] + [Input("prop", "The ExplicitBulk to get the MaterialComposition from.")] + [Output("materialComposition", "The kind of matter the ExplicitBulk is composed of and in which ratios.", typeof(Ratio))] public static MaterialComposition IMaterialComposition(this IConstruction prop) { return MaterialComposition(prop as dynamic); @@ -193,12 +199,28 @@ private static MaterialComposition IMaterialComposition(this IOpening prop) private static MaterialComposition MaterialComposition(this Construction prop) { - if (prop.Layers.Any(x => x.Material == null)) + if (prop == null) + { + Compute.RecordError("Cannot evaluate MaterialComposition because the Construction was null."); + return null; + } + + if (prop.Layers.IsNullOrEmpty()) //.IsNullOrEmpty raises it's own error + return null; + + if (prop.Layers.All(x => x.Material == null)) { - Engine.Base.Compute.RecordError("The Construction MaterialComposition could not be queried as no Material has been assigned."); + Compute.RecordError("Cannote evaluate MaterialComposition because all of the materials are null."); return null; } - return Matter.Create.MaterialComposition(prop.Layers.Select(x => x.Material), prop.Layers.Select(x => x.Thickness)); + + if (prop.Layers.Any(x => x.Material == null)) + { + Compute.RecordWarning("At least one Material in a Layered surface property was null. MaterialConstruction excludes this layer, assuming it is void space."); + } + + IEnumerable layers = prop.Layers.Where(x => x.Material != null); + return Matter.Create.MaterialComposition(layers.Select(x => x.Material), layers.Select(x => x.Thickness)); } /***************************************************/ @@ -219,6 +241,7 @@ private static MaterialComposition MaterialComposition(this ConstantFramingPrope Engine.Base.Compute.RecordError("The ConstantFramingProperty MaterialComposition could not be queried as no Material has been assigned to the ConstantFramingProperty."); return null; } + return (MaterialComposition)prop.Material; } @@ -231,8 +254,6 @@ private static MaterialComposition MaterialComposition(this IFramingElementPrope throw new NotImplementedException(); } - + /***************************************************/ } -} - - +} \ No newline at end of file diff --git a/Physical_Engine/Query/SolidVolume.cs b/Physical_Engine/Query/SolidVolume.cs index 85e2f0efa..3ce8796fb 100644 --- a/Physical_Engine/Query/SolidVolume.cs +++ b/Physical_Engine/Query/SolidVolume.cs @@ -26,7 +26,6 @@ using System.ComponentModel; using BH.oM.Base.Attributes; using BH.oM.Physical.Elements; - using BH.Engine.Base; using BH.oM.Physical.FramingProperties; using BH.oM.Geometry; @@ -44,12 +43,12 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - [Description("Gets an IFramingElement's solid volume from the average area and length")] - [Input("framingElement", "the IFramingElement to get the volume from")] + [Description("Gets an IFramingElement's solid volume from the average area and length.")] + [Input("framingElement", "the IFramingElement to get the volume from.")] [Output("volume", "The IFramingElement's solid material volume.", typeof(Volume))] public static double SolidVolume(this IFramingElement framingElement) { - if(framingElement == null) + if (framingElement == null) { BH.Engine.Base.Compute.RecordError("Cannot query the solid volume of a null framing element."); return 0; @@ -60,18 +59,18 @@ public static double SolidVolume(this IFramingElement framingElement) Engine.Base.Compute.RecordError("The IFramingElement Solid Volume could not be calculated as no property has been assigned. Returning zero volume."); return 0; } + return framingElement.Location.Length() * IAverageProfileArea(framingElement.Property); } /***************************************************/ - [Description("Returns an ISurface's solid volume based on thickness and area." + - "ISurfaces with offsets other than Centre are not fully supported.")] - [Input("surface", "the ISurface to get the volume from")] + [Description("Returns an ISurface's solid volume based on thickness and area." + "ISurfaces with offsets other than Centre are not fully supported.")] + [Input("surface", "the ISurface to get the volume from.")] [Output("volume", "The ISurface's solid material volume.", typeof(Volume))] public static double SolidVolume(this oM.Physical.Elements.ISurface surface) { - if(surface == null) + if (surface == null) { BH.Engine.Base.Compute.RecordError("Cannot query the solid volume of a null surface."); return 0; @@ -85,11 +84,9 @@ public static double SolidVolume(this oM.Physical.Elements.ISurface surface) if (surface.Offset != Offset.Centre && !surface.Location.IIsPlanar()) Base.Compute.RecordWarning("The SolidVolume for non-Planar ISurfaces with offsets other than Centre is approxamite at best"); - double area = surface.Location.IArea(); area -= surface.Openings.Sum(x => x.Location.IArea()); - - return area * surface.Construction.IThickness(); + return area * surface.Construction.IVolumePerArea(); } /***************************************************/ @@ -106,7 +103,6 @@ public static double SolidVolume(this SolidBulk solidBulk) } double solidVolume = solidBulk.Geometry.Select(x => x.IVolume()).Sum(); - if (solidVolume <= 0) { Engine.Base.Compute.RecordError("The queried volume has been nonpositive. Returning zero instead."); @@ -135,11 +131,12 @@ public static double SolidVolume(this ExplicitBulk explicitBulk) Engine.Base.Compute.RecordError("The queried volume has been nonpositive. Returning zero instead."); return 0; } + return solidVolume; } [Description("Returns an IOpening's solid volume based on thickness and area.")] - [Input("window", "the window to get the volume from")] + [Input("opening", "the window to get the volume from.")] [Output("volume", "The window's solid material volume.", typeof(Volume))] public static double SolidVolume(this IOpening opening) { @@ -150,12 +147,12 @@ public static double SolidVolume(this IOpening opening) } double area = opening.IArea(); - double thickness = 0; + if (opening is Window) - thickness = (opening as Window).Construction.IThickness(); + thickness = (opening as Window).Construction.IVolumePerArea(); else if (opening is Door) - thickness = (opening as Door).Construction.IThickness(); + thickness = (opening as Door).Construction.IVolumePerArea(); double solidVolume = area * thickness; @@ -167,9 +164,7 @@ public static double SolidVolume(this IOpening opening) return solidVolume; } - + /***************************************************/ } -} - - +} \ No newline at end of file diff --git a/Physical_Engine/Query/VolumePerArea.cs b/Physical_Engine/Query/VolumePerArea.cs new file mode 100644 index 000000000..a57bb123c --- /dev/null +++ b/Physical_Engine/Query/VolumePerArea.cs @@ -0,0 +1,90 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using BH.oM.Physical.Constructions; +using BH.oM.Base.Attributes; +using BH.oM.Quantities.Attributes; +using System.ComponentModel; +using BH.Engine.Base; + +namespace BH.Engine.Physical +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Gets the average thickness of the property for the purpose of calculating solid volume.")] + [Input("construction", "The property to evaluate the average thickness of.")] + [Output("volumePerArea", "The average thickness of the property for the purpose of calculating solid volume.", typeof(Length))] + public static double IVolumePerArea(this IConstruction construction) + { + if (construction == null) + { + Compute.RecordError("Cannot query the thickness of a null construction."); + return 0; + } + + return VolumePerArea(construction as dynamic); + } + + /***************************************************/ + + [Description("Gets the average thickness of the property for the purpose of calculating solid volume.")] + [Input("construction", "The property to evaluate the average thickness of.")] + [Output("volumePerArea", "The average thickness of the property for the purpose of calculating solid volume.", typeof(Length))] + public static double VolumePerArea(this Construction construction) + { + if (construction == null) + { + Compute.RecordError("Could not evaluate the VolumePerArea of the Construction because it was null."); + return 0; + } + + if (construction.Layers.IsNullOrEmpty()) // .IsNullOrEmpty() raises it's own error. + return 0; + + if (construction.Layers.Any(x => x.Material == null)) + Compute.RecordWarning("At least one Material in a Construction was null. VolumePerArea excludes this layer, assuming it is void space."); + + return construction.Layers.Where(x => x.Material != null).Sum(x => x.Thickness); + } + + /***************************************************/ + /**** Private Methods ****/ + /***************************************************/ + + private static double VolumePerArea(this object construction) + { + Compute.RecordError("Could not evaluate the VolumePerArea of the Construction because that type of Construction is not supported by the VolumePerArea method."); + return 0; //Fallback method + } + + /***************************************************/ + } +} \ No newline at end of file diff --git a/Structure_Engine/Create/Framing/ConstantFramingProperty.cs b/Structure_Engine/Create/Physical/ConstantFramingProperty.cs similarity index 97% rename from Structure_Engine/Create/Framing/ConstantFramingProperty.cs rename to Structure_Engine/Create/Physical/ConstantFramingProperty.cs index a9b9aa425..9042ab107 100644 --- a/Structure_Engine/Create/Framing/ConstantFramingProperty.cs +++ b/Structure_Engine/Create/Physical/ConstantFramingProperty.cs @@ -54,13 +54,11 @@ public static ConstantFramingProperty ConstantFramingProperty(ISectionProperty s else Base.Compute.RecordWarning("Was not able to extract any section profile."); - oM.Physical.Materials.Material material = null; - if (sectionProperty.Material != null) { string matName = sectionProperty.Material.Name ?? ""; - material = Physical.Create.Material(matName, new List { sectionProperty.Material }); + material = Physical.Create.Material(matName, new List{sectionProperty.Material}); } else { @@ -70,12 +68,8 @@ public static ConstantFramingProperty ConstantFramingProperty(ISectionProperty s name = string.IsNullOrEmpty(name) ? sectionProperty.Name : name; return Physical.Create.ConstantFramingProperty(profile, material, orientationAngle, name); - } - + /***************************************************/ } -} - - - +} \ No newline at end of file diff --git a/Structure_Engine/Create/Physical/Floor.cs b/Structure_Engine/Create/Physical/Floor.cs new file mode 100644 index 000000000..a63fc84b5 --- /dev/null +++ b/Structure_Engine/Create/Physical/Floor.cs @@ -0,0 +1,83 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System.Collections.Generic; +using System.Linq; +using BH.oM.Structure.Elements; +using BH.oM.Geometry; +using BH.oM.Base.Attributes; +using System.ComponentModel; +using BHPE = BH.oM.Physical.Elements; +using BHPC = BH.oM.Physical.Constructions; +using BH.oM.Physical.Reinforcement; +using BH.oM.Structure.SurfaceProperties; +using BH.oM.Structure.Reinforcement; +using BH.oM.Structure.Fragments; +using BH.Engine.Base; +using BH.oM.Quantities.Attributes; + +namespace BH.Engine.Structure +{ + public static partial class Create + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Creates a physical Floor from a Panel. The Floor will be assigned a Construction based on the SurfaceProperty of the Panel.")] + [Input("panel", "The Panel to use as the base for the framing element.")] + [Output("floor", "The created physical Floor based on the Panel element provided.")] + public static BHPE.Floor Floor(Panel panel) + { + if (panel.IsNull()) + return null; + + //Get Construction + ISurfaceProperty prop = panel.Property; + BHPC.Construction construction = null; + + if (prop == null) + Base.Compute.RecordWarning("The panel does not contain a surfaceProperty. Can not extract profile or material"); + else + construction = panel.Property.IConstruction(); + + //Get Location + PolyCurve externalEdges = Geometry.Create.PolyCurve(panel.ExternalEdges.Select(x => x.Curve)); + List internalEdges = panel.Openings.Select(opening => Geometry.Create.PolyCurve(opening.Edges.Select(edge => edge.Curve))).ToList(); + + //Create the physical element + BHPE.Floor surfaceElement = Physical.Create.Floor(construction, externalEdges, internalEdges); + + string name = panel.Name ?? ""; + surfaceElement.Name = name; + + if (panel.FindFragment() != null || panel.Property.FindFragment() != null) + { + Base.Compute.RecordWarning("The panel has reinforcement, but embedding this information in the physical element is not yet implemented."); + } + + return surfaceElement; + } + + /***************************************************/ + } +} \ No newline at end of file diff --git a/Structure_Engine/Create/Framing/FramingElement.cs b/Structure_Engine/Create/Physical/FramingElement.cs similarity index 98% rename from Structure_Engine/Create/Framing/FramingElement.cs rename to Structure_Engine/Create/Physical/FramingElement.cs index 15c0d09d4..cc766ccb7 100644 --- a/Structure_Engine/Create/Framing/FramingElement.cs +++ b/Structure_Engine/Create/Physical/FramingElement.cs @@ -81,21 +81,19 @@ public static BHPE.IFramingElement FramingElement(Bar bar, StructuralUsage1D str break; } - if (bar.HasReinforcement()) { List reinforcement = bar.ReinforcingBars(); + if (reinforcement.Count != 0) { - framingElement.Fragments.Add(new ReinforcementFragment { ReinforcingBars = reinforcement }); + framingElement.Fragments.Add(new ReinforcementFragment{ReinforcingBars = reinforcement}); } } + return framingElement; } - + /***************************************************/ } -} - - - +} \ No newline at end of file diff --git a/Structure_Engine/Create/Physical/ISurface.cs b/Structure_Engine/Create/Physical/ISurface.cs new file mode 100644 index 000000000..486656681 --- /dev/null +++ b/Structure_Engine/Create/Physical/ISurface.cs @@ -0,0 +1,93 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System.Collections.Generic; +using System.Linq; +using BH.oM.Structure.Elements; +using BH.oM.Geometry; +using BH.oM.Base.Attributes; +using System.ComponentModel; +using BHPE = BH.oM.Physical.Elements; +using BHPC = BH.oM.Physical.Constructions; +using BH.oM.Physical.Reinforcement; +using BH.oM.Structure.SurfaceProperties; +using BH.oM.Structure.Reinforcement; +using BH.oM.Structure.Fragments; +using BH.Engine.Base; +using BH.Engine.Geometry; +using BH.oM.Quantities.Attributes; +using System; + +namespace BH.Engine.Structure +{ + public static partial class Create + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Creates a physical surface element from a Panel. The Floor will be assigned a Construction based on the SurfaceProperty of the Panel, and the PanelType of the SufaceProperty will determine what type of surface element to create, unless overridden.")] + [Input("panel", "The Panel to use as the base for the framing element.")] + [Input("structuralUsage", "The type of surface element to create. if Undefined, the type will be based on the panel's SurfaceProperty.")] + [Output("surfaceElement", "The created surface element based on the Panel element provided.")] + public static BHPE.ISurface ISurface(Panel panel, StructuralUsage2D structuralUsage = StructuralUsage2D.Undefined) + { + if (panel.IsNull()) + return null; + + if (structuralUsage == StructuralUsage2D.Undefined) + { + object result = panel.Property?.PropertyValue("PanelType"); + + if (result is StructuralUsage2D ) + { + structuralUsage = (StructuralUsage2D)result; + } + } + + switch (structuralUsage) + { + case StructuralUsage2D.Wall: + return Wall(panel); + case StructuralUsage2D.DropPanel: + case StructuralUsage2D.PileCap: + case StructuralUsage2D.Slab: + return Floor(panel); + case StructuralUsage2D.Undefined: + default: + { + if (1 - Math.Abs(panel.Normal().DotProduct(Vector.ZAxis)) <= BH.oM.Geometry.Tolerance.Angle) + return Floor(panel); + else if (panel.Normal().DotProduct(Vector.ZAxis) <= BH.oM.Geometry.Tolerance.Angle) + return Wall(panel); + else + { + Base.Compute.RecordError("Could not identify whether the panel is a Floor or a Wall based on the structural property, input structuralUsage, or panel orientation. Please specify a StructuralUsage2D."); + return null; + } + } + } + } + + /***************************************************/ + } +} \ No newline at end of file diff --git a/Structure_Engine/Create/Physical/Wall.cs b/Structure_Engine/Create/Physical/Wall.cs new file mode 100644 index 000000000..aef0e3028 --- /dev/null +++ b/Structure_Engine/Create/Physical/Wall.cs @@ -0,0 +1,82 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System.Collections.Generic; +using System.Linq; +using BH.oM.Structure.Elements; +using BH.oM.Geometry; +using BH.oM.Base.Attributes; +using System.ComponentModel; +using BHPE = BH.oM.Physical.Elements; +using BHPC = BH.oM.Physical.Constructions; +using BH.oM.Physical.Reinforcement; +using BH.oM.Structure.SurfaceProperties; +using BH.oM.Structure.Reinforcement; +using BH.oM.Structure.Fragments; +using BH.Engine.Base; +using BH.oM.Quantities.Attributes; + +namespace BH.Engine.Structure +{ + public static partial class Create + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + [Description("Creates a physical Wall from a Panel. The Wall will be assigned a Construction based on the SurfaceProperty of the Panel.")] + [Input("panel", "The Panel to use as the base for the framing element.")] + [Output("wall", "The created physical Wall based on the Panel element provided.")] + public static BHPE.Wall Wall(Panel panel) + { + if (panel.IsNull()) + return null; + + //Get Construction + ISurfaceProperty prop = panel.Property; + BHPC.Construction construction = null; + + if (prop == null) + Base.Compute.RecordWarning("The panel does not contain a surfaceProperty. Can not extract profile or material"); + else + construction = panel.Property.IConstruction(); + + //Get Location + PolyCurve externalEdges = Geometry.Create.PolyCurve(panel.ExternalEdges.Select(x => x.Curve)); + List internalEdges = panel.Openings.Select(opening => Geometry.Create.PolyCurve(opening.Edges.Select(edge => edge.Curve))).ToList(); + + //Create the physical element + BHPE.Wall surfaceElement = Physical.Create.Wall(construction, externalEdges, internalEdges); + + string name = panel.Name ?? ""; + surfaceElement.Name = name; + + if (panel.FindFragment() != null || panel.Property.FindFragment() != null) + { + Base.Compute.RecordWarning("The panel has reinforcement, but embedding this information in the physical element is not yet implemented."); + } + + return surfaceElement; + } + + /***************************************************/ + } +} \ No newline at end of file diff --git a/Structure_Engine/Query/Construction.cs b/Structure_Engine/Query/Construction.cs new file mode 100644 index 000000000..a5f921d9e --- /dev/null +++ b/Structure_Engine/Query/Construction.cs @@ -0,0 +1,143 @@ +/* + * This file is part of the Buildings and Habitats object Model (BHoM) + * Copyright (c) 2015 - 2022, the respective contributors. All rights reserved. + * + * Each contributor holds copyright over their respective contributions. + * The project versioning (Git) records all such contribution source information. + * + * + * The BHoM is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3.0 of the License, or + * (at your option) any later version. + * + * The BHoM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this code. If not, see . + */ + +using System; +using System.Linq; +using System.Collections.Generic; +using System.ComponentModel; +using BH.oM.Base.Attributes; +using BH.oM.Physical.Constructions; +using BH.oM.Structure.SurfaceProperties; +using BH.oM.Quantities.Attributes; +using BH.oM.Physical.Materials; +using BH.oM.Structure.MaterialFragments; + +namespace BH.Engine.Structure +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Creates a physical Construction from a structural ISurfaceProperty. Extracts the Structural MaterialFragment and creates a physical material with the same name.")] + [Input("surfaceProperty", "Structural surface property to convert.")] + [Output("construction", "The physical Construction to be used with ISurface such as Walls and Floors.")] + public static Construction IConstruction(this ISurfaceProperty surfaceProperty) + { + if (surfaceProperty.IsNull()) + return null; + return Construction(surfaceProperty as dynamic); + } + + /***************************************************/ + + [Description("Creates a physical Construction from a structural ConstantThickness SurfaceProperty. Extracts the Structural MaterialFragment and creates a physical material with the same name.")] + [Input("surfaceProperty", "Structural surface property to convert.")] + [Output("construction", "The physical Construction to be used with ISurface such as Walls and Floors.")] + public static Construction Construction(this ConstantThickness surfaceProperty) + { + if (surfaceProperty.IsNull()) + return null; + + oM.Physical.Constructions.Layer layer = Physical.Create.Layer(surfaceProperty.Name, Physical.Create.Material(surfaceProperty.Material), surfaceProperty.Thickness); + + return Physical.Create.Construction(surfaceProperty.Name, new List { layer } ); + } + + /***************************************************/ + + [Description("Creates a physical Construction from a structural Layered SurfaceProperty. Extracts the Structural MaterialFragment and creates a physical material with the same name.")] + [Input("surfaceProperty", "Structural surface property to convert.")] + [Output("construction", "The physical Construction to be used with ISurface such as Walls and Floors.")] + public static Construction Construction(this Layered surfaceProperty) + { + if (surfaceProperty.IsNull()) + return null; + + if (surfaceProperty.Layers.All(x => x.Material == null)) + Base.Compute.RecordWarning("None of the layers in surfaceProperty have a valid material. A Construction has been created, but its materials will also be null."); + + List layers = surfaceProperty.Layers.Select(x => Physical.Create.Layer(x.Name, Material(x.Material), x.Thickness)).ToList(); + + return Physical.Create.Construction(surfaceProperty.Name, layers); + } + + /***************************************************/ + /**** Fallback Method ****/ + /***************************************************/ + + [Description("Creates a physical Construction from a structural ISurfaceProperty. Extracts the Structural MaterialFragment and creates a physical material with the same name.")] + [Input("surfaceProperty", "Structural surface property to convert.")] + [Output("construction", "The physical Construction to be used with ISurface such as Walls and Floors.")] + public static Construction Construction(this ISurfaceProperty surfaceProperty) + { + if (surfaceProperty.IsNull()) + return null; + + MaterialComposition comp = surfaceProperty.IMaterialComposition(); + double volume = surfaceProperty.IVolumePerArea(); + if (volume == 0) + Base.Compute.RecordWarning("the SurfaceProperty has zero volume - a Construction has been created, but will also have zero volume."); + + double thickness = surfaceProperty.ITotalThickness(); + if (thickness == 0) + Base.Compute.RecordWarning("the SurfaceProperty has zero thickness - a Construction has been created, but will also have zero thickness."); + + List layers = new List(); + + for (int i = 0; i < comp.Materials.Count(); i++) + layers.Add(new oM.Physical.Constructions.Layer + { + Material = comp.Materials[i], + Thickness = volume * comp.Ratios[i], + Name = comp.Materials[i].Name + }); + + if (volume < thickness) + { + layers.Add(new oM.Physical.Constructions.Layer + { + Material = null, + Thickness = thickness - volume, + Name = "void" + }); + + Base.Compute.RecordNote("A void layer has been added to the Construction to maintain total thickness. Ribbed or Waffle properties, for example, are flattened, respecting volume, material composition, and total thickness. "); + } + + return Physical.Create.Construction(surfaceProperty.Name, layers); + } + + /***************************************************/ + /**** Private Methods ****/ + /***************************************************/ + + private static Material Material(IMaterialFragment material) + { + return material == null? null : Physical.Create.Material(material); + } + + /***************************************************/ + + } +} \ No newline at end of file diff --git a/Structure_Engine/Query/MaterialComposition.cs b/Structure_Engine/Query/MaterialComposition.cs index 8a8fb28e7..b4822c0ce 100644 --- a/Structure_Engine/Query/MaterialComposition.cs +++ b/Structure_Engine/Query/MaterialComposition.cs @@ -76,15 +76,9 @@ public static MaterialComposition MaterialComposition(this Bar bar) [Output("materialComposition", "The kind of matter the AreaElement is composed of.")] public static MaterialComposition MaterialComposition(this IAreaElement areaElement) { - if (areaElement.IIsNull()) + if (areaElement.IIsNull() || areaElement.Property.IsNull()) return null; - if (areaElement.Property == null || areaElement.Property.Material == null) - { - Engine.Base.Compute.RecordError("The areaElements MaterialComposition could not be calculated as no Material has been assigned."); - return null; - } - if (areaElement.FindFragment() != null) Engine.Base.Compute.RecordWarning("The areaElement has a PanelRebarIntent, which will not be included in the MaterialComposition. Please account for replacement of concrete volume with reinforcement externally."); @@ -155,9 +149,15 @@ public static MaterialComposition MaterialComposition(this ConcreteSection prope [Output("materialComposition", "The MaterialComposition of the SurfaceProperty.")] public static MaterialComposition MaterialComposition(this Layered property, ReinforcementDensity reinforcementDensity = null) { - if (property.IsNull()) + if (property.IsNull() || property.Layers.All(x => x.Material.IsNull())) return null; + if (property.Layers.All(x => x.Material == null)) //cull any null layers, raise a warning. + { + Base.Compute.RecordError("Cannote evaluate MaterialComposition because all of the materials are null."); + return null; + } + if (reinforcementDensity != null) Base.Compute.RecordWarning("the layered property has a ReinforcementDensity which will not be included in the MaterialComposition, because it is not known which layer to replace. Please account for this reinforcement externally."); @@ -176,10 +176,13 @@ public static MaterialComposition MaterialComposition(this Layered property, Rei [Output("materialComposition", "The MaterialComposition of the SurfaceProperty.")] public static MaterialComposition MaterialComposition(this CorrugatedDeck property, ReinforcementDensity reinforcementDensity = null) { + if (property.IsNull() || property.Material.IsNull()) + return null; + if (reinforcementDensity != null) Base.Compute.RecordWarning("the CorrugatedDeck property has a ReinforcementDensity which will not be included in the MaterialComposition, because it is inconceivable."); - return property.IsNull() ? null : (MaterialComposition)Physical.Create.Material(property.Material); + return (MaterialComposition)Physical.Create.Material(property.Material); } /***************************************************/ @@ -246,7 +249,7 @@ public static MaterialComposition IMaterialComposition(this ISectionProperty pro [Output("materialComposition", "The MaterialComposition of the SurfaceProperty.")] public static MaterialComposition IMaterialComposition(this ISurfaceProperty property, ReinforcementDensity reinforcementDensity = null) { - if (property.IsNull()) + if (property.IsNull()) //Specific MaterialComposition(SurfaceProp) methods must check for material null- some properties ignore the base material. return null; return MaterialComposition(property as dynamic, reinforcementDensity); @@ -273,10 +276,7 @@ private static MaterialComposition MaterialComposition(this ISectionProperty sec private static MaterialComposition MaterialComposition(this ISurfaceProperty property, ReinforcementDensity reinforcementDensity = null) { if (property.IsNull() || property.Material.IsNull()) - { - Engine.Base.Compute.RecordError("The MaterialComposition could not be queried as a Material was not assigned."); return null; - } if (reinforcementDensity == null) return (MaterialComposition)Physical.Create.Material(property.Material); @@ -319,11 +319,6 @@ private static MaterialComposition MaterialComposition(this IMaterialFragment ba /***************************************************/ - - - - - } }