private TriangulatedSet Triangulate(int _beginId, int _endId, int _depth)
        {
            // Number of points in this set
            int size = _endId - _beginId + 1;

            if (size == 2) // Segment
            {
                HalfEdge h = CreateHalfEdge(_beginId, _endId);

                return(new TriangulatedSet(h.twin, h.twin));
            }
            else if (size == 3) // Triangle
            {
                HalfEdge hA = CreateHalfEdge(_beginId, _beginId + 1);
                HalfEdge hB = CreateHalfEdge(_beginId + 1, _endId);
                ConnectHalfedges(hA, hB);

                // A,B,C are in CCW, which means A,B,C are inner halfedges
                if (IsCcw(m_vertice[_beginId], m_vertice[_beginId + 1], m_vertice[_endId]))
                {
                    // DONOT delete this line since it update other connection infomation
                    HalfEdge hC = BridgeHalfedges(hB, hA);
                    return(new TriangulatedSet(hA.twin, hB.twin));
                }
                // A,B,C are in CW, which means A,B,C are outer halfedges
                else if (IsCcw(m_vertice[_beginId], m_vertice[_endId], m_vertice[_beginId + 1]))
                {
                    HalfEdge hC = BridgeHalfedges(hB, hA);
                    return(new TriangulatedSet(hC, hC));
                }
                else
                {
                    return(new TriangulatedSet(hA.twin, hB.twin));
                }
            }
            else // size >= 4, Separate
            {
                // Recursively delaunay triangulate L and R halves
                TriangulatedSet leftSet  = Triangulate(_beginId, _beginId + (size / 2) - 1, _depth + 1);
                TriangulatedSet rightSet = Triangulate(_beginId + (size / 2), _endId, _depth + 1);
                HalfEdge        LLh      = leftSet.leftHalfedge;
                HalfEdge        LRh      = leftSet.rightHalfedge;
                HalfEdge        RLh      = rightSet.leftHalfedge;
                HalfEdge        RRh      = rightSet.rightHalfedge;

                // Compute the lowest common tangent of L and R
                while (true)
                {
                    if (IsLeftOf(RLh.DstId, LRh))
                    {
                        LRh = LRh.next;
                    }
                    else if (IsLeftOf(LRh.orgId, RLh))
                    {
                        RLh = RLh.Prev;
                    }
                    else
                    {
                        break;
                    }
                }

                HalfEdge baseH = BridgeHalfedges(RLh, LRh);
                if (LRh.orgId == LLh.DstId)
                {
                    LLh = baseH;
                }
                if (RLh.DstId == RRh.orgId)
                {
                    RRh = baseH;
                }

                // Merge
                while (true)
                {
                    // Locate the first L point (Lcand.Org) to be encountered by the rising bubble
                    // and delete L edges that fail the circle test
                    HalfEdge Lcand = baseH.twin.Prev;
                    if (IsLeftOf(Lcand.orgId, baseH.twin))
                    {
                        while (IsInCircle(
                                   baseH.DstId,
                                   baseH.orgId,
                                   Lcand.orgId,
                                   Lcand.twin.Prev.orgId))
                        {
                            HalfEdge nextLcand = Lcand.twin.Prev;
                            DeleteHalfedge(Lcand);
                            Lcand = nextLcand;
                        }
                    }

                    HalfEdge Rcand = baseH.twin.next;
                    if (IsLeftOf(Rcand.DstId, baseH.twin))
                    {
                        while (IsInCircle(
                                   baseH.DstId,
                                   baseH.orgId,
                                   Rcand.DstId,
                                   Rcand.twin.next.DstId))
                        {
                            HalfEdge nextRcand = Rcand.twin.next;
                            DeleteHalfedge(Rcand);
                            Rcand = nextRcand;
                        }
                    }

                    // If both Lcand and Rcand are invalid, then baseH is the upper common tangent
                    if (IsLeftOf(Lcand.orgId, baseH.twin) == false && IsLeftOf(Rcand.DstId, baseH.twin) == false)
                    {
                        break;
                    }

                    // The next cross halfedge is to be connected to either Lcand.Org or rcand.Dst
                    // if both are valid, then choose the appropriate one using the inCircle test
                    if (IsLeftOf(Lcand.orgId, baseH.twin) && IsInCircle(Lcand.orgId, baseH.DstId, baseH.orgId, Rcand.DstId) == false)
                    {
                        baseH = BridgeHalfedges(baseH.twin, Lcand);
                    }
                    else
                    {
                        baseH = BridgeHalfedges(Rcand, baseH.twin);
                    }
                }

                return(new TriangulatedSet(LLh, RRh));
            }
        }
 /// <summary>
 /// Exclusive right
 /// </summary>
 /// <param name="_vId"></param>
 /// <param name="_h"></param>
 /// <returns></returns>
 private bool IsRightOf(int _vId, HalfEdge _h)
 {
     return(!IsNotCw(m_vertice[_vId], m_vertice[_h.orgId], m_vertice[_h.DstId]));
 }
 /// <summary>
 /// Exclusive left
 /// </summary>
 /// <param name="_vId"></param>
 /// <param name="_h"></param>
 /// <returns></returns>
 private bool IsLeftOf(int _vId, HalfEdge _h)
 {
     return(IsCcw(m_vertice[_vId], m_vertice[_h.orgId], m_vertice[_h.DstId]));
 }
 /// <summary>
 /// _hB should always be the isolated one to detach, _hA should be the base one.
 ///    _hB\ \
 ///        \ \
 /// _hA ----   ---
 /// </summary>
 /// <param name="_hA"></param>
 /// <param name="_hB"></param>
 private void DisconnectHalfedges(HalfEdge _hA, HalfEdge _hB)
 {
     _hA.next      = _hB.twin.next;
     _hB.twin.next = _hB;
 }
 /// <summary>
 /// Make halfedge A's head connect to halfedge B's rear
 /// </summary>
 /// <param name="_hA"></param>
 /// <param name="_hB"></param>
 private void ConnectHalfedges(HalfEdge _hA, HalfEdge _hB)
 {
     _hB.Prev.next = _hA.next;
     _hA.next      = _hB;
 }
Exemple #6
0
 public TriangulatedSet(HalfEdge _lh, HalfEdge _rh)
 {
     leftHalfedge  = _lh;
     rightHalfedge = _rh;
 }