Initial commit

This commit is contained in:
AbstractConcept 2022-09-13 00:36:34 -05:00
commit 3c7cc0c973
8391 changed files with 704313 additions and 0 deletions

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ce68bfd95b5c448dd8141dcb2b8bed85
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,270 @@
// -----------------------------------------------------------------------
// <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;
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7c725737cdc184d969ef5d53b813d1b0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,114 @@
// -----------------------------------------------------------------------
// <copyright file="Face.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;
/// <summary>
/// A face of DCEL mesh.
/// </summary>
internal class Face
{
#region Static initialization of "Outer Space" face
internal static readonly Face Empty;
static Face()
{
Empty = new Face(null);
Empty.id = -1;
}
#endregion
internal int id;
internal int mark = 0;
internal Point generator;
internal HalfEdge edge;
internal bool bounded;
/// <summary>
/// Gets or sets the face id.
/// </summary>
public int ID
{
get { return id; }
set { id = value; }
}
/// <summary>
/// Gets or sets a half-edge connected to the face.
/// </summary>
public HalfEdge Edge
{
get { return edge; }
set { edge = value; }
}
/// <summary>
/// Gets or sets a value, indicating if the face is bounded (for Voronoi diagram).
/// </summary>
public bool Bounded
{
get { return bounded; }
set { bounded = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="Face" /> class.
/// </summary>
/// <param name="generator">The generator of this face (for Voronoi diagram)</param>
public Face(Point generator)
: this(generator, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Face" /> class.
/// </summary>
/// <param name="generator">The generator of this face (for Voronoi diagram)</param>
/// <param name="edge">The half-edge connected to this face.</param>
public Face(Point generator, HalfEdge edge)
{
this.generator = generator;
this.edge = edge;
this.bounded = true;
if (generator != null)
{
this.id = generator.ID;
}
}
/// <summary>
/// Enumerates all half-edges of the face boundary.
/// </summary>
/// <returns></returns>
public IEnumerable<HalfEdge> EnumerateEdges()
{
var edge = this.Edge;
int first = edge.ID;
do
{
yield return edge;
edge = edge.Next;
}
while (edge.ID != first);
}
public override string ToString()
{
return string.Format("F-ID {0}", id);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 448d8fb02c0a5495ea149174a75f80c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,102 @@
// -----------------------------------------------------------------------
// <copyright file="HalfEdge.cs">
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace UnityEngine.U2D.Animation.TriangleNet
.Topology.DCEL
{
internal class HalfEdge
{
internal int id;
internal int mark;
internal Vertex origin;
internal Face face;
internal HalfEdge twin;
internal HalfEdge next;
/// <summary>
/// Gets or sets the half-edge id.
/// </summary>
public int ID
{
get { return id; }
set { id = value; }
}
public int Boundary
{
get { return mark; }
set { mark = value; }
}
/// <summary>
/// Gets or sets the origin of the half-edge.
/// </summary>
public Vertex Origin
{
get { return origin; }
set { origin = value; }
}
/// <summary>
/// Gets or sets the face connected to the half-edge.
/// </summary>
public Face Face
{
get { return face; }
set { face = value; }
}
/// <summary>
/// Gets or sets the twin of the half-edge.
/// </summary>
public HalfEdge Twin
{
get { return twin; }
set { twin = value; }
}
/// <summary>
/// Gets or sets the next pointer of the half-edge.
/// </summary>
public HalfEdge Next
{
get { return next; }
set { next = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="HalfEdge" /> class.
/// </summary>
/// <param name="origin">The origin of this half-edge.</param>
public HalfEdge(Vertex origin)
{
this.origin = origin;
}
/// <summary>
/// Initializes a new instance of the <see cref="HalfEdge" /> class.
/// </summary>
/// <param name="origin">The origin of this half-edge.</param>
/// <param name="face">The face connected to this half-edge.</param>
public HalfEdge(Vertex origin, Face face)
{
this.origin = origin;
this.face = face;
// IMPORTANT: do not remove the (face.edge == null) check!
if (face != null && face.edge == null)
{
face.edge = this;
}
}
public override string ToString()
{
return string.Format("HE-ID {0} (Origin = VID-{1})", id, origin.id);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 456daa24c602c419ba5653d9dac96c28
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,70 @@
// -----------------------------------------------------------------------
// <copyright file="Vertex.cs">
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace UnityEngine.U2D.Animation.TriangleNet
.Topology.DCEL
{
using System.Collections.Generic;
internal class Vertex : Animation.TriangleNet.Geometry.Point
{
internal HalfEdge leaving;
/// <summary>
/// Gets or sets a half-edge leaving the vertex.
/// </summary>
public HalfEdge Leaving
{
get { return leaving; }
set { leaving = value; }
}
/// <summary>
/// Initializes a new instance of the <see cref="Vertex" /> class.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
public Vertex(double x, double y)
: base(x, y)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Vertex" /> class.
/// </summary>
/// <param name="x">The x coordinate.</param>
/// <param name="y">The y coordinate.</param>
/// <param name="leaving">A half-edge leaving this vertex.</param>
public Vertex(double x, double y, HalfEdge leaving)
: base(x, y)
{
this.leaving = leaving;
}
/// <summary>
/// Enumerates all half-edges leaving this vertex.
/// </summary>
/// <returns></returns>
public IEnumerable<HalfEdge> EnumerateEdges()
{
var edge = this.Leaving;
int first = edge.ID;
do
{
yield return edge;
edge = edge.Twin.Next;
}
while (edge.ID != first);
}
public override string ToString()
{
return string.Format("V-ID {0}", base.id);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 87a0e38ad31404f7285fa9bf6fa08eaa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,256 @@
// -----------------------------------------------------------------------
// <copyright file="Osub.cs">
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace UnityEngine.U2D.Animation.TriangleNet
.Topology
{
using System;
using Animation.TriangleNet.Geometry;
/// <summary>
/// An oriented subsegment.
/// </summary>
/// <remarks>
/// Includes a pointer to a subsegment and an orientation. The orientation denotes a
/// side of the edge. Hence, there are two possible orientations. By convention, the
/// edge is always directed so that the "side" denoted is the right side of the edge.
/// </remarks>
internal struct Osub
{
internal SubSegment seg;
internal int orient; // Ranges from 0 to 1.
public SubSegment Segment
{
get { return seg; }
}
public override string ToString()
{
if (seg == null)
{
return "O-TID [null]";
}
return String.Format("O-SID {0}", seg.hash);
}
#region Osub primitives
/// <summary>
/// Reverse the orientation of a subsegment. [sym(ab) -> ba]
/// </summary>
public void Sym(ref Osub os)
{
os.seg = seg;
os.orient = 1 - orient;
}
/// <summary>
/// Reverse the orientation of a subsegment. [sym(ab) -> ba]
/// </summary>
public void Sym()
{
orient = 1 - orient;
}
/// <summary>
/// Find adjoining subsegment with the same origin. [pivot(ab) -> a*]
/// </summary>
/// <remarks>spivot() finds the other subsegment (from the same segment)
/// that shares the same origin.
/// </remarks>
public void Pivot(ref Osub os)
{
os = seg.subsegs[orient];
}
/// <summary>
/// Finds a triangle abutting a subsegment.
/// </summary>
internal void Pivot(ref Otri ot)
{
ot = seg.triangles[orient];
}
/// <summary>
/// Find next subsegment in sequence. [next(ab) -> b*]
/// </summary>
public void Next(ref Osub ot)
{
ot = seg.subsegs[1 - orient];
}
/// <summary>
/// Find next subsegment in sequence. [next(ab) -> b*]
/// </summary>
public void Next()
{
this = seg.subsegs[1 - orient];
}
/// <summary>
/// Get the origin of a subsegment
/// </summary>
public Vertex Org()
{
return seg.vertices[orient];
}
/// <summary>
/// Get the destination of a subsegment
/// </summary>
public Vertex Dest()
{
return seg.vertices[1 - orient];
}
#endregion
#region Osub primitives (internal)
/// <summary>
/// Set the origin or destination of a subsegment.
/// </summary>
internal void SetOrg(Vertex vertex)
{
seg.vertices[orient] = vertex;
}
/// <summary>
/// Set destination of a subsegment.
/// </summary>
internal void SetDest(Vertex vertex)
{
seg.vertices[1 - orient] = vertex;
}
/// <summary>
/// Get the origin of the segment that includes the subsegment.
/// </summary>
internal Vertex SegOrg()
{
return seg.vertices[2 + orient];
}
/// <summary>
/// Get the destination of the segment that includes the subsegment.
/// </summary>
internal Vertex SegDest()
{
return seg.vertices[3 - orient];
}
/// <summary>
/// Set the origin of the segment that includes the subsegment.
/// </summary>
internal void SetSegOrg(Vertex vertex)
{
seg.vertices[2 + orient] = vertex;
}
/// <summary>
/// Set the destination of the segment that includes the subsegment.
/// </summary>
internal void SetSegDest(Vertex vertex)
{
seg.vertices[3 - orient] = vertex;
}
/* Unused primitives.
/// <summary>
/// Find adjoining subsegment with the same origin. [pivot(ab) -> a*]
/// </summary>
public void PivotSelf()
{
this = seg.subsegs[orient];
}
/// <summary>
/// Read a boundary marker.
/// </summary>
/// <remarks>Boundary markers are used to hold user-defined tags for
/// setting boundary conditions in finite element solvers.</remarks>
public int Mark()
{
return seg.boundary;
}
/// <summary>
/// Set a boundary marker.
/// </summary>
public void SetMark(int value)
{
seg.boundary = value;
}
/// <summary>
/// Copy a subsegment.
/// </summary>
public void Copy(ref Osub o2)
{
o2.seg = seg;
o2.orient = orient;
}
//*/
/// <summary>
/// Bond two subsegments together. [bond(abc, ba)]
/// </summary>
internal void Bond(ref Osub os)
{
seg.subsegs[orient] = os;
os.seg.subsegs[os.orient] = this;
}
/// <summary>
/// Dissolve a subsegment bond (from one side).
/// </summary>
/// <remarks>Note that the other subsegment will still think it's
/// connected to this subsegment.</remarks>
internal void Dissolve(SubSegment dummy)
{
seg.subsegs[orient].seg = dummy;
}
/// <summary>
/// Test for equality of subsegments.
/// </summary>
internal bool Equal(Osub os)
{
return ((seg == os.seg) && (orient == os.orient));
}
/// <summary>
/// Dissolve a bond (from the subsegment side).
/// </summary>
internal void TriDissolve(Triangle dummy)
{
seg.triangles[orient].tri = dummy;
}
/// <summary>
/// Check a subsegment's deallocation.
/// </summary>
internal static bool IsDead(SubSegment sub)
{
return sub.subsegs[0].seg == null;
}
/// <summary>
/// Set a subsegment's deallocation.
/// </summary>
internal static void Kill(SubSegment sub)
{
sub.subsegs[0].seg = null;
sub.subsegs[1].seg = null;
}
#endregion
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a6bdf2f80b4745c9a689f3afaa4a134
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,482 @@
// -----------------------------------------------------------------------
// <copyright file="Otri.cs">
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace UnityEngine.U2D.Animation.TriangleNet
.Topology
{
using System;
using Animation.TriangleNet.Geometry;
/// <summary>
/// An oriented triangle.
/// </summary>
/// <remarks>
/// Includes a pointer to a triangle and orientation. The orientation denotes an edge
/// of the triangle. Hence, there are three possible orientations. By convention, each
/// edge always points counterclockwise about the corresponding triangle.
/// </remarks>
internal struct Otri
{
internal Triangle tri;
internal int orient; // Ranges from 0 to 2.
public Triangle Triangle
{
get { return tri; }
set { tri = value; }
}
public override string ToString()
{
if (tri == null)
{
return "O-TID [null]";
}
return String.Format("O-TID {0}", tri.hash);
}
#region Otri primitives (public)
// For fast access
static readonly int[] plus1Mod3 = { 1, 2, 0 };
static readonly int[] minus1Mod3 = { 2, 0, 1 };
// The following primitives are all described by Guibas and Stolfi.
// However, Guibas and Stolfi use an edge-based data structure,
// whereas I use a triangle-based data structure.
//
// lnext: finds the next edge (counterclockwise) of a triangle.
//
// onext: spins counterclockwise around a vertex; that is, it finds
// the next edge with the same origin in the counterclockwise direction. This
// edge is part of a different triangle.
//
// oprev: spins clockwise around a vertex; that is, it finds the
// next edge with the same origin in the clockwise direction. This edge is
// part of a different triangle.
//
// dnext: spins counterclockwise around a vertex; that is, it finds
// the next edge with the same destination in the counterclockwise direction.
// This edge is part of a different triangle.
//
// dprev: spins clockwise around a vertex; that is, it finds the
// next edge with the same destination in the clockwise direction. This edge
// is part of a different triangle.
//
// rnext: moves one edge counterclockwise about the adjacent
// triangle. (It's best understood by reading Guibas and Stolfi. It
// involves changing triangles twice.)
//
// rprev: moves one edge clockwise about the adjacent triangle.
// (It's best understood by reading Guibas and Stolfi. It involves
// changing triangles twice.)
/// <summary>
/// Find the abutting triangle; same edge. [sym(abc) -> ba*]
/// </summary>
/// Note that the edge direction is necessarily reversed, because the handle specified
/// by an oriented triangle is directed counterclockwise around the triangle.
/// </remarks>
public void Sym(ref Otri ot)
{
ot.tri = tri.neighbors[orient].tri;
ot.orient = tri.neighbors[orient].orient;
}
/// <summary>
/// Find the abutting triangle; same edge. [sym(abc) -> ba*]
/// </summary>
public void Sym()
{
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the next edge (counterclockwise) of a triangle. [lnext(abc) -> bca]
/// </summary>
public void Lnext(ref Otri ot)
{
ot.tri = tri;
ot.orient = plus1Mod3[orient];
}
/// <summary>
/// Find the next edge (counterclockwise) of a triangle. [lnext(abc) -> bca]
/// </summary>
public void Lnext()
{
orient = plus1Mod3[orient];
}
/// <summary>
/// Find the previous edge (clockwise) of a triangle. [lprev(abc) -> cab]
/// </summary>
public void Lprev(ref Otri ot)
{
ot.tri = tri;
ot.orient = minus1Mod3[orient];
}
/// <summary>
/// Find the previous edge (clockwise) of a triangle. [lprev(abc) -> cab]
/// </summary>
public void Lprev()
{
orient = minus1Mod3[orient];
}
/// <summary>
/// Find the next edge counterclockwise with the same origin. [onext(abc) -> ac*]
/// </summary>
public void Onext(ref Otri ot)
{
//Lprev(ref ot);
ot.tri = tri;
ot.orient = minus1Mod3[orient];
//ot.SymSelf();
int tmp = ot.orient;
ot.orient = ot.tri.neighbors[tmp].orient;
ot.tri = ot.tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the next edge counterclockwise with the same origin. [onext(abc) -> ac*]
/// </summary>
public void Onext()
{
//LprevSelf();
orient = minus1Mod3[orient];
//SymSelf();
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the next edge clockwise with the same origin. [oprev(abc) -> a*b]
/// </summary>
public void Oprev(ref Otri ot)
{
//Sym(ref ot);
ot.tri = tri.neighbors[orient].tri;
ot.orient = tri.neighbors[orient].orient;
//ot.LnextSelf();
ot.orient = plus1Mod3[ot.orient];
}
/// <summary>
/// Find the next edge clockwise with the same origin. [oprev(abc) -> a*b]
/// </summary>
public void Oprev()
{
//SymSelf();
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
//LnextSelf();
orient = plus1Mod3[orient];
}
/// <summary>
/// Find the next edge counterclockwise with the same destination. [dnext(abc) -> *ba]
/// </summary>
public void Dnext(ref Otri ot)
{
//Sym(ref ot);
ot.tri = tri.neighbors[orient].tri;
ot.orient = tri.neighbors[orient].orient;
//ot.LprevSelf();
ot.orient = minus1Mod3[ot.orient];
}
/// <summary>
/// Find the next edge counterclockwise with the same destination. [dnext(abc) -> *ba]
/// </summary>
public void Dnext()
{
//SymSelf();
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
//LprevSelf();
orient = minus1Mod3[orient];
}
/// <summary>
/// Find the next edge clockwise with the same destination. [dprev(abc) -> cb*]
/// </summary>
public void Dprev(ref Otri ot)
{
//Lnext(ref ot);
ot.tri = tri;
ot.orient = plus1Mod3[orient];
//ot.SymSelf();
int tmp = ot.orient;
ot.orient = ot.tri.neighbors[tmp].orient;
ot.tri = ot.tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the next edge clockwise with the same destination. [dprev(abc) -> cb*]
/// </summary>
public void Dprev()
{
//LnextSelf();
orient = plus1Mod3[orient];
//SymSelf();
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the next edge (counterclockwise) of the adjacent triangle. [rnext(abc) -> *a*]
/// </summary>
public void Rnext(ref Otri ot)
{
//Sym(ref ot);
ot.tri = tri.neighbors[orient].tri;
ot.orient = tri.neighbors[orient].orient;
//ot.LnextSelf();
ot.orient = plus1Mod3[ot.orient];
//ot.SymSelf();
int tmp = ot.orient;
ot.orient = ot.tri.neighbors[tmp].orient;
ot.tri = ot.tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the next edge (counterclockwise) of the adjacent triangle. [rnext(abc) -> *a*]
/// </summary>
public void Rnext()
{
//SymSelf();
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
//LnextSelf();
orient = plus1Mod3[orient];
//SymSelf();
tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the previous edge (clockwise) of the adjacent triangle. [rprev(abc) -> b**]
/// </summary>
public void Rprev(ref Otri ot)
{
//Sym(ref ot);
ot.tri = tri.neighbors[orient].tri;
ot.orient = tri.neighbors[orient].orient;
//ot.LprevSelf();
ot.orient = minus1Mod3[ot.orient];
//ot.SymSelf();
int tmp = ot.orient;
ot.orient = ot.tri.neighbors[tmp].orient;
ot.tri = ot.tri.neighbors[tmp].tri;
}
/// <summary>
/// Find the previous edge (clockwise) of the adjacent triangle. [rprev(abc) -> b**]
/// </summary>
public void Rprev()
{
//SymSelf();
int tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
//LprevSelf();
orient = minus1Mod3[orient];
//SymSelf();
tmp = orient;
orient = tri.neighbors[tmp].orient;
tri = tri.neighbors[tmp].tri;
}
/// <summary>
/// Origin [org(abc) -> a]
/// </summary>
public Vertex Org()
{
return tri.vertices[plus1Mod3[orient]];
}
/// <summary>
/// Destination [dest(abc) -> b]
/// </summary>
public Vertex Dest()
{
return tri.vertices[minus1Mod3[orient]];
}
/// <summary>
/// Apex [apex(abc) -> c]
/// </summary>
public Vertex Apex()
{
return tri.vertices[orient];
}
/// <summary>
/// Copy an oriented triangle.
/// </summary>
public void Copy(ref Otri ot)
{
ot.tri = tri;
ot.orient = orient;
}
/// <summary>
/// Test for equality of oriented triangles.
/// </summary>
public bool Equals(Otri ot)
{
return ((tri == ot.tri) && (orient == ot.orient));
}
#endregion
#region Otri primitives (internal)
/// <summary>
/// Set Origin
/// </summary>
internal void SetOrg(Vertex v)
{
tri.vertices[plus1Mod3[orient]] = v;
}
/// <summary>
/// Set Destination
/// </summary>
internal void SetDest(Vertex v)
{
tri.vertices[minus1Mod3[orient]] = v;
}
/// <summary>
/// Set Apex
/// </summary>
internal void SetApex(Vertex v)
{
tri.vertices[orient] = v;
}
/// <summary>
/// Bond two triangles together at the resepective handles. [bond(abc, bad)]
/// </summary>
internal void Bond(ref Otri ot)
{
tri.neighbors[orient].tri = ot.tri;
tri.neighbors[orient].orient = ot.orient;
ot.tri.neighbors[ot.orient].tri = this.tri;
ot.tri.neighbors[ot.orient].orient = this.orient;
}
/// <summary>
/// Dissolve a bond (from one side).
/// </summary>
/// <remarks>Note that the other triangle will still think it's connected to
/// this triangle. Usually, however, the other triangle is being deleted
/// entirely, or bonded to another triangle, so it doesn't matter.
/// </remarks>
internal void Dissolve(Triangle dummy)
{
tri.neighbors[orient].tri = dummy;
tri.neighbors[orient].orient = 0;
}
/// <summary>
/// Infect a triangle with the virus.
/// </summary>
internal void Infect()
{
tri.infected = true;
}
/// <summary>
/// Cure a triangle from the virus.
/// </summary>
internal void Uninfect()
{
tri.infected = false;
}
/// <summary>
/// Test a triangle for viral infection.
/// </summary>
internal bool IsInfected()
{
return tri.infected;
}
/// <summary>
/// Finds a subsegment abutting a triangle.
/// </summary>
internal void Pivot(ref Osub os)
{
os = tri.subsegs[orient];
}
/// <summary>
/// Bond a triangle to a subsegment.
/// </summary>
internal void SegBond(ref Osub os)
{
tri.subsegs[orient] = os;
os.seg.triangles[os.orient] = this;
}
/// <summary>
/// Dissolve a bond (from the triangle side).
/// </summary>
internal void SegDissolve(SubSegment dummy)
{
tri.subsegs[orient].seg = dummy;
}
/// <summary>
/// Check a triangle's deallocation.
/// </summary>
internal static bool IsDead(Triangle tria)
{
return tria.neighbors[0].tri == null;
}
/// <summary>
/// Set a triangle's deallocation.
/// </summary>
internal static void Kill(Triangle tri)
{
tri.neighbors[0].tri = null;
tri.neighbors[2].tri = null;
}
#endregion
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f5e55d6f95334cb29464817d94cd9fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,97 @@
// -----------------------------------------------------------------------
// <copyright file="Segment.cs" company="">
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace UnityEngine.U2D.Animation.TriangleNet
.Topology
{
using System;
using Animation.TriangleNet.Geometry;
/// <summary>
/// The subsegment data structure.
/// </summary>
internal class SubSegment : ISegment
{
// Hash for dictionary. Will be set by mesh instance.
internal int hash;
internal Osub[] subsegs;
internal Vertex[] vertices;
internal Otri[] triangles;
internal int boundary;
public SubSegment()
{
// Four NULL vertices.
vertices = new Vertex[4];
// Set the boundary marker to zero.
boundary = 0;
// Initialize the two adjoining subsegments to be the omnipresent
// subsegment.
subsegs = new Osub[2];
// Initialize the two adjoining triangles to be "outer space."
triangles = new Otri[2];
}
#region Public properties
/// <summary>
/// Gets the first endpoints vertex id.
/// </summary>
public int P0
{
get { return this.vertices[0].id; }
}
/// <summary>
/// Gets the seconds endpoints vertex id.
/// </summary>
public int P1
{
get { return this.vertices[1].id; }
}
/// <summary>
/// Gets the segment boundary mark.
/// </summary>
public int Label
{
get { return this.boundary; }
}
#endregion
/// <summary>
/// Gets the segments endpoint.
/// </summary>
public Vertex GetVertex(int index)
{
return this.vertices[index]; // TODO: Check range?
}
/// <summary>
/// Gets an adjoining triangle.
/// </summary>
public ITriangle GetTriangle(int index)
{
return triangles[index].tri.hash == Mesh.DUMMY ? null : triangles[index].tri;
}
public override int GetHashCode()
{
return this.hash;
}
public override string ToString()
{
return String.Format("SID {0}", hash);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc4f3446a7ed4468da9886cadbe2ad0c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,129 @@
// -----------------------------------------------------------------------
// <copyright file="Triangle.cs" company="">
// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
// </copyright>
// -----------------------------------------------------------------------
namespace UnityEngine.U2D.Animation.TriangleNet
.Topology
{
using System;
using Animation.TriangleNet.Geometry;
/// <summary>
/// The triangle data structure.
/// </summary>
internal class Triangle : ITriangle
{
// Hash for dictionary. Will be set by mesh instance.
internal int hash;
// The ID is only used for mesh output.
internal int id;
internal Otri[] neighbors;
internal Vertex[] vertices;
internal Osub[] subsegs;
internal int label;
internal double area;
internal bool infected;
/// <summary>
/// Initializes a new instance of the <see cref="Triangle" /> class.
/// </summary>
public Triangle()
{
// Three NULL vertices.
vertices = new Vertex[3];
// Initialize the three adjoining subsegments to be the omnipresent subsegment.
subsegs = new Osub[3];
// Initialize the three adjoining triangles to be "outer space".
neighbors = new Otri[3];
// area = -1.0;
}
#region Public properties
/// <summary>
/// Gets or sets the triangle id.
/// </summary>
public int ID
{
get { return this.id; }
set { this.id = value; }
}
/// <summary>
/// Region ID the triangle belongs to.
/// </summary>
public int Label
{
get { return this.label; }
set { this.label = value; }
}
/// <summary>
/// Gets the triangle area constraint.
/// </summary>
public double Area
{
get { return this.area; }
set { this.area = value; }
}
/// <summary>
/// Gets the specified corners vertex.
/// </summary>
public Vertex GetVertex(int index)
{
return this.vertices[index]; // TODO: Check range?
}
public int GetVertexID(int index)
{
return this.vertices[index].id;
}
/// <summary>
/// Gets a triangles' neighbor.
/// </summary>
/// <param name="index">The neighbor index (0, 1 or 2).</param>
/// <returns>The neigbbor opposite of vertex with given index.</returns>
public ITriangle GetNeighbor(int index)
{
return neighbors[index].tri.hash == Mesh.DUMMY ? null : neighbors[index].tri;
}
/// <inheritdoc />
public int GetNeighborID(int index)
{
return neighbors[index].tri.hash == Mesh.DUMMY ? -1 : neighbors[index].tri.id;
}
/// <summary>
/// Gets a triangles segment.
/// </summary>
/// <param name="index">The vertex index (0, 1 or 2).</param>
/// <returns>The segment opposite of vertex with given index.</returns>
public ISegment GetSegment(int index)
{
return subsegs[index].seg.hash == Mesh.DUMMY ? null : subsegs[index].seg;
}
#endregion
public override int GetHashCode()
{
return this.hash;
}
public override string ToString()
{
return String.Format("TID {0}", hash);
}
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 277552e57c26b45f38d5c788700c1b7e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: