123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- // -----------------------------------------------------------------------
- // <copyright file="DcelMesh.cs">
- // Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
- // </copyright>
- // -----------------------------------------------------------------------
- namespace UnityEngine.U2D.Animation.TriangleNet
- .Topology.DCEL
- {
- using System.Collections.Generic;
- using Animation.TriangleNet.Geometry;
- internal class DcelMesh
- {
- protected List<Vertex> vertices;
- protected List<HalfEdge> edges;
- protected List<Face> faces;
- /// <summary>
- /// Initializes a new instance of the <see cref="DcelMesh" /> class.
- /// </summary>
- public DcelMesh()
- : this(true)
- {
- }
- /// <summary>
- /// Initializes a new instance of the <see cref="" /> class.
- /// </summary>
- /// <param name="initialize">If false, lists will not be initialized.</param>
- protected DcelMesh(bool initialize)
- {
- if (initialize)
- {
- vertices = new List<Vertex>();
- edges = new List<HalfEdge>();
- faces = new List<Face>();
- }
- }
- /// <summary>
- /// Gets the vertices of the Voronoi diagram.
- /// </summary>
- public List<Vertex> Vertices
- {
- get { return vertices; }
- }
- /// <summary>
- /// Gets the list of half-edges specify the Voronoi diagram topology.
- /// </summary>
- public List<HalfEdge> HalfEdges
- {
- get { return edges; }
- }
- /// <summary>
- /// Gets the faces of the Voronoi diagram.
- /// </summary>
- public List<Face> Faces
- {
- get { return faces; }
- }
- /// <summary>
- /// Gets the collection of edges of the Voronoi diagram.
- /// </summary>
- public IEnumerable<IEdge> Edges
- {
- get { return EnumerateEdges(); }
- }
- /// <summary>
- /// Check if the DCEL is consistend.
- /// </summary>
- /// <param name="closed">If true, faces are assumed to be closed (i.e. all edges must have
- /// a valid next pointer).</param>
- /// <param name="depth">Maximum edge count of faces (default = 0 means skip check).</param>
- /// <returns></returns>
- public virtual bool IsConsistent(bool closed = true, int depth = 0)
- {
- // Check vertices for null pointers.
- foreach (var vertex in vertices)
- {
- if (vertex.id < 0)
- {
- continue;
- }
- if (vertex.leaving == null)
- {
- return false;
- }
- if (vertex.Leaving.Origin.id != vertex.id)
- {
- return false;
- }
- }
- // Check faces for null pointers.
- foreach (var face in faces)
- {
- if (face.ID < 0)
- {
- continue;
- }
- if (face.edge == null)
- {
- return false;
- }
- if (face.id != face.edge.face.id)
- {
- return false;
- }
- }
- // Check half-edges for null pointers.
- foreach (var edge in edges)
- {
- if (edge.id < 0)
- {
- continue;
- }
- if (edge.twin == null)
- {
- return false;
- }
- if (edge.origin == null)
- {
- return false;
- }
- if (edge.face == null)
- {
- return false;
- }
- if (closed && edge.next == null)
- {
- return false;
- }
- }
- // Check half-edges (topology).
- foreach (var edge in edges)
- {
- if (edge.id < 0)
- {
- continue;
- }
- var twin = edge.twin;
- var next = edge.next;
- if (edge.id != twin.twin.id)
- {
- return false;
- }
- if (closed)
- {
- if (next.origin.id != twin.origin.id)
- {
- return false;
- }
- if (next.twin.next.origin.id != edge.twin.origin.id)
- {
- return false;
- }
- }
- }
- if (closed && depth > 0)
- {
- // Check if faces are closed.
- foreach (var face in faces)
- {
- if (face.id < 0)
- {
- continue;
- }
- var edge = face.edge;
- var next = edge.next;
- int id = edge.id;
- int k = 0;
- while (next.id != id && k < depth)
- {
- next = next.next;
- k++;
- }
- if (next.id != id)
- {
- return false;
- }
- }
- }
- return true;
- }
- /// <summary>
- /// Search for half-edge without twin and add a twin. Connect twins to form connected
- /// boundary contours.
- /// </summary>
- /// <remarks>
- /// This method assumes that all faces are closed (i.e. no edge.next pointers are null).
- /// </remarks>
- public void ResolveBoundaryEdges()
- {
- // Maps vertices to leaving boundary edge.
- var map = new Dictionary<int, HalfEdge>();
- // TODO: parallel?
- foreach (var edge in this.edges)
- {
- if (edge.twin == null)
- {
- var twin = edge.twin = new HalfEdge(edge.next.origin, Face.Empty);
- twin.twin = edge;
- map.Add(twin.origin.id, twin);
- }
- }
- int j = edges.Count;
- foreach (var edge in map.Values)
- {
- edge.id = j++;
- edge.next = map[edge.twin.origin.id];
- this.edges.Add(edge);
- }
- }
- /// <summary>
- /// Enumerates all edges of the DCEL.
- /// </summary>
- /// <remarks>
- /// This method assumes that each half-edge has a twin (i.e. NOT null).
- /// </remarks>
- protected virtual IEnumerable<IEdge> EnumerateEdges()
- {
- var edges = new List<IEdge>(this.edges.Count / 2);
- foreach (var edge in this.edges)
- {
- var twin = edge.twin;
- // Report edge only once.
- if (edge.id < twin.id)
- {
- edges.Add(new Edge(edge.origin.id, twin.origin.id));
- }
- }
- return edges;
- }
- }
- }
|