// ----------------------------------------------------------------------- // // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/ // // ----------------------------------------------------------------------- namespace UnityEngine.U2D.Animation.TriangleNet .Meshing { using System; using System.Collections.Generic; using Animation.TriangleNet.Geometry; using Animation.TriangleNet.IO; using Animation.TriangleNet.Meshing.Algorithm; /// /// Create meshes of point sets or polygons. /// internal class GenericMesher { Configuration config; ITriangulator triangulator; public GenericMesher() : this(new Dwyer(), new Configuration()) { } public GenericMesher(ITriangulator triangulator) : this(triangulator, new Configuration()) { } public GenericMesher(Configuration config) : this(new Dwyer(), config) { } public GenericMesher(ITriangulator triangulator, Configuration config) { this.config = config; this.triangulator = triangulator; } /// public IMesh Triangulate(IList points) { return triangulator.Triangulate(points, config); } /// public IMesh Triangulate(IPolygon polygon) { return Triangulate(polygon, null, null); } /// public IMesh Triangulate(IPolygon polygon, ConstraintOptions options) { return Triangulate(polygon, options, null); } /// public IMesh Triangulate(IPolygon polygon, QualityOptions quality) { return Triangulate(polygon, null, quality); } /// public IMesh Triangulate(IPolygon polygon, ConstraintOptions options, QualityOptions quality) { var mesh = (Mesh)triangulator.Triangulate(polygon.Points, config); var cmesher = new ConstraintMesher(mesh, config); var qmesher = new QualityMesher(mesh, config); mesh.SetQualityMesher(qmesher); // Insert segments. cmesher.Apply(polygon, options); // Refine mesh. qmesher.Apply(quality); return mesh; } /// /// Generates a structured mesh with bounds [0, 0, width, height]. /// /// Width of the mesh (must be > 0). /// Height of the mesh (must be > 0). /// Number of segments in x direction. /// Number of segments in y direction. /// Mesh internal static IMesh StructuredMesh(double width, double height, int nx, int ny) { if (width <= 0.0) { throw new ArgumentException("width"); } if (height <= 0.0) { throw new ArgumentException("height"); } return StructuredMesh(new Rectangle(0.0, 0.0, width, height), nx, ny); } /// /// Generates a structured mesh. /// /// Bounds of the mesh. /// Number of segments in x direction. /// Number of segments in y direction. /// Mesh internal static IMesh StructuredMesh(Rectangle bounds, int nx, int ny) { var polygon = new Polygon((nx + 1) * (ny + 1)); double x, y, dx, dy, left, bottom; dx = bounds.Width / nx; dy = bounds.Height / ny; left = bounds.Left; bottom = bounds.Bottom; int i, j, k, l, n = 0; // Add vertices. var points = new Vertex[(nx + 1) * (ny + 1)]; for (i = 0; i <= nx; i++) { x = left + i * dx; for (j = 0; j <= ny; j++) { y = bottom + j * dy; points[n++] = new Vertex(x, y); } } polygon.Points.AddRange(points); n = 0; // Set vertex hash and id. foreach (var v in points) { v.hash = v.id = n++; } // Add boundary segments. var segments = polygon.Segments; segments.Capacity = 2 * (nx + ny); Vertex a, b; for (j = 0; j < ny; j++) { // Left a = points[j]; b = points[j + 1]; segments.Add(new Segment(a, b, 1)); a.Label = b.Label = 1; // Right a = points[nx * (ny + 1) + j]; b = points[nx * (ny + 1) + (j + 1)]; segments.Add(new Segment(a, b, 1)); a.Label = b.Label = 1; } for (i = 0; i < nx; i++) { // Bottom a = points[(ny + 1) * i]; b = points[(ny + 1) * (i + 1)]; segments.Add(new Segment(a, b, 1)); a.Label = b.Label = 1; // Top a = points[ny + (ny + 1) * i]; b = points[ny + (ny + 1) * (i + 1)]; segments.Add(new Segment(a, b, 1)); a.Label = b.Label = 1; } // Add triangles. var triangles = new InputTriangle[2 * nx * ny]; n = 0; for (i = 0; i < nx; i++) { for (j = 0; j < ny; j++) { k = j + (ny + 1) * i; l = j + (ny + 1) * (i + 1); // Create 2 triangles in rectangle [k, l, l + 1, k + 1]. if ((i + j) % 2 == 0) { // Diagonal from bottom left to top right. triangles[n++] = new InputTriangle(k, l, l + 1); triangles[n++] = new InputTriangle(k, l + 1, k + 1); } else { // Diagonal from top left to bottom right. triangles[n++] = new InputTriangle(k, l, k + 1); triangles[n++] = new InputTriangle(l, l + 1, k + 1); } } } return Converter.ToMesh(polygon, triangles); } } }