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
        void RelaxMesh()
        {
            // Esegue la procedura di "Mesh Relaxation"
            bool bPrev = m_bFlagClassific;

            m_bFlagClassific = false;
            for (int DiffDegree = 3; DiffDegree >= 2; DiffDegree--)
            {
                for (int i = 0; i < m_ArrayWEdges.Count; i++)
                {
                    AM_Edge edge = m_ArrayWEdges[i].Edge();
                    if (edge.CcwFace() != null && edge.CwFace() != null)
                    {
                        AM_Vertex [] Vertex = { edge.Origin(),
                                                edge.Destination(),
                                                edge.Next.Destination(),
                                                edge.Prev.Destination(), };
                        double []    degree = { 0, 0, 0, 0 };
                        for (int j = 0; j < degree.Length; j++)
                        {
                            degree[j] = Vertex[j].Degree();
                        }

                        double R = 0;
                        for (int j = 0; j < 4; j++)
                        {
                            R += (6 - degree[j]) * (6 - degree[j]);
                        }

                        // aggiorna il grado con l'ipotesi do swap
                        degree[0] -= 1;
                        degree[1] -= 1;
                        degree[2] += 1;
                        degree[3] += 1;

                        double R1 = 0;
                        for (int j = 0; j < 4; j++)
                        {
                            R1 += (6 - degree[j]) * (6 - degree[j]);
                        }

                        if (R - R1 >= DiffDegree)
                        {
                            Swap(edge);
                        }
                    }
                }
            }
            m_bFlagClassific = bPrev;
        }
Esempio n. 3
0
        internal bool CheckWEdge()
        {
            for (int i = 0; i < m_ArrayWEdges.Count; i++)
            {
                AM_Edge edge = m_ArrayWEdges[i].Edge();
                Debug.Assert(edge.Origin() != edge.Destination());
            }

            for (int i = 0; i < m_ArrayFaces.Count; i++)
            {
                AM_Face edge = m_ArrayFaces[i];
                double  area = AM_Util.TriArea(edge[0].OrgCoord(),
                                               edge[1].OrgCoord(),
                                               edge[2].OrgCoord());
                Debug.Assert(area > 0);
            }

            return(true);
        }
Esempio n. 4
0
        // --- Impostazioni ---
        internal Point2d InsertPoint(AM_Mesh2d pSpaceFunction)
        {
            AM_Edge pRif = null;

            for (int i = 0; i < 3; i++)
            {
                if (GetNearTriangle(i) == null)
                {
                    pRif = m_pEdges[i];
                    break;
                }

                if (GetNearTriangle(i).m_FaceType == EFaceType.FT_ACCEPTED)
                {
                    pRif = m_pEdges[i];
                }
            }

            if (pRif == null)
            {
                return(Vertex(0).Coord);
            }

            Point2d thirdPoint     = Point2d.Origin;
            Point2d midPoint       = 0.5 * (pRif.OrgCoord() + pRif.DestCoord());
            Point2d directionPoint = m_CircumCenter;

            for (int i = 0; i < 3; i++)
            {
                if (Vertex(i) != pRif.Origin() &&
                    Vertex(i) != pRif.Destination())
                {
                    thirdPoint = Vertex(i).Coord;
                    break;
                }
            }

            if (m_CircumCenter == midPoint) //triangolo rettangolo
            {
                directionPoint = thirdPoint;
            }

            double radius = TeoricRadius(midPoint, pSpaceFunction);
            double p      = (pRif.OrgCoord() - pRif.DestCoord()).Length / 2;
            double q      = (midPoint - m_CircumCenter).Length;

            if (radius < p)
            {
                radius = p;
            }
            if (q != 0)
            {
                double tmp = (p * p + q * q) / (2 * q);
                if (radius > tmp)
                {
                    radius = tmp;
                }
            }

            Vector2d versor;

            if (AM_Edge.LeftOf(directionPoint, pRif) && AM_Edge.RightOf(thirdPoint, pRif) ||
                AM_Edge.LeftOf(thirdPoint, pRif) && AM_Edge.RightOf(directionPoint, pRif))
            {
                versor = midPoint - directionPoint;
            }
            else
            {
                versor = directionPoint - midPoint;
            }
            versor.Unitize();

            double  d     = radius + Math.Sqrt(radius * radius - p * p);
            Point2d point = midPoint + d * versor;

            return(point);
        }
Esempio n. 5
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. 6
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);
        }