Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structure_Engine: Add engine methods for foundation classes #3138

Merged
merged 35 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
65fc797
Initial commit for Create methods and empty GrahamScan
peterjamesnugent Aug 12, 2023
572dbdc
Update PileGroup.cs
peterjamesnugent Aug 12, 2023
404392c
Update GrahamScan.cs
Maria1129 Aug 14, 2023
12c1da4
Update engine methods to follow changes to PadFoundation object
peterjamesnugent Aug 15, 2023
e9baa08
Add required methods for IElement2D as per https://github.com/BHoM/do…
peterjamesnugent Aug 15, 2023
c487da3
Update OutlineElements1D.cs
peterjamesnugent Aug 15, 2023
476824a
Add VolumetricMaterialTakeOff for PileFoundation
peterjamesnugent Aug 15, 2023
6a6ad9e
Add IsNull methods for foundation objects
peterjamesnugent Aug 15, 2023
6e624bb
Update descriptions and use of GrahamScan for PileFoundation
peterjamesnugent Aug 15, 2023
9bf1b32
Update create methods for PadFoundation and PileFoundation
peterjamesnugent Aug 15, 2023
6553fc2
Add additional checks for GrahamScan method and update descriptions
peterjamesnugent Aug 15, 2023
0f299e5
Update descriptions for GrahamScan
peterjamesnugent Aug 22, 2023
81de384
Response to @pawelbaran 's comments
peterjamesnugent Aug 22, 2023
6bd6c59
Update to reflect changes to oM, adding Pile object and removing Pile…
peterjamesnugent Aug 25, 2023
41517bb
Updates to GrahamScan based on comments
peterjamesnugent Aug 25, 2023
c7eadef
Add required and optional methods for IElement1D and Pile
peterjamesnugent Aug 25, 2023
c1ab7cc
Add VolumetricMaterialTakeOff for new IElementM types
peterjamesnugent Aug 25, 2023
72cef8f
Changes for MaterialTakeOff
peterjamesnugent Aug 29, 2023
8100ffc
Remove duplicate point in GrahamScan
peterjamesnugent Aug 29, 2023
c354a10
Compliance fixes
peterjamesnugent Aug 29, 2023
be7b41f
Documentation-compliance fix
peterjamesnugent Aug 29, 2023
08b354a
Add default values
peterjamesnugent Aug 29, 2023
858456a
Update GrahamScan to allow points in any plane to be analysed
peterjamesnugent Aug 31, 2023
192e39c
Add null handling and update descriptions
peterjamesnugent Aug 31, 2023
81aa95a
Response to @pawelbaran's comments
peterjamesnugent Sep 1, 2023
ec67857
Remove surface/section property comparers and remove HasMergeAbleProp…
peterjamesnugent Sep 1, 2023
c19bde2
Add transform methods and local orientation method for PadFoundation …
peterjamesnugent Sep 1, 2023
c3755f2
Remove VolumetricMaterialTakeOff and add lower level methods for Soli…
peterjamesnugent Sep 1, 2023
241a8a8
Fix documentation-compliance fail
peterjamesnugent Sep 4, 2023
85c1993
Update SetOutlineElements1D.cs
peterjamesnugent Sep 4, 2023
1aea6f3
Formatting
peterjamesnugent Sep 5, 2023
397e47d
Update Transform.cs
peterjamesnugent Sep 5, 2023
52f9ddf
Merge branch 'develop' into Structure_oM-#1543-AddFoundationClasses
peterjamesnugent Sep 5, 2023
fca5811
Unit tests for GrahamScan method
peterjamesnugent Sep 8, 2023
09b4b0b
Fix copyright-compliance failure
peterjamesnugent Sep 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions Geometry_Engine/Compute/GrahamScan.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using BH.oM.Geometry;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using BH.Engine.Base;
using BH.Engine.Geometry;

