PO/Library/PackageCache/com.unity.2d.animation@5.0.7/Runtime/Triangle/Meshing/GenericMesher.cs

235 lines
6.7 KiB
C#

// -----------------------------------------------------------------------
// <copyright file="GenericMesher.cs">
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
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;
/// <summary>
/// Create meshes of point sets or polygons.
/// </summary>
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;
}
/// <inheritdoc />
public IMesh Triangulate(IList<Vertex> points)
{
return triangulator.Triangulate(points, config);
}
/// <inheritdoc />
public IMesh Triangulate(IPolygon polygon)
{
return Triangulate(polygon, null, null);
}
/// <inheritdoc />
public IMesh Triangulate(IPolygon polygon, ConstraintOptions options)
{
return Triangulate(polygon, options, null);
}
/// <inheritdoc />
public IMesh Triangulate(IPolygon polygon, QualityOptions quality)
{
return Triangulate(polygon, null, quality);
}
/// <inheritdoc />
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;
}
/// <summary>
/// Generates a structured mesh with bounds [0, 0, width, height].
/// </summary>
/// <param name="width">Width of the mesh (must be > 0).</param>
/// <param name="height">Height of the mesh (must be > 0).</param>
/// <param name="nx">Number of segments in x direction.</param>
/// <param name="ny">Number of segments in y direction.</param>
/// <returns>Mesh</returns>
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);
}
/// <summary>
/// Generates a structured mesh.
/// </summary>
/// <param name="bounds">Bounds of the mesh.</param>
/// <param name="nx">Number of segments in x direction.</param>
/// <param name="ny">Number of segments in y direction.</param>
/// <returns>Mesh</returns>
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);
}
}
}