private static void handle(string input_filename, Func <int, int, int, GeometrySampleResult> sample_routine) //****************************************************************************80 // // Purpose: // // HANDLE handles a single file. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 July 2005 // // Author: // // John Burkardt // // Reference: // // Max Gunzburger, John Burkardt, // Uniformity Measures for Point Samples in Hypercubes. // // Parameters: // // Input, char *INPUT_FILENAME, the name of the input file. // // Local parameters: // // Local, int DIM_NUM, the spatial dimension of the point set. // // Local, int N, the number of points. // // Local, double Z[DIM_NUM*N], the point set. // // Local, int NS, the number of sample points. // // Input, double *SAMPLE_ROUTINE, the name of a routine which // is used to produce an DIM_NUM by N array of sample points in the region, // of the form: // double *sample_routine ( int dim_num, int n, int *seed ) // { double gamma_std; int i; const int ns = 100000; int nt = 0; const int seed_init = 123456789; int[] triangle = null; int triangle_order; TableHeader h = typeMethods.dtable_header_read(input_filename); int dim_num = h.m; int n = h.n; // // Read the point set. // double[] z = typeMethods.dtable_data_read(input_filename, dim_num, n); switch (dim_num) { // // For 2D datasets, compute the Delaunay triangulation. // case 2: triangle = new int[3 * 2 * n]; int[] triangle_neighbor = new int[3 * 2 * n]; Delauney.dtris2(n, 0, ref z, ref nt, ref triangle, ref triangle_neighbor); Console.WriteLine(""); Console.WriteLine(" Triangulated data generates " + nt + " triangles."); break; default: nt = 0; break; } Console.WriteLine(""); Console.WriteLine(" Measures of uniform point dispersion."); Console.WriteLine(""); Console.WriteLine(" The pointset was read from \"" + input_filename + "\"."); Console.WriteLine(" The sample routine will be SAMPLE_HYPERCUBE_UNIFORM."); Console.WriteLine(""); Console.WriteLine(" Spatial dimension DIM_NUM = " + dim_num + ""); Console.WriteLine(" The number of points N = " + n + ""); Console.WriteLine(" The number of sample points NS = " + ns + ""); Console.WriteLine(" The random number SEED_INIT = " + seed_init + ""); Console.WriteLine(""); switch (dim_num) { case 2: triangle_order = 3; Console.WriteLine(" The minimum angle measure Alpha = " + Quality.alpha_measure(n, z, triangle_order, nt, triangle) + ""); break; default: Console.WriteLine(" The minimum angle measure Alpha = (omitted)"); break; } Console.WriteLine(" Relative spacing deviation Beta = " + Quality.beta_measure(dim_num, n, z) + ""); Console.WriteLine(" The regularity measure Chi = " + Quality.chi_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); Console.WriteLine(" 2nd moment determinant measure D = " + Quality.d_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); Console.WriteLine(" The Voronoi energy measure E = " + Quality.e_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); Console.WriteLine(" The mesh ratio Gamma = " + Quality.gamma_measure(dim_num, n, z) + ""); Console.WriteLine(" The point distribution norm H = " + Quality.h_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); Console.WriteLine(" The COV measure Lambda = " + Quality.lambda_measure(dim_num, n, z) + ""); Console.WriteLine(" The point distribution ratio Mu = " + Quality.mu_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); Console.WriteLine(" The cell volume deviation Nu = " + Quality.nu_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); switch (dim_num) { case 2: triangle_order = 2; Console.WriteLine(" The triangle uniformity measure Q = " + Quality.q_measure(n, z, triangle_order, nt, triangle) + ""); break; default: Console.WriteLine(" The triangle uniformity measure Q = (omitted)"); break; } Console.WriteLine(" The Riesz S = 0 energy measure R0 = " + Quality.r0_measure(dim_num, n, z) + ""); if (typeMethods.r8mat_in_01(dim_num, n, z)) { Console.WriteLine(" Nonintersecting sphere volume S = " + Quality.sphere_measure(dim_num, n, z) + ""); } else { Console.WriteLine(" Nonintersecting sphere volume S = (omitted)"); } Console.WriteLine(" 2nd moment trace measure Tau = " + Quality.tau_measure(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init) + ""); double[] gamma = Spacing.pointset_spacing(dim_num, n, z); double gamma_ave = 0.0; for (i = 0; i < n; i++) { gamma_ave += gamma[i]; } gamma_ave /= n; double gamma_min = typeMethods.r8vec_min(n, gamma); double gamma_max = typeMethods.r8vec_max(n, gamma); switch (n) { case > 1: { gamma_std = 0.0; for (i = 0; i < n; i++) { gamma_std += Math.Pow(gamma[i] - gamma_ave, 2); } gamma_std = Math.Sqrt(gamma_std / (n - 1)); break; } default: gamma_std = 0.0; break; } Console.WriteLine(""); Console.WriteLine(" Minimum spacing Gamma_min = " + gamma_min + ""); Console.WriteLine(" Average spacing Gamma_ave = " + gamma_ave + ""); Console.WriteLine(" Maximum spacing Gamma_max = " + gamma_max + ""); Console.WriteLine(" Spacing standard deviate Gamma_std = " + gamma_std + ""); }
private static void Main(string[] args) //****************************************************************************80 // // Purpose: // // MAIN is the main program for TABLE_DELAUNAY. // // Discussion: // // TABLE_DELAUNAY computes the Delaunay triangulation of a TABLE dataset. // // The dataset is simply a set of points in the plane. // // Thus, given a set of points V1, V2, ..., VN, we apply a standard // Delaunay triangulation. The Delaunay triangulation is an organization // of the data into triples, forming a triangulation of the data, with // the property that the circumcircle of each triangle never contains // another data point. // // Usage: // // table_delaunay prefix // // where: // // 'prefix' is the common prefix for the node and triangle files: // // * prefix_nodes.txt, the node coordinates (input). // * prefix_elements.txt, the nodes that make up each triangle (output). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 22 June 2006 // // Author: // // John Burkardt // { const int base_ = 1; string prefix; int triangle_num = 0; int triangle_order = 0; Console.WriteLine(""); Console.WriteLine(""); Console.WriteLine("TABLE_DELAUNAY"); Console.WriteLine(""); Console.WriteLine(" Read a TABLE dataset of N points in 2 dimensions,"); Console.WriteLine(" Compute the Delaunay triangulation."); Console.WriteLine(" Write an integer TABLE dataset of the triangulation."); // // First argument is the file prefix. // try { prefix = args[0]; } catch { Console.WriteLine(""); Console.WriteLine("TABLE_DELAUNAY:"); Console.WriteLine(" Please enter the file prefix."); prefix = Console.ReadLine(); } // // Create the filenames. // string node_filename = prefix + "_nodes.txt"; string triangle_filename = prefix + "_elements.txt"; // // Read the point coordinates. // TableHeader h = typeMethods.r8mat_header_read(node_filename); int node_dim = h.m; int node_num = h.n; Console.WriteLine(""); Console.WriteLine(" Read the header of \"" + node_filename + "\""); Console.WriteLine(""); Console.WriteLine(" Node dimension NODE_DIM = " + node_dim + ""); Console.WriteLine(" Node number NODE_NUM = " + node_num + ""); if (node_dim != 2) { Console.WriteLine(""); Console.WriteLine("TABLE_DELAUNAY - Fatal error!"); Console.WriteLine(" The node dimension is not 2."); return; } double[] node_xy = typeMethods.r8mat_data_read(node_filename, node_dim, node_num); Console.WriteLine(""); Console.WriteLine(" Read the data of \"" + node_filename + "\""); typeMethods.r8mat_transpose_print_some(node_dim, node_num, node_xy, 1, 1, node_dim, 5, " Initial portion of node data:"); // // Determine the Delaunay triangulation. // triangle_order = 3; int[] triangle_node = new int[triangle_order * 3 * node_num]; int[] triangle_neighbor = new int[triangle_order * 3 * node_num]; Delauney.dtris2(node_num, base_, ref node_xy, ref triangle_num, ref triangle_node, ref triangle_neighbor); // // Print a portion of the triangulation. // Console.WriteLine(""); Console.WriteLine(" Computed the triangulation."); Console.WriteLine(" Number of triangles is " + triangle_num + ""); typeMethods.i4mat_transpose_print_some(triangle_order, triangle_num, triangle_node, 1, 1, 3, 5, " Initial portion of triangulation data:"); // // Write the triangulation to a file. // typeMethods.i4mat_write(triangle_filename, triangle_order, triangle_num, triangle_node); Console.WriteLine(""); Console.WriteLine(" Wrote the triangulation data to \"" + triangle_filename + "\"."); // // Terminate execution. // Console.WriteLine(""); Console.WriteLine("TABLE_DELAUNAY:"); Console.WriteLine(" Normal end of execution."); Console.WriteLine(""); }
private static void voronoi_data(int g_num, double[] g_xy, ref int[] g_degree, ref int[] g_start, ref int[] g_face, ref int v_num, ref double[] v_xy, ref int i_num, ref double[] i_xy) //****************************************************************************80 // // Purpose: // // VORONOI_DATA returns data defining the Voronoi diagram. // // Discussion: // // The routine first determines the Delaunay triangulation. // // The Voronoi diagram is then determined from this information. // // In particular, the circumcenter of each Delaunay triangle // is a vertex of a Voronoi polygon. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 February 2005 // // Author: // // John Burkardt // // Parameters: // // Input, int G_NUM, the number of generators. // // Input, double G_XY[2*G_NUM], the point coordinates. // // Output, int G_DEGREE[G_NUM], the degree of each Voronoi cell. // // Output, int G_START[G_NUM], the index in G_FACE of the first // vertex at which to begin a traversal of the boundary of the // cell associated with each point. // // Output, int G_FACE[6*G_NUM], the sequence of vertices to be used // in a traversal of the boundary of the cell associated with each point. // // Output, int *V_NUM, the number of vertices of the Voronoi diagram. // // Output, double V_XY[2*V_NUM], the coordinates of the vertices // of the Voronoi diagram. // // Output, int *I_NUM, the number of vertices at infinity of the // Voronoi diagram. // // Output, double I_XY[2*I_NUM], the direction of the // vertices at infinity. // { const int NDIM = 2; const bool debug = true; int g; int i; int j; int k; int s_next = 0; double[] t = new double[NDIM * 3]; int v; // // Compute the Delaunay triangulation. // int[] nodtri = new int[3 * 2 * g_num]; int[] tnbr = new int[3 * 2 * g_num]; Delauney.dtris2(g_num, 0, ref g_xy, ref v_num, ref nodtri, ref tnbr); // // At this point, you could extend the NODTRI and TNBR data structures // to account for the "vertices at infinity." // int v_inf = Triangle.tri_augment(v_num, ref nodtri); switch (debug) { case true: Console.WriteLine(""); Console.WriteLine(" The generators that form each Delaunay triangle:"); Console.WriteLine(" (Negative values are fictitious nodes at infinity.)"); Console.WriteLine(""); typeMethods.i4mat_transpose_print(3, v_num + v_inf, nodtri, " Triangle nodes:"); break; } // // Negative entries in TNBR indicate a semi-infinite Voronoi side. // However, DTRIS2 uses a peculiar numbering. Renumber them. // i_num = 0; for (v = 0; v < v_num; v++) { for (i = 0; i < 3; i++) { switch (tnbr[i + v * 3]) { case < 0: i_num += 1; tnbr[i + v * 3] = -i_num; break; } } } switch (debug) { case true: Console.WriteLine(""); Console.WriteLine(" Neighboring triangles of each Delaunay triangle:"); Console.WriteLine(" Negative values indicate no finite neighbor."); Console.WriteLine(""); typeMethods.i4mat_transpose_print(3, v_num, tnbr, " Neighbor triangles:"); break; } // // Determine the degree of each cell. // for (g = 0; g < g_num; g++) { g_degree[g] = 0; } for (j = 0; j < v_num + v_inf; j++) { for (i = 0; i < 3; i++) { k = nodtri[i + j * 3]; switch (k) { case > 0: g_degree[k - 1] += 1; break; } } } switch (debug) { case true: typeMethods.i4vec_print(g_num, g_degree, " Voronoi cell degrees:"); break; } // // Each (finite) Delaunay triangle contains a vertex of the Voronoi polygon, // at the triangle's circumcenter. // for (j = 0; j < v_num; j++) { int i1 = nodtri[0 + j * 3]; int i2 = nodtri[1 + j * 3]; int i3 = nodtri[2 + j * 3]; t[0 + 0 * 2] = g_xy[0 + (i1 - 1) * 2]; t[1 + 0 * 2] = g_xy[1 + (i1 - 1) * 2]; t[0 + 1 * 2] = g_xy[0 + (i2 - 1) * 2]; t[1 + 1 * 2] = g_xy[1 + (i2 - 1) * 2]; t[0 + 2 * 2] = g_xy[0 + (i3 - 1) * 2]; t[1 + 2 * 2] = g_xy[1 + (i3 - 1) * 2]; double[] center = typeMethods.triangle_circumcenter_2d(t); v_xy[0 + j * 2] = center[0]; v_xy[1 + j * 2] = center[1]; } switch (debug) { case true: typeMethods.r8mat_transpose_print(2, v_num, v_xy, " The Voronoi vertices:"); break; } // // For each generator G: // Determine if its region is infinite. // Find a Delaunay triangle containing G. // Seek another triangle containing the next node in that triangle. // int count = 0; for (g = 0; g < g_num; g++) { g_start[g] = 0; } for (g = 1; g <= g_num; g++) { int v_next = 0; int s; for (v = 1; v <= v_num + v_inf; v++) { for (s = 1; s <= 3; s++) { if (nodtri[s - 1 + (v - 1) * 3] != g) { continue; } v_next = v; s_next = s; break; } if (v_next != 0) { break; } } int v_save = v_next; int g_next; int v_old; int sp1; for (;;) { s_next = typeMethods.i4_wrap(s_next + 1, 1, 3); g_next = nodtri[s_next - 1 + (v_next - 1) * 3]; if (g_next == g) { s_next = typeMethods.i4_wrap(s_next + 1, 1, 3); g_next = nodtri[s_next - 1 + (v_next - 1) * 3]; } v_old = v_next; v_next = 0; for (v = 1; v <= v_num + v_inf; v++) { if (v == v_old) { continue; } for (s = 1; s <= 3; s++) { if (nodtri[s - 1 + (v - 1) * 3] != g) { continue; } sp1 = typeMethods.i4_wrap(s + 1, 1, 3); if (nodtri[sp1 - 1 + (v - 1) * 3] == g_next) { v_next = v; s_next = sp1; break; } sp1 = typeMethods.i4_wrap(s + 2, 1, 3); if (nodtri[sp1 - 1 + (v - 1) * 3] != g_next) { continue; } v_next = v; s_next = sp1; break; } if (v_next != 0) { break; } } if (v_next == v_save) { break; } if (v_next != 0) { continue; } v_next = v_old; break; } // // Now, starting in the current triangle, V_NEXT, cycle again, // and copy the list of nodes into the array. // v_save = v_next; count += 1; g_start[g - 1] = count; g_face[count - 1] = v_next; for (;;) { s_next = typeMethods.i4_wrap(s_next + 1, 1, 3); g_next = nodtri[s_next - 1 + (v_next - 1) * 3]; if (g_next == g) { s_next = typeMethods.i4_wrap(s_next + 1, 1, 3); g_next = nodtri[s_next - 1 + (v_next - 1) * 3]; } v_old = v_next; v_next = 0; for (v = 1; v <= v_num + v_inf; v++) { if (v == v_old) { continue; } for (s = 1; s <= 3; s++) { if (nodtri[s - 1 + (v - 1) * 3] != g) { continue; } sp1 = typeMethods.i4_wrap(s + 1, 1, 3); if (nodtri[sp1 - 1 + (v - 1) * 3] == g_next) { v_next = v; s_next = sp1; break; } sp1 = typeMethods.i4_wrap(s + 2, 1, 3); if (nodtri[sp1 - 1 + (v - 1) * 3] != g_next) { continue; } v_next = v; s_next = sp1; break; } if (v_next != 0) { break; } } if (v_next == v_save) { break; } if (v_next == 0) { break; } count += 1; g_face[count - 1] = v_next; } } // // Mark all the vertices at infinity with a negative sign, // so that the data in G_FACE is easier to interpret. // for (i = 0; i < count; i++) { if (v_num < g_face[i]) { g_face[i] = -g_face[i]; } } Console.WriteLine(""); Console.WriteLine(" G_START: The index of the first Voronoi vertex"); Console.WriteLine(" G_FACE: The Voronoi vertices"); Console.WriteLine(""); Console.WriteLine(" G G_START G_FACE"); Console.WriteLine(""); for (j = 0; j < g_num; j++) { k = g_start[j] - 1; Console.WriteLine(""); Console.WriteLine(" " + (j + 1).ToString().PadLeft(4) + " " + (k + 1).ToString().PadLeft(4) + " " + g_face[k].ToString().PadLeft(4) + ""); for (i = 1; i < g_degree[j]; i++) { k += 1; Console.WriteLine(" " + g_face[k].ToString().PadLeft(4) + ""); } } // // For each (finite) Delaunay triangle, I // For each side J, // for (i = 0; i < v_num; i++) { for (j = 0; j < 3; j++) { k = tnbr[j + i * 3]; switch (k) { // // If there is no neighboring triangle on that side, // extend a line from the circumcenter of I in the direction of the // outward normal to that side. This is an infinite edge of // an infinite Voronoi polygon. // case < 0: int ix1 = nodtri[j + i * 3]; // x1 = g_xy[0+(ix1-1)*2]; // y1 = g_xy[1+(ix1-1)*2]; int jp1 = typeMethods.i4_wrap(j + 1, 0, 2); int ix2 = nodtri[jp1 + i * 3]; // x2 = g_xy[0+(ix2-1)*2]; // y2 = g_xy[1+(ix2-1)*2]; // // Compute the direction I_XY(1:2,-K). // double[] normal = Burkardt.LineNS.Geometry.line_exp_normal_2d(g_xy, g_xy, p1Index: +(ix1 - 1) * 2, p2Index: +(ix2 - 1) * 2); i_xy[0 + (-k - 1) * 2] = normal[0]; i_xy[1 + (-k - 1) * 2] = normal[1]; break; } } } }
private static void test_cvt() //****************************************************************************80 // // Purpose: // // TEST_CVT carries out tests of a pointset in the unit hypercube. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 16 February 2007 // // Author: // // John Burkardt // { int[] triangle_node = null; int triangle_num = 0; Console.WriteLine(""); Console.WriteLine("TEST_HALTON"); Console.WriteLine(" Analyze a pointset in the unit hypercube."); Console.WriteLine(""); Console.WriteLine(" We use a built-in sample routine."); int ns = 100000; int seed_init = 123456789; string input_filename = "cvt_02_00100.txt"; TableHeader h = typeMethods.dtable_header_read(input_filename); int dim_num = h.m; int n = h.n; Console.WriteLine(""); Console.WriteLine(" Measures of uniform point dispersion."); Console.WriteLine(""); Console.WriteLine(" The pointset was read from \"" + input_filename + "\""); Console.WriteLine(" The sample routine will be SAMPLE_HYPERCUBE_UNIFORM."); Console.WriteLine(""); Console.WriteLine(" Spatial dimension DIM_NUM = " + dim_num + ""); Console.WriteLine(" The number of points N = " + n + ""); Console.WriteLine(" The number of sample points NS = " + ns + ""); Console.WriteLine(" The random number SEED_INIT = " + seed_init + ""); Console.WriteLine(""); double[] z = typeMethods.dtable_data_read(input_filename, dim_num, n); typeMethods.r8mat_transpose_print_some(dim_num, n, z, 1, 1, 5, 5, " 5x5 portion of data read from file:"); switch (dim_num) { // // For 2D datasets, compute the Delaunay triangulation. // case 2: triangle_node = new int[3 * 2 * n]; int[] triangle_neighbor = new int[3 * 2 * n]; Delauney.dtris2(n, 0, ref z, ref triangle_num, ref triangle_node, ref triangle_neighbor); Console.WriteLine(""); Console.WriteLine(" Triangulated data generates " + triangle_num + " triangles."); break; default: triangle_num = 0; break; } switch (dim_num) { case 2: test005(n, z, triangle_num, triangle_node); test006(n, z, triangle_num, triangle_node); break; } test007(dim_num, n, z); test01(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); test02(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); test03(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); test04(dim_num, n, z); test05(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); test06(dim_num, n, z); test07(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); test08(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); switch (dim_num) { case 2: test083(n, z, triangle_num, triangle_node); break; } test085(dim_num, n, z); test09(dim_num, n, z); test10(dim_num, n, z, ns, Burkardt.HyperGeometry.Hypercube.Sample.sample_hypercube_uniform, seed_init); test11(dim_num, n, z); }