/// <summary> /// Based upon the info of the nearest vertex (of each vertex), the triangles are created /// </summary> /// <param name="myModel"></param> //private static List<Triangle> CreateTrianglesByNearestVertices(PointCloud pointCloud) //{ // List<Triangle> listTriangles = new List<Triangle>(); // //create triangles // //for (int i = pointCloud.Count - 1; i >= 0; i--) // for (int i = 0; i < pointCloud.Count; i++) // { // Vertex v = pointCloud[i]; // if (v.KDTreeSearch.Count >= 2) // { // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[0].Key, v.KDTreeSearch[1].Key, listTriangles, v); // } // if (v.KDTreeSearch.Count >= 3) // { // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[0].Key, v.KDTreeSearch[2].Key, listTriangles, v); // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[1].Key, v.KDTreeSearch[2].Key, listTriangles, v); // } // if (v.KDTreeSearch.Count >= 4) // { // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[0].Key, v.KDTreeSearch[3].Key, listTriangles, v); // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[1].Key, v.KDTreeSearch[3].Key, listTriangles, v); // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[2].Key, v.KDTreeSearch[3].Key, listTriangles, v); // } // if (v.KDTreeSearch.Count >= 5) // { // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[0].Key, v.KDTreeSearch[4].Key, listTriangles, v); // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[1].Key, v.KDTreeSearch[4].Key, listTriangles, v); // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[2].Key, v.KDTreeSearch[4].Key, listTriangles, v); // Triangle.AddTriangleToList(v.Index, v.KDTreeSearch[3].Key, v.KDTreeSearch[4].Key, listTriangles, v); // } // } // //RemoveDuplicateTriangles(listTriangles); // listTriangles.Sort(new TriangleComparer()); // return listTriangles; //} public void Triangulate_KDTree(int numberNeighbours) { KDTreeKennell kdTree = new KDTreeKennell(); kdTree.Build(this); List <Triangle> listTriangles = new List <Triangle>(); for (int i = 0; i < this.Vectors.Length; i++) { VertexKDTree vSource = new VertexKDTree(this.Vectors[i], this.Colors[i], i); uint indexI = Convert.ToUInt32(i); ListKDTreeResultVectors listResult = kdTree.Find_N_Nearest(vSource.Vector, numberNeighbours); for (int j = 1; j < listResult.Count; j++) { for (int k = j + 1; k < listResult.Count; k++) { Triangle t = new Triangle(indexI, listResult[j].IndexNeighbour, listResult[k].IndexNeighbour); listTriangles.Add(t); } } } this.Triangles = listTriangles; CreateIndicesFromTriangles(); }
/// <summary> /// Algorithm based on ignoring points with less neighbours int thresholdNeighboursCount = 10; float thresholdDistance = 15e-5f; /// at given distance. /// </summary> /// <param name="source"></param> /// <param name="threshold"></param> /// <returns></returns> public static PointCloud ByLessNeighbours(PointCloud source, float thresholdDistance, int thresholdNeighboursCount) { PointCloud pcResult = new PointCloud(); KDTreeKennell kdTree = new KDTreeKennell(); kdTree.Build(source); VertexKDTree[] resultArray = new VertexKDTree[source.Count]; try { List <Vector3> listV = new List <Vector3>(); List <Vector3> listC = new List <Vector3>(); System.Threading.Tasks.Parallel.For(0, source.Count, i => { VertexKDTree vSource = new VertexKDTree(source.Vectors[i], source.Colors[i], i); int neighboursCount = 0; kdTree.FindClosestPoints_Radius(vSource, thresholdDistance, ref neighboursCount); if (neighboursCount >= thresholdNeighboursCount) { resultArray[i] = vSource; } }); for (int i = 0; i < source.Count; i++) { if (resultArray[i] != null) { listV.Add(resultArray[i].Vector); listC.Add(resultArray[i].Color); } } pcResult.Vectors = listV.ToArray(); pcResult.Colors = listC.ToArray(); pcResult.SetDefaultIndices(); } catch (Exception err) { System.Windows.Forms.MessageBox.Show("Error in KDTreeKennnellRemoveDuplicates: " + err.Message); } return(pcResult); }
/// <summary> /// mergedPoints /// </summary> /// <param name="pointsTransformed"></param> /// <param name="pointsTarget"></param> /// <param name="kdTree"></param> /// <param name="meanDistance"></param> /// <returns></returns> public static PointCloud CalculateMergedPoints(PointCloud pointsTransformed, PointCloud pointsTarget, IKDTree kdTree, float threshold, out int pointsAdded, bool changeColorsOfMergedPoints) { if (pointsTransformed.Colors == null || pointsTransformed.Colors.Length != pointsTransformed.Vectors.Length) { pointsTransformed.Colors = new Vector3[pointsTransformed.Vectors.Length]; } if (pointsTarget.Colors == null || pointsTarget.Colors.Length != pointsTarget.Vectors.Length) { pointsTarget.Colors = new Vector3[pointsTarget.Vectors.Length]; } //search in tree // PointCloud resultKDTree = kdTree.FindClosestPointCloud_Parallel(result); KDTreeKennell kdTreeKennell = kdTree as KDTreeKennell; PointCloud pcToAdd = kdTreeKennell.RemoveDuplicates(pointsTransformed, threshold); pointsAdded = pcToAdd.Vectors.Length; //System.Diagnostics.Debug.WriteLine("target points added : " + pcToAdd.Vectors.Length.ToString() + " - outof " + result.Vectors.Length.ToString()); if (changeColorsOfMergedPoints) { pcToAdd.SetColor(new Vector3(0, 1, 1)); } List <Vector3> listV = pointsTarget.ListVectors; List <Vector3> listC = pointsTarget.ListColors; listV.AddRange(pcToAdd.ListVectors); listC.AddRange(pcToAdd.ListColors); PointCloud pMerged = new PointCloud(listV, listC, null, null, null, null); return(pMerged); }
public KDTreeNodeKennell(KDTreeKennell parent) { Parent = parent; }
public static void StandardDeviation(PointCloud source, int numberOfNeighbours, out float meanDistance, out float standardDeviation, out float[] distances) { meanDistance = 0; standardDeviation = 0f; distances = new float[source.Count]; KDTreeKennell kdTree = new KDTreeKennell(); kdTree.Build(source); PointCloud pcResult = new PointCloud(); VertexKDTree[] resultArray = new VertexKDTree[source.Count]; VertexKDTree[] outliers = new VertexKDTree[source.Count]; try { List <Vector3> listV = new List <Vector3>(); List <Vector3> listC = new List <Vector3>(); //1. mean distance of one point to his next "numberOfNeighbours" neighbours - stored in the "distances" array for (int i = 0; i < source.Count; i++) { VertexKDTree vSource = new VertexKDTree(source.Vectors[i], source.Colors[i], i); ListKDTreeResultVectors listResult = kdTree.Find_N_Nearest(vSource.Vector, numberOfNeighbours); float distSum = 0f; for (int k = 1; k < listResult.Count; ++k) // k = 0 is the query point { distSum += listResult[k].Distance; } distances[i] = (distSum / (listResult.Count - 1)); } //2. calculate the mean distance of ALL points for (int i = 0; i < distances.Length; ++i) { meanDistance += distances[i]; } meanDistance /= distances.Length; //3. calculate the deviation of each data point from the mean, and square the result of each for (int i = 0; i < distances.Length; i++) { float dev = distances[i] - meanDistance; dev *= dev; standardDeviation += dev; } standardDeviation /= distances.Length; standardDeviation = Convert.ToSingle(Math.Sqrt(standardDeviation)); } catch (Exception err) { System.Windows.Forms.MessageBox.Show("Error in KDTreeKennnellRemoveDuplicates: " + err.Message); } }