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