EdgeSign() public static method

Returns a number whose sign matches EdgeEval(u,v,w) but which is cheaper to evaluate. Returns > 0, == 0 , or < 0 as v is above, on, or below the edge uw.
public static EdgeSign ( LibTessDotNet.MeshUtils.Vertex u, LibTessDotNet.MeshUtils.Vertex v, LibTessDotNet.MeshUtils.Vertex w ) : Real
u LibTessDotNet.MeshUtils.Vertex
v LibTessDotNet.MeshUtils.Vertex
w LibTessDotNet.MeshUtils.Vertex
return Real
示例#1
0
        private bool EdgeLeq(ActiveRegion reg1, ActiveRegion reg2)
        {
            MeshUtils.Edge eUp  = reg1._eUp;
            MeshUtils.Edge eUp2 = reg2._eUp;
            if (eUp._Dst == _event)
            {
                if (eUp2._Dst == _event)
                {
                    if (Geom.VertLeq(eUp._Org, eUp2._Org))
                    {
                        return(Geom.EdgeSign(eUp2._Dst, eUp._Org, eUp2._Org) <= 0f);
                    }
                    return(Geom.EdgeSign(eUp._Dst, eUp2._Org, eUp._Org) >= 0f);
                }
                return(Geom.EdgeSign(eUp2._Dst, _event, eUp2._Org) <= 0f);
            }
            if (eUp2._Dst == _event)
            {
                return(Geom.EdgeSign(eUp._Dst, _event, eUp._Org) >= 0f);
            }
            float num  = Geom.EdgeEval(eUp._Dst, _event, eUp._Org);
            float num2 = Geom.EdgeEval(eUp2._Dst, _event, eUp2._Org);

            return(num >= num2);
        }
示例#2
0
        private bool CheckForLeftSplice(ActiveRegion regUp)
        {
            ActiveRegion activeRegion = RegionBelow(regUp);

            MeshUtils.Edge eUp  = regUp._eUp;
            MeshUtils.Edge eUp2 = activeRegion._eUp;
            if (Geom.VertLeq(eUp._Dst, eUp2._Dst))
            {
                if (Geom.EdgeSign(eUp._Dst, eUp2._Dst, eUp._Org) < 0f)
                {
                    return(false);
                }
                RegionAbove(regUp)._dirty = (regUp._dirty = true);
                MeshUtils.Edge edge = _mesh.SplitEdge(eUp);
                _mesh.Splice(eUp2._Sym, edge);
                edge._Lface._inside = regUp._inside;
            }
            else
            {
                if (Geom.EdgeSign(eUp2._Dst, eUp._Dst, eUp2._Org) > 0f)
                {
                    return(false);
                }
                regUp._dirty = (activeRegion._dirty = true);
                MeshUtils.Edge edge2 = _mesh.SplitEdge(eUp2);
                _mesh.Splice(eUp._Lnext, eUp2._Sym);
                edge2._Rface._inside = regUp._inside;
            }
            return(true);
        }
示例#3
0
        /// <summary>
        /// TessellateMonoRegion( 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).
        /// </summary>
        private void TessellateMonoRegion(MeshUtils.Face face)
        {
            // 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.
            var up = face._anEdge;

            Debug.Assert(up._Lnext != up && up._Lnext._Lnext != up);

            int dummy = 0;

            for (; Geom.VertLeq(up._Dst, up._Org); up = up._Lprev)
            {
                dummy += 1;
            }
            for (; Geom.VertLeq(up._Org, up._Dst); up = up._Lnext)
            {
                dummy += 1;
            }

            var lo = up._Lprev;

            while (up._Lnext != lo)
            {
                if (Geom.VertLeq(up._Dst, lo._Org))
                {
                    // up.Dst 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._Dst, lo._Lnext._Dst) <= 0.0f))
                    {
                        lo = _mesh.Connect(lo._Lnext, lo)._Sym;
                    }
                    lo = lo._Lprev;
                }
                else
                {
                    // lo.Org is on the left.  We can make CCW triangles from up.Dst.
                    while (lo._Lnext != up && (Geom.EdgeGoesRight(up._Lprev) ||
                                               Geom.EdgeSign(up._Dst, up._Org, up._Lprev._Org) >= 0.0f))
                    {
                        up = _mesh.Connect(up, up._Lprev)._Sym;
                    }
                    up = up._Lnext;
                }
            }

            // Now lo.Org == up.Dst == the leftmost vertex.  The remaining region
            // can be tessellated in a fan from this leftmost vertex.
            Debug.Assert(lo._Lnext != up);
            while (lo._Lnext._Lnext != up)
            {
                lo = _mesh.Connect(lo._Lnext, lo)._Sym;
            }
        }
