Esempio n. 1
0
        internal static void SwapEdge(AM_Edge pedge)
        {
            Debug.Assert(pedge.CcwFace().NumEdges == 3);
            Debug.Assert(pedge.CwFace().NumEdges == 3);

            AM_Edge pstart = pedge;

            do
            {
                Point2d p1 = pedge.CcwEdge().DestCoord();
                Point2d p2 = pedge.OrgCoord();
                Point2d p3 = pedge.DestCoord();
                Point2d p4 = pedge.Symm().CcwEdge().DestCoord();

                //int n1 = pedge.CcwEdge().Destination().Index;
                //int n2 = pedge.Origin().Index;
                //int n3 = pedge.Destination().Index;
                //int n4 = pedge.Symm().CcwEdge().Destination().Index;

                //int v1 = pedge.CcwEdge().Symm().m_nVertex;
                //int v2 = pedge.m_nVertex;
                //int v3 = pedge.Symm().m_nVertex;
                //int v4 = pedge.Symm().CcwEdge().Symm().m_nVertex;

                AM_Edge poldPrev = pedge.Prev;
                AM_Edge poldNext = pedge.Next;
                AM_Edge pnewNext = pedge.Prev.Symm();
                AM_Edge pnewPrev = pnewNext.Prev;
                AM_Face poldFace = pedge.Face;


                pedge.Origin().Edge = poldNext;
                pedge.Vertex = pnewNext.Vertex; // Ripristina l'origine...
                pedge.Origin().Edge = pedge;    // e aggiorna il suo puntatore

                // ripristina i collegamenti corretti
                poldPrev.Next = poldNext;
                poldNext.Prev = poldPrev;
                pnewPrev.Next = pedge;
                pnewNext.Prev = pedge;
                pedge.Next    = pnewNext;
                pedge.Prev    = pnewPrev;

                Debug.Assert(pedge.Origin() != pedge.Destination());

                // parte dallo spigolo che definisce la faccia sinistra
                // e che è precedente in senso antiorario
                pnewNext = poldNext.Symm();
                for (int i = 0; i < 3; i++)
                {
                    pnewNext.Face = poldFace;
                    poldFace[i]   = pnewNext;
                    pnewNext      = pnewNext.CcwEdge();
                }

                pedge = pedge.Symm();
            } while (pstart != pedge);
        }
Esempio n. 2
0
        bool CheckSwapEdge(AM_Edge pedge)
        {
            // Controlla l'ammissibilità dello swap.
            // Uno spigolo può essere scambiato all'interno di un quadrangolo
            // se quest'ultimo è convesso.

            Point2d p1 = pedge.CcwEdge().DestCoord();
            Point2d p2 = pedge.OrgCoord();
            Point2d p3 = pedge.DestCoord();
            Point2d p4 = pedge.Symm().CcwEdge().DestCoord();

            Vector2d v1 = p4 - p2;
            Vector2d v2 = p1 - p2;

            v1.Unitize();
            v2.Unitize();

            if ((v1.X * v2.Y - v2.X * v1.Y) < AM_Util.FLT_EPSILON)
            {
                return(false);
            }

            Vector2d v3 = p1 - p3;
            Vector2d v4 = p4 - p3;

            v3.Unitize();
            v4.Unitize();

            if ((v3.X * v4.Y - v4.X * v3.Y) < AM_Util.FLT_EPSILON)
            {
                return(false);
            }

            return(true);
        }
Esempio n. 3
0
        AM_Edge Locate(Point2d x)
        {
            AM_Edge e          = m_StartingEdge;
            int     actualEdge = 0;
            int     numEdge    = m_ArrayWEdges.Count;

            while (actualEdge++ <= numEdge)
            {
                if (x == e.OrgCoord() || x == e.DestCoord())
                {
                    return(e);
                }
                else if (AM_Edge.RightOf(x, e))
                {
                    e = e.Symm();
                }
                else if (!AM_Edge.RightOf(x, e.Next))
                {
                    e = e.Next;
                }
                else if (!AM_Edge.RightOf(x, e.CcwEdge().Symm()))
                {
                    e = e.CcwEdge().Symm();
                }
                else
                {
                    return(e);
                }
            }
            return(null);
        }
