/SqlSpatialIndexing/Indices/Voronoi/VoronoiDiagram.cs
C# | 451 lines | 358 code | 69 blank | 24 comment | 24 complexity | e356a6bb4b97c4f15e9c6c13f5e082e1 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Data.SqlClient;
- using System.Data;
-
- namespace Elte.SqlSpIdx.Indices
- {
- public class VoronoiDiagram : DBObjectBase
- {
- public struct Pair<T>
- {
- public T a;
- public T b;
- }
-
- #region Member variables
-
- internal int dimensions;
- private VoronoiIndex index;
-
- List<VoronoiCell> cells = new List<VoronoiCell>();
- List<double[]> vertices = new List<double[]>();
- List<Pair<int>> ridges = new List<Pair<int>>();
- HalfspaceList halfspaces = new HalfspaceList();
-
- #endregion
-
- #region Properties
-
- public List<VoronoiCell> Cells
- {
- get { return cells; }
- }
-
- public List<double[]> Vertices
- {
- get { return vertices; }
- }
-
- public HalfspaceList Halfspaces
- {
- get { return halfspaces; }
- }
-
- #endregion
-
- #region Constructors
-
- //****
- public VoronoiDiagram(VoronoiIndex index)
- {
- this.databaseConnection = index.DatabaseConnection;
- this.databaseTransaction = index.DatabaseTransaction;
- this.index = index;
- this.dimensions = index.Dimensions;
- }
-
- #endregion
-
-
-
- public void Generate(double[][] seeds)
- {
- int rescount;
-
- // copy seeds
- for (int i = 0; i < seeds.Length; i++)
- {
- VoronoiCell c = new VoronoiCell(this);
- c.Id = i;
- c.Coord = seeds[i];
- cells.Add(c);
- }
-
- // Reading random cells and sending to QHull for Voronoi generation
-
- System.Diagnostics.ProcessStartInfo pinfo = new System.Diagnostics.ProcessStartInfo();
-
- pinfo.FileName = "C:\\QHullExe\\qvoronoi.exe";
- pinfo.Arguments = "s Fi Fo p FN";
- if (index.ComputeRidges) pinfo.Arguments += " Fn";
- pinfo.CreateNoWindow = true;
- pinfo.RedirectStandardInput = true;
- pinfo.RedirectStandardOutput = true;
- pinfo.RedirectStandardError = true;
- pinfo.UseShellExecute = false;
-
- // starting QHull
- System.Diagnostics.Process p = System.Diagnostics.Process.Start(pinfo);
-
- p.StandardInput.Write("{0}\n", dimensions);
- p.StandardInput.Write("{0}\n", seeds.Length);
-
- for (int i = 0; i < seeds.Length; i++)
- {
- for (int k = 0; k < seeds[i].Length; k++)
- {
- if (k > 0) p.StandardInput.Write(" ");
- p.StandardInput.Write(seeds[i][k].ToString(System.Globalization.CultureInfo.InvariantCulture.NumberFormat));
- }
- p.StandardInput.Write("\n");
- }
-
- p.StandardInput.Flush();
- p.StandardInput.Close();
-
- // Halfspaces
- for (int q = 0; q <= 1; q++)
- {
- //hplaneinsert.Parameters["@Inner"].Value = (q == 0); // reading inner or outer
-
- rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- for (int i = 0; i < rescount; i++)
- {
- string[] parts = p.StandardOutput.ReadLine().Split(' ');
-
- double[] vector = new double[dimensions];
- for (int k = 0; k < dimensions; k++)
- vector[k] = double.Parse(parts[3 + k], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- double offset = double.Parse(parts[dimensions + 3], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
-
- int cid1 = int.Parse(parts[1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- int cid2 = int.Parse(parts[2], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
-
- Halfspace l = new Halfspace(vector, offset);
- l.CellId1 = cid1;
- l.CellId2 = cid2;
- halfspaces.Add(l);
- cells[cid1].halfspaces.Add(halfspaces.Count - 1);
- cells[cid2].halfspaces.Add(halfspaces.Count - 1);
-
- if (q == 1)
- {
- cells[cid1].Inner = false;
- cells[cid2].Inner = false;
- }
- }
- }
-
- // Vertices
-
- p.StandardOutput.ReadLine(); // dimensions
- rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // # of vertices
- for (int i = 0; i < rescount; i++)
- {
- string[] parts = p.StandardOutput.ReadLine().Split(' ');
-
- double[] vector = new double[dimensions];
- for (int k = 0; k < dimensions; k++)
- vector[k] = double.Parse(parts[k], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
-
- vertices.Add(vector);
- }
-
- // Vertex - Cell relations
- rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // # of cells
- for (int i = 0; i < rescount; i++)
- {
- string[] parts = p.StandardOutput.ReadLine().Split(' ');
-
- // first number indicates # of vertices belonging to the seed
- int numvertices = int.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- for (int k = 0; k < numvertices; k++)
- {
- int vid = int.Parse(parts[k + 1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- if (vid >= 0)
- {
- cells[i].vertices.Add(vid);
- }
- }
-
- if (index.ComputeStatistics)
- {
- cells[i].CalculateBoundingBall();
- cells[i].CalculatePca();
- cells[i].CalculateMinMax();
- }
- }
-
- // Ridges
- if (index.ComputeRidges)
- {
- rescount = int.Parse(p.StandardOutput.ReadLine(), System.Globalization.CultureInfo.InvariantCulture.NumberFormat); // # of vertices
- for (int i = 0; i < rescount; i++)
- {
- string[] parts = p.StandardOutput.ReadLine().Split(' ');
-
- // first number indicates # of neighboring vertices belonging to the vertex
- int numvertices = int.Parse(parts[0], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- for (int k = 0; k < numvertices; k++)
- {
- int vid = int.Parse(parts[k + 1], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
- if (vid >= 0)
- {
- Pair<int> pa;
- pa.a = i;
- pa.b = vid;
- ridges.Add(pa);
- }
- }
- }
- }
- }
-
- public void Load()
- {
- LoadCells();
- LoadHalfspaces();
- LoadVertices();
- LoadVSRelations();
- }
-
- public void LoadCells()
- {
- cells.Clear();
- string sql = "SELECT * FROM " + index.Table + "_SPIDX_" + index.Name + "_Cells ORDER BY CellID";
- using (SqlCommand cmd = CreateCommand(sql))
- {
- using (SqlDataReader dr = cmd.ExecuteReader())
- {
- while (dr.Read())
- {
- VoronoiCell cell = new VoronoiCell(this, dr);
- cells.Add(cell);
- }
- dr.Close();
- }
- }
- }
-
- public void LoadHalfspaces()
- {
- string sql = "SELECT CellID1, CellID2, Coord, Offset FROM " + index.Table + "_SPIDX_" + index.Name + "_HSpaces";
- using (SqlCommand cmd = CreateCommand(sql))
- {
- using (SqlDataReader dr = cmd.ExecuteReader())
- {
- double offset;
- double[] v;
- while (dr.Read())
- {
- int id1 = dr.GetInt32(0);
- int id2 = dr.GetInt32(1);
-
- VoronoiCell c1, c2;
- c1 = cells[id1];
- c2 = cells[id2];
-
- c1.neighbors.Add(id2);
- c2.neighbors.Add(id1);
-
- v = Converters.VectorConverter.ToArray(dr.GetSqlBinary(2));
- offset = dr.GetDouble(3);
-
- Halfspace l = new Halfspace(v, offset);
- l.CellId1 = id1;
- l.CellId2 = id2;
- this.halfspaces.Add(l);
-
- //**** itt azt is el kellene tárolni, hogy melyik cella irányába mutat a normális....
- c1.halfspaces.Add(halfspaces.Count - 1);
- c2.halfspaces.Add(halfspaces.Count - 1);
-
- /*if (!dr.GetBoolean(4))
- {
- c1.Inner = false;
- c2.Inner = false;
- }*/
- }
- dr.Close();
- }
- }
- }
-
- public void LoadVertices()
- {
- string sql = "SELECT VertexID, Coord " +
- "FROM " + index.Table + "_SPIDX_" + index.Name + "_Vertices " +
- "ORDER BY VertexID";
- using (SqlCommand cmd = CreateCommand(sql))
- {
- using (SqlDataReader dr = cmd.ExecuteReader())
- {
- double[] v;
- while (dr.Read())
- {
- int id = dr.GetInt32(0);
-
- v = Converters.VectorConverter.ToArray(dr.GetSqlBinary(1));
- this.vertices.Add(v);
- }
- dr.Close();
- }
- }
- }
-
- public void LoadVSRelations()
- {
- string sql = "SELECT VertexID, CellID " +
- "FROM " + index.Table + "_SPIDX_" + index.Name + "_VSRel a ";
- using (SqlCommand cmd = CreateCommand(sql))
- {
- using (SqlDataReader dr = cmd.ExecuteReader())
- {
- while (dr.Read())
- {
- int vid = dr.GetInt32(0);
- int cid = dr.GetInt32(1);
-
- this.cells[cid].vertices.Add(vid);
- }
- dr.Close();
- }
- }
- }
-
- public void Save()
- {
- SaveHalfspaces();
- SaveVertices();
- SaveVSRelations();
- SaveRidges();
- SaveCells();
- }
-
- public void SaveHalfspaces()
- {
- // Hyperplanes
- string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_Hspaces (CellID1, CellID2, Coord, Offset) VALUES (@CellID1, @CellID2, @Coord, @Offset)";
- using (SqlCommand hplaneinsert = CreateCommand(sql))
- {
- hplaneinsert.Parameters.Add("@CellID1", SqlDbType.Int);
- hplaneinsert.Parameters.Add("@CellID2", SqlDbType.Int);
- hplaneinsert.Parameters.Add("@Coord", SqlDbType.VarBinary);
- hplaneinsert.Parameters.Add("@Offset", SqlDbType.Float);
-
- foreach (Halfspace l in halfspaces)
- {
- hplaneinsert.Parameters["@CellID1"].Value = l.CellId1;
- hplaneinsert.Parameters["@CellID2"].Value = l.CellId2;
- hplaneinsert.Parameters["@Coord"].Value = Converters.VectorConverter.ToBinary(l.A);
- hplaneinsert.Parameters["@Offset"].Value = l.B;
-
- hplaneinsert.ExecuteNonQuery();
- }
- }
- }
-
- public void SaveVertices()
- {
- string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_Vertices (VertexID, Coord) VALUES (@VertexID, @Coord)";
- using (SqlCommand vertexinsert = CreateCommand(sql))
- {
- vertexinsert.Parameters.Add("@VertexID", SqlDbType.Int);
- vertexinsert.Parameters.Add("@Coord", SqlDbType.VarBinary);
-
- int i = 0;
- foreach (double[] v in vertices)
- {
- vertexinsert.Parameters["@VertexID"].Value = i;
- vertexinsert.Parameters["@Coord"].Value = Converters.VectorConverter.ToBinary(v);
-
- vertexinsert.ExecuteNonQuery();
-
- i++;
- }
- }
- }
-
- public void SaveVSRelations()
- {
- // Vertex - Cell relations
- string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_VSRel (CellID, VertexID) VALUES (@CellID, @VertexID)";
- using (SqlCommand cmd = CreateCommand(sql))
- {
- cmd.Parameters.Add("@CellID", SqlDbType.Int);
- cmd.Parameters.Add("@VertexID", SqlDbType.Int);
-
- foreach (VoronoiCell cell in cells)
- {
- cmd.Parameters["@CellID"].Value = cell.Id;
-
- // first number indicates # of vertices belonging to the seed
- foreach (int vid in cell.vertices)
- {
- //****
- try
- {
- cmd.Parameters["@VertexID"].Value = vid;
- cmd.ExecuteNonQuery();
- }
- catch
- {
- }
- }
- }
- }
- }
-
- public void SaveRidges()
- {
- // Ridges
- string sql = "INSERT " + index.Table + "_SPIDX_" + index.Name + "_Ridges (VertexID1, VertexID2) VALUES (@VertexID1, @VertexID2)";
- using (SqlCommand cmd = CreateCommand(sql))
- {
- cmd.Parameters.Add("@VertexID1", SqlDbType.Int);
- cmd.Parameters.Add("@VertexID2", SqlDbType.Int);
-
- foreach (Pair<int> p in ridges)
- {
- cmd.Parameters["@VertexID1"].Value = p.a;
- cmd.Parameters["@VertexID2"].Value = p.b;
- cmd.ExecuteNonQuery();
- }
- }
- }
-
- public void SaveCells()
- {
- // cells update to store volume etc
- string sql = "UPDATE " + index.Table + "_SPIDX_" + index.Name + "_Cells SET " +
- " Center = @Center, [Inner] = @Inner, Radius = @Radius, Volume = @Volume, Eigenvalues = @Eigenvalues, " +
- " [Min] = @Min, [Max] = @Max " +
- " WHERE CellID = @CellID";
- using (SqlCommand cmd2 = CreateCommand(sql))
- {
- cmd2.Parameters.Add("@CellID", SqlDbType.Int);
- cmd2.Parameters.Add("@Center", SqlDbType.VarBinary);
- cmd2.Parameters.Add("@Inner", SqlDbType.Bit);
- cmd2.Parameters.Add("@Radius", SqlDbType.Float);
- cmd2.Parameters.Add("@Volume", SqlDbType.Float);
- cmd2.Parameters.Add("@Eigenvalues", SqlDbType.VarBinary);
- cmd2.Parameters.Add("@Min", SqlDbType.VarBinary);
- cmd2.Parameters.Add("@Max", SqlDbType.VarBinary);
-
- foreach (VoronoiCell cell in cells)
- cell.Save(cmd2);
- }
- }
-
- public void CheckCellSections(HalfspaceList ls, bool useVertices, bool useRadius)
- {
- //for (int i = 0; i < cells.Count; i ++)
- foreach (VoronoiCell cell in cells)
- cell.CheckSection(ls, useVertices, useRadius);
-
- return;
- }
- }
- }