namespace BH.Engine.Geometry
{
public static partial class Compute
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Implements the GrahamScan algorithim to determine the convex hull of a list of points.")]
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
[Input("pts", "The points to determine the convex hull.")]
[Output("c", "The convex hull of the point list.")]
public static List<Point> GrahamScan(List<Point> pts)
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
{
if (pts.IsNullOrEmpty())
{
Base.Compute.RecordError("The point list is null or empty.");
return null;
}

// Find the point with the lowest Y coordination
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
IOrderedEnumerable<Point> orderedPts = pts.OrderBy(pt => pt.Y);

Point p = pts.First();
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved

// Check if there is more than one point with the lowest Y
if (Math.Abs(p.Y - pts[1].Y) < Tolerance.MicroDistance)
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
{
// Get points with lowest Y coordinate and select the point with the lowest X
pts = orderedPts.ThenBy(x => x.X).ToList();
p = pts.First();
}
else
pts = orderedPts.ToList();

// Remove the P from the list of points
pts.Remove(p);

// Sort by the increasing order of the angle the point and P make with the x-axis
pts = pts.OrderBy(pt => Math.Atan2(pt.Y - p.Y, pt.X - p.X)).ToList(); // TODO: If several points have the same angle - break ties by increasing distance
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved

// Group by angle between P and the points
IEnumerable<IGrouping<double,Point>> groupedPts = pts.GroupBy(pt => Math.Atan2(pt.Y - p.Y, pt.X - p.X));
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved

// Add to the start of selPts as it has been removed from pts
List<Point> selPts = new List<Point>() { p };

bool duplicateAngle = false;

// Check for points that have the same angle
if (groupedPts.Where(grp => grp.Count() > 1).Any())
{
// For each group, sort by distance from P and select the furthest point
pts = groupedPts.Select(g => new { s = g.OrderByDescending(i => i.Distance(p)) }).Select(x => x.s.First()).ToList();
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
duplicateAngle = true;
}

// Iterate through the algorithim
while (pts.Count > 0)
{
GrahamScanInt(ref pts, ref selPts);
};

// Due to the grouping, it is necessary to add the first point to close the polyline
if (duplicateAngle)
selPts.Add(selPts.First());

return selPts;
}

private static List<Point> GrahamScanInt(ref List<Point> pts, ref List<Point> selPts)
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
{
if (pts.Count > 0)
{
// Update the reference as the method moves along the curve
var p = pts[0];

// Add the next point along, needs a minimum of two points to begin (the third coming from p)
if (selPts.Count <= 1)
{
selPts.Add(p);
pts.RemoveAt(0);
}
else
{
Point pt1 = selPts[selPts.Count - 1];
Point pt2 = selPts[selPts.Count - 2];
Vector dir1 = pt1 - pt2;
Vector dir2 = p - pt1;

if (Query.CrossProduct(dir1, dir2).Z < 0)
{
// Less than zero, therefore clockwise and the point is within the boundary
selPts.RemoveAt(selPts.Count - 1);
}
else
{
// Greater than zero, therefore anticlockwise - so point is not within the boundary
selPts.Add(p);
pts.RemoveAt(0);
}
}
}
return selPts;
}
}
}




53 changes: 53 additions & 0 deletions Structure_Engine/Create/Elements/PadFoundation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using BH.oM.Geometry;
using BH.oM.Spatial.ShapeProfiles;
using BH.oM.Structure.Elements;
using BH.oM.Structure.SurfaceProperties;
using BH.Engine.Base;
using BH.Engine.Geometry;


namespace BH.Engine.Structure
{
public static partial class Create
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Creates a PadFoundation from its fundamental parts and a basis.")]
[Input("profile", "The section profile defining the edges of the pad. All section constants are derived based on the dimensions of this.")]
[InputFromProperty("property")]
[Input("coordinates", "The Cartesian coordinate system to control the position and orientation of the PadFoundation.")]
public static PadFoundation PadFoundation(List<Edge> topSurface, ISurfaceProperty property = null, Basis orientation = null)
{
if (topSurface.IsNullOrEmpty() || topSurface.Any(x => x.IsNull()))
return null;

if (orientation == null)
orientation = new Basis(new Vector() { X = 1 }, new Vector() { Y = 1 }, new Vector() { Z = 1 });
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved

return new PadFoundation() { TopSurface = topSurface, Property = property, Orientation = orientation };
}

/***************************************************/

[Description("Creates a PadFoundation from its fundamental parts and a basis.")]
[Input("width", "The width of the PadFoundation aligned with Global X.")]
[Input("length", "The length of the PadFoundation aligned with Global Y.")]
[InputFromProperty("property")]
[Input("coordinates", "The Cartesian coordinate system to control the position and orientation of the PadFoundation.")]
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
public static PadFoundation PadFoundation(double width, double length, ConstantThickness thickness, Basis orientation)
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved
{
List<Edge> edges = Spatial.Create.RectangleProfile(length, width).Edges.Select(x => new Edge() { Curve = x }).ToList();

return PadFoundation(edges, thickness, orientation);
}
}
}
56 changes: 56 additions & 0 deletions Structure_Engine/Create/Elements/PileFoundaton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using BH.oM.Geometry;
using BH.oM.Structure.Elements;
using BH.oM.Structure.SurfaceProperties;
using BH.Engine.Geometry;


