static void ComputeWinding(Tesselator tess, ActiveRegion reg) { reg.windingNumber = reg.RegionAbove().windingNumber + reg.upperHalfEdge.winding; reg.inside = tess.IsWindingInside(reg.windingNumber); }
static void AddRightEdges(Tesselator tess, ActiveRegion regUp, HalfEdge eFirst, HalfEdge eLast, HalfEdge eTopLeft, bool cleanUp) /* * Purpose: insert right-going edges into the edge dictionary, and update * winding numbers and mesh connectivity appropriately. All right-going * edges share a common origin vOrg. Edges are inserted CCW starting at * eFirst; the last edge inserted is eLast.Oprev. If vOrg has any * left-going edges already processed, then eTopLeft must be the edge * such that an imaginary upward vertical segment from vOrg would be * contained between eTopLeft.Oprev and eTopLeft; otherwise eTopLeft * should be null. */ { ActiveRegion reg, regPrev; HalfEdge e, ePrev; bool firstTime = true; /* Insert the new right-going edges in the dictionary */ e = eFirst; do { if (!e.originVertex.VertLeq(e.directionVertex)) { throw new Exception(); } AddRegionBelow(tess, regUp, e.otherHalfOfThisEdge); e = e.nextEdgeCCWAroundOrigin; } while (e != eLast); /* Walk *all* right-going edges from e.Org, in the dictionary order, * updating the winding numbers of each region, and re-linking the mesh * edges to match the dictionary ordering (if necessary). */ if (eTopLeft == null) { eTopLeft = RegionBelow(regUp).upperHalfEdge.Rprev; } regPrev = regUp; ePrev = eTopLeft; for (;;) { reg = RegionBelow(regPrev); e = reg.upperHalfEdge.otherHalfOfThisEdge; if (e.originVertex != ePrev.originVertex) break; if (e.nextEdgeCCWAroundOrigin != ePrev) { /* Unlink e from its current position, and relink below ePrev */ Mesh.meshSplice(e.Oprev, e); Mesh.meshSplice(ePrev.Oprev, e); } /* Compute the winding number and "inside" flag for the new regions */ reg.windingNumber = regPrev.windingNumber - e.winding; reg.inside = tess.IsWindingInside(reg.windingNumber); /* Check for two outgoing edges with same slope -- process these * before any intersection tests (see example in __gl_computeInterior). */ regPrev.dirty = true; if (!firstTime && CheckForRightSplice(tess, regPrev)) { AddWinding(e, ePrev); DeleteRegion(regPrev); Mesh.DeleteHalfEdge(ePrev); } firstTime = false; regPrev = reg; ePrev = e; } regPrev.dirty = true; if (regPrev.windingNumber - e.winding != reg.windingNumber) { throw new Exception(); } if (cleanUp) { /* Check for intersections between newly adjacent edges. */ WalkDirtyRegions(tess, regPrev); } }
/* * Purpose: insert right-going edges into the edge dictionary, and update * winding numbers and mesh connectivity appropriately. All right-going * edges share a common origin vOrg. Edges are inserted CCW starting at * eFirst; the last edge inserted is eLast.Oprev. If vOrg has any * left-going edges already processed, then eTopLeft must be the edge * such that an imaginary upward vertical segment from vOrg would be * contained between eTopLeft.Oprev and eTopLeft; otherwise eTopLeft * should be null. */ static void AddRightEdges(Tesselator tess, ActiveRegion regUp, HalfEdge eFirst, HalfEdge eLast, HalfEdge eTopLeft, bool cleanUp) { ActiveRegion reg, regPrev; HalfEdge e, ePrev; bool firstTime = true; /* Insert the new right-going edges in the dictionary */ e = eFirst; do { if (!e.originVertex.VertLeq(e.directionVertex)) { throw new Exception(); } AddRegionBelow(tess, regUp, e.otherHalfOfThisEdge); e = e.nextEdgeCCWAroundOrigin; } while (e != eLast); /* Walk *all* right-going edges from e.Org, in the dictionary order, * updating the winding numbers of each region, and re-linking the mesh * edges to match the dictionary ordering (if necessary). */ if (eTopLeft == null) { eTopLeft = RegionBelow(regUp).upperHalfEdge.Rprev; } regPrev = regUp; ePrev = eTopLeft; for (; ; ) { reg = RegionBelow(regPrev); e = reg.upperHalfEdge.otherHalfOfThisEdge; if (e.originVertex != ePrev.originVertex) break; if (e.nextEdgeCCWAroundOrigin != ePrev) { /* Unlink e from its current position, and relink below ePrev */ Mesh.meshSplice(e.Oprev, e); Mesh.meshSplice(ePrev.Oprev, e); } /* Compute the winding number and "inside" flag for the new regions */ reg.windingNumber = regPrev.windingNumber - e.winding; reg.inside = tess.IsWindingInside(reg.windingNumber); /* Check for two outgoing edges with same slope -- process these * before any intersection tests (see example in __gl_computeInterior). */ regPrev.dirty = true; if (!firstTime && CheckForRightSplice(tess, regPrev)) { AddWinding(e, ePrev); DeleteRegion(regPrev); Mesh.DeleteHalfEdge(ePrev); } firstTime = false; regPrev = reg; ePrev = e; } regPrev.dirty = true; if (regPrev.windingNumber - e.winding != reg.windingNumber) { throw new Exception(); } if (cleanUp) { /* Check for intersections between newly adjacent edges. */ WalkDirtyRegions(tess, regPrev); } }