bool SetBoundary() { { m_Mesh2D.DeleteInit(); int numBoundary = m_ArrayMeshBoundary.Count; for (int i = 0; i < numBoundary; i++) { if (m_ArrayMeshBoundary[i].FlagHole) { m_Mesh2D.SetBoundary(m_ArrayMeshBoundary[i]); } } // Elimina eventuali spigoli isolati for (int i = 0; i < m_Mesh2D.ArrayWEdges.Count; i++) { AM_Edge pedge = m_Mesh2D.ArrayWEdges[i].Edge(); if (pedge.CcwFace() == null && pedge.CwFace() == null) { m_Mesh2D.DeleteEdge(pedge); } } } 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); }
bool OnEdge(Point2d p, AM_Edge edge) { double t1, t2, t3; double EPS = 1e-6; Point2d org = edge.OrgCoord(); t1 = (p - org).Length; t2 = (p - edge.DestCoord()).Length; if (t1 < EPS || t2 < EPS) { return(true); } Vector2d vector = org - edge.DestCoord(); t3 = vector.Length; if (t1 > t3 || t2 > t3) { return(false); } double a = vector.Y / t3; double b = -vector.X / t3; double c = -(a * org.X + b * org.Y); return(Math.Abs((a * p.X + b * p.Y + c)) < EPS); }
private void AddTransitionVertexes(AM_Vertex v, List <int> transitionVts) { if ((v.Flag & 0x02) == 0) { v.Flag |= 0x02; transitionVts.Add(v.Index); AM_Edge start_edge = v.Edge; AM_Edge edge = start_edge.Next; while (edge != start_edge) { if ((edge.Flag & 0x04) == 0) { edge.Flag |= 0x04; var dest = edge.Destination(); if ((dest.Flag & 0x01) == 0) { AddTransitionVertexes(dest, transitionVts); } } edge = edge.Next; } } }
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); }
internal AM_Coedge(AM_Vertex vtx_org, AM_Vertex vtx_dest) { m_Edges[0] = new AM_Edge(this, 0); m_Edges[1] = new AM_Edge(this, 1); m_Edges[0].Vertex = vtx_org; m_Edges[1].Vertex = vtx_dest; }
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); }
void Init(Point3d a, Point3d b, Point3d c) { Debug.Assert(m_ArrayFaces.Count == 0); AM_Face face = new AM_Face(); Point3d[] coord = { a, b, c }; AddFace(face, coord); m_StartingEdge = face[0]; }
bool DeleteVertex(AM_Vertex vertex, bool bdelete = false) { // Cancella un vertice dall'array globale dei vertici if (vertex == null || vertex.Index < 0) { Debug.Assert(false); return(false); } int nindex = vertex.Index; int nlast = m_ArrayVertexes.Count - 1; // La cancellazione dall'array globale degli vertici avviene // spostando l'ultimo vertice dell'array al posto di quello da cancellare m_ArrayVertexes[nindex] = m_ArrayVertexes[nlast]; m_ArrayVertexes[nindex].Index = nindex; m_ArrayVertexes.RemoveAt(nlast); if (nlast != nindex) { // è necessario aggiornare opportunamente l'anello del vertice // aggiornando il dato membro m_nVertex; AM_Edge pstartEdge = m_ArrayVertexes[nindex].Edge; AM_Edge edge = pstartEdge; if (pstartEdge == null) { Debug.Assert(false); return(true); } do { edge.Vertex = m_ArrayVertexes[nindex]; edge = edge.Next; } while (edge != pstartEdge); if (bdelete) { //delete vertex; vertex.Edge = null; vertex.Index = -1; } else { vertex.Edge = null; vertex.Index = -1; } } return(true); }
internal AM_Edge FindEdge(AM_Vertex pVertex2) { AM_Edge pNext = m_Edge; do { if (pNext.Destination() == pVertex2) { return(pNext); } pNext = pNext.Next; } while (pNext != m_Edge); return(null); }
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; }
internal double Degree(bool bSimple = false) { int degree = 0; if (m_Edge == null) { Debug.Assert(false); return(0); } // Il "grado" di un vertice è definito come il numero di vertici // ad esso conneesso. if (bSimple) { // Se bSimple = true si conta semplicemente il numero // di spigoli connessi AM_Edge pNext = m_Edge; do { degree++; pNext = pNext.Next; } while (pNext != m_Edge); return(degree); } double angle = 0; { AM_Edge pNext = m_Edge; do { degree++; if (pNext.CcwFace() != null) { Vector2d v0 = (pNext.DestCoord() - m_Coord); Vector2d v1 = (pNext.Next.DestCoord() - m_Coord); v0.Unitize(); v1.Unitize(); double cos_ang = Vector2d.Multiply(v0, v1); angle += Math.Acos(cos_ang); } pNext = pNext.Next; } while (pNext != m_Edge); } return(degree * 2 * Math.PI / angle); }
bool RefineMeshStep() { AM_Face face = null; Point2d innerPoint; AM_Face triangleContaining = null; face = FindMaxActive(); if (face == null) { return(false); } m_StartingEdge = face.GetStartingEdge(); innerPoint = face.InsertPoint(m_pSpaceFunction); //localizzo il triangolo che contiene il punto per fare il test di spaziatura. AM_Edge e = Locate(innerPoint); triangleContaining = e != null? (AM_Edge.RightOf(innerPoint, e) ? e.CwFace() : e.CcwFace()) : null; if (triangleContaining == null) { DeleteActiveFace(face); } else { //innerPoint.Z = triangleContaining.SpaceFunction(innerPoint, m_pSpaceFunction); double s = triangleContaining.SpaceFunction(innerPoint, m_pSpaceFunction); if (triangleContaining.SpacingTest(innerPoint, m_pSpaceFunction)) { AM_Vertex vertex; if (!InsertPoint(innerPoint, s, out vertex)) { DeleteActiveFace(face); } } else { DeleteActiveFace(face); } } return(true); }
internal AM_Edge GetGenEdge(int i) { int numVertex = GetNumGenVertex(); if (i >= numVertex) { Debug.Assert(false); return(null); } AM_Vertex pV1 = m_ArrayVertex[i]; AM_Vertex pV2 = m_ArrayVertex[(i + 1) % numVertex]; AM_Edge pEdge = pV1.FindEdge(pV2);; return(pEdge); }
internal bool GetCoordZ(Point2d p, ref double Z) { // Localizza uno spigolo vicino AM_Edge edge = Locate(p); if (edge == null) { return(false); } AM_Face face = null; if (AM_Edge.LeftOf(p, edge)) { face = edge.CcwFace(); } else { face = edge.CwFace(); } Z = 0; if (face == null) { return(false); } Point2d p0 = face.Vertex(0).Coord; Point2d p1 = face.Vertex(1).Coord; Point2d p2 = face.Vertex(2).Coord; double det = AM_Util.TriArea(p0, p1, p2); Debug.Assert(det != 00); double alfa = AM_Util.TriArea(p0, p, p2) / det; double beta = AM_Util.TriArea(p0, p1, p) / det; double f0 = face.Vertex(0).Z; double f1 = face.Vertex(1).Z; double f2 = face.Vertex(2).Z; Z = f0 + alfa * (f1 - f0) + beta * (f2 - f0); return(true); }
AM_Edge FindEdge(AM_Vertex org, AM_Vertex dest) { AM_Edge pstart = org.Edge; if (pstart != null) { AM_Edge pnext = pstart; do { if (pnext.Destination() == dest) { return(pnext); // lo spigolo esiste già } pnext = pnext.Next; } while (pnext != pstart); } return(null); }
internal int NumDegree() { if (m_Edge == null) { return(0); } int degree = 0; AM_Edge pNext = m_Edge; do { degree++; pNext = pNext.Next; } while (pNext != m_Edge); return(degree); }
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); }
bool BelongToBorder(AM_Vertex v) { AM_Edge start_edge = v.Edge; if (start_edge != null) { AM_Edge edge = start_edge.Next; while (edge != start_edge) { if (edge.CcwFace() == null || edge.CwFace() == null) { return(true); } edge = edge.Next; } } return(false); }
AM_Edge AddEdge(AM_Vertex org, AM_Vertex dest) { AM_Coedge pwEdge = new AM_Coedge(org, dest); if (pwEdge == null) { Debug.Assert(false); //throw -1; } pwEdge.Index = m_ArrayWEdges.Count; m_ArrayWEdges.Add(pwEdge); AM_Edge edge = pwEdge.Edge(); //edge.m_pArrayVertex = &m_ArrayVertexes; //edge.Symm().m_pArrayVertex = &m_ArrayVertexes; return(edge); }
void Swap(AM_Edge edge) { AM_Face face1 = (AM_Face)edge.CcwFace(); AM_Face face2 = (AM_Face)edge.CwFace(); if (face1 == null || face2 == null) { if (face1 != null && face1.FaceType == AM_Face.EFaceType.FT_ACTIVE) { DeleteActiveFace(face1); } if (face2 != null && face2.FaceType == AM_Face.EFaceType.FT_ACTIVE) { DeleteActiveFace(face2); } return; } Debug.Assert(edge.CwFace() != null); Debug.Assert(edge.CcwFace() != null); if (face1.FaceType == AM_Face.EFaceType.FT_ACTIVE) { DeleteActiveFace(face1); } if (face2.FaceType == AM_Face.EFaceType.FT_ACTIVE) { DeleteActiveFace(face2); } AM_Face.SwapEdge(edge); if (m_bFlagClassific) { face1.SetTriangleParameter(m_pSpaceFunction); face2.SetTriangleParameter(m_pSpaceFunction); Classific(face1); Classific(face2); } }
internal bool InnerTest(Point2d p) { Point2d x = p; // Per appartenere alla faccia devono essere tutte a sinistra dello spigolo for (int i = 0; i < 3; i++) { AM_Edge e = m_pEdges[i]; if (x.EpsilonEquals(e.OrgCoord(), AM_Util.FLT_EPSILON)) { return(true); } if (AM_Edge.RightOf(x, e)) { return(false); } } return(true); }
internal int NumConnectedFace() { if (m_Edge == null) { return(0); } int nFace = 0; AM_Edge pNext = m_Edge; do { if (pNext.CcwFace() != null) { nFace++; } pNext = pNext.Next; } while (pNext != m_Edge); return(nFace); }
bool IsBoundaryVertex(AM_Vertex pvertex) { AM_Edge start = pvertex.Edge; if (start == null) { Debug.Assert(false); return(false); // Indefinito } AM_Edge edge = start; do { if (edge.CwFace() == null || edge.CcwFace() == null) { return(true); } edge = edge.Next; } while (start != edge); return(false); }
internal bool RecoverGenEdge(AM_Mesh2d mesh, int num, List <Point3d> AddArray, bool bStraight = false) { // se viene inserito un punto per aggiustare la conformità // il flag baddFlag diventa true bool baddFlag = false; if (!m_bFlagHole && num >= m_GenVertexArray.Count) { return(true); } int v1 = m_GenVertexArray[num]; int v2 = m_GenVertexArray[(num + 1) % m_GenVertexArray.Count]; if (v2 < v1) { v2 += GetNumVertex(); } AM_Edge pbase; AM_Edge pprev = pbase = Vertex(v1).Edge; for (int i = v1 + 1; i <= v2; i++) { AM_Vertex pV1 = Vertex((i - 1) % (GetNumVertex())); AM_Vertex pV2 = Vertex((i) % (GetNumVertex())); Point2d orgCoord = pV1.Coord; // si controlla che tutti i vertici siano in sequenza while (true) { Point2d baseCoord = pbase.DestCoord(); Point2d prvCoord = new Point2d(m_ArrayCoord[(i - 1) % (GetNumVertex())]); Point2d destCoord = new Point2d(m_ArrayCoord[i % (GetNumVertex())]); if (baseCoord == destCoord) { // il vertice è in sequenza: si continua con il successivo break; } else { pbase = pbase.Next; if (pbase == pprev) { // il ciclo dell'anello si è chiuso senza trovare il vertice // successivo; è necessario inserire un vertice in mezzeria del // lato mancante if (!bStraight) { // 1. Algoritmo di ripristino del bordo con l'aggiunta del punto medio baddFlag = true; // si segnala l'aggiunta di un vertice Point3d p1 = m_ArrayCoord[i - 1]; Point3d p2 = (m_ArrayCoord[i % (GetNumVertex())]); Point3d mid = 0.5 * (p1 + p2); Point3d insPt = new Point3d(mid.X, mid.Y, 0); // si inserisce un vertice nel mezzo del AM_Vertex pvertex; mesh.InsertPoint(new Point2d(insPt), insPt.Z, out pvertex); if (pvertex == null) { Debug.Assert(false); //throw 6; } InsertVertex(i, pvertex); v2++; AddArray.Add(insPt); // si ricomincia il controllo pbase = Vertex(i - 1).Edge; pprev = pbase; } else { // 2. Algoritmo di ripristino del bordo con swap di spigoli AM_Edge pdest = Vertex(i).Edge; Vector2d dir = destCoord - orgCoord; dir.Unitize(); var m = AM_Util.AffineMatrix(orgCoord, dir); while (pV1.FindEdge(pV2) == null) { bool bCoinc = false; AM_Edge pSearch = pbase; // Si controllano situazioni di appartenenza al lato da ripristinare do { double cosang = Vector2d.Multiply(pSearch.GetVersor(), dir); if (AM_Util.IsEqual(cosang, 1, AM_Util.FLT_EPSILON)) { // Lo spigolo appartiene già al lato da ripristinare InsertVertex(i, pSearch.Destination()); v2++; Point2d dc = pSearch.DestCoord(); AddArray.Add(new Point3d(dc.X, dc.Y, 0)); // si ricomincia il controllo pbase = Vertex(i - 1).Edge; pprev = pbase; bCoinc = true; break; } pSearch = pSearch.Next; } while (pSearch != pbase); if (bCoinc) { break; } // Trova il lato di partenza pSearch = pbase; while (!AM_Util.IsInside(pSearch.GetVector(), pSearch.Next.GetVector(), dir)) { pSearch = pSearch.Next; if (pSearch == pprev) { Debug.Assert(false); //mesh.ExportMesh("RecoverSt7.txt"); return(false); } } AM_Edge pStartEdge = pSearch.CcwEdge(); List <AM_Edge> swapArray = new List <AM_Edge>(); while (pStartEdge.Destination() != pV2) { Point2d o = pStartEdge.OrgCoord(); Point2d d = pStartEdge.DestCoord(); swapArray.Add(pStartEdge); pStartEdge = pStartEdge.Prev; Point2d pt = AM_Util.ToLocal(m, pStartEdge.DestCoord()); if (pt.Y < -AM_Util.FLT_EPSILON) { pStartEdge = pStartEdge.CcwEdge(); Debug.Assert(AM_Util.ToLocal(m, pStartEdge.DestCoord()).Y > 0); } } for (int j = 0; j < swapArray.Count; j++) { AM_Edge pSwapEdge = swapArray[j]; // Vengono ruotati gli spigoli all'interno if (AM_Util.CheckSwapEdge(pSwapEdge)) { Debug.Assert(pSearch.CcwFace() != null && pSearch.Next.CwFace() != null); Debug.Assert(pSwapEdge.CcwFace() != null && pSwapEdge.CwFace() != null); AM_Face.SwapEdge(pSwapEdge); } } } } } } } pbase = Vertex(i % (GetNumVertex())).Edge; pprev = pbase; } return(baddFlag); }
// --- Copia --- AM_Boundary CopyBoundary(AM_Mesh2d source, AM_Mesh2d dest, bool bSameGenVertex = true) { AM_Boundary pCopy = new AM_Boundary(); pCopy.m_LoopIndex = m_LoopIndex; if (bSameGenVertex) { // Il numero dei vertici generati è lo stesso; // viene normalmente usato in caso di 'merge' tra due mesh adiacenti pCopy.m_ArrayCoord.Capacity = m_ArrayCoord.Count; for (int i = 0; i < m_ArrayCoord.Count; i++) { pCopy.m_ArrayCoord[i] = m_ArrayCoord[i]; } pCopy.m_GenVertexArray.Capacity = m_GenVertexArray.Count; for (int i = 0; i < m_GenVertexArray.Count; i++) { pCopy.m_GenVertexArray[i] = m_GenVertexArray[i]; } // Trova il primo vertice int destVertex = dest.ArrayVertexes.Count; int nVertex = dest.AddVertex(new Point2d(m_ArrayCoord[0]), m_ArrayCoord[0].Z); Debug.Assert(nVertex < destVertex); // non vengono aggiunti vertici AM_Vertex pVertex = dest.ArrayVertexes[nVertex]; pVertex.Flag |= 0x01; pCopy.m_ArrayVertex.Add(pVertex); for (int i = 1; i < m_ArrayCoord.Count; i++) { Point2d ptDest = new Point2d(m_ArrayCoord[i]); AM_Edge pEdge = pVertex.Edge; AM_Edge pNextEdge = pEdge.Next; while ((ptDest - pNextEdge.DestCoord()).Length > AM_Util.FLT_EPSILON) { if (pNextEdge == pEdge) { Debug.Assert(false); nVertex = dest.AddVertex(ptDest, 0); Debug.Assert(nVertex < destVertex); pNextEdge = dest.ArrayVertexes[nVertex].Edge.Symm(); break; } pNextEdge = pNextEdge.Next; } pVertex = pNextEdge.Destination(); pVertex.Flag |= 0x01; pCopy.m_ArrayVertex.Add(pVertex); } Debug.Assert(pCopy.m_ArrayVertex.Count == m_ArrayVertex.Count); } else { // Il numero dei vertici generati è diverso; // viene normalmente usato in caso di ricostruzione di contorni pCopy.m_GenVertexArray.Capacity = m_GenVertexArray.Count; for (int i = 1; i < m_GenVertexArray.Count; i++) { Point2d p0 = new Point2d(m_ArrayCoord[m_GenVertexArray[i - 1]]); Point2d p1 = new Point2d(m_ArrayCoord[m_GenVertexArray[i]]); AM_Vertex pV0 = dest.RangeSearch.Search(p0.X, p0.Y); AM_Vertex pV1 = dest.RangeSearch.Search(p1.X, p1.Y); Debug.Assert(pV0 != null && pV1 != null); // La direzione è data dal vettore p0-p1 Vector2d vDir = (p1 - p0); vDir.Unitize(); pCopy.m_GenVertexArray[i - 1] = pCopy.m_ArrayCoord.Count; AM_Vertex pV = pV0; while (pV != pV1) { pCopy.m_ArrayCoord.Add(new Point3d(pV.Coord.X, pV.Coord.Y, 0)); pCopy.m_ArrayVertex.Add(pV); // Trova il vertice successivo double minCos = -double.MaxValue; AM_Edge pEdge = pV.Edge; AM_Edge pDirEdge = null; do { double dirCos = pEdge.GetVersor() * vDir; if (dirCos > minCos) { minCos = dirCos; pDirEdge = pEdge; } pEdge = pEdge.Next; } while (pEdge != pV.Edge); Debug.Assert(AM_Util.IsEqual(minCos, 1)); pV = pDirEdge.Destination(); } } } return(pCopy); }
internal static bool LeftOf(Point2d x, AM_Edge pedge) { return(AM_Util.CCW(x, pedge.OrgCoord(), pedge.DestCoord())); }
// 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); }
bool AdjustConnection(AM_Edge[] poldConn) { for (int i = 0; i < NumEdges; i++) { AM_Edge pconnSx = poldConn[i * 2]; AM_Edge pconnDx = poldConn[(i * 2 + (NumEdges * 2) - 1) % (NumEdges * 2)]; if (pconnDx == null && pconnSx == null) { if (Vertex(i).Edge != null) { // Inserisce i due spigoli della faccia nell'anello del vertice // individuato da Vertex(i) AM_Edge pedge = ((AM_Edge)(Vertex(i).Edge)).FindLastConnected(); Debug.Assert(pedge != null); AM_Edge poldnextEdge = pedge.Next; m_pEdges[i].Prev = pedge; pedge.Next = m_pEdges[i]; poldnextEdge.Prev = m_pEdges[i].Next; m_pEdges[i].Next.Next = poldnextEdge; } else { // Lo spigolo è isolato: inizializza l'anello m_pEdges[i].Prev = m_pEdges[i].Next; m_pEdges[i].Next.Next = m_pEdges[i]; Vertex(i).Edge = m_pEdges[i]; } } else { if (pconnSx == pconnDx) { continue; } // vi erano connessioni preesistenti: l'anello viene aggiornato if (pconnSx != null) // anello in senso antiorario { AM_Edge padjust = pconnSx; AM_Edge pstart = pconnSx.Prev; /*TRACE_EDGE(padjust); * TRACE_EDGE(pstart);*/ int ncheck = 0; //contatore per evitare loop infinito while (padjust != null) { if (ncheck++ > 300) { Debug.Assert(false); return(false); } if (padjust.Prev.Next == padjust) { break; } AM_Edge pnewconn = padjust; padjust.Prev = pstart.FindLastConnected(); pstart = padjust.Prev; padjust = pstart.Next; pstart.Next = pnewconn; } } if (pconnDx != null) // anello in senso orario { AM_Edge padjust = pconnDx; AM_Edge pstart = pconnDx.Next; /*TRACE_EDGE(padjust); * TRACE_EDGE(pstart);*/ int ncheck = 0; //contatore per evitare loop infinito while (padjust != null) { if (ncheck++ > 300) { Debug.Assert(false); return(false); } if (padjust.Next.Prev == padjust) { break; } AM_Edge pnewconn = padjust; padjust.Next = pstart.FindLastConnected(false); pstart = padjust.Next; padjust = pstart.Prev; pstart.Prev = pnewconn; } } } } return(true); }
// --- 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); }