public FaceDistTree(int maxFacesPerLeaf = 100) { // set the max faces MaxFaces = maxFacesPerLeaf; // allocate face list FaceRoot = new FaceDistTreeNode(); // allocate boundary list BoundaryFaces = new List<Face>(); }
private void FaceTreeStat(FaceDistTreeNode faceNode, ref int MaxDepth, ref int MinDepth, ref int NumNodes, ref int NumLeaf, ref int NumFaces, ref int NumFacesInNodes) { if (faceNode.isLeaf) { // inc the leafs NumLeaf++; // inc the NumFaces NumFaces += faceNode.FaceList.Count; MaxDepth++; MinDepth++; } else { int MaxDepth1 = 0, MaxDepth2 = 0, MaxDepth3 = 0, MaxDepth4 = 0; int MinDepth1 = 0, MinDepth2 = 0, MinDepth3 = 0, MinDepth4 = 0; // pass the Childs FaceTreeStat(faceNode.DownLeft, ref MaxDepth1, ref MinDepth1, ref NumNodes, ref NumLeaf, ref NumFaces, ref NumFacesInNodes); FaceTreeStat(faceNode.UpLeft, ref MaxDepth2, ref MinDepth2, ref NumNodes, ref NumLeaf, ref NumFaces, ref NumFacesInNodes); FaceTreeStat(faceNode.UpRight, ref MaxDepth3, ref MinDepth3, ref NumNodes, ref NumLeaf, ref NumFaces, ref NumFacesInNodes); FaceTreeStat(faceNode.DownRight, ref MaxDepth4, ref MinDepth4, ref NumNodes, ref NumLeaf, ref NumFaces, ref NumFacesInNodes); // add the min/max depth MaxDepth += Math.Max(Math.Max(MaxDepth1, MaxDepth2), Math.Max(MaxDepth3, MaxDepth4)); MinDepth += Math.Min(Math.Min(MinDepth1, MinDepth2), Math.Min(MinDepth3, MinDepth4)); MaxDepth++; MinDepth++; // inc the num Nodes NumNodes++; // inc the NumFaces NumFaces += faceNode.FaceList.Count; // inc the num faces only in the nodes NumFacesInNodes += faceNode.FaceList.Count; } }
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 FaceTreeFindRange( FaceDistTreeNode faceNode, IVertex<float> vertex, List<Face> results ) { // check if we are in leaf if (faceNode.isLeaf) { Half_Edge tmpEdge; int count = 3; // pass all the faces foreach (Face fa in faceNode.FaceList) { tmpEdge = fa.HalfEnd; count = 0; while (count < 3) { // check if we have hit if (tmpEdge.StartVertex.X == vertex.X && tmpEdge.StartVertex.Y == vertex.Y) { results.Add(fa); break; } // go to the next edge of the face tmpEdge = tmpEdge.NextEdge; count++; } } return; } else { // continue to the correct side if (vertex.X == faceNode.X_mid && vertex.Y == faceNode.Y_mid) { FaceTreeFindRange(faceNode.UpRight, vertex, results); FaceTreeFindRange(faceNode.DownRight, vertex, results); FaceTreeFindRange(faceNode.UpLeft, vertex, results); FaceTreeFindRange(faceNode.DownLeft, vertex, results); } else if (vertex.X > faceNode.X_mid) { if (vertex.Y == faceNode.Y_mid) { FaceTreeFindRange(faceNode.UpRight, vertex, results); FaceTreeFindRange(faceNode.DownRight, vertex, results); } else if (vertex.Y > faceNode.Y_mid) { FaceTreeFindRange(faceNode.UpRight, vertex, results); } else { FaceTreeFindRange(faceNode.DownRight, vertex,results); } } else if (vertex.X < faceNode.X_mid) { if (vertex.Y == faceNode.Y_mid) { FaceTreeFindRange(faceNode.UpLeft, vertex, results); FaceTreeFindRange(faceNode.DownLeft, vertex, results); } else if (vertex.Y > faceNode.Y_mid) { FaceTreeFindRange(faceNode.UpLeft, vertex, results); } else { FaceTreeFindRange(faceNode.DownLeft, vertex, results); } } else { if (vertex.Y > faceNode.Y_mid) { FaceTreeFindRange(faceNode.UpLeft, vertex, results); FaceTreeFindRange(faceNode.UpRight, vertex, results); } else { FaceTreeFindRange(faceNode.DownLeft, vertex, results); FaceTreeFindRange(faceNode.DownRight, vertex, results); } } } }
private Face FaceTreeFind( FaceDistTreeNode faceNode, IVertex<float> vertex ) { // check if we are in leaf if (faceNode.isLeaf) { // pass all the faces foreach (Face fa in faceNode.FaceList) { // check if we have hit if (fa.isHit(vertex)) { return fa; } } return null; } else { // continue to the correct side if (vertex.X >= faceNode.X_mid) { if (vertex.Y >= faceNode.Y_mid) { return FaceTreeFind(faceNode.UpRight, vertex); } else { return FaceTreeFind(faceNode.DownRight, vertex); } } else { if (vertex.Y >= faceNode.Y_mid) { return FaceTreeFind(faceNode.UpLeft, vertex); } else { return FaceTreeFind(faceNode.DownLeft, vertex); } } } }
private void FaceTreeExec(FaceDistTreeNode faceNode, FaceFunction func) { // check if we are in leaf if (faceNode.isLeaf) { // pass all the faces foreach (Face fa in faceNode.FaceList) { func(fa); } } else { FaceTreeExec(faceNode.DownLeft, func); FaceTreeExec(faceNode.UpLeft, func); FaceTreeExec(faceNode.DownRight, func); FaceTreeExec(faceNode.UpRight, func); } }
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); } } } }
private void FaceNodeSpliting(FaceDistTreeNode faceNode) { // check if the face is leaf just in case if (faceNode.isLeaf) { #if true // find the median // sort base on x faceNode.FaceList.Sort(delegate(Face fa1, Face fa2) { return fa1.Max_X.CompareTo(fa2.Max_X); }); // get the median value faceNode.X_mid = faceNode.FaceList[(int)Math.Truncate(faceNode.FaceList.Count / 2.0f)].Min_X; // sort base on y faceNode.FaceList.Sort(delegate(Face fa1, Face fa2) { return fa1.Max_Y.CompareTo(fa2.Max_Y); }); // get the median value faceNode.Y_mid = faceNode.FaceList[(int)Math.Truncate(faceNode.FaceList.Count / 2.0f)].Min_Y; #else float max_X = float.MinValue, min_X = float.MaxValue; float max_Y = float.MinValue, min_Y = float.MaxValue; foreach (Face fa in faceNode.FaceList) { // get the max x if (max_X < fa.Max_X) max_X = fa.Max_X; // get the min x if (min_X > fa.Min_X) min_X = fa.Min_X; // get the max Y if (max_Y < fa.Max_Y) max_Y = fa.Max_Y; // get the min Y if (min_Y > fa.Min_Y) min_Y = fa.Min_Y; } // get the mid value faceNode.X_mid = (min_X + max_X) / 2; faceNode.Y_mid = (min_Y + max_Y) / 2; #endif // create the 4 leaf faceNode.UpLeft = new FaceDistTreeNode(); faceNode.DownLeft = new FaceDistTreeNode(); faceNode.UpRight = new FaceDistTreeNode(); faceNode.DownRight = new FaceDistTreeNode(); // disable the leaf mode of the node faceNode.isLeaf = false; // fill the nodes foreach (Face fa in faceNode.FaceList) { if (fa.Min_X >= faceNode.X_mid) { if (fa.Min_Y >= faceNode.Y_mid) { faceNode.UpRight.FaceList.Add(fa); } else if (fa.Max_Y <= faceNode.Y_mid) { faceNode.DownRight.FaceList.Add(fa); } else { // add in both sides :P faceNode.UpRight.FaceList.Add(fa); faceNode.DownRight.FaceList.Add(fa); } } else if (fa.Max_X <= faceNode.X_mid) { if (fa.Min_Y >= faceNode.Y_mid) { faceNode.UpLeft.FaceList.Add(fa); } else if (fa.Max_Y <= faceNode.Y_mid) { faceNode.DownLeft.FaceList.Add(fa); } else { // add in both sides :P faceNode.UpLeft.FaceList.Add(fa); faceNode.DownLeft.FaceList.Add(fa); } } else { if (fa.Min_Y >= faceNode.Y_mid) { // add in both sides faceNode.UpLeft.FaceList.Add(fa); faceNode.UpRight.FaceList.Add(fa); } else if (fa.Max_Y <= faceNode.Y_mid) { // add in both sides faceNode.DownLeft.FaceList.Add(fa); faceNode.DownRight.FaceList.Add(fa); } else { // add in all sides :P faceNode.DownRight.FaceList.Add(fa); faceNode.DownLeft.FaceList.Add(fa); faceNode.UpRight.FaceList.Add(fa); faceNode.UpLeft.FaceList.Add(fa); } } } // clean the list faceNode.FaceList.Clear(); } }
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); } } }