示例#4
0
        private void ConnectLeftVertex(MeshUtils.Vertex vEvent)
        {
            ActiveRegion activeRegion = new ActiveRegion();

            activeRegion._eUp = vEvent._anEdge._Sym;
            ActiveRegion key           = _dict.Find(activeRegion).Key;
            ActiveRegion activeRegion2 = RegionBelow(key);

            if (activeRegion2 != null)
            {
                MeshUtils.Edge eUp  = key._eUp;
                MeshUtils.Edge eUp2 = activeRegion2._eUp;
                if (Geom.EdgeSign(eUp._Dst, vEvent, eUp._Org) == 0f)
                {
                    ConnectLeftDegenerate(key, vEvent);
                }
                else
                {
                    ActiveRegion activeRegion3 = Geom.VertLeq(eUp2._Dst, eUp._Dst) ? key : activeRegion2;
                    if (key._inside || activeRegion3._fixUpperEdge)
                    {
                        MeshUtils.Edge edge = (activeRegion3 != key) ? _mesh.Connect(eUp2._Dnext, vEvent._anEdge)._Sym : _mesh.Connect(vEvent._anEdge._Sym, eUp._Lnext);
                        if (activeRegion3._fixUpperEdge)
                        {
                            FixUpperEdge(activeRegion3, edge);
                        }
                        else
                        {
                            ComputeWinding(AddRegionBelow(key, edge));
                        }
                        SweepEvent(vEvent);
                    }
                    else
                    {
                        AddRightEdges(key, vEvent._anEdge, vEvent._anEdge, null, true);
                    }
                }
            }
        }
示例#5
0
        private bool CheckForRightSplice(ActiveRegion regUp)
        {
            ActiveRegion activeRegion = RegionBelow(regUp);

            MeshUtils.Edge eUp  = regUp._eUp;
            MeshUtils.Edge eUp2 = activeRegion._eUp;
            if (Geom.VertLeq(eUp._Org, eUp2._Org))
            {
                if (Geom.EdgeSign(eUp2._Dst, eUp._Org, eUp2._Org) > 0f)
                {
                    return(false);
                }
                if (!Geom.VertEq(eUp._Org, eUp2._Org))
                {
                    _mesh.SplitEdge(eUp2._Sym);
                    _mesh.Splice(eUp, eUp2._Oprev);
                    regUp._dirty = (activeRegion._dirty = true);
                }
                else if (eUp._Org != eUp2._Org)
                {
                    _pq.Remove(eUp._Org._pqHandle);
                    SpliceMergeVertices(eUp2._Oprev, eUp);
                }
            }
            else
            {
                if (Geom.EdgeSign(eUp._Dst, eUp2._Org, eUp._Org) < 0f)
                {
                    return(false);
                }
                RegionAbove(regUp)._dirty = (regUp._dirty = true);
                _mesh.SplitEdge(eUp._Sym);
                _mesh.Splice(eUp2._Oprev, eUp);
            }
            return(true);
        }
