static void Swap(ref MeshUtils.Vertex a, ref MeshUtils.Vertex b) { var tmp = a; a = b; b = tmp; }
public static float TransSign(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w) { Debug.Assert(TransLeq(u, v) && TransLeq(v, w)); float gapL = v._t - u._t; float gapR = w._t - v._t; if (gapL + gapR > 0.0f) { return((v._s - w._s) * gapL + (v._s - u._s) * gapR); } /* vertical line */ return(0.0f); }
/// <summary> /// Returns a number whose sign matches EdgeEval(u,v,w) but which /// is cheaper to evaluate. Returns > 0, == 0 , or less than 0 /// as v is above, on, or below the edge uw. /// </summary> public static float EdgeSign(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w) { // Debug.Assert(VertLeq(u, v) && VertLeq(v, w)); float gapL = v._s - u._s; float gapR = w._s - v._s; if (gapL + gapR > 0.0f) { return((v._t - w._t) * gapL + (v._t - u._t) * gapR); } /* vertical line */ return(0.0f); }
/// <summary> /// Given three vertices u,v,w such that VertLeq(u,v) .and. VertLeq(v,w), /// evaluates the t-coord of the edge uw at the s-coord of the vertex v. /// Returns v->t - (uw)(v->s), ie. the signed distance from uw to v. /// If uw is vertical (and thus passes thru v), the result is zero. /// /// The calculation is extremely accurate and stable, even when v /// is very close to u or w. In particular if we set v->t = 0 and /// let r be the negated result (this evaluates (uw)(v->s)), then /// r is guaranteed to satisfy MIN(u->t,w->t) less than or equal r less than or equal MAX(u->t,w->t). /// </summary> public static float EdgeEval(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w) { Debug.Assert(VertLeq(u, v) && VertLeq(v, w)); float gapL = v._s - u._s; float gapR = w._s - v._s; if (gapL + gapR > 0.0f) { if (gapL < gapR) { return((v._t - u._t) + (u._t - w._t) * (gapL / (gapL + gapR))); } return((v._t - w._t) + (w._t - u._t) * (gapR / (gapL + gapR))); } /* vertical line */ return(0.0f); }
public static float TransEval(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w) { Debug.Assert(TransLeq(u, v) && TransLeq(v, w)); float gapL = v._t - u._t; float gapR = w._t - v._t; if (gapL + gapR > 0.0f) { if (gapL < gapR) { return((v._s - u._s) + (u._s - w._s) * (gapL / (gapL + gapR))); } return((v._s - w._s) + (w._s - u._s) * (gapR / (gapL + gapR))); } /* vertical line */ return(0.0f); }
// ReSharper restore InconsistentNaming public Mesh() { var v = _vHead = new MeshUtils.Vertex(); var f = _fHead = new MeshUtils.Face(); var pair = MeshUtils.EdgePair.Create(); var e = _eHead = pair._e; var eSym = _eHeadSym = pair._eSym; v._next = v._prev = v; v._anEdge = null; f._next = f._prev = f; f._anEdge = null; f._trail = null; f._marked = false; f._inside = false; e._next = e; e._Sym = eSym; e._Onext = null; e._Lnext = null; e._Org = null; e._Lface = null; e._winding = 0; e._activeRegion = null; eSym._next = eSym; eSym._Sym = e; eSym._Onext = null; eSym._Lnext = null; eSym._Org = null; eSym._Lface = null; eSym._winding = 0; eSym._activeRegion = null; }
public static bool VertLeq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs) { // ReSharper disable CompareOfFloatsByEqualityOperator return((lhs._s < rhs._s) || (lhs._s == rhs._s && lhs._t <= rhs._t)); // ReSharper restore CompareOfFloatsByEqualityOperator }
public static bool VertCcw(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w) { return((u._s * (v._t - w._t) + v._s * (w._t - u._t) + w._s * (u._t - v._t)) >= 0.0f); }
/// <summary> /// Given edges (o1,d1) and (o2,d2), compute their point of intersection. /// The computed point is guaranteed to lie in the intersection of the /// bounding rectangles defined by each edge. /// </summary> public static void EdgeIntersect(MeshUtils.Vertex o1, MeshUtils.Vertex d1, MeshUtils.Vertex o2, MeshUtils.Vertex d2, MeshUtils.Vertex v) { float z1, z2; // This is certainly not the most efficient way to find the intersection // of two line segments, but it is very numerically stable. // // Strategy: find the two middle vertices in the VertLeq ordering, // and interpolate the intersection s-value from these. Then repeat // using the TransLeq ordering to find the intersection t-value. if (!VertLeq(o1, d1)) { Swap(ref o1, ref d1); } if (!VertLeq(o2, d2)) { Swap(ref o2, ref d2); } if (!VertLeq(o1, o2)) { Swap(ref o1, ref o2); Swap(ref d1, ref d2); } if (!VertLeq(o2, d1)) { // Technically, no intersection -- do our best v._s = (o2._s + d1._s) / 2.0f; } else if (VertLeq(d1, d2)) { // Interpolate between o2 and d1 z1 = EdgeEval(o1, o2, d1); z2 = EdgeEval(o2, d1, d2); if (z1 + z2 < 0.0f) { z1 = -z1; z2 = -z2; } v._s = Interpolate(z1, o2._s, z2, d1._s); } else { // Interpolate between o2 and d2 z1 = EdgeSign(o1, o2, d1); z2 = -EdgeSign(o1, d2, d1); if (z1 + z2 < 0.0f) { z1 = -z1; z2 = -z2; } v._s = Interpolate(z1, o2._s, z2, d2._s); } // Now repeat the process for t if (!TransLeq(o1, d1)) { Swap(ref o1, ref d1); } if (!TransLeq(o2, d2)) { Swap(ref o2, ref d2); } if (!TransLeq(o1, o2)) { Swap(ref o1, ref o2); Swap(ref d1, ref d2); } if (!TransLeq(o2, d1)) { // Technically, no intersection -- do our best v._t = (o2._t + d1._t) / 2.0f; } else if (TransLeq(d1, d2)) { // Interpolate between o2 and d1 z1 = TransEval(o1, o2, d1); z2 = TransEval(o2, d1, d2); if (z1 + z2 < 0.0f) { z1 = -z1; z2 = -z2; } v._t = Interpolate(z1, o2._t, z2, d1._t); } else { // Interpolate between o2 and d2 z1 = TransSign(o1, o2, d1); z2 = -TransSign(o1, d2, d1); if (z1 + z2 < 0.0f) { z1 = -z1; z2 = -z2; } v._t = Interpolate(z1, o2._t, z2, d2._t); } }
public static float VertL1Dist(MeshUtils.Vertex u, MeshUtils.Vertex v) { return(Math.Abs(u._s - v._s) + Math.Abs(u._t - v._t)); }