PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/SqlSpatialIndexing/Indices/Voronoi/VoronoiDiagram.cs

#
C# | 451 lines | 358 code | 69 blank | 24 comment | 24 complexity | e356a6bb4b97c4f15e9c6c13f5e082e1 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Data.SqlClient;
  5. using System.Data;
  6. namespace Elte.SqlSpIdx.Indices
  7. {
  8. public class VoronoiDiagram : DBObjectBase
  9. {
  10. public struct Pair<T>
  11. {
  12. public T a;
  13. public T b;
  14. }
  15. #region Member variables
  16. internal int dimensions;
  17. private VoronoiIndex index;
  18. List<VoronoiCell> cells = new List<VoronoiCell>();
  19. List<double[]> vertices = new List<double[]>();
  20. List<Pair<int>> ridges = new List<Pair<int>>();
  21. HalfspaceList halfspaces = new HalfspaceList();
  22. #endregion
  23. #region Properties
  24. public List<VoronoiCell> Cells
  25. {
  26. get { return cells; }
  27. }
  28. public List<double[]> Vertices
  29. {
  30. get { return vertices; }
  31. }
  32. public HalfspaceList Halfspaces
  33. {
  34. get { return halfspaces; }
  35. }
  36. #endregion
  37. #region Constructors
  38. //****
  39. public VoronoiDiagram(VoronoiIndex index)
  40. {
  41. this.databaseConnection = index.DatabaseConnection;
  42. this.databaseTransaction = index.DatabaseTransaction;
  43. this.index = index;
  44. this.dimensions = index.Dimensions;
  45. }
  46. #endregion
  47. public void Generate(double[][] seeds)
  48. {
  49. int rescount;
  50. // copy seeds
  51. for (int i = 0; i < seeds.Length; i++)
  52. {
  53. VoronoiCell c = new VoronoiCell(this);
  54. c.Id = i;
  55. c.Coord = seeds[i];
  56. cells.Add(c);
  57. }
  58. // Reading random cells and sending to QHull for Voronoi generation
  59. System.Diagnostics.ProcessStartInfo pinfo = new System.Diagnostics.ProcessStartInfo();
  60. pinfo.FileName = "C:\\QHullExe\\qvoronoi.exe";
  61. pinfo.Arguments = "s Fi Fo p FN";
  62. if (index.ComputeRidges) pinfo.Arguments += " Fn";
  63. pinfo.CreateNoWindow = true;
  64. pinfo.RedirectStandardInput = true;
  65. pinfo.RedirectStandardOutput = true;
  66. pinfo.RedirectStandardError = true;
  67. pinfo.UseShellExecute = false;
  68. // starting QHull
  69. System.Diagnostics.Process p = System.Diagnostics.Process.Start(pinfo);
  70. p.StandardInput.Write("{0}\n", dimensions);
  71. p.StandardInput.Write("{0}\n", seeds.Length);
  72. for (int i = 0; i < seeds.Length; i++)
  73. {
  74. for (int k = 0; k < seeds[i].Length; k++)
  75. {
  76. if (k > 0) p.StandardInput.Write(" ");
  77. p.StandardInput.Write(seeds[i][k].ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
  78. }
  79. p.StandardInput.Write("\n");
  80. }
  81. p.StandardInput.Flush();
  82. p.StandardInput.Close();
  83. // Halfspaces
  84. for (int q = 0; q <= 1; q++)
  85. {
  86. //hplaneinsert.Parameters["@Inner"].Value = (q == 0); // reading inner or outer
  87. rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  88. for (int i = 0; i < rescount; i++)
  89. {
  90. string[] parts = p.StandardOutput.ReadLine().Split(' ');
  91. double[] vector = new double[dimensions];
  92. for (int k = 0; k < dimensions; k++)
  93. vector[k] = double.Parse(parts[3 + k], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  94. double offset = double.Parse(parts[dimensions + 3], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  95. int cid1 = int.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  96. int cid2 = int.Parse(parts[2], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  97. Halfspace l = new Halfspace(vector, offset);
  98. l.CellId1 = cid1;
  99. l.CellId2 = cid2;
  100. halfspaces.Add(l);
  101. cells[cid1].halfspaces.Add(halfspaces.Count - 1);
  102. cells[cid2].halfspaces.Add(halfspaces.Count - 1);
  103. if (q == 1)
  104. {
  105. cells[cid1].Inner = false;
  106. cells[cid2].Inner = false;
  107. }
  108. }
  109. }
  110. // Vertices
  111. p.StandardOutput.ReadLine(); // dimensions
  112. rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // # of vertices
  113. for (int i = 0; i < rescount; i++)
  114. {
  115. string[] parts = p.StandardOutput.ReadLine().Split(' ');
  116. double[] vector = new double[dimensions];
  117. for (int k = 0; k < dimensions; k++)
  118. vector[k] = double.Parse(parts[k], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  119. vertices.Add(vector);
  120. }
  121. // Vertex - Cell relations
  122. rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // # of cells
  123. for (int i = 0; i < rescount; i++)
  124. {
  125. string[] parts = p.StandardOutput.ReadLine().Split(' ');
  126. // first number indicates # of vertices belonging to the seed
  127. int numvertices = int.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  128. for (int k = 0; k < numvertices; k++)
  129. {
  130. int vid = int.Parse(parts[k + 1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  131. if (vid >= 0)
  132. {
  133. cells[i].vertices.Add(vid);
  134. }
  135. }
  136. if (index.ComputeStatistics)
  137. {
  138. cells[i].CalculateBoundingBall();
  139. cells[i].CalculatePca();
  140. cells[i].CalculateMinMax();
  141. }
  142. }
  143. // Ridges
  144. if (index.ComputeRidges)
  145. {
  146. rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // # of vertices
  147. for (int i = 0; i < rescount; i++)
  148. {
  149. string[] parts = p.StandardOutput.ReadLine().Split(' ');
  150. // first number indicates # of neighboring vertices belonging to the vertex
  151. int numvertices = int.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  152. for (int k = 0; k < numvertices; k++)
  153. {
  154. int vid = int.Parse(parts[k + 1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  155. if (vid >= 0)
  156. {
  157. Pair<int> pa;
  158. pa.a = i;
  159. pa.b = vid;
  160. ridges.Add(pa);
  161. }
  162. }
  163. }
  164. }
  165. }
  166. public void Load()
  167. {
  168. LoadCells();
  169. LoadHalfspaces();
  170. LoadVertices();
  171. LoadVSRelations();
  172. }
  173. public void LoadCells()
  174. {
  175. cells.Clear();
  176. string sql = "SELECT * FROM " + index.Table + "_SPIDX_" + index.Name + "_Cells ORDER BY CellID";
  177. using (SqlCommand cmd = CreateCommand(sql))
  178. {
  179. using (SqlDataReader dr = cmd.ExecuteReader())
  180. {
  181. while (dr.Read())
  182. {
  183. VoronoiCell cell = new VoronoiCell(this, dr);
  184. cells.Add(cell);
  185. }
  186. dr.Close();
  187. }
  188. }
  189. }
  190. public void LoadHalfspaces()
  191. {
  192. string sql = "SELECT CellID1, CellID2, Coord, Offset FROM " + index.Table + "_SPIDX_" + index.Name + "_HSpaces";
  193. using (SqlCommand cmd = CreateCommand(sql))
  194. {
  195. using (SqlDataReader dr = cmd.ExecuteReader())
  196. {
  197. double offset;
  198. double[] v;
  199. while (dr.Read())
  200. {
  201. int id1 = dr.GetInt32(0);
  202. int id2 = dr.GetInt32(1);
  203. VoronoiCell c1, c2;
  204. c1 = cells[id1];
  205. c2 = cells[id2];
  206. c1.neighbors.Add(id2);
  207. c2.neighbors.Add(id1);
  208. v = Converters.VectorConverter.ToArray(dr.GetSqlBinary(2));
  209. offset = dr.GetDouble(3);
  210. Halfspace l = new Halfspace(v, offset);
  211. l.CellId1 = id1;
  212. l.CellId2 = id2;
  213. this.halfspaces.Add(l);
  214. //**** itt azt is el kellene tárolni, hogy melyik cella irányába mutat a normális....
  215. c1.halfspaces.Add(halfspaces.Count - 1);
  216. c2.halfspaces.Add(halfspaces.Count - 1);
  217. /*if (!dr.GetBoolean(4))
  218. {
  219. c1.Inner = false;
  220. c2.Inner = false;
  221. }*/
  222. }
  223. dr.Close();
  224. }
  225. }
  226. }
  227. public void LoadVertices()
  228. {
  229. string sql = "SELECT VertexID, Coord " +
  230. "FROM " + index.Table + "_SPIDX_" + index.Name + "_Vertices " +
  231. "ORDER BY VertexID";
  232. using (SqlCommand cmd = CreateCommand(sql))
  233. {
  234. using (SqlDataReader dr = cmd.ExecuteReader())
  235. {
  236. double[] v;
  237. while (dr.Read())
  238. {
  239. int id = dr.GetInt32(0);
  240. v = Converters.VectorConverter.ToArray(dr.GetSqlBinary(1));
  241. this.vertices.Add(v);
  242. }
  243. dr.Close();
  244. }
  245. }
  246. }
  247. public void LoadVSRelations()
  248. {
  249. string sql = "SELECT VertexID, CellID " +
  250. "FROM " + index.Table + "_SPIDX_" + index.Name + "_VSRel a ";
  251. using (SqlCommand cmd = CreateCommand(sql))
  252. {
  253. using (SqlDataReader dr = cmd.ExecuteReader())
  254. {
  255. while (dr.Read())
  256. {
  257. int vid = dr.GetInt32(0);
  258. int cid = dr.GetInt32(1);
  259. this.cells[cid].vertices.Add(vid);
  260. }
  261. dr.Close();
  262. }
  263. }
  264. }
  265. public void Save()
  266. {
  267. SaveHalfspaces();
  268. SaveVertices();
  269. SaveVSRelations();
  270. SaveRidges();
  271. SaveCells();
  272. }
  273. public void SaveHalfspaces()
  274. {
  275. // Hyperplanes
  276. string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_Hspaces (CellID1, CellID2, Coord, Offset) VALUES (@CellID1, @CellID2, @Coord, @Offset)";
  277. using (SqlCommand hplaneinsert = CreateCommand(sql))
  278. {
  279. hplaneinsert.Parameters.Add("@CellID1", SqlDbType.Int);
  280. hplaneinsert.Parameters.Add("@CellID2", SqlDbType.Int);
  281. hplaneinsert.Parameters.Add("@Coord", SqlDbType.VarBinary);
  282. hplaneinsert.Parameters.Add("@Offset", SqlDbType.Float);
  283. foreach (Halfspace l in halfspaces)
  284. {
  285. hplaneinsert.Parameters["@CellID1"].Value = l.CellId1;
  286. hplaneinsert.Parameters["@CellID2"].Value = l.CellId2;
  287. hplaneinsert.Parameters["@Coord"].Value = Converters.VectorConverter.ToBinary(l.A);
  288. hplaneinsert.Parameters["@Offset"].Value = l.B;
  289. hplaneinsert.ExecuteNonQuery();
  290. }
  291. }
  292. }
  293. public void SaveVertices()
  294. {
  295. string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_Vertices (VertexID, Coord) VALUES (@VertexID, @Coord)";
  296. using (SqlCommand vertexinsert = CreateCommand(sql))
  297. {
  298. vertexinsert.Parameters.Add("@VertexID", SqlDbType.Int);
  299. vertexinsert.Parameters.Add("@Coord", SqlDbType.VarBinary);
  300. int i = 0;
  301. foreach (double[] v in vertices)
  302. {
  303. vertexinsert.Parameters["@VertexID"].Value = i;
  304. vertexinsert.Parameters["@Coord"].Value = Converters.VectorConverter.ToBinary(v);
  305. vertexinsert.ExecuteNonQuery();
  306. i++;
  307. }
  308. }
  309. }
  310. public void SaveVSRelations()
  311. {
  312. // Vertex - Cell relations
  313. string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_VSRel (CellID, VertexID) VALUES (@CellID, @VertexID)";
  314. using (SqlCommand cmd = CreateCommand(sql))
  315. {
  316. cmd.Parameters.Add("@CellID", SqlDbType.Int);
  317. cmd.Parameters.Add("@VertexID", SqlDbType.Int);
  318. foreach (VoronoiCell cell in cells)
  319. {
  320. cmd.Parameters["@CellID"].Value = cell.Id;
  321. // first number indicates # of vertices belonging to the seed
  322. foreach (int vid in cell.vertices)
  323. {
  324. //****
  325. try
  326. {
  327. cmd.Parameters["@VertexID"].Value = vid;
  328. cmd.ExecuteNonQuery();
  329. }
  330. catch
  331. {
  332. }
  333. }
  334. }
  335. }
  336. }
  337. public void SaveRidges()
  338. {
  339. // Ridges
  340. string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_Ridges (VertexID1, VertexID2) VALUES (@VertexID1, @VertexID2)";
  341. using (SqlCommand cmd = CreateCommand(sql))
  342. {
  343. cmd.Parameters.Add("@VertexID1", SqlDbType.Int);
  344. cmd.Parameters.Add("@VertexID2", SqlDbType.Int);
  345. foreach (Pair<int> p in ridges)
  346. {
  347. cmd.Parameters["@VertexID1"].Value = p.a;
  348. cmd.Parameters["@VertexID2"].Value = p.b;
  349. cmd.ExecuteNonQuery();
  350. }
  351. }
  352. }
  353. public void SaveCells()
  354. {
  355. // cells update to store volume etc
  356. string sql = "UPDATE " + index.Table + "_SPIDX_" + index.Name + "_Cells SET " +
  357. " Center = @Center, [Inner] = @Inner, Radius = @Radius, Volume = @Volume, Eigenvalues = @Eigenvalues, " +
  358. " [Min] = @Min, [Max] = @Max " +
  359. " WHERE CellID = @CellID";
  360. using (SqlCommand cmd2 = CreateCommand(sql))
  361. {
  362. cmd2.Parameters.Add("@CellID", SqlDbType.Int);
  363. cmd2.Parameters.Add("@Center", SqlDbType.VarBinary);
  364. cmd2.Parameters.Add("@Inner", SqlDbType.Bit);
  365. cmd2.Parameters.Add("@Radius", SqlDbType.Float);
  366. cmd2.Parameters.Add("@Volume", SqlDbType.Float);
  367. cmd2.Parameters.Add("@Eigenvalues", SqlDbType.VarBinary);
  368. cmd2.Parameters.Add("@Min", SqlDbType.VarBinary);
  369. cmd2.Parameters.Add("@Max", SqlDbType.VarBinary);
  370. foreach (VoronoiCell cell in cells)
  371. cell.Save(cmd2);
  372. }
  373. }
  374. public void CheckCellSections(HalfspaceList ls, bool useVertices, bool useRadius)
  375. {
  376. //for (int i = 0; i < cells.Count; i ++)
  377. foreach (VoronoiCell cell in cells)
  378. cell.CheckSection(ls, useVertices, useRadius);
  379. return;
  380. }
  381. }
  382. }