示例#6
0
        private bool CheckForIntersect(ActiveRegion regUp)
        {
            ActiveRegion activeRegion = RegionBelow(regUp);

            MeshUtils.Edge   eUp  = regUp._eUp;
            MeshUtils.Edge   eUp2 = activeRegion._eUp;
            MeshUtils.Vertex org  = eUp._Org;
            MeshUtils.Vertex org2 = eUp2._Org;
            MeshUtils.Vertex dst  = eUp._Dst;
            MeshUtils.Vertex dst2 = eUp2._Dst;
            if (org == org2)
            {
                return(false);
            }
            float num  = Math.Min(org._t, dst._t);
            float num2 = Math.Max(org2._t, dst2._t);

            if (num > num2)
            {
                return(false);
            }
            if (Geom.VertLeq(org, org2))
            {
                if (Geom.EdgeSign(dst2, org, org2) > 0f)
                {
                    return(false);
                }
            }
            else if (Geom.EdgeSign(dst, org2, org) < 0f)
            {
                return(false);
            }
            MeshUtils.Vertex vertex = MeshUtils.Pooled <MeshUtils.Vertex> .Create();

            Geom.EdgeIntersect(dst, org, dst2, org2, vertex);
            if (Geom.VertLeq(vertex, _event))
            {
                vertex._s = _event._s;
                vertex._t = _event._t;
            }
            MeshUtils.Vertex vertex2 = Geom.VertLeq(org, org2) ? org : org2;
            if (Geom.VertLeq(vertex2, vertex))
            {
                vertex._s = vertex2._s;
                vertex._t = vertex2._t;
            }
            if (Geom.VertEq(vertex, org) || Geom.VertEq(vertex, org2))
            {
                CheckForRightSplice(regUp);
                return(false);
            }
            if ((!Geom.VertEq(dst, _event) && Geom.EdgeSign(dst, _event, vertex) >= 0f) || (!Geom.VertEq(dst2, _event) && Geom.EdgeSign(dst2, _event, vertex) <= 0f))
            {
                if (dst2 == _event)
                {
                    _mesh.SplitEdge(eUp._Sym);
                    _mesh.Splice(eUp2._Sym, eUp);
                    regUp = TopLeftRegion(regUp);
                    eUp   = RegionBelow(regUp)._eUp;
                    FinishLeftRegions(RegionBelow(regUp), activeRegion);
                    ActiveRegion   regUp2 = regUp;
                    MeshUtils.Edge oprev  = eUp._Oprev;
                    MeshUtils.Edge edge   = eUp;
                    AddRightEdges(regUp2, oprev, edge, edge, true);
                    return(true);
                }
                if (dst == _event)
                {
                    _mesh.SplitEdge(eUp2._Sym);
                    _mesh.Splice(eUp._Lnext, eUp2._Oprev);
                    activeRegion = regUp;
                    regUp        = TopRightRegion(regUp);
                    MeshUtils.Edge rprev = RegionBelow(regUp)._eUp._Rprev;
                    activeRegion._eUp = eUp2._Oprev;
                    eUp2 = FinishLeftRegions(activeRegion, null);
                    AddRightEdges(regUp, eUp2._Onext, eUp._Rprev, rprev, true);
                    return(true);
                }
                if (Geom.EdgeSign(dst, _event, vertex) >= 0f)
                {
                    RegionAbove(regUp)._dirty = (regUp._dirty = true);
                    _mesh.SplitEdge(eUp._Sym);
                    eUp._Org._s = _event._s;
                    eUp._Org._t = _event._t;
                }
                if (Geom.EdgeSign(dst2, _event, vertex) <= 0f)
                {
                    regUp._dirty = (activeRegion._dirty = true);
                    _mesh.SplitEdge(eUp2._Sym);
                    eUp2._Org._s = _event._s;
                    eUp2._Org._t = _event._t;
                }
                return(false);
            }
            _mesh.SplitEdge(eUp._Sym);
            _mesh.SplitEdge(eUp2._Sym);
            _mesh.Splice(eUp2._Oprev, eUp);
            eUp._Org._s        = vertex._s;
            eUp._Org._t        = vertex._t;
            eUp._Org._pqHandle = _pq.Insert(eUp._Org);
            if (eUp._Org._pqHandle._handle == PQHandle.Invalid)
            {
                throw new InvalidOperationException("PQHandle should not be invalid");
            }
            GetIntersectData(eUp._Org, org, dst, org2, dst2);
            RegionAbove(regUp)._dirty = (regUp._dirty = (activeRegion._dirty = true));
            return(false);
        }
示例#7
0
 private void TessellateMonoRegion(MeshUtils.Face face)
 {
     MeshUtils.Edge edge = face._anEdge;
     while (Geom.VertLeq(edge._Dst, edge._Org))
     {
         edge = edge._Lprev;
     }
     while (Geom.VertLeq(edge._Org, edge._Dst))
     {
         edge = edge._Lnext;
     }
     MeshUtils.Edge edge2 = edge._Lprev;
     while (edge._Lnext != edge2)
     {
         if (Geom.VertLeq(edge._Dst, edge2._Org))
         {
             while (edge2._Lnext != edge && (Geom.EdgeGoesLeft(edge2._Lnext) || Geom.EdgeSign(edge2._Org, edge2._Dst, edge2._Lnext._Dst) <= 0f))
             {
                 edge2 = _mesh.Connect(edge2._Lnext, edge2)._Sym;
             }
             edge2 = edge2._Lprev;
         }
         else
         {
             while (edge2._Lnext != edge && (Geom.EdgeGoesRight(edge._Lprev) || Geom.EdgeSign(edge._Dst, edge._Org, edge._Lprev._Org) >= 0f))
             {
                 Mesh           mesh  = _mesh;
                 MeshUtils.Edge edge3 = edge;
                 edge = mesh.Connect(edge3, edge3._Lprev)._Sym;
             }
             edge = edge._Lnext;
         }
     }
     while (edge2._Lnext._Lnext != edge)
     {
         edge2 = _mesh.Connect(edge2._Lnext, edge2)._Sym;
     }
 }