Esempio n. 4
0
        // Connessioni
        internal bool SetConnection()
        {
            // testa la compatibilità delle facce. Eventuali problemi
            // possono insorgere se vi è incoerenza tra le normali di
            // due facce adiacenti
            for (int i = 0; i < NumEdges; i++)
            {
                if (m_pEdges[i].Face != null)
                {
                    return(false);
                }
            }

            Debug.Assert(NumEdges <= 4);

            // Inizializza le connessioni preesistenti
            AM_Edge [] poldConn = new AM_Edge[8];
            for (int i = 0; i < 8; i++)
            {
                poldConn[i] = null;
            }

            for (int i = 0; i < NumEdges; i++)
            {
                AM_Edge pedge = m_pEdges[i];
                AM_Edge psymm = pedge.Symm();
                pedge.Face = this;

                if (pedge.Next != null)
                {
                    poldConn[i * 2] = pedge.Next;
                }
                pedge.Next = m_pEdges[(i + NumEdges - 1) % NumEdges].Symm();

                if (psymm.Prev != null)
                {
                    poldConn[i * 2 + 1] = psymm.Prev;
                }
                psymm.Prev = m_pEdges[(i + 1) % NumEdges];
            }

            if (!AdjustConnection(poldConn))
            {
                // la connessione è fallita: si ripristinano
                // le connessioni precedenti
                for (int i = 0; i < NumEdges; i++)
                {
                    AM_Edge pedge = m_pEdges[i];
                    AM_Edge psymm = pedge.Symm();
                    pedge.Face = null;

                    if (poldConn[i * 2] != null)
                    {
                        pedge.Next = poldConn[i * 2];
                    }
                    else
                    {
                        pedge.Next = null;
                    }

                    if (poldConn[i * 2 + 1] != null)
                    {
                        psymm.Prev = poldConn[i * 2 + 1];
                    }
                    else
                    {
                        psymm.Prev = null;
                    }
                }

                return(false);
            }
            return(true);
        }
Esempio n. 5
0
 internal AM_Edge CwEdge()
 {
     return(m_pNext.Symm());
 }
Esempio n. 6
0
        internal bool InsertPoint(Point2d x, double space, out AM_Vertex pvertex)
        {
            pvertex = null;
            AM_Face face = null;

            // Localizza uno spigolo vicino
            AM_Edge edge = Locate(x);

            if (edge == null)
            {
                return(false);
            }

            // Localizza il triangolo che contiene il punto x
            // e imposta 'm_pStartingEdge', primo spigolo del triangolo o del quadrilatero
            // che deve essere riconnesso al punto x
            if (AM_Edge.LeftOf(x, edge))
            {
                face           = (AM_Face)(edge.CcwFace());
                m_StartingEdge = edge.CcwEdge();
            }
            else
            {
                face           = (AM_Face)(edge.CwFace());
                m_StartingEdge = edge.Symm().CcwEdge();
            }

            if (face == null)
            {
                return(false);
            }

            // Verifica dell'eventuale esistenza del punto
            if (x == edge.OrgCoord())
            {
                pvertex = edge.Origin();
                return(false);
            }

            if (x == edge.DestCoord())
            {
                pvertex = edge.Destination();
                return(false);
            }

            Point2d[] v1 = { face.Vertex(0).Coord, face.Vertex(1).Coord, face.Vertex(2).Coord, };

            //isOnEdge = OnEdge(x, edge);
            AM_Edge pOnEdge = OnFaceEdge(x, face);

            if (pOnEdge != null)
            {
                m_StartingEdge = pOnEdge.CcwEdge();

                // il punto si trova su un contorno!
                AM_Face pCwFace  = pOnEdge.CwFace();
                AM_Face pCcwFace = pOnEdge.CcwFace();

                if (pCwFace == null || pCcwFace == null)
                {
                    return(false);
                }
            }

            // Il punto è all'interno di un triangolo o su uno spigolo
            if (face.FaceType == AM_Face.EFaceType.FT_ACTIVE)
            {
                DeleteActiveFace(face);
            }

            DeleteFace(face);
            if (pOnEdge != null)
            {
                // Cancella lo spigolo su cui si appoggia e
                // conseguentemente anche l'altro spigolo

                AM_Face pCwFace  = pOnEdge.CwFace();
                AM_Face pCcwFace = pOnEdge.CcwFace();

                if (pCwFace != null && pCwFace.FaceType == AM_Face.EFaceType.FT_ACTIVE)
                {
                    DeleteActiveFace(pCwFace);
                }
                if (pCcwFace != null && pCcwFace.FaceType == AM_Face.EFaceType.FT_ACTIVE)
                {
                    DeleteActiveFace(pCcwFace);
                }

                DeleteEdge(pOnEdge);
            }

            // Inserisce il nuovo vertice nell'array globale
            pvertex = new AM_Vertex(x, 0, space);
            if (pvertex == null)
            {
                Debug.Assert(false);
                //throw -1;
            }


            int m_nVertex = m_ArrayVertexes.Count;

            pvertex.Index = m_ArrayVertexes.Count;
            m_ArrayVertexes.Add(pvertex);

            // Inserisce i nuovi triangoli (facce)
            edge = m_StartingEdge.CcwEdge();
            int numEdge = (pOnEdge != null? 4 : 3);

            for (int ne = 0; ne < numEdge; ne++)
            {
                AM_Face new_face = new AM_Face();
                if (new_face == null)
                {
                    Debug.Assert(false);
                    //throw -1;
                }

                AM_Edge actEdge = edge;
                edge = edge.CcwEdge();
                int [] nCoord = { m_nVertex, actEdge.Vertex.Index, actEdge.DestVertex().Index };
                AddFace(new_face, nCoord);

                if (m_bFlagClassific)
                {
                    new_face.SetTriangleParameter(m_pSpaceFunction);
                    Classific(new_face);
                }
            }

            // Esamina gli spigoli per assicurare che la condizione di
            // Delaunay sia soddisfatta
            edge           = m_StartingEdge;
            m_StartingEdge = m_StartingEdge.CcwEdge();
            do
            {
                //TRACE_EDGE(edge);
                AM_Edge t = edge.Prev;
                if (edge.CwFace() != null && AM_Edge.RightOf(t.DestCoord(), edge) &&
                    AM_Util.InCircle(edge.OrgCoord(), t.DestCoord(), edge.DestCoord(), x))
                {
                    //TRACE0("Faccia swap:  ");
                    //TRACE_EDGE(edge);
                    Swap(edge);
                    edge = edge.Prev;
                }
                else if (edge.Next == m_StartingEdge)
                {
                    // Non ci sono più spigoli
                    break;
                }
                else
                {
                    // Recupera un altro spigolo sospetto
                    edge = edge.Next.CwEdge();
                }
            } while (true);

            return(true);
        }
