/// <summary> /// Add new face to the tree /// </summary> /// <param name="newFace"></param> public void Add( Face newFace ) { // add the face FaceTreeAdd( FaceRoot, newFace ); // check if the face is boundary face if ( newFace.HalfEnd.TwinEdge == null || newFace.HalfEnd.NextEdge.TwinEdge == null || newFace.HalfEnd.NextEdge.NextEdge.TwinEdge == null ) { // add the face to the boundary BoundaryFaces.Add( newFace ); } }
private void FaceTreeRemove(FaceDistTreeNode faceNode, Face newFace) { // check if we are in leaf if (faceNode.isLeaf) { // just remove the face to the list faceNode.FaceList.Remove(newFace); } else { // continue to the correct side if (newFace.Min_X > faceNode.X_mid) { if (newFace.Min_Y > faceNode.Y_mid) { FaceTreeRemove(faceNode.UpRight, newFace); } else if (newFace.Max_Y < faceNode.Y_mid) { FaceTreeRemove(faceNode.DownRight, newFace); } else { // add in both sides :P FaceTreeRemove(faceNode.UpRight, newFace); FaceTreeRemove(faceNode.DownRight, newFace); } } else if (newFace.Max_X < faceNode.X_mid) { if (newFace.Min_Y > faceNode.Y_mid) { FaceTreeRemove(faceNode.UpLeft, newFace); } else if (newFace.Max_Y < faceNode.Y_mid) { FaceTreeRemove(faceNode.DownLeft, newFace); } else { // add in both sides :P FaceTreeRemove(faceNode.UpLeft, newFace); FaceTreeRemove(faceNode.DownLeft, newFace); } } else { if (newFace.Min_Y > faceNode.Y_mid) { // add in both sides FaceTreeRemove(faceNode.UpRight, newFace); FaceTreeRemove(faceNode.UpLeft, newFace); } else if (newFace.Max_Y < faceNode.Y_mid) { // add in both sides FaceTreeRemove(faceNode.DownRight, newFace); FaceTreeRemove(faceNode.DownLeft, newFace); } else { // add in all sides :P FaceTreeRemove(faceNode.DownRight, newFace); FaceTreeRemove(faceNode.DownLeft, newFace); FaceTreeRemove(faceNode.UpRight, newFace); FaceTreeRemove(faceNode.UpLeft, newFace); } } } }
private void FaceTreeAdd(FaceDistTreeNode faceNode, Face newFace) { // check if we are in leaf if (faceNode.isLeaf) { // check if we are pass the max num of faces per leaf if (faceNode.FaceList.Count < MaxFaces) { // just add the face to the list faceNode.FaceList.Add(newFace); } else { // split the leaf to 4 nodes FaceNodeSpliting(faceNode); // re-call this function as node FaceTreeAdd(faceNode, newFace); } } else { // continue to the correct side if (newFace.Min_X >= faceNode.X_mid) { if (newFace.Min_Y >=faceNode.Y_mid) { FaceTreeAdd(faceNode.UpRight, newFace); } else if (newFace.Max_Y <= faceNode.Y_mid) { FaceTreeAdd(faceNode.DownRight, newFace); } else { // add in both sides :P FaceTreeAdd(faceNode.UpRight, newFace); FaceTreeAdd(faceNode.DownRight, newFace); } } else if (newFace.Max_X <= faceNode.X_mid) { if (newFace.Min_Y >= faceNode.Y_mid) { FaceTreeAdd(faceNode.UpLeft, newFace); } else if (newFace.Max_Y <= faceNode.Y_mid) { FaceTreeAdd(faceNode.DownLeft, newFace); } else { // add in both sides :P FaceTreeAdd(faceNode.UpLeft, newFace); FaceTreeAdd(faceNode.DownLeft, newFace); } } else { if (newFace.Min_Y >= faceNode.Y_mid) { // add in both sides FaceTreeAdd(faceNode.UpRight, newFace); FaceTreeAdd(faceNode.UpLeft, newFace); } else if (newFace.Max_Y <= faceNode.Y_mid) { // add in both sides FaceTreeAdd(faceNode.DownRight, newFace); FaceTreeAdd(faceNode.DownLeft, newFace); } else { // add in all sides :P FaceTreeAdd(faceNode.DownRight, newFace); FaceTreeAdd(faceNode.DownLeft, newFace); FaceTreeAdd(faceNode.UpRight, newFace); FaceTreeAdd(faceNode.UpLeft, newFace); } } } }
/// <summary> /// remove the face from the tree /// </summary> /// <param name="oldFace"></param> public void Remove( Face oldFace ) { // remove the face FaceTreeRemove( FaceRoot, oldFace ); // check if the face is boundary face if ( oldFace.HalfEnd.TwinEdge == null || oldFace.HalfEnd.NextEdge.TwinEdge == null || oldFace.HalfEnd.NextEdge.NextEdge.TwinEdge == null ) { // add the face to the boundary BoundaryFaces.Remove( oldFace ); } }
/// <summary> /// update all the internal structs base on the specific struct /// </summary> public void Update( Face face ) { // update all the internal face face.Update(); }
/// <summary> /// remove the face from the tree /// </summary> /// <param name="oldFace"></param> public void Remove( Face oldFace ) { // remove the face FaceList.Remove( oldFace ); }
/// <summary> /// Add new face to the tree /// </summary> /// <param name="newFace"></param> public void Add( Face newFace ) { FaceList.Add( newFace ); }
/// <summary> /// Init the internal state /// </summary> /// <param name="ver1"></param> /// <param name="ver2"></param> /// <param name="ver3"></param> /// <param name="faceTree"></param> private void Init(IVertex<float> ver1, IVertex<float> ver2, IVertex<float> ver3, IFaceTree faceTree) { // init the face tree this.faceTree = faceTree; // ini the min max boundary BoundaryMinMax = new BoundaryNodeMaxMin(); // add the 3 half edge Half_Edge he1, he2, he3; // crate the triangle Half_Edge.CreateTriangle(ver1, ver2, ver3, out he1, out he2, out he3); // create and link the boundary list { // create the boundary list RootBoundaryNode = new BoundaryNode(he1, true); BoundaryNode nextBoundaryNode1 = new BoundaryNode(he1.NextEdge); BoundaryNode nextBoundaryNode2 = new BoundaryNode(he1.NextEdge.NextEdge); // link the root with the next node RootBoundaryNode.NextNode = nextBoundaryNode1; nextBoundaryNode1.PrevNode = RootBoundaryNode; // link the root with the next node nextBoundaryNode1.NextNode = nextBoundaryNode2; nextBoundaryNode2.PrevNode = nextBoundaryNode1; // link the first with the last one nextBoundaryNode2.NextNode = RootBoundaryNode; RootBoundaryNode.PrevNode = nextBoundaryNode2; // select the min/max nodes { // init min/max BoundaryMinMax.X_Max = RootBoundaryNode; BoundaryMinMax.X_Min = RootBoundaryNode; BoundaryMinMax.Y_Max = RootBoundaryNode; BoundaryMinMax.Y_Min = RootBoundaryNode; // set the start node and move to the next one // because we use the first for init BoundaryNode tmpNode = RootBoundaryNode; tmpNode = tmpNode.NextNode; while (true) { // update the boundary max/min UpdateBoundaryMaxMin(tmpNode); // move to the next node tmpNode = tmpNode.NextNode; // break if we are in the start if (tmpNode.IsTheRoot) break; } } } // create a face base on the 3 vertex Face newFace = new Face(he1); // add the face to the tree faceTree.Add(newFace); }
private void DrawFace( Face fe ) { Half_Edge he = fe.HalfEnd; if (false && (he.TwinEdge == null || he.NextEdge.TwinEdge == null || he.NextEdge.NextEdge.TwinEdge == null)) { // start the figure point.X = he.StartVertex.X; point.Y = he.StartVertex.Y; meshGeo_Sink_Color.BeginFigure(point, FigureBegin.Hollow); he = he.NextEdge; // add the first edge point.X = he.StartVertex.X; point.Y = he.StartVertex.Y; meshGeo_Sink_Color.AddLine(point); he = he.NextEdge; // add the sec edge point.X = he.StartVertex.X; point.Y = he.StartVertex.Y; meshGeo_Sink_Color.AddLine(point); // close the face meshGeo_Sink_Color.EndFigure(FigureEnd.Closed); } else { // start the figure point.X = he.StartVertex.X; point.Y = he.StartVertex.Y; meshGeo_Sink.BeginFigure(point, FigureBegin.Hollow); he = he.NextEdge; // add the first edge point.X = he.StartVertex.X; point.Y = he.StartVertex.Y; meshGeo_Sink.AddLine(point); he = he.NextEdge; // add the sec edge point.X = he.StartVertex.X; point.Y = he.StartVertex.Y; meshGeo_Sink.AddLine(point); // close the face meshGeo_Sink.EndFigure(FigureEnd.Closed); } if ( ShowVertex ) { DrawVertex( he.StartVertex ); DrawVertex( he.NextEdge.StartVertex ); DrawVertex( he.NextEdge.NextEdge.StartVertex ); } }
/// <summary> /// Remove external face /// </summary> /// <param name="face"></param> public void RemoveFace( Face face ) { // add the external face faceTree.Remove( face ); }
/// <summary> /// Add vertex to data struct. /// </summary> /// <param name="vert"></param> public void AddVertex(IVertex<float> vert) { // find the face to attach Face selectFace = faceTree.FindFace(vert); // check if we find a triangle if (selectFace != null) { // disable the add base on select faces #if true Half_Edge minEdge; double minDist = selectFace.minDistEdge(vert, out minEdge); // check how close we are in the edges if (minDist > 0.1) { #region split the face to 3 faces // get the he of the prev face Half_Edge he1 = selectFace.HalfEnd; Half_Edge he2 = selectFace.HalfEnd.NextEdge; Half_Edge he3 = selectFace.HalfEnd.NextEdge.NextEdge; // remove the old face faceTree.Remove(selectFace); // ------------------------------------------------------------------------------ // // create the first triangle Half_Edge he_a1, he_a2; Half_Edge.CreateTriangle(he1, he2.StartVertex, vert, out he_a1, out he_a2); // ------------------------------------------------------------------------------ // // create the sec triangle Half_Edge he_b1, he_b2; Half_Edge.CreateTriangle(he2, he3.StartVertex, vert, out he_b1, out he_b2); // ------------------------------------------------------------------------------ // // create the third triangle Half_Edge he_c1, he_c2; Half_Edge.CreateTriangle(he3, he1.StartVertex, vert, out he_c1, out he_c2); // ------------------------------------------------------------------------------ // // link he twin edge he_a1.TwinEdge = he_b2; he_b2.TwinEdge = he_a1; he_a2.TwinEdge = he_c1; he_c1.TwinEdge = he_a2; he_b1.TwinEdge = he_c2; he_c2.TwinEdge = he_b1; // create 3 new faces Face fa1 = new Face(he1); Face fa2 = new Face(he2); Face fa3 = new Face(he3); // add the new faces to the tree faceTree.Add(fa1); faceTree.Add(fa2); faceTree.Add(fa3); // test for edge swap he_a2.DelaunayCorrection(he1.TwinEdge, faceTree); he_b2.DelaunayCorrection(he2.TwinEdge, faceTree); he_c2.DelaunayCorrection(he3.TwinEdge, faceTree); #endregion } else { #if false #region split the face to 4 faces Console.WriteLine( "Find minDist:" + minDist.ToString() ); // calc the dist from the vert double dx = minEdge.StartVertex.X - vert.X; double dy = minEdge.StartVertex.Y - vert.Y; double dist1 = Math.Sqrt( dx * dx + dy * dy ); dx = minEdge.NextEdge.StartVertex.X - vert.X; dy = minEdge.NextEdge.StartVertex.Y - vert.Y; double dist2 = Math.Sqrt( dx * dx + dy * dy ); Console.WriteLine( "vert1 dist :" + dist1.ToString() ); Console.WriteLine( "vert2 dist :" + dist2.ToString() ); #endregion #endif } #endif } else { //Console.WriteLine("Out of Boundary "); #region add new triangle to the Boundary // start the node from the start BoundaryNode tmpNode = RootBoundaryNode; int count = 0; BoundaryNode firstNode = null, lastNode = null; Boolean foundTheFirst = false, firstMatchIsRoot = false; Boolean TooClose = false; #region Forward Test // pass all the nodes and find the first and the last one that we can use while (true) { Half_Edge he = tmpNode.currentEdge; if ((vert.X - he.StartVertex.X) * (vert.X - he.StartVertex.X) + (vert.Y - he.StartVertex.Y) * (vert.Y - he.StartVertex.Y) < 0.1) { TooClose = true; break; } // test the angle if is negative // (neg mean that we are outside from the mesh ) if (Half_Edge.SideTest(he.StartVertex, he.NextEdge.StartVertex, vert)) { count++; if (foundTheFirst) { lastNode = tmpNode; } else { // set the first node firstNode = tmpNode; // set the last node lastNode = tmpNode; // set the flag that we have find the first foundTheFirst = true; if (tmpNode.IsTheRoot) firstMatchIsRoot = true; } } else if (foundTheFirst) break; // go to the next node tmpNode = tmpNode.NextNode; // check that we are in the beginning if (tmpNode.IsTheRoot) break; } #endregion if (firstNode == null) return; if (TooClose) return; #region Backward Test // reset the variables tmpNode = RootBoundaryNode.PrevNode; // pass all the nodes and find the first and the last one that we can use if (firstMatchIsRoot) while (true) { Half_Edge he = tmpNode.currentEdge; if ((vert.X - he.StartVertex.X) * (vert.X - he.StartVertex.X) + (vert.Y - he.StartVertex.Y) * (vert.Y - he.StartVertex.Y) < 0.1) { TooClose = true; break; } // test the angle if is negative // (neg mean that we are outside from the mesh ) if (Half_Edge.SideTest(he.StartVertex, he.NextEdge.StartVertex, vert)) { count++; // set the first node firstNode = tmpNode; } else break; // go to the next node tmpNode = tmpNode.PrevNode; // check that we are in the beginning if (tmpNode.IsTheRoot) break; } #endregion if (TooClose) return; #region Link the new nodes // pass the nodes from the first to last tmpNode = firstNode; foundTheFirst = false; int count2 = 0; BoundaryNode endNode = lastNode.NextNode; while (tmpNode != endNode) { Half_Edge he = tmpNode.currentEdge; count2++; Half_Edge he1, he2, he3; // create the triangle Half_Edge.CreateTriangle(he.StartVertex, vert, he.NextEdge.StartVertex, out he1, out he2, out he3); // link the twin edge he.TwinEdge = he3; he3.TwinEdge = he; // if we are in the mid of the search // link the prev edge to the triangle if (foundTheFirst) { // link the twin edges he1.TwinEdge = tmpNode.PrevNode.currentEdge; tmpNode.PrevNode.currentEdge.TwinEdge = he1; // check if we are going to remove the root node if (tmpNode.PrevNode.IsTheRoot) { // change the root node tmpNode.PrevNode.PrevNode.IsTheRoot = true; RootBoundaryNode = tmpNode.PrevNode.PrevNode; } // remove the prev one tmpNode.PrevNode.Remove(); // replace the current edge with this one tmpNode.currentEdge = he2; // update the boundary node UpdateBoundaryMaxMin(tmpNode); } else { // replace the board node with the 2 news tmpNode.currentEdge = he1; // update the boundary size UpdateBoundaryMaxMin(tmpNode); // add a new one after the one that we are now tmpNode.InsertNode(new BoundaryNode(he2), true); // move to the next one tmpNode = tmpNode.NextNode; //update the new node UpdateBoundaryMaxMin(tmpNode); // set that we have find the first that is correct foundTheFirst = true; } Face newFace = new Face(he1); // add the triangle to the list faceTree.Add(newFace); // fix the triangulation newFace.HalfEnd.NextEdge.DelaunayCorrection(newFace.HalfEnd.NextEdge.NextEdge.TwinEdge, faceTree); // move one to the list tmpNode = tmpNode.NextNode; } #endregion #endregion } }
/// <summary> /// Add external face /// </summary> /// <param name="face"></param> public void AddFace( Face face ) { // add the external face faceTree.Add( face ); }
private void FaceTreeRemove(FaceDistTreeNode faceNode, Face newFace) { // check if we are in leaf if (faceNode.isLeaf) { // just remove the face from the list faceNode.FaceList.Remove(newFace); } else { Boolean isRemoved = false; // continue to the correct side if (newFace.Min_X > faceNode.X_mid) { if (newFace.Min_Y > faceNode.Y_mid) { FaceTreeRemove(faceNode.UpRight, newFace); isRemoved = true; } else if (newFace.Max_Y < faceNode.Y_mid) { FaceTreeRemove(faceNode.DownRight, newFace); isRemoved = true; } } else if (newFace.Max_X < faceNode.X_mid) { if (newFace.Min_Y > faceNode.Y_mid) { FaceTreeRemove(faceNode.UpLeft, newFace); isRemoved = true; } else if (newFace.Max_Y < faceNode.Y_mid) { FaceTreeRemove(faceNode.DownLeft, newFace); isRemoved = true; } } if (!isRemoved) { // just remove the face from the list faceNode.FaceList.Remove(newFace); } } }
/// <summary> /// update all the internal structs base on the specific struct /// </summary> public void Update( Face face ) { // update all the internal face face.Update(); /// update the position in the tree // find the face in the tree }