rj-action-library/External/Triangle.NET/Triangle/Topology/Otri.cs

482 lines
14 KiB
C#

// -----------------------------------------------------------------------
// <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 TriangleNet.Topology
{
using System;
using 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>
public 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
}
}