public void Check()
{
MeshUtils.Edge e;
MeshUtils.Face fPrev = _fHead, f;
for (fPrev = _fHead; (f = fPrev._next) != _fHead; fPrev = f)
{
e = f._anEdge;
do {
Debug.Assert(e._Sym != e);
Debug.Assert(e._Sym._Sym == e);
Debug.Assert(e._Lnext._Onext._Sym == e);
Debug.Assert(e._Onext._Sym._Lnext == e);
Debug.Assert(e._Lface == f);
e = e._Lnext;
} while (e != f._anEdge);
}
Debug.Assert(f._prev == fPrev && f._anEdge == null);
MeshUtils.Vertex vPrev = _vHead, v;
for (vPrev = _vHead; (v = vPrev._next) != _vHead; vPrev = v)
{
Debug.Assert(v._prev == vPrev);
e = v._anEdge;
do
{
Debug.Assert(e._Sym != e);
Debug.Assert(e._Sym._Sym == e);
Debug.Assert(e._Lnext._Onext._Sym == e);
Debug.Assert(e._Onext._Sym._Lnext == e);
Debug.Assert(e._Org == v);
e = e._Onext;
} while (e != v._anEdge);
}
Debug.Assert(v._prev == vPrev && v._anEdge == null);
MeshUtils.Edge ePrev = _eHead;
for (ePrev = _eHead; (e = ePrev._next) != _eHead; ePrev = e)
{
Debug.Assert(e._Sym._next == ePrev._Sym);
Debug.Assert(e._Sym != e);
Debug.Assert(e._Sym._Sym == e);
Debug.Assert(e._Org != null);
Debug.Assert(e._Dst != null);
Debug.Assert(e._Lnext._Onext._Sym == e);
Debug.Assert(e._Onext._Sym._Lnext == e);
}
Debug.Assert(e._Sym._next == ePrev._Sym
&& e._Sym == _eHeadSym
&& e._Sym._Sym == e
&& e._Org == null && e._Dst == null
&& e._Lface == null && e._Rface == null);
}
}
/// <summary> /// Tessellates the input contours. /// </summary> /// <param name="windingRule"> Winding rule used for tessellation. See <see cref="WindingRule"/> for details. </param> /// <param name="elementType"> Tessellation output type. See <see cref="ElementType"/> for details. </param> /// <param name="polySize"> Number of vertices per polygon if output is polygons. </param> /// <param name="combineCallback"> Interpolator used to determine the data payload of generated vertices. </param> /// <param name="normal"> Normal of the input contours. If set to zero, the normal will be calculated during tessellation. </param> public void Tessellate(WindingRule windingRule = WindingRule.EvenOdd, ElementType elementType = ElementType.Polygons, int polySize = 3, CombineCallback combineCallback = null, Vec3 normal = new Vec3()) { _normal = normal; _vertices = null; _elements = null; _windingRule = windingRule; _combineCallback = combineCallback; if (_mesh == null) { return; } // Determine the polygon normal and project vertices onto the plane // of the polygon. ProjectPolygon(); // ComputeInterior computes the planar arrangement specified // by the given contours, and further subdivides this arrangement // into regions. Each region is marked "inside" if it belongs // to the polygon, according to the rule given by windingRule. // Each interior region is guaranteed be monotone. ComputeInterior(); // If the user wants only the boundary contours, we throw away all edges // except those which separate the interior from the exterior. // Otherwise we tessellate all the regions marked "inside". if (elementType == ElementType.BoundaryContours) { SetWindingNumber(1, true); } else { TessellateInterior(); } _mesh.Check(); if (elementType == ElementType.BoundaryContours) { OutputContours(); } else { OutputPolymesh(elementType, polySize); } _pool.Return(_mesh); _mesh = null; }