Example #1
0
        /* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
         * (what else would it do??)  The region must consist of a single
         * loop of half-edges (see mesh.h) oriented CCW.  "Monotone" in this
         * case means that any vertical line intersects the interior of the
         * region in a single interval.
         *
         * Tessellation consists of adding interior edges (actually pairs of
         * half-edges), to split the region into non-overlapping triangles.
         *
         * The basic idea is explained in Preparata and Shamos (which I don''t
         * have handy right now), although their implementation is more
         * complicated than this one.  The are two edge chains, an upper chain
         * and a lower chain.  We process all vertices from both chains in order,
         * from right to left.
         *
         * The algorithm ensures that the following invariant holds after each
         * vertex is processed: the untessellated region consists of two
         * chains, where one chain (say the upper) is a single edge, and
         * the other chain is concave.  The left vertex of the single edge
         * is always to the left of all vertices in the concave chain.
         *
         * Each step consists of adding the rightmost unprocessed vertex to one
         * of the two chains, and forming a fan of triangles from the rightmost
         * of two chain endpoints.  Determining whether we can add each triangle
         * to the fan is a simple orientation test.  By making the fan as large
         * as possible, we restore the invariant (check it yourself).
         */
        internal static bool __gl_meshTessellateMonoRegion(GLUface face)
        {
            GLUhalfEdge up, lo;

            /* All edges are oriented CCW around the boundary of the region.
             * First, find the half-edge whose origin vertex is rightmost.
             * Since the sweep goes from left to right, face->anEdge should
             * be close to the edge we want.
             */
            up = face.anEdge;
            //assert(up.Lnext != up && up.Lnext.Lnext != up);

            for (; Geom.VertLeq(up.Sym.Org, up.Org); up = up.Onext.Sym)
            {
                ;
            }
            for (; Geom.VertLeq(up.Org, up.Sym.Org); up = up.Lnext)
            {
                ;
            }
            lo = up.Onext.Sym;

            while (up.Lnext != lo)
            {
                if (Geom.VertLeq(up.Sym.Org, lo.Org))
                {
                    /* up.Sym.Org is on the left.  It is safe to form triangles from lo.Org.
                     * The EdgeGoesLeft test guarantees progress even when some triangles
                     * are CW, given that the upper and lower chains are truly monotone.
                     */
                    while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext) || Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0))
                    {
                        GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
                        if (tempHalfEdge == null)
                        {
                            return(false);
                        }
                        lo = tempHalfEdge.Sym;
                    }
                    lo = lo.Onext.Sym;
                }
                else
                {
                    /* lo.Org is on the left.  We can make CCW triangles from up.Sym.Org. */
                    while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym) || Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0))
                    {
                        GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym);
                        if (tempHalfEdge == null)
                        {
                            return(false);
                        }
                        up = tempHalfEdge.Sym;
                    }
                    up = up.Lnext;
                }
            }

            /* Now lo.Org == up.Sym.Org == the leftmost vertex.  The remaining region
             * can be tessellated in a fan from this leftmost vertex.
             */
            //assert(lo.Lnext != up);
            while (lo.Lnext.Lnext != up)
            {
                GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
                if (tempHalfEdge == null)
                {
                    return(false);
                }
                lo = tempHalfEdge.Sym;
            }

            return(true);
        }
Example #2
0
        /* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
        * (what else would it do??)  The region must consist of a single
        * loop of half-edges (see mesh.h) oriented CCW.  "Monotone" in this
        * case means that any vertical line intersects the interior of the
        * region in a single interval.
        *
        * Tessellation consists of adding interior edges (actually pairs of
        * half-edges), to split the region into non-overlapping triangles.
        *
        * The basic idea is explained in Preparata and Shamos (which I don''t
        * have handy right now), although their implementation is more
        * complicated than this one.  The are two edge chains, an upper chain
        * and a lower chain.  We process all vertices from both chains in order,
        * from right to left.
        *
        * The algorithm ensures that the following invariant holds after each
        * vertex is processed: the untessellated region consists of two
        * chains, where one chain (say the upper) is a single edge, and
        * the other chain is concave.  The left vertex of the single edge
        * is always to the left of all vertices in the concave chain.
        *
        * Each step consists of adding the rightmost unprocessed vertex to one
        * of the two chains, and forming a fan of triangles from the rightmost
        * of two chain endpoints.  Determining whether we can add each triangle
        * to the fan is a simple orientation test.  By making the fan as large
        * as possible, we restore the invariant (check it yourself).
        */
        internal static bool __gl_meshTessellateMonoRegion(GLUface face)
        {
            GLUhalfEdge up, lo;

            /* All edges are oriented CCW around the boundary of the region.
            * First, find the half-edge whose origin vertex is rightmost.
            * Since the sweep goes from left to right, face->anEdge should
            * be close to the edge we want.
            */
            up = face.anEdge;
            //assert(up.Lnext != up && up.Lnext.Lnext != up);

            for (; Geom.VertLeq(up.Sym.Org, up.Org); up = up.Onext.Sym)
                ;
            for (; Geom.VertLeq(up.Org, up.Sym.Org); up = up.Lnext)
                ;
            lo = up.Onext.Sym;

            while (up.Lnext != lo)
            {
                if (Geom.VertLeq(up.Sym.Org, lo.Org))
                {
                    /* up.Sym.Org is on the left.  It is safe to form triangles from lo.Org.
                    * The EdgeGoesLeft test guarantees progress even when some triangles
                    * are CW, given that the upper and lower chains are truly monotone.
                    */
                    while (lo.Lnext != up && (Geom.EdgeGoesLeft(lo.Lnext) || Geom.EdgeSign(lo.Org, lo.Sym.Org, lo.Lnext.Sym.Org) <= 0))
                    {
                        GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
                        if (tempHalfEdge == null)
                            return false;
                        lo = tempHalfEdge.Sym;
                    }
                    lo = lo.Onext.Sym;
                }
                else
                {
                    /* lo.Org is on the left.  We can make CCW triangles from up.Sym.Org. */
                    while (lo.Lnext != up && (Geom.EdgeGoesRight(up.Onext.Sym) || Geom.EdgeSign(up.Sym.Org, up.Org, up.Onext.Sym.Org) >= 0))
                    {
                        GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(up, up.Onext.Sym);
                        if (tempHalfEdge == null)
                            return false;
                        up = tempHalfEdge.Sym;
                    }
                    up = up.Lnext;
                }
            }

            /* Now lo.Org == up.Sym.Org == the leftmost vertex.  The remaining region
            * can be tessellated in a fan from this leftmost vertex.
            */
            //assert(lo.Lnext != up);
            while (lo.Lnext.Lnext != up)
            {
                GLUhalfEdge tempHalfEdge = Mesh.__gl_meshConnect(lo.Lnext, lo);
                if (tempHalfEdge == null)
                    return false;
                lo = tempHalfEdge.Sym;
            }

            return true;
        }