Skip to content

Geometry_Engine: Add controls to external edges for mesh #2957

New issue

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

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

Already on GitHub? Sign in to your account

1 change: 1 addition & 0 deletions .ci/Datasets/Geometry_Engine/Query/ExternalEdges.json

Large diffs are not rendered by default.

64 changes: 53 additions & 11 deletions Geometry_Engine/Query/ExternalEdges.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;

namespace BH.Engine.Geometry
{
Expand All @@ -35,6 +36,7 @@ public static partial class Query
/**** Public Methods - Surfaces ****/
/***************************************************/

[Description("Gets the external edge curves of the Extrusion.")]
public static List<ICurve> ExternalEdges(this Extrusion surface)
{
ICurve curve = surface.Curve;
Expand All @@ -61,13 +63,15 @@ public static List<ICurve> ExternalEdges(this Extrusion surface)

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

[Description("Gets the external edge curves of the Loft as the curves of the Loft.")]
public static List<ICurve> ExternalEdges(this Loft surface)
{
return surface.Curves; //TODO: Is that always correct?
}

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

[Description("Gets the external edge curves of the Pipe. If the Pipe is capped, this returns a circle at each end of the centre curve. If the pipe is uncapped, this method returns an empty list.")]
public static List<ICurve> ExternalEdges(this Pipe surface)
{
if (!surface.Capped)
Expand All @@ -85,13 +89,15 @@ public static List<ICurve> ExternalEdges(this Pipe surface)

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

[Description("Gets the external edge curves of the PlanarSurface as its ExternalBoundary.")]
public static List<ICurve> ExternalEdges(this PlanarSurface surface)
{
return new List<ICurve> { surface.ExternalBoundary };
}

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

[Description("Gets the external edge curves of the PolySurface the external edge curves of all of its parts.")]
public static List<ICurve> ExternalEdges(this PolySurface surface)
{
return surface.Surfaces.SelectMany(x => x.IExternalEdges()).ToList();
Expand All @@ -102,38 +108,74 @@ public static List<ICurve> ExternalEdges(this PolySurface surface)
/**** Public Methods - Mesh ****/
/***************************************************/

public static List<Line> ExternalEdges(this Mesh mesh)
[PreviousVersion("6.0", "BH.Engine.Geometry.Query.ExternalEdges(BH.oM.Geometry.Mesh)")]
[Description("Gets the external edge curves of a mesh as a set of lines. Extraction is done by finding all unique edges in the mesh.")]
[Input("mesh", "The mesh to extract external edge curves from.")]
[Input("filterByTopology", "If true, edges with unique topology are returned. If false, edges with unique geometry is returned. Toggle only renders different result for meshes with duplicate nodes.")]
[Input("tolerance", "Tolerance to be used for identifying duplicate edges. Only used if filterByTopology is false.")]
[Output("edges", "The external edge curves of the mesh.")]
public static List<Line> ExternalEdges(this Mesh mesh, bool filterByTopology = false, double tolerance = Tolerance.Distance)
{
if (mesh == null)
return null;

if (mesh.Faces.Count < 1)
return null;

List<Line> edges = mesh.Faces.SelectMany(f => f.Edges(mesh)).ToList();
if (filterByTopology)
{
List<Tuple<int, int>> allEdgeTopologies = new List<Tuple<int, int>>();

//Creates tuples of indecies of edges of each face, ordering the index order so the lowest number is always first (to simplify grouping lower down)
foreach (Face face in mesh.Faces)
{
allEdgeTopologies.Add(new Tuple<int, int>(Math.Min(face.A, face.B), Math.Max(face.A, face.B)));
allEdgeTopologies.Add(new Tuple<int, int>(Math.Min(face.B, face.C), Math.Max(face.B, face.C)));
if (face.D == -1)
{
allEdgeTopologies.Add(new Tuple<int, int>(Math.Min(face.C, face.A), Math.Max(face.C, face.A)));
}
else
{
allEdgeTopologies.Add(new Tuple<int, int>(Math.Min(face.C, face.D), Math.Max(face.C, face.D)));
allEdgeTopologies.Add(new Tuple<int, int>(Math.Min(face.D, face.A), Math.Max(face.D, face.A)));
}
}

IEnumerable<Tuple<int, int>> unique = allEdgeTopologies.GroupBy(x => x).Where(x => x.Count() == 1).SelectMany(x => x); //Get out instances that are uniqe

for (int i = edges.Count - 1; i > 0; i--)
return unique.Select(x => new Line { Start = mesh.Vertices[x.Item1], End = mesh.Vertices[x.Item2] }).ToList(); //Generate lines based on the unique tuples
}
else
{
for (int n = i - 1; n >= 0; n--)
List<Line> edges = mesh.Faces.SelectMany(f => f.Edges(mesh)).ToList();

double sqTol = tolerance * tolerance;

for (int i = edges.Count - 1; i > 0; i--)
{
if ((edges[i].Start == edges[n].Start & edges[i].End == edges[n].End) | // edge[i] == edge[n]
(edges[i].Start == edges[n].End & edges[i].End == edges[n].Start)) // edge[i] == edge[n].Reverse()
for (int n = i - 1; n >= 0; n--)
{
edges.RemoveAt(i); // shared edge so remove both
edges.RemoveAt(n);
i--;
break;
if ((edges[i].Start.SquareDistance(edges[n].Start) < sqTol && edges[i].End.SquareDistance(edges[n].End) < sqTol) || // edge[i] == edge[n]
(edges[i].Start.SquareDistance(edges[n].End) < sqTol && edges[i].End.SquareDistance(edges[n].Start) < sqTol)) // edge[i] == edge[n].Reverse()
{
edges.RemoveAt(i); // shared edge so remove both
edges.RemoveAt(n);
i--;
break;
}
}
}
return edges;
}
return edges;
}


/***************************************************/
/**** Public Methods - Interfaces ****/
/***************************************************/

[Description("Gets the external edge curves of the ISurface.")]
public static List<ICurve> IExternalEdges(this ISurface surface)
{
return ExternalEdges(surface as dynamic);
Expand Down