using System.Linq; using UnityEngine; using Jobberwocky.TriangleNet.Meshing; using Jobberwocky.TriangleNet.Geometry; using Jobberwocky.GeometryAlgorithms.Source.Core; using Jobberwocky.GeometryAlgorithms.Source.Parameters; namespace Jobberwocky.GeometryAlgorithms.Source.Algorithms.Triangulation2D { public class Triangulation2DWrapper { /// /// Constructor /// public Triangulation2DWrapper() { } /// /// Creates a 2D triangulation of the given input. It is important to note that /// the vector3 points input should not include the boundary and holes points. /// /// /// Geometry public Geometry Triangulate2D(Triangulation2DParameters parameters) { var geometry = new Geometry(); if (parameters == null) { parameters = new Triangulation2DParameters(); } // We only triangulate if the are enough points or boundary points available if ((parameters.Points != null && parameters.Points.Length > 2) || (parameters.Boundary != null && parameters.Boundary.Length > 2)) { // Create triangulation IMesh triangulatedMesh = Triangulate2DBase(parameters); // Somtimes points are removed from the triangulation process, so we need to make sure // that these points are removed from the index numbering triangulatedMesh.Renumber(); var vertices = triangulatedMesh.Vertices.ToArray(); var triangles = triangulatedMesh.Triangles.ToArray(); geometry.Vertices = new Core.Vertex[vertices.Length]; for (int i = 0; i < vertices.Length; i++) { TriangleNet.Geometry.Vertex vertex = vertices[i]; geometry.Vertices[vertex.ID] = new Core.Vertex( Utils.FromCoordinateSystemDefaultTo( new Vector3((float) vertex.X, (float) vertex.Y, (float) vertex.Z), parameters.CoordinateSystem), vertex.ID); ; } var indices = new int[triangles.Length * 3 * (parameters.Side == Side.Double ? 2 : 1)]; for (int i = 0; i < triangles.Length; i++) { for (int j = 0; j < 3; j++) { indices[(i * 3) + j] = triangles[i].GetVertexID(j); } if (parameters.Side == Side.Back) { var tempVertex = indices[(i * 3) + 0]; indices[(i * 3) + 0] = indices[(i * 3) + 2]; indices[(i * 3) + 2] = tempVertex; } } if (parameters.Side == Side.Double) { for (int i = 0; i < indices.Length / 2; i++) { indices[indices.Length / 2 + i] = indices[indices.Length / 2 - 1 - i]; } } geometry.Indices = indices; } return geometry; } /// /// The base method for creating the 2D triangulation. /// /// /// IMesh private IMesh Triangulate2DBase(Triangulation2DParameters parameters) { // Setting up objects for triangulation GenericMesher genericMesher = new GenericMesher(); ConstraintOptions cOptions = new ConstraintOptions(); // Assume as default value that the shape is convex cOptions.Convex = true; cOptions.ConformingDelaunay = parameters.Delaunay; // We use a polygon for the triangulation of the 2D data Polygon polygon = new Polygon(); // Check whether the regular points are not null // else add these points to the polygon var points = parameters.Points; if (points != null) { TriangleNet.Geometry.Vertex[] pointVertices = VectorToVertex(points, parameters.CoordinateSystem); for (var i = 0; i < pointVertices.Length; i++) { polygon.Add(pointVertices[i]); } } var boundary = parameters.Boundary; if (boundary != null) { TriangleNet.Geometry.Vertex[] boundVertices = VectorToVertex(boundary, parameters.CoordinateSystem); polygon.Add(new Contour(boundVertices), false); // Assume that the shape is not convex anymore when we use boundary points cOptions.Convex = false; } var holes = parameters.Holes; if (holes != null) { for (var i = 0; i < holes.Length; i++) { TriangleNet.Geometry.Vertex[] holeVertices = VectorToVertex(holes[i], parameters.CoordinateSystem); polygon.Add(new Contour(holeVertices), true); } } // Create triangulation return genericMesher.Triangulate(polygon, cOptions); } /// /// Transforms Vector data to Vertex points which can be used by the TriangleNet library. /// /// /// private TriangleNet.Geometry.Vertex[] VectorToVertex(Vector3[] vectors, CoordinateSystem coordinateSystem) { TriangleNet.Geometry.Vertex[] vertices = new TriangleNet.Geometry.Vertex[vectors.Length]; for (var i = 0; i < vectors.Length; i++) { var vector = Utils.ToCoordinateSystemDefault(vectors[i], coordinateSystem); var vertex = new TriangleNet.Geometry.Vertex(vector.x, vector.y); vertex.Z = vector.z; vertices[i] = vertex; } return vertices; } } }