3 using System.Collections.Generic;
8 public class Array3D<T>
11 public int xx, yy, zz;
13 public Array3D(int x, int y, int z)
15 data = new T[x * y * z];
21 public T Get(int x, int y, int z)
23 return data[x + y * xx + z * xx * yy];
26 public void Set(int x, int y, int z, T v)
28 data[x + y * xx + z * xx * yy] = v;
32 public class PointCluster
34 public List<Point3> points;
37 public Array3D<List<int>> clusters;
38 public Point3 min = new Point3(float.MaxValue, float.MaxValue, float.MaxValue);
39 public Point3 max = new Point3(float.MinValue, float.MinValue, float.MinValue);
41 public PointCluster(int n)
43 points = new List<Point3>(n);
46 public Point3 GetPoint(int i)
51 public void Add(Point3 p)
54 if (p.x < min.x) min.x = p.x; else if (p.x > max.x) max.x = p.x;
55 if (p.y < min.y) min.y = p.y; else if (p.y > max.y) max.y = p.y;
56 if (p.z < min.z) min.z = p.z; else if (p.z > max.z) max.z = p.z;
59 public void Add(float x, float y, float z)
61 Add(new Point3(x, y, z));
64 public void Clustering()
66 float x = max.x - min.x;
67 float y = max.y - min.y;
68 float z = max.z - min.z;
69 div = (int)Math.Ceiling((float)Math.Sqrt(Math.Sqrt(points.Count)));
71 if (x >= y && x >= z) divu = x / div;
72 else if (y >= x && y >= z) divu = y / div;
73 else if (z >= x && z >= y) divu = z / div;
75 clusters = new Array3D<List<int>>
76 (Math.Max(1, (int)(x / divu)),
77 Math.Max(1, (int)(y / divu)),
78 Math.Max(1, (int)(z / divu)));
80 for (int i = 0, n = points.Count; i < n; ++i)
81 AddCluster(i, points[i].x, points[i].y, points[i].z);
84 public int Clump(int a, int min, int max)
86 return a < min ? min : a > max ? max : a;
89 public int IndexX(float x) { return Clump((int)((x - min.x) / divu), 0, clusters.xx - 1); }
90 public int IndexY(float y) { return Clump((int)((y - min.y) / divu), 0, clusters.yy - 1); }
91 public int IndexZ(float z) { return Clump((int)((z - min.z) / divu), 0, clusters.zz - 1); }
93 public void AddCluster(int i, float x, float y, float z)
95 int a = IndexX(x), b = IndexY(y), c = IndexZ(z);
100 l = clusters.Get(a, b, c);
103 clusters.Set(a, b, c, l = new List<int>());
107 catch (Exception exception)
109 System.Diagnostics.Debug.WriteLine(exception);
113 public int NearestIndex(float x, float y, float z)
120 float distsq = float.MaxValue;
125 for (int i = 0; i <= limit; ++i)
127 for (int xx = a - i; xx <= a + i; ++xx)
128 for (int yy = b - i; yy <= b + i; ++yy)
129 for (int zz = c - i; zz <= c + i; ++zz)
131 if (xx < 0 || xx >= clusters.xx) continue;
132 if (yy < 0 || yy >= clusters.yy) continue;
133 if (zz < 0 || zz >= clusters.zz) continue;
135 List<int> l = clusters.Get(xx, yy, zz);
142 Point3 p = points[j];
146 float d = p.x * p.x + p.y * p.y + p.z * p.z;
161 System.Diagnostics.Debug.WriteLine(string.Format(
162 "dbgcount:{0} index:{1} distance:{2}", dbgcount, near, distsq));