/// <summary> /// Returns the Vector3 Vertex Positions of the triangle. /// </summary> /// <param name="triangle"></param> /// <returns> /// A Vector3 List. /// </returns> public static List <Vector3> Points(this Elements.Geometry.Triangle triangle) { var points = new List <Vector3>(); triangle.Vertices.ToList().ForEach(v => points.Add(v.Position)); return(points); }
/// <summary> /// Returns a Mesh by applying the Delauney triangulation algorithm to this Polygon. /// </summary> /// <param name="polygon"></param> /// <returns> /// A Mesh. /// </returns> public static Mesh ToMesh(this Polygon polygon, bool top = true) { var points = new List <IPoint>(); polygon.Vertices.ToList().ForEach(v => points.Add(new Point(v.X, v.Y))); var elev = polygon.Vertices.First().Z; var delTriangles = new Delaunator(points.ToArray()).GetTriangles().ToList(); var mesh = new Mesh(); foreach (var triangle in delTriangles) { var vertices = new List <Vector3>(); triangle.Points.ToList().ForEach(p => vertices.Add(new Vector3(p.X, p.Y, elev))); var winder = new Polygon(vertices); if (!polygon.Covers(winder)) { continue; } if (winder.IsClockWise() && top || !winder.IsClockWise() && !top) { winder = winder.Reversed(); } var mTriangle = new Elements.Geometry.Triangle(new Elements.Geometry.Solids.Vertex(winder.Vertices[0]), new Elements.Geometry.Solids.Vertex(winder.Vertices[1]), new Elements.Geometry.Solids.Vertex(winder.Vertices[2])); mesh.AddTriangle(mTriangle); mesh.AddVertex(mTriangle.Vertices[0].Position); mesh.AddVertex(mTriangle.Vertices[1].Position); mesh.AddVertex(mTriangle.Vertices[2].Position); } mesh.ComputeNormals(); return(mesh); }
/// <summary> /// Returns the centroid of the triangle. /// </summary> /// <returns>A double.</returns> public static Vector3 Centroid(this Elements.Geometry.Triangle triangle) { var a = triangle.Vertices[0].Position; var b = triangle.Vertices[1].Position; var c = triangle.Vertices[2].Position; return(new Line(a, new Line(b, c).Midpoint()).PointAt(0.666666666)); }
/// <summary> /// Returns the area of the triangle. /// </summary> /// <returns>A double.</returns> public static double Area(this Elements.Geometry.Triangle triangle) { var a = triangle.Vertices[0].Position; var b = triangle.Vertices[1].Position; var c = triangle.Vertices[2].Position; return(Math.Abs((a.X * (b.Y - c.Y) + b.X * (c.Y - a.Y) + c.X * (a.Y - b.Y)) * 0.5)); }
/// <summary> /// Returns the edges of a Triangle as a List of Lines. /// </summary> /// <returns>A List of Lines.</returns> public static List <Line> Edges(this Elements.Geometry.Triangle triangle) { var edges = new List <Line>(); var points = new List <Vector3>(); triangle.Vertices.ToList().ForEach(v => points.Add(v.Position)); edges.Add(new Line(points[0], points[1])); edges.Add(new Line(points[1], points[2])); edges.Add(new Line(points[2], points[0])); return(edges); }
/// <summary> /// Return true if an Equal Elements.Geometry.Triangle appears at least once in the supplied list. /// </summary> /// <returns> /// True if the Triangle vertex positions are AlmostEqual to those of any Triangle in the supplied List. /// </returns> public static bool IsListed(this Elements.Geometry.Triangle triangle, List <Elements.Geometry.Triangle> triangles) { foreach (var entry in triangles) { if (triangle.IsEqualTo(entry)) { return(true); } } return(false); }
/// <summary> /// Return true if the supplied Elements.Geometry.Triangle has the same vertices as this Triangle. /// </summary> /// <param name="thatTriangle">Triangle to compare to this Triangle.</param> /// <returns> /// True if the Triangle vertex positions are AlmostEqual to those of the supplied Triangle. /// </returns> public static bool IsEqualTo(this Elements.Geometry.Triangle triangle, Elements.Geometry.Triangle thatTriangle) { var points = triangle.Points(); var thosePnts = thatTriangle.Points(); var common = 0; points.ForEach(p => common += p.Occurs(thosePnts)); if (common == 3) { return(true); } return(false); }
/// <summary> /// Return the number of times an equal Elements.Geometry.Triangle in the supplied list. /// </summary> /// <returns> /// An integer. /// </returns> public static int Occurs(this Elements.Geometry.Triangle triangle, List <Elements.Geometry.Triangle> triangles) { int count = 0; foreach (var entry in triangles) { if (triangle.IsEqualTo(entry)) { count++; } } return(count); }
/// <summary> /// Returns the Triangle as a CCW Polygon. /// </summary> /// <returns></returns> public static Polygon ToPolygon(this Elements.Geometry.Triangle triangle) { var polygon = new Polygon(triangle.Points()); return(polygon.IsClockWise() ? polygon.Reversed() : polygon); }
/// <summary> /// Inserts this Triangle into a new List. /// </summary> /// <returns>A new List containing this Triangle.</returns> public static List <Elements.Geometry.Triangle> ToList(this Elements.Geometry.Triangle triangle) { return(new List <Elements.Geometry.Triangle> { triangle }); }
/// <summary> /// Creates a Roof from a supplied Polygon sketch and a supplied elevation. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A RoofBySketchOutputs instance containing computed results and the model with any new elements.</returns> public static RoofBySketchOutputs Execute(Dictionary <string, Model> inputModels, RoofBySketchInputs input) { var topSide = new Elements.Geometry.Mesh(); var area = 0.0; foreach (var triangle in input.Mesh.Triangles) { var a = topSide.AddVertex(triangle.Vertices[0].Position); var b = topSide.AddVertex(triangle.Vertices[1].Position); var c = topSide.AddVertex(triangle.Vertices[2].Position); var triAng = new Elements.Geometry.Triangle(a, b, c); topSide.AddTriangle(triAng); area += triAng.Area(); } topSide.ComputeNormals(); // Find the Mesh's lowest point and use the // roof thickness to the set the Roof's underside elevation. var vertices = input.Mesh.Vertices.ToList(); vertices = vertices.OrderBy(v => v.Position.Z).ToList(); var elevation = vertices.First().Position.Z - input.Thickness; // Find the topSide Mesh's perimeter points and use them to // construct a Mesh representing the underside of the Roof. var perimeter = topSide.EdgesPerimeters().First(); var ePoints = new List <Vector3>(); perimeter.ForEach(e => ePoints.AddRange(e.Points())); ePoints = ePoints.Distinct().ToList(); var uPoints = new List <Vector3>(); ePoints.ForEach(p => uPoints.Add(new Vector3(p.X, p.Y, elevation))); var underBoundary = new Polygon(uPoints); var underSide = underBoundary.ToMesh(false); // Use the topSide Mesh's edgePoints and the lower Mesh's underPoints // to construct a series of triangles forming the sides of the Roof. var sideTriangles = new List <Elements.Geometry.Triangle>(); for (var i = 0; i < ePoints.Count; i++) { sideTriangles.Add( new Elements.Geometry.Triangle(new Vertex(ePoints[i]), new Vertex(uPoints[i]), new Vertex(uPoints[(i + 1) % uPoints.Count]))); sideTriangles.Add( new Elements.Geometry.Triangle(new Vertex(ePoints[i]), new Vertex(uPoints[(i + 1) % uPoints.Count]), new Vertex(ePoints[(i + 1) % ePoints.Count]))); } // Construct the roof envelope in Elements.Geometry.mesh form. // We add vertices individually by position so that we don't affect // the original vertices of hte individual faces var Envelope = new Elements.Geometry.Mesh(); foreach (var t in topSide.Triangles) { var a = Envelope.AddVertex(t.Vertices[0].Position); var b = Envelope.AddVertex(t.Vertices[1].Position); var c = Envelope.AddVertex(t.Vertices[2].Position); Envelope.AddTriangle(new Triangle(a, b, c)); } foreach (var t in underSide.Triangles) { var a = Envelope.AddVertex(t.Vertices[0].Position); var b = Envelope.AddVertex(t.Vertices[1].Position); var c = Envelope.AddVertex(t.Vertices[2].Position); Envelope.AddTriangle(new Triangle(a, b, c)); } foreach (var t in sideTriangles) { var a = Envelope.AddVertex(t.Vertices[0].Position); var b = Envelope.AddVertex(t.Vertices[1].Position); var c = Envelope.AddVertex(t.Vertices[2].Position); Envelope.AddTriangle(new Triangle(a, b, c)); } // enVertices.ToList().ForEach(v => Envelope.AddVertex(v)); // envTriangles.ToList().ForEach(t => Envelope.AddTriangle(t)); Envelope.ComputeNormals(); //Record roof high point from topSide mesh. var highPoint = topSide.Points().OrderByDescending(p => p.Z).First().Z; // // code for when debugging the function. // var envelope = MakeEnvelope(); // var topside = MakeTopside(); // var underside = MakeUnderside(); // var underBoundary = Polygon.Rectangle(20.0, 20.0); // var elevation = 10.0; // var highPoint = 15.0; // var area = 100.0; var roof = new Roof( Envelope, topSide, underSide, underBoundary, elevation, highPoint, input.Thickness, area, new Transform(), BuiltInMaterials.Concrete, null, false, Guid.NewGuid(), "Roof"); var output = new RoofBySketchOutputs(area); output.Model.AddElement(new MeshElement(Envelope, BuiltInMaterials.Concrete)); output.Model.AddElement(roof); return(output); }