namespace BH.Engine.Structure
{
public static partial class Create
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Creates a structural PileFoundation from a pile cap and pile groups.")]
[Input("pileCap", "The pile cap defining the outer edge of the PileFoundation and location in 3D.")]
[Input("pileGroups", "Groups of piles contained within the outline of the pile cap.")]
public static PileFoundation PileFoundation(PadFoundation pileCap, List<PileGroup> pileGroups)
{
return new PileFoundation() { PileCap = pileCap, PileGroups = pileGroups };
}

/***************************************************/

[Description("Creates a structural PileFoundation from the pile groups, an offset and the PileCap properties.")]
[Input("pileGroups", "Groups of piles used to define the outline of the PileCap.")]
[InputFromProperty("property")]
[Input("offset", "The offset from the centre of the piles to the edge of the PileCap.")]
[Input("coordinates", "The Cartesian coordinate system to control the position and orientation of the PadFoundation.")]
public static PileFoundation PileFoundation(List<PileGroup> pileGroups, ConstantThickness property, double offset, Basis orientation)
{
List<Point> pts = new List<Point>();

foreach (PileGroup pileGroup in pileGroups)
{
pts.AddRange(pileGroup.PileLayout.Points);
}

pts.Add(pts.First());
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved

List<Edge> edges = new List<Edge>() { new Edge() { Curve = Geometry.Create.Polyline(Geometry.Compute.GrahamScan(pts)).Offset(offset) } };

return new PileFoundation() { PileCap = PadFoundation(edges, property, orientation), PileGroups = pileGroups };
}

/***************************************************/

}
}
32 changes: 32 additions & 0 deletions Structure_Engine/Create/Elements/PileGroup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using BH.oM.Spatial.Layouts;
using BH.oM.Structure.Elements;
using BH.oM.Structure.SectionProperties;

namespace BH.Engine.Structure
{
public static partial class Create
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Creates a structural PileGroup defining a group of piles with the same length and section. The object is used with a PileFoundation whereby the PileCap defines the location and orientation.")]
[Input("pileLength", "The length of the piles within the group.")]
[InputFromProperty("sectionProperty")]
[Input("pileLayout", "Pile Layout defining the position of the piles about the World Origin.")]
public static PileGroup PileGroup(double pileLength, ISectionProperty pileSection, ExplicitLayout pileLayout)
{
return new PileGroup() { PileLength = pileLength, PileSection = pileSection, PileLayout = pileLayout };
}

/***************************************************/

}
}
65 changes: 65 additions & 0 deletions Structure_Engine/Modify/SetOutlineElements1D.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* This file is part of the Buildings and Habitats object Model (BHoM)
* Copyright (c) 2015 - 2023, 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 <https://www.gnu.org/licenses/lgpl-3.0.html>.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using BH.oM.Base.Attributes;
using BH.oM.Dimensional;
using BH.oM.Geometry;
using BH.oM.Structure.Elements;
using BH.Engine.Geometry;
using BH.Engine.Base;


namespace BH.Engine.Structure
{
public static partial class Modify
{
/***************************************************/
/**** Public Methods ****/
/***************************************************/

[Description("Sets the Outline Element1Ds of a PadFoundation, i.e. the ExternalBoundary. Method required for all IElement2Ds.\n" +
"The provided edges all need to be ICurves and should form a closed loop. No checking for planarity is made by the method.\n" +
"The Method will return a new PadFoundation with the provided edges as the TopSurface.")]
[Input("padFoundation", "The PadFoundation to update the ExternalEdge of.")]
[Input("edges", "A list of IElement1Ds which all should be of a type of ICurve.")]
[Output("padFoundation", "A new PadFoundation with TopSurface matching the provided edges.")]
public static PadFoundation SetOutlineElements1D(this PadFoundation padFoundation, IEnumerable<IElement1D> edges)
{
if (padFoundation.IsNull())
return padFoundation;

List<Edge> externalEdges = edges.Cast<Edge>().ToList();
peterjamesnugent marked this conversation as resolved.
Show resolved Hide resolved

return Create.PadFoundation(externalEdges, padFoundation.Property, padFoundation.Orientation);
}

/***************************************************/

}
}



27 changes: 27 additions & 0 deletions Structure_Engine/Modify/Transform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,33 @@ public static FEMesh Transform(this FEMesh mesh, TransformMatrix transform, doub
}

/***************************************************/

/***************************************************/

[Description("Transforms the PadFoundation's edges, openings and basis by the transform matrix. Only rigid body transformations are supported.")]
[Input("padFoundation", "PadFoundation to transform.")]
[Input("transform", "Transform matrix.")]
[Input("tolerance", "Tolerance used in the check whether the input matrix is equivalent to the rigid body transformation.")]
[Output("transformed", "Modified PadFoundation with unchanged properties, but transformed edges and basis.")]
public static PadFoundation Transform(this PadFoundation padFoundation, TransformMatrix transform, double tolerance = Tolerance.Distance)
pawelbaran marked this conversation as resolved.
Show resolved Hide resolved
{
if (padFoundation == null)
{
Base.Compute.RecordError("Could not transform the PadFoundation because it was null.");
return null;
}

if (!transform.IsRigidTransformation(tolerance))
{
Base.Compute.RecordError("Transformation failed: only rigid body transformations are currently supported.");
return null;
}

PadFoundation result = padFoundation.ShallowClone();
result.Orientation = result.Orientation.Transform(transform);

return result;
}
}
}

Expand Down
Loading