1 //#define SEARCH_DEBUG
\r
3 using System.Collections.Generic;
\r
5 using Microsoft.DirectX;
\r
6 using Microsoft.DirectX.Direct3D;
\r
10 public class Array3D<T>
\r
13 public int xx, yy, zz;
\r
15 public Array3D(int x, int y, int z)
\r
17 data = new T[x*y*z];
\r
23 public T Get(int x, int y, int z)
\r
25 return data[x+y*xx+z*xx*yy];
\r
28 public void Set(int x, int y, int z, T v)
\r
30 data[x+y*xx+z*xx*yy] = v;
\r
34 public class PointCluster
\r
36 public List<Vector3> points;
\r
39 public Array3D<List<int>> clusters;
\r
40 public Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
\r
41 public Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
\r
43 public PointCluster(int n)
\r
45 points = new List<Vector3>(n);
\r
48 public Vector3 GetPoint(int i)
\r
53 public void Add(Vector3 p)
\r
56 if(p.X < min.X) min.X= p.X; else if(p.X > max.X) max.X= p.X;
\r
57 if(p.Y < min.Y) min.Y= p.Y; else if(p.Y > max.Y) max.Y= p.Y;
\r
58 if(p.Z < min.Z) min.Z= p.Z; else if(p.Z > max.Z) max.Z= p.Z;
\r
61 public void Add(float x, float y, float z)
\r
63 Add(new Vector3(x, y, z));
\r
66 public void Clustering()
\r
68 float x = max.X - min.X;
\r
69 float y = max.Y - min.Y;
\r
70 float z = max.Z - min.Z;
\r
71 div = (int)Math.Ceiling((float)Math.Sqrt(Math.Sqrt(points.Count)));
\r
73 if(x >= y && x >= z) divu= x / div;
\r
74 else if(y >= x && y >= z) divu= y / div;
\r
75 else if(z >= x && z >= y) divu= z / div;
\r
77 clusters = new Array3D<List<int>>
\r
78 (Math.Max(1, (int)(x / divu)),
\r
79 Math.Max(1, (int)(y / divu)),
\r
80 Math.Max(1, (int)(z / divu)));
\r
82 for(int i= 0, n= points.Count; i < n; ++i)
\r
83 AddCluster(i, points[i].X, points[i].Y, points[i].Z);
\r
86 public int Clump(int a, int min, int max)
\r
88 return a < min ? min : a > max ? max : a;
\r
91 public int IndexX(float x) { return Clump((int)((x-min.X) / divu), 0, clusters.xx-1); }
\r
92 public int IndexY(float y) { return Clump((int)((y-min.Y) / divu), 0, clusters.yy-1); }
\r
93 public int IndexZ(float z) { return Clump((int)((z-min.Z) / divu), 0, clusters.zz-1); }
\r
95 public void AddCluster(int i, float x, float y, float z)
\r
97 int a = IndexX(x), b= IndexY(y), c= IndexZ(z);
\r
102 l = clusters.Get(a, b, c);
\r
105 clusters.Set(a, b, c, l= new List<int>());
\r
108 } catch(Exception e)
\r
110 System.Diagnostics.Debug.WriteLine(e);
\r
114 public int NearestIndex(float x, float y, float z)
\r
121 float distsq = float.MaxValue;
\r
126 for(int i= 0; i <= limit; ++i)
\r
128 for(int xx= a-i; xx <= a+i; ++xx)
\r
129 for(int yy= b-i; yy <= b+i; ++yy)
\r
130 for(int zz= c-i; zz <= c+i; ++zz)
\r
132 if(xx < 0 || xx >= clusters.xx) continue;
\r
133 if(yy < 0 || yy >= clusters.yy) continue;
\r
134 if(zz < 0 || zz >= clusters.zz) continue;
\r
136 List<int> l = clusters.Get(xx, yy, zz);
\r
141 foreach(int j in l)
\r
143 Vector3 p = points[j];
\r
147 float d = p.X*p.X + p.Y*p.Y + p.Z*p.Z;
\r
162 System.Diagnostics.Debug.WriteLine(string.Format(
\r
163 "dbgcount:{0} index:{1} distance:{2}", dbgcount, near, distsq));
\r