Esempio n. 7
0
        internal bool SetBoundary(AM_Boundary boundary)
        {
            AM_Edge edge;

            int numVertex = boundary.GetNumVertex();

            // Viene marcato il flag di contorno
            for (int i = 0; i < boundary.GetNumVertex(); i++)
            {
                edge = boundary.Vertex(i).Edge;
                Point2d nextCoord = new Point2d(boundary[(i + 1) % numVertex]);

                // si trova lo spigolo del contorno
                while (!edge.DestCoord().EpsilonEquals(nextCoord, AM_Util.FLT_EPSILON))
                {
                    edge = edge.Next;
                }

                edge.Flag |= 0x02;
                edge.Symm().Flag |= 0x02;
            }

            // Trova lo spigolo iniziale
            AM_Edge pprevEdge = boundary.Vertex(numVertex - 1).Edge;

            while (!pprevEdge.DestCoord().EpsilonEquals(new Point2d(boundary[0]), 1e-8))
            {
                pprevEdge = pprevEdge.Next;
            }
            pprevEdge = pprevEdge.Symm(); // viene usato come sentinella

            // controllo su tutti gli spigoli del contorno
            for (int i = 1; i <= boundary.GetNumVertex(); i++)
            {
                edge = boundary.Vertex(i - 1).Edge;

                Point2d nextCoord = new Point2d(boundary[i % numVertex]);

                // si trova lo spigolo del contorno
                while (edge.DestCoord() != nextCoord)
                {
                    edge = edge.Next;
                }

                if (edge.CwFace() != null)
                {
                    // se c'è una faccia a dx dello spigolo
                    // ci sono spigoli da eliminare
                    AM_Edge plookEdge = edge.Prev;
                    while (plookEdge != pprevEdge)
                    {
                        AM_Edge pdeleteEdge = plookEdge;
                        plookEdge = plookEdge.Prev;

                        if ((pdeleteEdge.Flag & 0x02) == 0)
                        {
                            // Non è uno spigolo di bordo
                            DeleteEdge(pdeleteEdge);
                        }
                    }
                }
                pprevEdge = edge.Symm();
            }

            return(true);
        }
Esempio n. 8
0
        internal bool DeleteEdge(AM_Edge edge, bool bDelIsolatedVertex = false)
        {
            Debug.Assert(edge != null);
            // Cancella le facce collegate allo spigolo
            DeleteFace(edge.CwFace());
            DeleteFace(edge.CcwFace());

            AM_Coedge pwEdge        = edge.WingedEdge;
            AM_Coedge pdeletingEdge = m_ArrayWEdges[pwEdge.Index];
            int       nlast         = m_ArrayWEdges.Count - 1;

            Debug.Assert(pdeletingEdge == pwEdge);

            // La cancellazione dall'array globale degli spigoli avviene
            // spostando l'ultimo spigolo dell'array al posto di quello da cancellare
            m_ArrayWEdges[pwEdge.Index]       = m_ArrayWEdges[nlast];
            m_ArrayWEdges[pwEdge.Index].Index = pwEdge.Index;
            m_ArrayWEdges.RemoveAt(nlast);

            AM_Vertex pIsolated1 = null;
            AM_Vertex pIsolated2 = null;

            // ripristina le connessioni
            edge.Next.Prev = edge.Prev;
            edge.Prev.Next = edge.Next;
            if (edge.Next == edge && edge.Prev == edge)
            {
                // rimane un vertice isolato
                pIsolated1      = edge.Origin();
                pIsolated1.Edge = null;
            }
            else
            {
                edge.Origin().Edge = edge.Next;
            }

            // ripristina le connessioni del duale
            edge           = edge.Symm();
            edge.Next.Prev = edge.Prev;
            edge.Prev.Next = edge.Next;
            if (edge.Next == edge && edge.Prev == edge)
            {
                // rimane un vertice isolato
                pIsolated2      = edge.Origin();
                pIsolated2.Edge = null;
            }
            else
            {
                edge.Origin().Edge = edge.Next;
            }

            //delete pwEdge;

            if (bDelIsolatedVertex)
            {
                if (pIsolated1 != null)
                {
                    DeleteVertex(pIsolated1, true);
                }

                if (pIsolated2 != null)
                {
                    DeleteVertex(pIsolated2, true);
                }
            }

            edge.Next = null;
            edge.Prev = null;

            return(true);
        }