Exemplo n.º 1
0
    /// <summary>
    /// 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.
    /// </summary>
    private void AddRightEdges(ActiveRegion regUp, MeshUtils.Edge eFirst, MeshUtils.Edge eLast, MeshUtils.Edge eTopLeft, bool cleanUp)
    {
        bool firstTime = true;

        MeshUtils.Edge e = eFirst; do
        {
            Debug.Assert(Geom.VertLeq(e._Org, e._Dst));
            AddRegionBelow(regUp, e._Sym);
            e = e._Onext;
        } while (e != eLast);

        eTopLeft = eTopLeft switch
        {
            // 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).
            null => RegionBelow(regUp)._eUp._Rprev,
            _ => eTopLeft
        };

        ActiveRegion regPrev = regUp, reg;

        MeshUtils.Edge ePrev = eTopLeft;
        while (true)
        {
            reg = RegionBelow(regPrev);
            e   = reg._eUp._Sym;
            if (e._Org != ePrev._Org)
            {
                break;
            }

            if (e._Onext != ePrev)
            {
                // Unlink e from its current position, and relink below ePrev
                Mesh.Splice(_pool, e._Oprev, e);
                Mesh.Splice(_pool, ePrev._Oprev, e);
            }
            // Compute the winding number and "inside" flag for the new regions
            reg._windingNumber = regPrev._windingNumber - e._winding;
            reg._inside        = Geom.IsWindingInside(_windingRule, reg._windingNumber);

            // Check for two outgoing edges with same slope -- process these
            // before any intersection tests (see example in tessComputeInterior).
            regPrev._dirty = true;
            switch (firstTime)
            {
            case false when CheckForRightSplice(regPrev):
                Geom.AddWinding(e, ePrev);

                DeleteRegion(regPrev);
                Mesh.Delete(_pool, ePrev);
                break;
            }
            firstTime = false;
            regPrev   = reg;
            ePrev     = e;
        }
        regPrev._dirty = true;
        Debug.Assert(regPrev._windingNumber - e._winding == reg._windingNumber);

        switch (cleanUp)
        {
        case true:
            // Check for intersections between newly adjacent edges.
            WalkDirtyRegions(regPrev);
            break;
        }
    }