From a40e33522088926b29138b9e4a4cc8944e49ce21 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 23 May 2022 15:33:43 +0200 Subject: [PATCH 01/17] Create methods for Polygon and Polycurve --- Geometry_Engine/Create/BoundaryCurve.cs | 96 +++++++++++++++++++++++++ Geometry_Engine/Create/Polygon.cs | 90 +++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 Geometry_Engine/Create/BoundaryCurve.cs create mode 100644 Geometry_Engine/Create/Polygon.cs diff --git a/Geometry_Engine/Create/BoundaryCurve.cs b/Geometry_Engine/Create/BoundaryCurve.cs new file mode 100644 index 000000000..8ad503a14 --- /dev/null +++ b/Geometry_Engine/Create/BoundaryCurve.cs @@ -0,0 +1,96 @@ +/* + * 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 BH.oM.Base; +using BH.oM.Base.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using BH.Engine.Base; +using BH.oM.Geometry; +using BH.oM.Quantities.Attributes; + +namespace BH.Engine.Geometry +{ + public static partial class Create + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Creates a BoundaryCurve from a set of curves defining its shape. The curves are required to be co-planar and form a non self-intersecting closed loop. Sub-parts of the incoming curves will be extracted, and joined to ensure the validity of the inputs. This means the order of the Curves on the BoundaryCurve might be different than the input.")] + [Input("curves", "Set of Curves forming a closed, planar, non self-intersecting loop. If not a valid loop, null is returned.")] + [Input("tolerance", "Tolerance used for checking the validity of the incoming curves.", typeof(Length))] + [Output("boundaryCurve", "The created BoundaryCurve.")] + public static BoundaryCurve BoundaryCurve(List curves, double tolerance = Tolerance.Distance) + { + if (curves.IsNullOrEmpty()) + return null; + + if (curves.Count == 1 && (curves[0] is Circle || curves[0] is Ellipse)) //Special case of single circle or ellipse + return new BoundaryCurve(curves); + + //Try joining all segments into a single polycurve + List subParts = curves.SelectMany(x => x.ISubParts()).ToList(); + + if (subParts.Any(x => x is NurbsCurve)) + { + Engine.Base.Compute.RecordError("Input curves contaisn NubrsCurves which cannot be validated. BoundaryCurve not created."); + return null; + } + + + List joinedCurves = Compute.IJoin(curves.SelectMany(x => x.ISubParts()).ToList(),tolerance); + + if (joinedCurves.Count != 1) + { + Engine.Base.Compute.RecordError("Provided curves are not joined. Unable to create BoundaryCurve."); + return null; + } + + PolyCurve polyCurve = joinedCurves[0]; + + if (!polyCurve.IsClosed(tolerance)) + { + Engine.Base.Compute.RecordError("Provided curves does not form a closed loop. Unable to create BoundaryCurve."); + return null; + } + + if (!polyCurve.IsPlanar(tolerance)) + { + Engine.Base.Compute.RecordError("Provided curves are not co-planar. Unable to create BoundaryCurve."); + return null; + } + + if (polyCurve.IsSelfIntersecting(tolerance)) + { + Engine.Base.Compute.RecordError("Provided curves are self-intersecting or intersecting each other. Unable to create BoundaryCurve."); + return null; + } + + return new BoundaryCurve(polyCurve.Curves); + } + + /***************************************************/ + } +} diff --git a/Geometry_Engine/Create/Polygon.cs b/Geometry_Engine/Create/Polygon.cs new file mode 100644 index 000000000..e328ae6b7 --- /dev/null +++ b/Geometry_Engine/Create/Polygon.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 BH.oM.Base; +using BH.oM.Base.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using BH.oM.Geometry; +using BH.oM.Quantities.Attributes; +using BH.Engine.Base; + +namespace BH.Engine.Geometry +{ + public static partial class Create + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Creates a Polygon from the set of provided Points. The provided points will be checked for planarity and a check will be made to ensure that no segments are intersecting with each other. If those checks are failed, null will be returned.")] + [Input("vertices", "The set of vertices of the Polygon. Will be checkef for planarity and ensured to not be self intersecting. For a polygon no duplicate points are stored, meaning the first point in the list will be both the start and end point. If the first point provided is the same as the last point, the last point will be culled with no warning given.")] + [Input("tolerance", "Tolerance used for checking the validity of the incoming vertices.", typeof(Length))] + [Output("polygon", "The created Polygon.")] + public static Polygon Polygon(List vertices, double tolerance = Tolerance.Distance) + { + if (vertices.IsNullOrEmpty()) + return null; + + List checkedVertices = vertices.ToList(); + + if (checkedVertices[0].SquareDistance(checkedVertices.Last()) < tolerance * tolerance) + checkedVertices.RemoveAt(checkedVertices.Count - 1); + + int count = checkedVertices.Count; + if (count < 3) + { + Engine.Base.Compute.RecordError("Insufficent number of points provided to create a Polygon. At least 3 unique points required."); + return null; + } + + if (checkedVertices.IsCollinear(tolerance)) + { + Engine.Base.Compute.RecordError("Provided vertices are co-linear. Polygon not created."); + return null; + } + + if (count > 3) //3 non-colinear vertices are gurarantiued to be planar and non-selfintersecting. + { + if (!checkedVertices.IsCoplanar(tolerance)) + { + Engine.Base.Compute.RecordError("Provided vertices are not co-planar. Polygon not created."); + return null; + } + //Temporary polyline to check for self-intersections + Polyline pLine = new Polyline { ControlPoints = checkedVertices.ToList() }; + pLine.ControlPoints.Add(checkedVertices[0]); + + if (pLine.IsSelfIntersecting(tolerance)) + { + Engine.Base.Compute.RecordError("The provided vertices creates line segments that intersect each other. Polygon not created."); + return null; + } + } + return new Polygon(checkedVertices); + } + + /***************************************************/ + } +} From 04549ab5ebd538e0978ca25ae4cdd0b54c57d292 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 23 May 2022 16:50:47 +0200 Subject: [PATCH 02/17] Adding IsClosed, IsPlanar and IsSelfIntersecting methods for Polygon and BoundaryCurve Also, significant amount of missing descriptions added --- Geometry_Engine/Query/IsClosed.cs | 61 ++++++++++++++- Geometry_Engine/Query/IsPlanar.cs | 87 +++++++++++++++++++++ Geometry_Engine/Query/IsSelfIntersecting.cs | 21 +++++ 3 files changed, 168 insertions(+), 1 deletion(-) diff --git a/Geometry_Engine/Query/IsClosed.cs b/Geometry_Engine/Query/IsClosed.cs index adbf56c3e..651057762 100644 --- a/Geometry_Engine/Query/IsClosed.cs +++ b/Geometry_Engine/Query/IsClosed.cs @@ -25,6 +25,8 @@ using System.Collections.Generic; using System.Linq; using System; +using System.ComponentModel; +using BH.oM.Quantities.Attributes; namespace BH.Engine.Geometry { @@ -34,13 +36,21 @@ public static partial class Query /**** Public Methods - Curves ****/ /***************************************************/ + [Description("Checks if the Arc is closed, i.e. forms a closed loop by checking if the end points are within tolerance of each other.")] + [Input("arc", "The Arc to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true if the Arc is closed, i.e. a circle.")] public static bool IsClosed(this Arc arc, double tolerance = Tolerance.Distance) { - return (arc.Angle() - Math.PI * 2)*arc.Radius > -tolerance; + return (arc.Angle() - Math.PI * 2) * arc.Radius > -tolerance; } /***************************************************/ + [Description("Checks if the Circle is closed, i.e. forms a closed loop. A Circle is by definition always closed, why this method always returns true.")] + [Input("circle", "The Circle to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true for all cases.")] public static bool IsClosed(this Circle circle, double tolerance = Tolerance.Distance) { return true; @@ -48,6 +58,10 @@ public static bool IsClosed(this Circle circle, double tolerance = Tolerance.Dis /***************************************************/ + [Description("Checks if the Line is closed, i.e. forms a closed loop. A Line is by definition never closed, why this method always returns false.")] + [Input("line", "The Circle to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns false for all cases.")] public static bool IsClosed(this Line line, double tolerance = Tolerance.Distance) { return false; @@ -55,6 +69,10 @@ public static bool IsClosed(this Line line, double tolerance = Tolerance.Distanc /***************************************************/ + [Description("Checks if the Ellipse is closed, i.e. forms a closed loop. An Ellipse is by definition always closed, why this method always returns true.")] + [Input("ellipse", "The Ellipse to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true for all cases.")] public static bool IsClosed(this Ellipse ellipse, double tolerance = Tolerance.Distance) { return true; @@ -62,6 +80,10 @@ public static bool IsClosed(this Ellipse ellipse, double tolerance = Tolerance.D /***************************************************/ + [Description("Checks if the NurbsCurve is closed, i.e. forms a closed loop, by checking if the end points are within tolerance of each other or if it is a periodic curve.")] + [Input("curve", "The NurbsCurve to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true if the NurbsCurve is closed.")] public static bool IsClosed(this NurbsCurve curve, double tolerance = Tolerance.Distance) { if (curve == null || curve.ControlPoints == null || curve.ControlPoints.Count < 2) @@ -72,6 +94,10 @@ public static bool IsClosed(this NurbsCurve curve, double tolerance = Tolerance. /***************************************************/ + [Description("Checks if the PolyCurve is closed, i.e. forms a closed loop, by checking if the end points are within tolerance of each other or if it is made up of a single inner Curve that is itself closed.")] + [Input("curve", "The PolyCurve to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true if the PolyCurve is closed.")] public static bool IsClosed(this PolyCurve curve, double tolerance = Tolerance.Distance) { if (curve.Curves.Count == 1) @@ -93,6 +119,10 @@ public static bool IsClosed(this PolyCurve curve, double tolerance = Tolerance.D /***************************************************/ + [Description("Checks if the PolyCurve is closed, i.e. forms a closed loop, by checking if the first and last control points are within tolerance of each other.")] + [Input("curve", "The Polyline to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true if the Polyline is closed.")] public static bool IsClosed(this Polyline curve, double tolerance = Tolerance.Distance) { List pts = curve.ControlPoints; @@ -102,11 +132,36 @@ public static bool IsClosed(this Polyline curve, double tolerance = Tolerance.Di return pts.First().SquareDistance(pts.Last()) < tolerance * tolerance; } + /***************************************************/ + + [Description("Checks if the Polygon is closed, i.e. forms a closed loop. A Polygon is always ensured to be closed at creation, why this method always returns true.")] + [Input("curve", "The Polygon to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "A Polygon is checked for closedness at creation, why this method always returns true.")] + public static bool IsClosed(this Polygon curve, double tolerance = Tolerance.Distance) + { + return true; + } + + /***************************************************/ + + [Description("Checks if the BoundaryCurve is closed, i.e. forms a closed loop. A BoundaryCurve is always ensured to be closed at creation, why this method always returns true.")] + [Input("curve", "The BoundaryCurve to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "A BoundaryCurve is checked for closedness at creation, why this method always returns true.")] + public static bool IsClosed(this BoundaryCurve curve, double tolerance = Tolerance.Distance) + { + return true; + } /***************************************************/ /**** Public Methods - Interfaces ****/ /***************************************************/ + [Description("Checks if the ICurve is closed, i.e. forms a closed loop.")] + [Input("curve", "The ICurve to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true if the ICurve is closed.")] public static bool IIsClosed(this ICurve curve, double tolerance = Tolerance.Distance) { return IsClosed(curve as dynamic, tolerance); @@ -117,6 +172,10 @@ public static bool IIsClosed(this ICurve curve, double tolerance = Tolerance.Dis /**** Public Methods - Nurbs Surfaces ****/ /***************************************************/ + [Description("Checks if the NurbsSurface is closed, i.e. forms a closed loop, in at least one direction, i.e. if one of the edges overlap fully with the edge on the oposite side in the u/v domain.")] + [Input("surface", "The NurbsSurface to check for closedness.")] + [Input("tolerance", "Distance tolerance for closedness validation.", typeof(Length))] + [Output("isClosed", "Returns true if the NurbsSurface is closed in at least one direction.")] public static bool IsClosed(this NurbsSurface surface, double tolerance = Tolerance.Distance) { if (surface.IsPeriodic()) diff --git a/Geometry_Engine/Query/IsPlanar.cs b/Geometry_Engine/Query/IsPlanar.cs index 2c42fe2ba..776413344 100644 --- a/Geometry_Engine/Query/IsPlanar.cs +++ b/Geometry_Engine/Query/IsPlanar.cs @@ -24,7 +24,9 @@ using BH.oM.Base.Attributes; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using BH.oM.Quantities.Attributes; namespace BH.Engine.Geometry { @@ -34,6 +36,10 @@ public static partial class Query /**** Public Methods - Vectors ****/ /***************************************************/ + [Description("Checks if the Point is planar, i.e. all of its parts fit in a single plane. For a Point this is always the case, why this method always returns true.")] + [Input("pt", "The Point to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Point is always planar, why this method always returns true.")] public static bool IsPlanar(this Point pt, double tolerance = Tolerance.Distance) { return true; @@ -41,6 +47,10 @@ public static bool IsPlanar(this Point pt, double tolerance = Tolerance.Distance /***************************************************/ + [Description("Checks if the Vector is planar, i.e. all of its parts fit in a single plane. For a Vector this is always the case, why this method always returns true.")] + [Input("vector", "The Vector to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Vector is always planar, why this method always returns true.")] public static bool IsPlanar(this Vector vector, double tolerance = Tolerance.Distance) { return true; @@ -48,6 +58,10 @@ public static bool IsPlanar(this Vector vector, double tolerance = Tolerance.Dis /***************************************************/ + [Description("Checks if the Plane is planar, i.e. all of its parts fit in a single plane. For a Plane this is always the case, why this method always returns true.")] + [Input("plane", "The Plane to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Plane is always planar, why this method always returns true.")] public static bool IsPlanar(this Plane plane, double tolerance = Tolerance.Distance) { return true; @@ -58,6 +72,10 @@ public static bool IsPlanar(this Plane plane, double tolerance = Tolerance.Dista /**** public Methods - Curves ****/ /***************************************************/ + [Description("Checks if the Line is planar, i.e. all of its parts fit in a single plane. For a Line this is always the case, why this method always returns true.")] + [Input("line", "The Plane to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Line is always planar, why this method always returns true.")] public static bool IsPlanar(this Line line, double tolerance = Tolerance.Distance) { return true; @@ -65,6 +83,10 @@ public static bool IsPlanar(this Line line, double tolerance = Tolerance.Distanc /***************************************************/ + [Description("Checks if the Arc is planar, i.e. all of its parts fit in a single plane. For a Arc this is always the case, why this method always returns true.")] + [Input("arc", "The Arc to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Arc is always planar, why this method always returns true.")] public static bool IsPlanar(this Arc arc, double tolerance = Tolerance.Distance) { return true; @@ -72,6 +94,10 @@ public static bool IsPlanar(this Arc arc, double tolerance = Tolerance.Distance) /***************************************************/ + [Description("Checks if the Circle is planar, i.e. all of its parts fit in a single plane. For a Circle this is always the case, why this method always returns true.")] + [Input("circle", "The Circle to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Circle is always planar, why this method always returns true.")] public static bool IsPlanar(this Circle circle, double tolerance = Tolerance.Distance) { return true; @@ -79,6 +105,10 @@ public static bool IsPlanar(this Circle circle, double tolerance = Tolerance.Dis /***************************************************/ + [Description("Checks if the Ellipse is planar, i.e. all of its parts fit in a single plane. For a Ellipse this is always the case, why this method always returns true.")] + [Input("ellipse", "The Ellipse to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Ellipse is always planar, why this method always returns true.")] public static bool IsPlanar(this Ellipse ellipse, double tolerance = Tolerance.Distance) { return true; @@ -86,6 +116,10 @@ public static bool IsPlanar(this Ellipse ellipse, double tolerance = Tolerance.D /***************************************************/ + [Description("Checks if the NurbsCurve is planar, i.e. all of its parts fit in a single plane. Check is done by evaluating if all the controlpoints are co-planar within the provided tolerance.")] + [Input("curve", "The NurbsCurve to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided NurbsCurve is planar, i.e. all of its controlpoints are in the same plane within tolerance.")] public static bool IsPlanar(this NurbsCurve curve, double tolerance = Tolerance.Distance) { return curve.ControlPoints.IsCoplanar(tolerance); @@ -93,6 +127,10 @@ public static bool IsPlanar(this NurbsCurve curve, double tolerance = Tolerance. /***************************************************/ + [Description("Checks if the Polyline is planar, i.e. all of its parts fit in a single plane. Check is done by evaluating if all the controlpoints are co-planar within the provided tolerance.")] + [Input("curve", "The Polyline to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided Polyline is planar, i.e. all of its controlpoints are in the same plane within tolerance.")] public static bool IsPlanar(this Polyline curve, double tolerance = Tolerance.Distance) { return curve.ControlPoints.IsCoplanar(tolerance); @@ -100,16 +138,45 @@ public static bool IsPlanar(this Polyline curve, double tolerance = Tolerance.Di /***************************************************/ + [Description("Checks if the PolyCurve is planar, i.e. all of its parts fit in a single plane. Check is done by evaluating if all the controlpoints are co-planar within the provided tolerance.")] + [Input("curve", "The PolyCurve to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided PolyCurve is planar, i.e. all of its controlpoints are in the same plane within tolerance.")] public static bool IsPlanar(this PolyCurve curve, double tolerance = Tolerance.Distance) { return curve.ControlPoints().IsCoplanar(tolerance); } + /***************************************************/ + + [Description("Checks if the Polygon is planar, i.e. all of its parts fit in a single plane. Polygons are ensured to be planar at creation, why this method always returns true.")] + [Input("polygon", "The Polygon to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A Polygon is ensured to be planar at creation, why this method always returns true.")] + public static bool IsPlanar(this Polygon polygon, double tolerance = Tolerance.Distance) + { + return true; + } + + /***************************************************/ + + [Description("Checks if the BoundaryCurve is planar, i.e. all of its parts fit in a single plane. BoundaryCurve are ensured to be planar at creation, why this method always returns true.")] + [Input("curve", "The BoundaryCurve to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "A BoundaryCurve is ensured to be planar at creation, why this method always returns true.")] + public static bool IsPlanar(this BoundaryCurve curve, double tolerance = Tolerance.Distance) + { + return true; + } /***************************************************/ /**** Public Methods - Surfaces ****/ /***************************************************/ + [Description("Checks if the PlanarSurface is planar, i.e. all of its parts fit in a single plane. A PlanarSurface is ensured to be planar at creation, why this method always returns true if the default tolerance is provided. For other tolerances the method returns true if the controlpoints of external and internal boundaries are co-planar within tolerance.")] + [Input("surface", "The PlanarSurface to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided PlanarSurface is planar, i.e. if the control points of the external and internal boundaries are in the same plane within tolerance.")] public static bool IsPlanar(this PlanarSurface surface, double tolerance = Tolerance.Distance) { // This is not a bug: PlanarSurface is IImmutable with all necessary planarity checks being made by the Create method. @@ -130,6 +197,10 @@ public static bool IsPlanar(this PlanarSurface surface, double tolerance = Toler /***************************************************/ + [Description("Checks if the Extrusion is planar, i.e. all of its parts fit in a single plane. This is true if the direction vector has a length lower than the tolerance, or if the base curve is linear.")] + [Input("surface", "The Extrusion to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided Extrusion is planar.")] public static bool IsPlanar(this Extrusion surface, double tolerance = Tolerance.Distance) { return (surface.Direction.Length() <= tolerance || surface.Curve.IIsLinear()); @@ -137,6 +208,10 @@ public static bool IsPlanar(this Extrusion surface, double tolerance = Tolerance /***************************************************/ + [Description("Checks if the Loft is planar, i.e. all of its parts fit in a single plane, by checking if the controlpoints of all the curves are co-planar.")] + [Input("surface", "The Loft to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided Loft is planar, i.e. if the control points of all of its curves are all in the same plane within tolerance.")] public static bool IsPlanar(this Loft surface, double tolerance = Tolerance.Distance) { List controlPts = new List(); @@ -149,6 +224,10 @@ public static bool IsPlanar(this Loft surface, double tolerance = Tolerance.Dist /***************************************************/ + [Description("Checks if the Pipe is planar, i.e. all of its parts fit in a single plane. This is true if the Centreline has a length lower than the tolerance, or if the radiues is smaller than the tolerance.")] + [Input("surface", "The Pipe to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided Pipe is planar.")] public static bool IsPlanar(this Pipe surface, double tolerance = Tolerance.Distance) { return surface.Centreline.ILength() <= tolerance || surface.Radius == 0; @@ -171,6 +250,10 @@ public static bool IsPlanar(this PolySurface surface, double tolerance = Toleran /**** Public Methods - Others ****/ /***************************************************/ + [Description("Checks if the Mesh is planar, i.e. all of its parts fit in a single plane. Check is done by evaluating if all the vertices are co-planar within the provided tolerance.")] + [Input("mesh", "The Mesh to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided Mesh is planar, i.e. all of its vertices are in the same plane within tolerance.")] public static bool IsPlanar(this Mesh mesh, double tolerance = Tolerance.Distance) { return mesh.Vertices.IsCoplanar(tolerance); @@ -193,6 +276,10 @@ public static bool IsPlanar(this CompositeGeometry group, double tolerance = Tol /**** Public Methods = Interfaces ****/ /***************************************************/ + [Description("Checks if the IGeometry is planar, i.e. all of its parts fit in a single plane.")] + [Input("geometry", "The IGeometry to check for planarity.")] + [Input("tolerance", "Distance tolerance for planarity validation.", typeof(Length))] + [Output("isPlanar", "Returns true if the provided IGeometry is planar.")] public static bool IIsPlanar(this IGeometry geometry, double tolerance = Tolerance.Distance) { return IsPlanar(geometry as dynamic, tolerance); diff --git a/Geometry_Engine/Query/IsSelfIntersecting.cs b/Geometry_Engine/Query/IsSelfIntersecting.cs index c13766231..69c07b975 100644 --- a/Geometry_Engine/Query/IsSelfIntersecting.cs +++ b/Geometry_Engine/Query/IsSelfIntersecting.cs @@ -156,6 +156,27 @@ public static bool IsSelfIntersecting(this PolyCurve curve, double tolerance = T return false; } + /***************************************************/ + + [Description("Checks if any part of the the Polygon is intersecting with any other part of the curve. A Polygon is checked to not be self intersecting at creation, hence this method always returns false.")] + [Input("curve", "The curve to check for self intersection. A for a Polygon, this method always returns false.")] + [Input("tolerance", "Distance tolerance to be used by the method. For a Polygon this in unused.", (typeof(Length)))] + [Output("isIntersecting", "Returns true if the Polygon is self intersecting. For a Polygon this always returns false.")] + public static bool IsSelfIntersecting(this Polygon curve, double tolerance = Tolerance.Distance) + { + return false; + } + + /***************************************************/ + + [Description("Checks if any part of the the BoundaryCurve is intersecting with any other part of the curve. A BoundaryCurve is checked to not be self intersecting at creation, hence this method always returns false.")] + [Input("curve", "The curve to check for self intersection. A for a Polygon, this method always returns false.")] + [Input("tolerance", "Distance tolerance to be used by the method. For a Polygon this in unused.", (typeof(Length)))] + [Output("isIntersecting", "Returns true if the BoundaryCurve is self intersecting. For a BoundaryCurve this always returns false.")] + public static bool IsSelfIntersecting(this BoundaryCurve curve, double tolerance = Tolerance.Distance) + { + return false; + } /***************************************************/ /**** Public Methods = Interfaces ****/ From f6f203a44660040711255eac3986544f495eb522 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 23 May 2022 16:56:24 +0200 Subject: [PATCH 03/17] Adding methods for ControlPoints and Vertices --- Geometry_Engine/Query/ControlPoints.cs | 12 ++++++++ Geometry_Engine/Query/Vertices.cs | 39 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/Geometry_Engine/Query/ControlPoints.cs b/Geometry_Engine/Query/ControlPoints.cs index c610a369d..61bafe0e8 100644 --- a/Geometry_Engine/Query/ControlPoints.cs +++ b/Geometry_Engine/Query/ControlPoints.cs @@ -25,6 +25,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.ComponentModel; namespace BH.Engine.Geometry { @@ -91,6 +92,17 @@ public static List ControlPoints(this Polyline curve) return curve.ControlPoints; } + /***************************************************/ + + [Description("Gets the controlpoints of the Polygon. These will be the Vertices of the Polygon, with the first point duplicated as the last control point.")] + [Input("curve", "The Polygon to extract the ControlPoints from.")] + [Output("points", "The controlpoints of the Polygon. The first and last point will be the same.")] + public static List ControlPoints(this Polygon curve) + { + List controlPoints = curve.Vertices.ToList(); + controlPoints.Add(controlPoints[0]); + return controlPoints; + } /***************************************************/ /**** Public Methods - Interfaces ****/ diff --git a/Geometry_Engine/Query/Vertices.cs b/Geometry_Engine/Query/Vertices.cs index 259dba020..95cf51dd9 100644 --- a/Geometry_Engine/Query/Vertices.cs +++ b/Geometry_Engine/Query/Vertices.cs @@ -23,6 +23,7 @@ using BH.oM.Geometry; using BH.oM.Base.Attributes; using System.Collections.Generic; +using System.Linq; using System.ComponentModel; namespace BH.Engine.Geometry @@ -55,6 +56,44 @@ public static int[] Vertices(this Face face) } /***************************************************/ + + [Description("Returns all the unique of the polyline if it is closed. This means that the last control point will be omitted for a closed Polyline. Undefined if the curve is open.")] + [Input("pLine", "The Polyline to extract vertices from.")] + [Output("vertices", "Vertices of the Polyline.")] + public static List Vertices(this Polyline pLine, double tolerance = Tolerance.Distance) + { + if (!pLine.IsClosed(tolerance)) + { + Base.Compute.RecordError("Input curve is not closed. Verticies not defined."); + return new List(); + } + + return pLine.ControlPoints.GetRange(0, pLine.ControlPoints.Count - 1); + } + + /***************************************************/ + + [Description("Returns the Vertices of the Polygon.")] + [Input("pGon", "The Polygon to extract the Vertices from.")] + [Output("vertices", "Vertices of the Polyline.")] + public static List Vertices(this Polygon pGon, double tolerance = Tolerance.Distance) + { + return pGon.Vertices.ToList(); + } + + /***************************************************/ + /**** Public Methods - Interface ****/ + /***************************************************/ + + [Description("Returns the Vertices of the IPolyline if it is closed. Undefined for open IPolylines.")] + [Input("pline", "The IPolyline to extract the Vertices from.")] + [Output("vertices", "Vertices of the IPolyline.")] + public static List IVertices(this IPolyline pline, double tolerance = Tolerance.Distance) + { + return Vertices(pline as dynamic, tolerance); + } + + /***************************************************/ } } From 80c38cfa64bfb77f23107291214b70dde5f473c8 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 23 May 2022 17:01:35 +0200 Subject: [PATCH 04/17] Adding method for extracting the inner curves from an IPolyCurve --- Geometry_Engine/Query/Curves.cs | 74 +++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Geometry_Engine/Query/Curves.cs diff --git a/Geometry_Engine/Query/Curves.cs b/Geometry_Engine/Query/Curves.cs new file mode 100644 index 000000000..9c2d4bdd2 --- /dev/null +++ b/Geometry_Engine/Query/Curves.cs @@ -0,0 +1,74 @@ +/* + * 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 BH.oM.Base; +using BH.oM.Base.Attributes; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using BH.oM.Geometry; + +namespace BH.Engine.Geometry +{ + public static partial class Query + { + /***************************************************/ + /**** Public Methods ****/ + /***************************************************/ + + [Description("Returns the inner curves of the PolyCurve.")] + [Input("curve", "The PolyCurve to extract the inner curves from.")] + [Output("curves", "The inner curves fo the PolyCurve.")] + public static List Curves(this PolyCurve curve) + { + return curve?.Curves; + } + + /***************************************************/ + + [Description("Returns the inner curves of the BoundaryCurve.")] + [Input("curve", "The BoundaryCurve to extract the inner curves from.")] + [Output("curves", "The inner curves fo the BoundaryCurve.")] + public static List Curves(this BoundaryCurve curve) + { + return curve?.Curves?.ToList(); + } + + /***************************************************/ + /**** Public Methods - Interface ****/ + /***************************************************/ + + [Description("Returns the inner curves of the IPolyCurve.")] + [Input("curve", "The IPolyCurve to extract the inner curves from.")] + [Output("curves", "The inner curves fo the IPolyCurve.")] + public static List ICurves(this IPolyCurve curve) + { + if (curve == null) + return null; + + return Curves(curve as dynamic); + } + + /***************************************************/ + } +} From acb540f62bdfe21d837c7edb33e99b9f2481d5bc Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 23 May 2022 17:37:49 +0200 Subject: [PATCH 05/17] Update Centroid methods to use the interface rather than class --- Geometry_Engine/Query/Centroid.cs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Geometry_Engine/Query/Centroid.cs b/Geometry_Engine/Query/Centroid.cs index 6e91df93f..d1f1c9ef6 100644 --- a/Geometry_Engine/Query/Centroid.cs +++ b/Geometry_Engine/Query/Centroid.cs @@ -37,7 +37,6 @@ public static partial class Query /**** Public Methods - Surfaces ****/ /***************************************************/ - //TODO: Remove when PlanarSurface will implement IElement2D [Description("Queries the centre of area for a PlanarSurface.")] [Input("surface", "The PlanarSurface to get the centre of area of.")] [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance")] @@ -89,23 +88,24 @@ public static Point Centroid(this IEnumerable outlines, IEnumerable controlPoints = curve.IControlPoints(); + Point pA = controlPoints[0]; Vector normal = Normal(curve, tolerance); @@ -122,10 +123,10 @@ public static Point Centroid(this Polyline curve, double tolerance = Tolerance.D if (normal == null) return null; - for (int i = 1; i < curve.ControlPoints.Count - 2; i++) + for (int i = 1; i < controlPoints.Count - 2; i++) { - Point pB = curve.ControlPoints[i]; - Point pC = curve.ControlPoints[i + 1]; + Point pB = controlPoints[i]; + Point pC = controlPoints[i + 1]; double triangleArea = Area(pB - pA, pC - pA); @@ -154,29 +155,30 @@ public static Point Centroid(this Polyline curve, double tolerance = Tolerance.D /***************************************************/ + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Centroid(BH.oM.Geometry.PolyCurve, System.Double)")] [Description("Queries the centre of area enclosed by a closed, planar, non-self-intersecting PolyCurve.")] [Input("curve", "The PolyCurve to get the centre of area of.")] [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance")] [Output("centroid", "The Point at the centre of area enclosed by given PolyCurve.")] - public static Point Centroid(this PolyCurve curve, double tolerance = Tolerance.Distance) + public static Point Centroid(this IPolyCurve curve, double tolerance = Tolerance.Distance) { - if (!curve.IsPlanar(tolerance)) + if (!curve.IIsPlanar(tolerance)) { Base.Compute.RecordError("Input curve is not planar. Cannot calculate centroid."); return null; } - else if (!curve.IsClosed(tolerance)) + else if (!curve.IIsClosed(tolerance)) { Base.Compute.RecordError("Input curve is not closed. Cannot calculate centroid."); return null; } - else if (curve.IsSelfIntersecting(tolerance)) + else if (curve.IIsSelfIntersecting(tolerance)) { Base.Compute.RecordError("Input curve is self-intersecting. Cannot calculate centroid."); return null; } - List curveSubParts = curve.SubParts(); + List curveSubParts = curve.ISubParts().ToList(); if (curveSubParts.Count == 1 && curveSubParts[0] is Circle) return (curveSubParts[0] as Circle).Centre; From 7d24648476d2f4202937a598ca75dbe8cb30dbae Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Tue, 24 May 2022 14:58:39 +0200 Subject: [PATCH 06/17] Methods for Area, DiscontinuityPoints, IsCLockwise and Normal to operate on the new interfaces --- Geometry_Engine/Query/Area.cs | 29 +++++++++----------- Geometry_Engine/Query/DiscontinuityPoints.cs | 14 ++++++---- Geometry_Engine/Query/IsClockwise.cs | 13 +++++---- Geometry_Engine/Query/Normal.cs | 21 ++++++++------ 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Geometry_Engine/Query/Area.cs b/Geometry_Engine/Query/Area.cs index 87859bb36..615574354 100644 --- a/Geometry_Engine/Query/Area.cs +++ b/Geometry_Engine/Query/Area.cs @@ -61,7 +61,6 @@ public static double IArea(this IGeometry geometry, double tolerance = Tolerance [Input("curve", "The Arc to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this Arc curve, double tolerance = Tolerance.Distance) { if (curve == null) @@ -85,7 +84,6 @@ public static double Area(this Arc curve, double tolerance = Tolerance.Distance) [Input("curve", "The Circle to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this Circle curve, double tolerance = Tolerance.Distance) { if (curve == null) @@ -121,7 +119,6 @@ public static double Area(this Ellipse curve, double tolerance = Tolerance.Dista [Input("curve", "The Line to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this Line curve, double tolerance = Tolerance.Distance) { Base.Compute.RecordWarning("Cannot calculate area for an open curve."); @@ -130,36 +127,36 @@ public static double Area(this Line curve, double tolerance = Tolerance.Distance /***************************************************/ + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Area(BH.oM.Geometry.PolyCurve, System.Double)")] [Description("Calculates the area of the provided geometry.")] [Input("curve", "The PolyCurve to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - - public static double Area(this PolyCurve curve, double tolerance = Tolerance.Distance) + public static double Area(this IPolyCurve curve, double tolerance = Tolerance.Distance) { if (curve == null) { BH.Engine.Base.Compute.RecordError("Cannot query area as the geometry is null."); return double.NaN; } - - if (curve.Curves.Count == 1 && curve.Curves[0] is Circle) - return (curve.Curves[0] as Circle).Area(tolerance); + List curves = curve.ICurves(); + if (curves.Count == 1 && curves[0] is Circle) + return (curves[0] as Circle).Area(tolerance); - if (!curve.IsClosed(tolerance)) + if (!curve.IIsClosed(tolerance)) { Base.Compute.RecordWarning("Cannot calculate area for an open curve."); return 0; } - Plane p = curve.FitPlane(tolerance); + Plane p = curve.IFitPlane(tolerance); if (p == null) return 0.0; // points are collinear - Point sPt = curve.StartPoint(); + Point sPt = curve.IStartPoint(); double area = 0; - foreach (ICurve c in curve.SubParts()) + foreach (ICurve c in curve.ISubParts()) { if (c is NurbsCurve) { @@ -191,12 +188,12 @@ public static double Area(this PolyCurve curve, double tolerance = Tolerance.Dis /***************************************************/ + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Area(BH.oM.Geometry.Polyline, System.Double)")] [Description("Calculates the area of the provided geometry.")] [Input("curve", "The Polyline to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - - public static double Area(this Polyline curve, double tolerance = Tolerance.Distance) + public static double Area(this IPolyline curve, double tolerance = Tolerance.Distance) { if (curve == null) { @@ -204,13 +201,13 @@ public static double Area(this Polyline curve, double tolerance = Tolerance.Dist return double.NaN; } - if (!curve.IsClosed(tolerance)) + if (!curve.IIsClosed(tolerance)) { Base.Compute.RecordWarning("Cannot calculate area for an open curve."); return 0; } - List pts = curve.ControlPoints; + List pts = curve.IControlPoints(); int ptsCount = pts.Count; if (ptsCount < 4) return 0.0; diff --git a/Geometry_Engine/Query/DiscontinuityPoints.cs b/Geometry_Engine/Query/DiscontinuityPoints.cs index 0bac20793..1be61ebe0 100644 --- a/Geometry_Engine/Query/DiscontinuityPoints.cs +++ b/Geometry_Engine/Query/DiscontinuityPoints.cs @@ -55,11 +55,12 @@ public static List DiscontinuityPoints(this Line curve, double distanceTo /***************************************************/ - public static List DiscontinuityPoints(this PolyCurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.PolyCurve, System.Double, System.Double)")] + public static List DiscontinuityPoints(this IPolyCurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { List result = new List(); - List curves = curve.SubParts().Where(c => !(c is Circle || c is Ellipse)).ToList(); - bool closed = curve.IsClosed(distanceTolerance); + List curves = curve.ISubParts().Where(c => !(c is Circle || c is Ellipse)).ToList(); + bool closed = curve.IIsClosed(distanceTolerance); if (curves.Count == 0) return result; @@ -85,16 +86,17 @@ public static List DiscontinuityPoints(this PolyCurve curve, double dista /***************************************************/ - public static List DiscontinuityPoints(this Polyline curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.Polyline, System.Double, System.Double)")] + public static List DiscontinuityPoints(this IPolyline curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { - List ctrlPts = new List(curve.ControlPoints); + List ctrlPts = new List(curve.IControlPoints()); if (ctrlPts.Count < 3) return ctrlPts; double sqTol = distanceTolerance * distanceTolerance; int j = 0; - if (!curve.IsClosed(distanceTolerance)) + if (!curve.IIsClosed(distanceTolerance)) j += 2; for (int i = j; i < ctrlPts.Count; i++) diff --git a/Geometry_Engine/Query/IsClockwise.cs b/Geometry_Engine/Query/IsClockwise.cs index 70f8711ff..6641c858d 100644 --- a/Geometry_Engine/Query/IsClockwise.cs +++ b/Geometry_Engine/Query/IsClockwise.cs @@ -24,6 +24,7 @@ using System.Linq; using System.Collections.Generic; using System; +using BH.oM.Base.Attributes; using BH.Engine.Base; namespace BH.Engine.Geometry @@ -34,9 +35,10 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - public static bool IsClockwise(this Polyline polyline, Vector normal, double tolerance = Tolerance.Distance) + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.Polyline, BH.oM.Geometry.Vector, System.Double)")] + public static bool IsClockwise(this IPolyline polyline, Vector normal, double tolerance = Tolerance.Distance) { - if (!polyline.IsClosed(tolerance)) + if (!polyline.IIsClosed(tolerance)) throw new Exception("The polyline is not closed. IsClockwise method is relevant only to closed curves."); List cc = polyline.DiscontinuityPoints(tolerance); @@ -64,13 +66,14 @@ public static bool IsClockwise(this Polyline polyline, Vector normal, double tol /***************************************************/ - public static bool IsClockwise(this PolyCurve curve, Vector normal, double tolerance = Tolerance.Distance) + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.PolyCurve, BH.oM.Geometry.Vector, System.Double)")] + public static bool IsClockwise(this IPolyCurve curve, Vector normal, double tolerance = Tolerance.Distance) { - if (!curve.IsClosed(tolerance)) + if (!curve.IIsClosed(tolerance)) throw new Exception("The curve is not closed. IsClockwise method is relevant only to closed curves."); List cPts = new List { curve.IStartPoint() }; - foreach (ICurve c in curve.SubParts()) + foreach (ICurve c in curve.ISubParts()) { if (c is Line) cPts.Add(c.IEndPoint()); diff --git a/Geometry_Engine/Query/Normal.cs b/Geometry_Engine/Query/Normal.cs index a71e3edca..755881fc5 100644 --- a/Geometry_Engine/Query/Normal.cs +++ b/Geometry_Engine/Query/Normal.cs @@ -107,18 +107,19 @@ public static List Normals(this Mesh3D mesh) /**** Public Methods - Curves ****/ /***************************************************/ + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Normal(BH.oM.Geometry.Polyline, System.Double)")] [Description("Returns a vector normal to the plane of a given curve, oriented according to the right hand rule. Works only for closed, planar curves.")] [Input("curve", "The Polyline to get the normal to.")] [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance.")] [Output("normal", "Vector normal to the plane of a curve.")] - public static Vector Normal(this Polyline curve, double tolerance = Tolerance.Distance) + public static Vector Normal(this IPolyline curve, double tolerance = Tolerance.Distance) { - if (!curve.IsPlanar(tolerance)) + if (!curve.IIsPlanar(tolerance)) { Base.Compute.RecordError("A single normal vector is not unambiguously definable for non-planar curves."); return null; } - else if (!curve.IsClosed(tolerance)) + else if (!curve.IIsClosed(tolerance)) { Base.Compute.RecordError("A single normal vector is not unambiguously definable for open curves."); return null; @@ -127,12 +128,13 @@ public static Vector Normal(this Polyline curve, double tolerance = Tolerance.Di //else if (curve.IsSelfIntersecting(tolerance)) // Base.Compute.RecordWarning("Input curve is self-intersecting. Resulting normal vector might be flipped."); - Point avg = curve.ControlPoints.Average(); + List ctrlPts = curve.IControlPoints(); + Point avg = ctrlPts.Average(); Vector normal = new Vector(); //Get out normal, from cross products between vectors from the average point to adjecent controlpoints on the curve - for (int i = 0; i < curve.ControlPoints.Count - 1; i++) - normal += (curve.ControlPoints[i] - avg).CrossProduct(curve.ControlPoints[i + 1] - avg); + for (int i = 0; i < ctrlPts.Count - 1; i++) + normal += (ctrlPts[i] - avg).CrossProduct(ctrlPts[i + 1] - avg); if (normal.Length() < tolerance) { @@ -152,11 +154,12 @@ public static Vector Normal(this Polyline curve, double tolerance = Tolerance.Di /***************************************************/ + [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Normal(BH.oM.Geometry.PolyCurve, System.Double)")] [Description("Returns a vector normal to the plane of a given curve, oriented according to the right hand rule. Works only for closed and planar curves.")] [Input("curve", "The PolyCurve to get the normal to.")] [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance.")] [Output("normal", "Vector normal to the plane of a curve.")] - public static Vector Normal(this PolyCurve curve, double tolerance = Tolerance.Distance) + public static Vector Normal(this IPolyCurve curve, double tolerance = Tolerance.Distance) { List crvs = new List(curve.ISubParts()); if (crvs.Any(x => x is NurbsCurve)) @@ -165,12 +168,12 @@ public static Vector Normal(this PolyCurve curve, double tolerance = Tolerance.D return null; } - if (!curve.IsPlanar(tolerance)) + if (!curve.IIsPlanar(tolerance)) { Base.Compute.RecordError("A single normal vector is not unambiguously definable for non-planar curves."); return null; } - else if (!curve.IsClosed(tolerance)) + else if (!curve.IIsClosed(tolerance)) { Base.Compute.RecordError("A single normal vector is not unambiguously definable for open curves."); return null; From d514e85b4fa524fd2f6d6c8741baacd5b9cbee4e Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Wed, 25 May 2022 15:55:16 +0200 Subject: [PATCH 07/17] Tweak inner working of Centroid method for two lists of curves Following changes done to avoid unneccesary calls to BooleanUnion, as that changes the curve type to PolyCurve, meaning and performance gain from using BoundaryCurve is lost. Logic used for outer and inner curves is: - If one curve, just use centroid and area from it - If more than one curve, cluster (dbscan) by overlapping boundingboxes. For each cluster, then if single curve, just use it, if multiple curve, use boolean union, and then loop through the curve. --- Geometry_Engine/Query/Centroid.cs | 70 +++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/Geometry_Engine/Query/Centroid.cs b/Geometry_Engine/Query/Centroid.cs index d1f1c9ef6..75d479b53 100644 --- a/Geometry_Engine/Query/Centroid.cs +++ b/Geometry_Engine/Query/Centroid.cs @@ -24,7 +24,7 @@ using System.Collections.Generic; using System.Linq; using System; -using BH.Engine.Reflection; +using BH.Engine.Data; using BH.oM.Base.Attributes; using BH.oM.Base; using System.ComponentModel; @@ -63,24 +63,17 @@ public static Point Centroid(this IEnumerable outlines, IEnumerable boundaryCurves, out double area, double tolerance) + { + Point centroid = new Point(); + area = 0; + List curveList = boundaryCurves == null ? new List() : boundaryCurves.ToList(); + if (curveList.Count == 1) //If only one outline curve provided, just add it. No need for additional clustering/uninon + { + ICurve outline = curveList[0]; + double outlineArea = outline.IArea(); + centroid += (outline.ICentroid() * outlineArea); + area += outlineArea; + } + else if (curveList.Count > 1) //If more than one outline, some processing required + { + //Cluster curves based on boundingboxes overlapping + List> clusterCurves = Data.Compute.DomainTreeClusters(curveList, x => x.IBounds().DomainBox(), (a, b) => a.SquareDistance(b) < tolerance * tolerance, (a, b) => true, 1); + + foreach (List curves in clusterCurves) //For each cluster + { + if (curves.Count == 1) //If only one curve in cluster, simply add it + { + ICurve outline = curves.First(); + double outlineArea = outline.IArea(); + centroid += (outline.ICentroid() * outlineArea); + area += outlineArea; + } + else + { + foreach (ICurve outline in curves.BooleanUnion(tolerance)) //More than one curve in cluster, run BooleanUnion + { + double outlineArea = outline.IArea(); + centroid += (outline.ICentroid() * outlineArea); + area += outlineArea; + } + } + } + } + + return centroid; + } + + /***************************************************/ } } From 6fc314264f28f864c4c41394fa4c33ba0888f346 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 10:19:43 +0200 Subject: [PATCH 08/17] Update creation of PlanarSurface to try to get curves of IBoundary --- Geometry_Engine/Create/PlanarSurface.cs | 86 ++++++++++++++++++++----- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/Geometry_Engine/Create/PlanarSurface.cs b/Geometry_Engine/Create/PlanarSurface.cs index 4a60e09be..c33e4eb22 100644 --- a/Geometry_Engine/Create/PlanarSurface.cs +++ b/Geometry_Engine/Create/PlanarSurface.cs @@ -151,7 +151,10 @@ public static PlanarSurface PlanarSurface(ICurve externalBoundary, List { Base.Compute.RecordWarning("At least one of the internalBoundaries is not contained by the externalBoundary. And have been disregarded."); } - + + externalBoundary = externalBoundary.TryGetBoundaryCurve(tolerance); + internalBoundaries = internalBoundaries.Select(x => x.TryGetBoundaryCurve(tolerance)).ToList(); + //------------------Return-Valid-Surface------------------------// return new PlanarSurface(externalBoundary, internalBoundaries); } @@ -169,6 +172,37 @@ public static List PlanarSurface(List boundaryCurves, dou return null; } + List checkedCurves = boundaryCurves.ValidateCurves(tolerance); + + + if (checkedCurves.Count == 0) + { + Base.Compute.RecordError("Planar surface could not be created because all input boundary curves are invalid (null, unsupported type, non-planar, not closed within the tolerance)."); + return new List(); + } + + List> distributed = Compute.DistributeOutlines(checkedCurves, tolerance); + + List surfaces = new List(); + for (int i = 0; i < distributed.Count; i++) + { + PlanarSurface srf = new PlanarSurface( + distributed[i][0], + distributed[i].Skip(1).ToList() + ); + + surfaces.Add(srf); + } + + return surfaces; + } + + /***************************************************/ + /**** Private Methods ****/ + /***************************************************/ + + private static List ValidateCurves(this List boundaryCurves, double tolerance) + { //--------------Null-Boundary-Curves-----------------------// int count = boundaryCurves.Count; List checkedCurves = boundaryCurves.Where(x => x != null).ToList(); @@ -193,28 +227,48 @@ public static List PlanarSurface(List boundaryCurves, dou if (checkedCurves.Count != count) Base.Compute.RecordWarning("Some of the input boundary curves were not closed within the tolerance and have been ignored on planar surface creation. Please make sure if the output is correct and tweak the input tolerance if needed."); - if (checkedCurves.Count == 0) + + //--------------Self-intersecting-Boundary-Curves-----------------------// + count = checkedCurves.Count; + checkedCurves = checkedCurves.Where(x => !x.IIsSelfIntersecting(tolerance)).ToList(); + if (checkedCurves.Count != count) + Base.Compute.RecordWarning("Some of the input boundary curves were self-intersecting within the tolerance and have been ignored on planar surface creation. Please make sure if the output is correct and tweak the input tolerance if needed."); + + + return checkedCurves.Select(x => x.TryGetBoundaryCurve(tolerance)).ToList(); + } + + /***************************************************/ + + private static ICurve TryGetBoundaryCurve(this ICurve curve, double tolerance) + { + if (curve is IBoundary) { - Base.Compute.RecordError("Planar surface could not be created because all input boundary curves are invalid (null, unsupported type, non-planar, not closed within the tolerance)."); - return new List(); + return curve; } + else if (curve is PolyCurve) + { + List subParts = curve.ISubParts().ToList(); + if (subParts.Any(x => x is NurbsCurve)) + return curve; - List> distributed = Compute.DistributeOutlines(checkedCurves, tolerance); + if (subParts.Count == 1) + return TryGetBoundaryCurve(subParts[0], tolerance); - List surfaces = new List(); - for (int i = 0; i < distributed.Count; i++) + return new BoundaryCurve(Compute.IJoin(subParts, tolerance).First().Curves); + } + else if (curve is Polyline) { - PlanarSurface srf = new PlanarSurface( - distributed[i][0], - distributed[i].Skip(1).ToList() - ); - - surfaces.Add(srf); + Polyline pLine = curve as Polyline; + return new Polygon(pLine.ControlPoints.GetRange(0, pLine.ControlPoints.Count - 1)); } - - return surfaces; + else + { + return curve; + } + } - + /***************************************************/ } } From 013dda34111c43337d3643bdf3d389612f732283 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 15:18:39 +0200 Subject: [PATCH 09/17] Minor tweak to TryGetBoundaryCurve --- Geometry_Engine/Create/PlanarSurface.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Geometry_Engine/Create/PlanarSurface.cs b/Geometry_Engine/Create/PlanarSurface.cs index c33e4eb22..cfa364be2 100644 --- a/Geometry_Engine/Create/PlanarSurface.cs +++ b/Geometry_Engine/Create/PlanarSurface.cs @@ -240,6 +240,7 @@ private static List ValidateCurves(this List boundaryCurves, dou /***************************************************/ + [Description("Try get out the curve as suitable type of IBoundary curve. Method assumes curves to have been pre-checked for validity (Closed, planar, non-self intersecting)")] private static ICurve TryGetBoundaryCurve(this ICurve curve, double tolerance) { if (curve is IBoundary) @@ -248,6 +249,10 @@ private static ICurve TryGetBoundaryCurve(this ICurve curve, double tolerance) } else if (curve is PolyCurve) { + PolyCurve pCurve = curve as PolyCurve; + if (pCurve.Curves.Count == 1) + return TryGetBoundaryCurve(pCurve.Curves[0], tolerance); + List subParts = curve.ISubParts().ToList(); if (subParts.Any(x => x is NurbsCurve)) return curve; From 633e70f2f37dc9e897ad5597343733a3b2a9fa5b Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 16:18:40 +0200 Subject: [PATCH 10/17] ControlPoints descriptions --- Geometry_Engine/Query/ControlPoints.cs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Geometry_Engine/Query/ControlPoints.cs b/Geometry_Engine/Query/ControlPoints.cs index 61bafe0e8..cff45de56 100644 --- a/Geometry_Engine/Query/ControlPoints.cs +++ b/Geometry_Engine/Query/ControlPoints.cs @@ -35,6 +35,9 @@ public static partial class Query /**** Public Methods - Curves ****/ /***************************************************/ + [Description("Gets points at start, quarter, mid thre quarters and end points on the Arc.")] + [Input("curve", "The Arc to get control points from.")] + [Output("pts", "Points at start, quarter, mid, three quarters and end along the Arc.")] public static List ControlPoints(this Arc curve) { //TODO: Should this give back the control points of an arc in nurbs form? @@ -43,6 +46,9 @@ public static List ControlPoints(this Arc curve) /***************************************************/ + [Description("Gets points at start, quarter, mid thre quarters and end points on the Circle.")] + [Input("curve", "The Circle to get control points from.")] + [Output("pts", "Points at start, quarter, mid, three quarters and end along the Circle.")] public static List ControlPoints(this Circle curve) { //TODO: Should this give back the control points of a circle in nurbs form? @@ -51,6 +57,9 @@ public static List ControlPoints(this Circle curve) /***************************************************/ + [Description("Gets points at the vertices and co-vertices of the Ellipse.")] + [Input("curve", "The Ellipse to get control points from.")] + [Output("pts", "Points at the vertices and co-vertices of the Ellipse.")] public static List ControlPoints(this Ellipse curve) { //TODO: Should this give back the control points of a circle in nurbs form? @@ -66,6 +75,9 @@ public static List ControlPoints(this Ellipse curve) /***************************************************/ + [Description("Gets the start and end points of the Line.")] + [Input("curve", "The Line to get control points from.")] + [Output("pts", "The start and end points of the Line.")] public static List ControlPoints(this Line curve) { return new List { curve.Start, curve.End }; @@ -73,6 +85,9 @@ public static List ControlPoints(this Line curve) /***************************************************/ + [Description("Gets the ControlPoints of the NurbsCurve. Note that these points might not be on the curve.")] + [Input("curve", "The NurbsCurve to get control points from.")] + [Output("pts", "The ControlPoints of the NurbsCurve.")] public static List ControlPoints(this NurbsCurve curve) { return curve.ControlPoints; @@ -80,6 +95,9 @@ public static List ControlPoints(this NurbsCurve curve) /***************************************************/ + [Description("Gets the ControlPoints of the PolyCurve as the ControlPoints of all of its inner curves.")] + [Input("curve", "The PolyCurve to get control points from.")] + [Output("pts", "The ControlPoints of the PolyCurve.")] public static List ControlPoints(this PolyCurve curve) { return curve.Curves.SelectMany((x, i) => x.IControlPoints().Skip((i > 0) ? 1 : 0)).ToList(); @@ -87,6 +105,9 @@ public static List ControlPoints(this PolyCurve curve) /***************************************************/ + [Description("Gets the ControlPoints of the Polyline.")] + [Input("curve", "The Polyline to get control points from.")] + [Output("pts", "The ControlPoints of the Polyline.")] public static List ControlPoints(this Polyline curve) { return curve.ControlPoints; @@ -108,6 +129,9 @@ public static List ControlPoints(this Polygon curve) /**** Public Methods - Interfaces ****/ /***************************************************/ + [Description("Gets the ControlPoints of the ICurve. Result will depend on the curve provided. Note that for NurbsCurves might not returns curves that are on the curve.")] + [Input("curve", "The ICurve to get control points from.")] + [Output("pts", "The ControlPoints of the ICurve.")] public static List IControlPoints(this ICurve curve) { return ControlPoints(curve as dynamic); From fc56a5df18cf0793b4bbcffcaccd823ef161bd93 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 16:31:41 +0200 Subject: [PATCH 11/17] Adding desciptions for Discontinuity points Also, adding method for Ellipse returning empty list --- Geometry_Engine/Query/DiscontinuityPoints.cs | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Geometry_Engine/Query/DiscontinuityPoints.cs b/Geometry_Engine/Query/DiscontinuityPoints.cs index 1be61ebe0..4ba3722b0 100644 --- a/Geometry_Engine/Query/DiscontinuityPoints.cs +++ b/Geometry_Engine/Query/DiscontinuityPoints.cs @@ -25,6 +25,8 @@ using System.Linq; using System; using BH.oM.Base.Attributes; +using System.ComponentModel; +using BH.oM.Quantities.Attributes; namespace BH.Engine.Geometry { @@ -34,6 +36,11 @@ public static partial class Query /**** Public Methods - Curves ****/ /***************************************************/ + [Description("Gets the points at kinks of the curve. For an Arc this is the start and end points.")] + [Input("curve", "The Arc to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points. Not used for Arcs.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points. Not used for Arcs.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this Arc curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { return new List { curve.StartPoint(), curve.EndPoint() }; @@ -41,6 +48,11 @@ public static List DiscontinuityPoints(this Arc curve, double distanceTol /***************************************************/ + [Description("Gets the points at kinks of the curve. A Circle does not have any discontinuity points, why this method is returning an empty list.")] + [Input("curve", "The Circle to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points. Not used for Circle.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points. Not used for Circle.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this Circle curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { return new List(); @@ -48,6 +60,23 @@ public static List DiscontinuityPoints(this Circle curve, double distance /***************************************************/ + [Description("Gets the points at kinks of the curve. An Ellipse does not have any discontinuity points, why this method is returning an empty list.")] + [Input("curve", "The Ellipse to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points. Not used for Ellipse.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points. Not used for Ellipse.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] + public static List DiscontinuityPoints(this Ellipse curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) + { + return new List(); + } + + /***************************************************/ + + [Description("Gets the points at kinks of the curve. For an Line this is the start and end points.")] + [Input("curve", "The Line to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points. Not used for Line.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points. Not used for Line.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this Line curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { return new List { curve.Start, curve.End }; @@ -56,6 +85,11 @@ public static List DiscontinuityPoints(this Line curve, double distanceTo /***************************************************/ [PreviousVersion("5.2", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.PolyCurve, System.Double, System.Double)")] + [Description("Gets the points at kinks of the curve, i.e. Points where the tangent between two sub curves coming in to the same point is outside of the provided tolerance.")] + [Input("curve", "The IPolyCurve to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points. Not used for IPolyCurve.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this IPolyCurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { List result = new List(); @@ -87,6 +121,11 @@ public static List DiscontinuityPoints(this IPolyCurve curve, double dist /***************************************************/ [PreviousVersion("5.2", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.Polyline, System.Double, System.Double)")] + [Description("Gets the points at kinks of the curve, i.e. points where the tangent between two segments coming in to the same point is outside of the provided tolerance.")] + [Input("curve", "The IPolyline to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this IPolyline curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { List ctrlPts = new List(curve.IControlPoints()); @@ -123,6 +162,11 @@ public static List DiscontinuityPoints(this IPolyline curve, double dista /**** Public Methods - Interfaces ****/ /***************************************************/ + [Description("Gets the points at kinks of the curve, i.e. points where the tangent between two segments coming in to the same point is outside of the provided tolerance.")] + [Input("curve", "The IPolyline to get the discontinuity points from.")] + [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points.", typeof(Length))] + [Input("angleTolerance", "Angle tolerance for extracting discontinuity points.", typeof(Length))] + [Output("discPoints", "The list of discontinuity points.")] public static List IDiscontinuityPoints(this ICurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { return DiscontinuityPoints(curve as dynamic, distanceTolerance, angleTolerance); From 01f3335e8cf4d987f9b61acbe9b33dbd865e521e Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 17:04:05 +0200 Subject: [PATCH 12/17] IsCLockwise descriptions --- Geometry_Engine/Query/IsClockwise.cs | 43 +++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/Geometry_Engine/Query/IsClockwise.cs b/Geometry_Engine/Query/IsClockwise.cs index 6641c858d..824d50fbb 100644 --- a/Geometry_Engine/Query/IsClockwise.cs +++ b/Geometry_Engine/Query/IsClockwise.cs @@ -24,7 +24,9 @@ using System.Linq; using System.Collections.Generic; using System; +using System.ComponentModel; using BH.oM.Base.Attributes; +using BH.oM.Quantities.Attributes; using BH.Engine.Base; namespace BH.Engine.Geometry @@ -36,6 +38,11 @@ public static partial class Query /***************************************************/ [PreviousVersion("5.2", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.Polyline, BH.oM.Geometry.Vector, System.Double)")] + [Description("Checks if the segments of the IPolyline are defined in a clockwise order around the provided normal vector. Curve needs to be closed for the method to function.")] + [Input("polyline", "The closed IPolyline to check if it is defined in a clockwise manner in relation to the Vector.")] + [Input("normal", "The normal vector to check against.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the IPolyline is defined clockwise around the provided normal.")] public static bool IsClockwise(this IPolyline polyline, Vector normal, double tolerance = Tolerance.Distance) { if (!polyline.IIsClosed(tolerance)) @@ -67,6 +74,11 @@ public static bool IsClockwise(this IPolyline polyline, Vector normal, double to /***************************************************/ [PreviousVersion("5.2", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.PolyCurve, BH.oM.Geometry.Vector, System.Double)")] + [Description("Checks if the segments of the IPolyCurve are defined in a clockwise order around the provided normal vector. Curve needs to be closed for the method to function.")] + [Input("curve", "The closed IPolyCurve to check if it is defined in a clockwise manner in relation to the Vector.")] + [Input("normal", "The normal vector to check against.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the IPolyCurve is defined clockwise around the provided normal.")] public static bool IsClockwise(this IPolyCurve curve, Vector normal, double tolerance = Tolerance.Distance) { if (!curve.IIsClosed(tolerance)) @@ -100,6 +112,13 @@ public static bool IsClockwise(this IPolyCurve curve, Vector normal, double tole /***************************************************/ + [Description("Checks if the segments of the Polyline are defined in a clockwise if inspected from the provided view point.\n" + + "This is done by projecting the point to the plane of the curve and creating a normal vector from the view point to the projected point. The segments of the Polyline are then checked if they are defined clockwise around this vector.\n" + + "Curve needs to be closed and the point needs to be outside the plane of the curve for the method to function.")] + [Input("polyline", "The closed Polyline to check if it is defined in a clockwise manner in relation to the view Point.")] + [Input("viewPoint", "The the point from where the the curve is to be checked. Requires the curve to not be in the plane of the curve.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the Polyline is defined clockwise when inspected from the provided viewpoint.")] public static bool IsClockwise(this Polyline polyline, Point viewPoint, double tolerance = Tolerance.Distance) { Plane plane = polyline.FitPlane(tolerance); @@ -111,6 +130,13 @@ public static bool IsClockwise(this Polyline polyline, Point viewPoint, double t /***************************************************/ + [Description("Checks if the segments of the PolyCurve are defined in a clockwise if inspected from the provided view point.\n" + + "This is done by projecting the point to the plane of the curve and creating a normal vector from the view point to the projected point. The segments of the PolyCurve are then checked if they are defined clockwise around this vector.\n" + + "Curve needs to be closed and the point needs to be outside the plane of the curve for the method to function.")] + [Input("polyline", "The closed PolyCurve to check if it is defined in a clockwise manner in relation to the view Point.")] + [Input("viewPoint", "The the point from where the the curve is to be checked. Requires the curve to not be in the plane of the curve.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the PolyCurve is defined clockwise when inspected from the provided viewpoint.")] public static bool IsClockwise(this PolyCurve curve, Point viewPoint, double tolerance = Tolerance.Distance) { Plane plane = curve.FitPlane(tolerance); @@ -120,8 +146,13 @@ public static bool IsClockwise(this PolyCurve curve, Point viewPoint, double tol return IsClockwise(curve, vector); } - /***************************************************/ + /***************************************************/ + [Description("Checks if the Arc is defined in a clockwise order around the provided axis Vector.")] + [Input("curve", "The Arc to check if it is defined in a clockwise manner in relation to the Vector.")] + [Input("axis", "The axis vector to check against.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the Arc is defined clockwise around the provided axis.")] public static bool IsClockwise(this Arc arc, Vector axis, double tolerance = Tolerance.Distance) { Vector normal = arc.CoordinateSystem.Z; @@ -130,6 +161,11 @@ public static bool IsClockwise(this Arc arc, Vector axis, double tolerance = Tol /***************************************************/ + [Description("Checks if the Circle is defined in a clockwise order around the provided axis Vector.")] + [Input("curve", "The Circle to check if it is defined in a clockwise manner in relation to the Vector.")] + [Input("axis", "The axis vector to check against.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the Circle is defined clockwise around the provided axis.")] public static bool IsClockwise(this Circle curve, Vector axis, double tolerance = Tolerance.Distance) { return axis.DotProduct(curve.Normal()) > 0; @@ -139,6 +175,11 @@ public static bool IsClockwise(this Circle curve, Vector axis, double tolerance /**** Public Methods - Interfaces ****/ /***************************************************/ + [Description("Checks if the ICurve is defined in a clockwise order around the provided axis Vector.")] + [Input("curve", "The ICurve to check if it is defined in a clockwise manner in relation to the Vector.")] + [Input("axis", "The axis vector to check against.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] + [Output("isClockwise", "Returns true if the ICurve is defined clockwise around the provided axis.")] public static bool IIsClockwise(this ICurve curve, Vector axis, double tolerance = Tolerance.Distance) { return IsClockwise(curve as dynamic, axis, tolerance); From 7ab3fa6c56aa4376dfc73c7721a3796d69156482 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 17:10:03 +0200 Subject: [PATCH 13/17] Minor description updates --- Geometry_Engine/Create/PlanarSurface.cs | 5 ++++- Geometry_Engine/Query/Centroid.cs | 17 +++++++++-------- Geometry_Engine/Query/Vertices.cs | 4 ++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Geometry_Engine/Create/PlanarSurface.cs b/Geometry_Engine/Create/PlanarSurface.cs index cfa364be2..795b66c34 100644 --- a/Geometry_Engine/Create/PlanarSurface.cs +++ b/Geometry_Engine/Create/PlanarSurface.cs @@ -26,6 +26,7 @@ using System.ComponentModel; using BH.oM.Base.Attributes; using BH.oM.Geometry; +using BH.oM.Quantities.Attributes; namespace BH.Engine.Geometry { @@ -38,6 +39,7 @@ public static partial class Create [Description("Creates a PlanarSurface based on boundary curves. Only processing done by this method is checking (co)planarity and that the curves are closed. Internal edges will be assumed to be inside the External.")] [Input("externalBoundary", "The outer boundary curve of the surface. Needs to be closed and planar.")] [Input("internalBoundaries", "Optional internal boundary curves descibing any openings inside the external. All internal edges need to be closed and co-planar with the external edge.")] + [Input("tolerance", "Distance tolerance used for checking the validity of the inputs for PlanarSurface creation.", typeof(Length))] [Output("PlanarSurface", "Planar surface corresponding to the provided edge curves.")] public static PlanarSurface PlanarSurface(ICurve externalBoundary, List internalBoundaries = null, double tolerance = Tolerance.Distance) { @@ -163,6 +165,7 @@ public static PlanarSurface PlanarSurface(ICurve externalBoundary, List [Description("Distributes the edge curve and creates a set of boundary planar surfaces.")] [Input("boundaryCurves", "Boundary curves to be used. Non-planar and non-closed curves are ignored.")] + [Input("tolerance", "Distance tolerance used for checking the validity of the inputs for PlanarSurface creation.", typeof(Length))] [Output("PlanarSurface", "List of planar surfaces created.")] public static List PlanarSurface(List boundaryCurves, double tolerance = Tolerance.Distance) { @@ -240,7 +243,7 @@ private static List ValidateCurves(this List boundaryCurves, dou /***************************************************/ - [Description("Try get out the curve as suitable type of IBoundary curve. Method assumes curves to have been pre-checked for validity (Closed, planar, non-self intersecting)")] + [Description("Try get out the curve as suitable type of IBoundary curve. Method assumes curves to have been pre-checked for validity (Closed, planar, non-self intersecting).")] private static ICurve TryGetBoundaryCurve(this ICurve curve, double tolerance) { if (curve is IBoundary) diff --git a/Geometry_Engine/Query/Centroid.cs b/Geometry_Engine/Query/Centroid.cs index 75d479b53..4546025c5 100644 --- a/Geometry_Engine/Query/Centroid.cs +++ b/Geometry_Engine/Query/Centroid.cs @@ -28,6 +28,7 @@ using BH.oM.Base.Attributes; using BH.oM.Base; using System.ComponentModel; +using BH.oM.Quantities.Attributes; namespace BH.Engine.Geometry { @@ -39,7 +40,7 @@ public static partial class Query [Description("Queries the centre of area for a PlanarSurface.")] [Input("surface", "The PlanarSurface to get the centre of area of.")] - [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance")] + [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance.", typeof(Length))] [Output("centroid", "The Point at the centre of given PlanarSurface.")] public static Point Centroid(this PlanarSurface surface, double tolerance = Tolerance.Distance) { @@ -54,7 +55,7 @@ public static Point Centroid(this PlanarSurface surface, double tolerance = Tole [Description("Queries the combined centre of area enclosed by a set of ICurves with an optional set of openings.\nTo give a correct result all input curves must be planar, coplanar, closed and non-self-intersecting.\nOpening curves should also be inside of outline curves.")] [Input("outlines", "Set of planar, coplanar, closed and non-self-intersecting ICurves to get the combined centre of area of.")] [Input("openings", "Set of planar, coplanar, closed and non-self-intersecting ICurves illustrating openings in initial set of outlines.")] - [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance")] + [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance.", typeof(Length))] [Output("centroid", "The Point at the centre of given geometry.")] public static Point Centroid(this IEnumerable outlines, IEnumerable openings = null, double tolerance = Tolerance.Distance) { @@ -84,7 +85,7 @@ public static Point Centroid(this IEnumerable outlines, IEnumerable Vertices(this Polyline pLine, double tolerance = Tolerance.Distance) { @@ -75,6 +77,7 @@ public static List Vertices(this Polyline pLine, double tolerance = Toler [Description("Returns the Vertices of the Polygon.")] [Input("pGon", "The Polygon to extract the Vertices from.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] [Output("vertices", "Vertices of the Polyline.")] public static List Vertices(this Polygon pGon, double tolerance = Tolerance.Distance) { @@ -87,6 +90,7 @@ public static List Vertices(this Polygon pGon, double tolerance = Toleran [Description("Returns the Vertices of the IPolyline if it is closed. Undefined for open IPolylines.")] [Input("pline", "The IPolyline to extract the Vertices from.")] + [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] [Output("vertices", "Vertices of the IPolyline.")] public static List IVertices(this IPolyline pline, double tolerance = Tolerance.Distance) { From af0391af726603140816fbff0c270e1e09b87005 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Fri, 27 May 2022 17:16:44 +0200 Subject: [PATCH 14/17] fix input wrong name --- Geometry_Engine/Query/IsClockwise.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Geometry_Engine/Query/IsClockwise.cs b/Geometry_Engine/Query/IsClockwise.cs index 824d50fbb..b52fe9c16 100644 --- a/Geometry_Engine/Query/IsClockwise.cs +++ b/Geometry_Engine/Query/IsClockwise.cs @@ -133,7 +133,7 @@ public static bool IsClockwise(this Polyline polyline, Point viewPoint, double t [Description("Checks if the segments of the PolyCurve are defined in a clockwise if inspected from the provided view point.\n" + "This is done by projecting the point to the plane of the curve and creating a normal vector from the view point to the projected point. The segments of the PolyCurve are then checked if they are defined clockwise around this vector.\n" + "Curve needs to be closed and the point needs to be outside the plane of the curve for the method to function.")] - [Input("polyline", "The closed PolyCurve to check if it is defined in a clockwise manner in relation to the view Point.")] + [Input("curve", "The closed PolyCurve to check if it is defined in a clockwise manner in relation to the view Point.")] [Input("viewPoint", "The the point from where the the curve is to be checked. Requires the curve to not be in the plane of the curve.")] [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] [Output("isClockwise", "Returns true if the PolyCurve is defined clockwise when inspected from the provided viewpoint.")] @@ -149,7 +149,7 @@ public static bool IsClockwise(this PolyCurve curve, Point viewPoint, double tol /***************************************************/ [Description("Checks if the Arc is defined in a clockwise order around the provided axis Vector.")] - [Input("curve", "The Arc to check if it is defined in a clockwise manner in relation to the Vector.")] + [Input("arc", "The Arc to check if it is defined in a clockwise manner in relation to the Vector.")] [Input("axis", "The axis vector to check against.")] [Input("tolerance", "Distance tolerance to be used in the method.", typeof(Length))] [Output("isClockwise", "Returns true if the Arc is defined clockwise around the provided axis.")] From 6997d847e71e371866d2956f27edc185a7fc6750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isak=20N=C3=A4slund?= Date: Mon, 30 May 2022 10:34:52 +0200 Subject: [PATCH 15/17] Update Geometry_Engine/Create/BoundaryCurve.cs Co-authored-by: Alessio Lombardi --- Geometry_Engine/Create/BoundaryCurve.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Geometry_Engine/Create/BoundaryCurve.cs b/Geometry_Engine/Create/BoundaryCurve.cs index 8ad503a14..409c7e6da 100644 --- a/Geometry_Engine/Create/BoundaryCurve.cs +++ b/Geometry_Engine/Create/BoundaryCurve.cs @@ -55,7 +55,7 @@ public static BoundaryCurve BoundaryCurve(List curves, double tolerance if (subParts.Any(x => x is NurbsCurve)) { - Engine.Base.Compute.RecordError("Input curves contaisn NubrsCurves which cannot be validated. BoundaryCurve not created."); + Engine.Base.Compute.RecordError("Input curves include NurbsCurves whose validation is not supported. BoundaryCurve not created."); return null; } From a6abd33f0499fe821bbcbdbacaba343d8d27d933 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 30 May 2022 11:39:43 +0200 Subject: [PATCH 16/17] null handling --- Geometry_Engine/Query/Centroid.cs | 12 +++++++ Geometry_Engine/Query/ControlPoints.cs | 5 +++ Geometry_Engine/Query/DiscontinuityPoints.cs | 25 ++++++++++++++ Geometry_Engine/Query/IsClockwise.cs | 23 +++++++++++++ Geometry_Engine/Query/Normal.cs | 35 ++++++++++++++++++++ Geometry_Engine/Query/Vertices.cs | 15 +++++++++ 6 files changed, 115 insertions(+) diff --git a/Geometry_Engine/Query/Centroid.cs b/Geometry_Engine/Query/Centroid.cs index 4546025c5..280e1af0d 100644 --- a/Geometry_Engine/Query/Centroid.cs +++ b/Geometry_Engine/Query/Centroid.cs @@ -89,6 +89,12 @@ public static Point Centroid(this IEnumerable outlines, IEnumerable ControlPoints(this Polyline curve) [Output("points", "The controlpoints of the Polygon. The first and last point will be the same.")] public static List ControlPoints(this Polygon curve) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot extract control points from a null curve."); + return new List(); + } List controlPoints = curve.Vertices.ToList(); controlPoints.Add(controlPoints[0]); return controlPoints; diff --git a/Geometry_Engine/Query/DiscontinuityPoints.cs b/Geometry_Engine/Query/DiscontinuityPoints.cs index 4ba3722b0..58ea8f63c 100644 --- a/Geometry_Engine/Query/DiscontinuityPoints.cs +++ b/Geometry_Engine/Query/DiscontinuityPoints.cs @@ -43,6 +43,11 @@ public static partial class Query [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this Arc curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Input curve is null. Discontinuity points can not be evaluated."); + return new List(); + } return new List { curve.StartPoint(), curve.EndPoint() }; } @@ -79,6 +84,11 @@ public static List DiscontinuityPoints(this Ellipse curve, double distanc [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this Line curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Input curve is null. Discontinuity points can not be evaluated."); + return new List(); + } return new List { curve.Start, curve.End }; } @@ -92,6 +102,11 @@ public static List DiscontinuityPoints(this Line curve, double distanceTo [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this IPolyCurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Input curve is null. Discontinuity points can not be evaluated."); + return new List(); + } List result = new List(); List curves = curve.ISubParts().Where(c => !(c is Circle || c is Ellipse)).ToList(); bool closed = curve.IIsClosed(distanceTolerance); @@ -128,6 +143,11 @@ public static List DiscontinuityPoints(this IPolyCurve curve, double dist [Output("discPoints", "The list of discontinuity points.")] public static List DiscontinuityPoints(this IPolyline curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Input curve is null. Discontinuity points can not be evaluated."); + return new List(); + } List ctrlPts = new List(curve.IControlPoints()); if (ctrlPts.Count < 3) @@ -169,6 +189,11 @@ public static List DiscontinuityPoints(this IPolyline curve, double dista [Output("discPoints", "The list of discontinuity points.")] public static List IDiscontinuityPoints(this ICurve curve, double distanceTolerance = Tolerance.Distance, double angleTolerance = Tolerance.Angle) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Input curve is null. Discontinuity points can not be evaluated."); + return new List(); + } return DiscontinuityPoints(curve as dynamic, distanceTolerance, angleTolerance); } diff --git a/Geometry_Engine/Query/IsClockwise.cs b/Geometry_Engine/Query/IsClockwise.cs index b52fe9c16..499c8f491 100644 --- a/Geometry_Engine/Query/IsClockwise.cs +++ b/Geometry_Engine/Query/IsClockwise.cs @@ -45,6 +45,17 @@ public static partial class Query [Output("isClockwise", "Returns true if the IPolyline is defined clockwise around the provided normal.")] public static bool IsClockwise(this IPolyline polyline, Vector normal, double tolerance = Tolerance.Distance) { + if (polyline == null) + { + Engine.Base.Compute.RecordError("Cannot evaluate IsClockwise for a null curve. False returned."); + return false; + } + if (normal == null) + { + Engine.Base.Compute.RecordError("Cannot evaluate if a curve is clockwise around a null normal vector. False returned."); + return false; + } + if (!polyline.IIsClosed(tolerance)) throw new Exception("The polyline is not closed. IsClockwise method is relevant only to closed curves."); @@ -81,6 +92,18 @@ public static bool IsClockwise(this IPolyline polyline, Vector normal, double to [Output("isClockwise", "Returns true if the IPolyCurve is defined clockwise around the provided normal.")] public static bool IsClockwise(this IPolyCurve curve, Vector normal, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot evaluate IsClockwise for a null curve. False returned."); + return false; + } + if (normal == null) + { + Engine.Base.Compute.RecordError("Cannot evaluate if a curve is clockwise around a null normal vector. False returned."); + return false; + } + + if (!curve.IIsClosed(tolerance)) throw new Exception("The curve is not closed. IsClockwise method is relevant only to closed curves."); diff --git a/Geometry_Engine/Query/Normal.cs b/Geometry_Engine/Query/Normal.cs index 755881fc5..c03cdc292 100644 --- a/Geometry_Engine/Query/Normal.cs +++ b/Geometry_Engine/Query/Normal.cs @@ -114,6 +114,11 @@ public static List Normals(this Mesh3D mesh) [Output("normal", "Vector normal to the plane of a curve.")] public static Vector Normal(this IPolyline curve, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null curve."); + return null; + } if (!curve.IIsPlanar(tolerance)) { Base.Compute.RecordError("A single normal vector is not unambiguously definable for non-planar curves."); @@ -161,6 +166,11 @@ public static Vector Normal(this IPolyline curve, double tolerance = Tolerance.D [Output("normal", "Vector normal to the plane of a curve.")] public static Vector Normal(this IPolyCurve curve, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null curve."); + return null; + } List crvs = new List(curve.ISubParts()); if (crvs.Any(x => x is NurbsCurve)) { @@ -234,6 +244,11 @@ public static Vector Normal(this IPolyCurve curve, double tolerance = Tolerance. [Output("normal", "Vector normal to the plane of a curve.")] public static Vector Normal(this Circle curve, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null curve."); + return null; + } return curve.Normal; } @@ -245,6 +260,11 @@ public static Vector Normal(this Circle curve, double tolerance = Tolerance.Dist [Output("normal", "Vector normal to the plane of a curve.")] public static Vector Normal(this Ellipse curve, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null curve."); + return null; + } Vector normal = (curve.Axis1).CrossProduct(curve.Axis2); return normal; } @@ -257,6 +277,11 @@ public static Vector Normal(this Ellipse curve, double tolerance = Tolerance.Dis [Output("normal", "Vector normal to the plane of a curve.")] public static Vector Normal(this Arc curve, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null curve."); + return null; + } if (curve.Angle() > 0) return curve.CoordinateSystem.Z; else @@ -273,6 +298,11 @@ public static Vector Normal(this Arc curve, double tolerance = Tolerance.Distanc [Output("normal", "Vector normal to the surface.")] public static Vector Normal(this PlanarSurface surface) { + if (surface == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null surface."); + return null; + } return surface.ExternalBoundary.INormal(); } @@ -287,6 +317,11 @@ public static Vector Normal(this PlanarSurface surface) [Output("normal", "Vector normal to the plane of a curve.")] public static Vector INormal(this ICurve curve, double tolerance = Tolerance.Distance) { + if (curve == null) + { + Engine.Base.Compute.RecordError("Cannot compute the normal of a null curve."); + return null; + } return Normal(curve as dynamic, tolerance); } diff --git a/Geometry_Engine/Query/Vertices.cs b/Geometry_Engine/Query/Vertices.cs index 7d8e22c8d..01666ab1e 100644 --- a/Geometry_Engine/Query/Vertices.cs +++ b/Geometry_Engine/Query/Vertices.cs @@ -64,6 +64,11 @@ public static int[] Vertices(this Face face) [Output("vertices", "Vertices of the Polyline.")] public static List Vertices(this Polyline pLine, double tolerance = Tolerance.Distance) { + if (pLine == null) + { + Engine.Base.Compute.RecordError("Cannot get vertices from a null curve."); + return new List(); + } if (!pLine.IsClosed(tolerance)) { Base.Compute.RecordError("Input curve is not closed. Verticies not defined."); @@ -81,6 +86,11 @@ public static List Vertices(this Polyline pLine, double tolerance = Toler [Output("vertices", "Vertices of the Polyline.")] public static List Vertices(this Polygon pGon, double tolerance = Tolerance.Distance) { + if (pGon == null) + { + Engine.Base.Compute.RecordError("Cannot get vertices from a null curve."); + return new List(); + } return pGon.Vertices.ToList(); } @@ -94,6 +104,11 @@ public static List Vertices(this Polygon pGon, double tolerance = Toleran [Output("vertices", "Vertices of the IPolyline.")] public static List IVertices(this IPolyline pline, double tolerance = Tolerance.Distance) { + if (pline == null) + { + Engine.Base.Compute.RecordError("Cannot get vertices from a null curve."); + return new List(); + } return Vertices(pline as dynamic, tolerance); } From 78964479d5d5936172f37739546e17052a334591 Mon Sep 17 00:00:00 2001 From: Isak Naslund Date: Mon, 26 Sep 2022 09:46:16 +0200 Subject: [PATCH 17/17] Updating previous version attributes --- Geometry_Engine/Query/Area.cs | 8 ++------ Geometry_Engine/Query/Centroid.cs | 4 ++-- Geometry_Engine/Query/DiscontinuityPoints.cs | 4 ++-- Geometry_Engine/Query/IsClockwise.cs | 4 ++-- Geometry_Engine/Query/Normal.cs | 4 ++-- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Geometry_Engine/Query/Area.cs b/Geometry_Engine/Query/Area.cs index 615574354..41af5152d 100644 --- a/Geometry_Engine/Query/Area.cs +++ b/Geometry_Engine/Query/Area.cs @@ -127,7 +127,7 @@ public static double Area(this Line curve, double tolerance = Tolerance.Distance /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Area(BH.oM.Geometry.PolyCurve, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.Area(BH.oM.Geometry.PolyCurve, System.Double)")] [Description("Calculates the area of the provided geometry.")] [Input("curve", "The PolyCurve to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] @@ -188,7 +188,7 @@ public static double Area(this IPolyCurve curve, double tolerance = Tolerance.Di /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Area(BH.oM.Geometry.Polyline, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.Area(BH.oM.Geometry.Polyline, System.Double)")] [Description("Calculates the area of the provided geometry.")] [Input("curve", "The Polyline to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] @@ -238,7 +238,6 @@ public static double Area(this IPolyline curve, double tolerance = Tolerance.Dis [Input("mesh", "The mesh to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this Mesh mesh, double tolerance = Tolerance.Distance) { if (mesh == null) @@ -271,7 +270,6 @@ public static double Area(this Mesh mesh, double tolerance = Tolerance.Distance) [Input("pSurf", "The PolySurface to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this PolySurface pSurf, double tolerance = Tolerance.Distance) { if (pSurf == null) @@ -289,7 +287,6 @@ public static double Area(this PolySurface pSurf, double tolerance = Tolerance.D [Input("pSurf", "The PlanarSurface to get the area of.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this PlanarSurface pSurf, double tolerance = Tolerance.Distance) { if (pSurf == null) @@ -318,7 +315,6 @@ public static double Area(this PlanarSurface pSurf, double tolerance = Tolerance [Input("v2", "Second vector to use for vector-based area calculation.")] [Input("tolerance", "The tolerance to apply to the area calculation.")] [Output("area", "The area of the geometry.", typeof(Area))] - public static double Area(this Vector v1, Vector v2, double tolerance = Tolerance.Distance) { if (v2 == null || v2 == null) diff --git a/Geometry_Engine/Query/Centroid.cs b/Geometry_Engine/Query/Centroid.cs index 280e1af0d..868935319 100644 --- a/Geometry_Engine/Query/Centroid.cs +++ b/Geometry_Engine/Query/Centroid.cs @@ -82,7 +82,7 @@ public static Point Centroid(this IEnumerable outlines, IEnumerable DiscontinuityPoints(this Line curve, double distanceTo /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.PolyCurve, System.Double, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.PolyCurve, System.Double, System.Double)")] [Description("Gets the points at kinks of the curve, i.e. Points where the tangent between two sub curves coming in to the same point is outside of the provided tolerance.")] [Input("curve", "The IPolyCurve to get the discontinuity points from.")] [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points.", typeof(Length))] @@ -135,7 +135,7 @@ public static List DiscontinuityPoints(this IPolyCurve curve, double dist /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.Polyline, System.Double, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.DiscontinuityPoints(BH.oM.Geometry.Polyline, System.Double, System.Double)")] [Description("Gets the points at kinks of the curve, i.e. points where the tangent between two segments coming in to the same point is outside of the provided tolerance.")] [Input("curve", "The IPolyline to get the discontinuity points from.")] [Input("distanceTolerance", "Distance tolerance for extracting discontinuity points.", typeof(Length))] diff --git a/Geometry_Engine/Query/IsClockwise.cs b/Geometry_Engine/Query/IsClockwise.cs index 499c8f491..ff6af61fc 100644 --- a/Geometry_Engine/Query/IsClockwise.cs +++ b/Geometry_Engine/Query/IsClockwise.cs @@ -37,7 +37,7 @@ public static partial class Query /**** Public Methods ****/ /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.Polyline, BH.oM.Geometry.Vector, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.Polyline, BH.oM.Geometry.Vector, System.Double)")] [Description("Checks if the segments of the IPolyline are defined in a clockwise order around the provided normal vector. Curve needs to be closed for the method to function.")] [Input("polyline", "The closed IPolyline to check if it is defined in a clockwise manner in relation to the Vector.")] [Input("normal", "The normal vector to check against.")] @@ -84,7 +84,7 @@ public static bool IsClockwise(this IPolyline polyline, Vector normal, double to /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.PolyCurve, BH.oM.Geometry.Vector, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.IsClockwise(BH.oM.Geometry.PolyCurve, BH.oM.Geometry.Vector, System.Double)")] [Description("Checks if the segments of the IPolyCurve are defined in a clockwise order around the provided normal vector. Curve needs to be closed for the method to function.")] [Input("curve", "The closed IPolyCurve to check if it is defined in a clockwise manner in relation to the Vector.")] [Input("normal", "The normal vector to check against.")] diff --git a/Geometry_Engine/Query/Normal.cs b/Geometry_Engine/Query/Normal.cs index c03cdc292..698d998a9 100644 --- a/Geometry_Engine/Query/Normal.cs +++ b/Geometry_Engine/Query/Normal.cs @@ -107,7 +107,7 @@ public static List Normals(this Mesh3D mesh) /**** Public Methods - Curves ****/ /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Normal(BH.oM.Geometry.Polyline, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.Normal(BH.oM.Geometry.Polyline, System.Double)")] [Description("Returns a vector normal to the plane of a given curve, oriented according to the right hand rule. Works only for closed, planar curves.")] [Input("curve", "The Polyline to get the normal to.")] [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance.")] @@ -159,7 +159,7 @@ public static Vector Normal(this IPolyline curve, double tolerance = Tolerance.D /***************************************************/ - [PreviousVersion("5.2", "BH.Engine.Geometry.Query.Normal(BH.oM.Geometry.PolyCurve, System.Double)")] + [PreviousVersion("6.0", "BH.Engine.Geometry.Query.Normal(BH.oM.Geometry.PolyCurve, System.Double)")] [Description("Returns a vector normal to the plane of a given curve, oriented according to the right hand rule. Works only for closed and planar curves.")] [Input("curve", "The PolyCurve to get the normal to.")] [Input("tolerance", "Distance tolerance used in geometry processing, default set to BH.oM.Geometry.Tolerance.Distance.")]