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); }
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); }
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); }
// 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); }
internal AM_Edge CwEdge() { return(m_pNext.Symm()); }
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); }
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); }
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); }