public void spawnDelauney(int vertices, float size) { iDelauney = new Delauney(); iDelauney.createDelauney(vertices, size, iTerrain); iDelauneyObject = new GameObject("iDelauney"); iDelauneyObject.transform.parent = iSelf.transform; iDelauneyObject.AddComponent <MeshFilter> (); iDelauneyObject.AddComponent <MeshRenderer> (); iDelauneyObject.AddComponent <CustomRender> (); workingMesh = new Mesh(); iDelauneyObject.GetComponent <MeshFilter> ().mesh = workingMesh; workingMesh.vertices = iDelauney.getVertices(); workingMesh.triangles = iDelauney.getTriangles(); workingMesh.RecalculateNormals(); iDelauneyObject.GetComponent <CustomRender> ().passColor(iLineColor); iDelauneyObject.GetComponent <CustomRender> ().CreateLinesFromMesh(); iDelauneyObject.GetComponent <Renderer> ().material = iMaterial01; spawnBackfaceObject(); }
/** * Given a face and a point, this will add a vertex to the pb_Object and retriangulate the face. */ public static bool AppendVerticesToFace(this pb_Object pb, pb_Face face, List <Vector3> points, out pb_Face newFace) { if (!face.isValid()) { newFace = face; return(false); } // First order of business - project face to 2d int[] distinctIndices = face.distinctIndices; Vector3[] verts = pb.GetVertices(distinctIndices); // Get the face normal before modifying the vertex array Vector3 nrm = pb_Math.Normal(pb.GetVertices(face.indices)); Vector3 projAxis = pb_Math.GetProjectionAxis(nrm).ToVector3(); // Add the new point Vector3[] t_verts = new Vector3[verts.Length + points.Count]; System.Array.Copy(verts, 0, t_verts, 0, verts.Length); System.Array.Copy(points.ToArray(), 0, t_verts, verts.Length, points.Count); verts = t_verts; // Project List <Vector2> plane = new List <Vector2>(pb_Math.VerticesTo2DPoints(verts, projAxis)); // Save the sharedIndices index for each distinct vertex pb_IntArray[] sharedIndices = pb.sharedIndices; int[] sharedIndex = new int[distinctIndices.Length + points.Count]; for (int i = 0; i < distinctIndices.Length; i++) { sharedIndex[i] = sharedIndices.IndexOf(distinctIndices[i]); } for (int i = distinctIndices.Length; i < distinctIndices.Length + points.Count; i++) { sharedIndex[i] = -1; // add the new vertex to it's own sharedIndex } // Triangulate the face with the new point appended int[] tris = Delauney.Triangulate(plane).ToIntArray(); // Check to make sure the triangulated face is facing the same direction, and flip if not Vector3 del = Vector3.Cross(verts[tris[2]] - verts[tris[0]], verts[tris[1]] - verts[tris[0]]).normalized; if (Vector3.Dot(nrm, del) > 0) { System.Array.Reverse(tris); } // Compose new face newFace = pb.AppendFace(verts, new pb_Face(tris, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, -1, face.color), sharedIndex); // And delete the old pb.DeleteFace(face); return(true); }
private static void test01() //****************************************************************************80 // // Purpose: // // TEST01 tests R8TRIS2. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 October 2012 // // Author: // // John Burkardt // { int[] element_neighbor = new int[3 * 2 * 9]; int element_num = 0; const int node_num = 9; double[] node_xy = { 0.0, 0.0, 0.0, 1.0, 0.2, 0.5, 0.3, 0.6, 0.4, 0.5, 0.6, 0.4, 0.6, 0.5, 1.0, 0.0, 1.0, 1.0 }; int[] triangle = new int[3 * 2 * 9]; Console.WriteLine(""); Console.WriteLine("TEST01"); Console.WriteLine(" R8TRIS2 computes the Delaunay triangulation of"); Console.WriteLine(" a set of nodes in 2D."); // // Set up the Delaunay triangulation. // Delauney.r8tris2(node_num, ref node_xy, ref element_num, ref triangle, ref element_neighbor); Print.triangulation_order3_print(node_num, element_num, node_xy, triangle, element_neighbor); }
private static void Main(string[] args) //****************************************************************************80 // // Purpose: // // MAIN is the main program for TRIANGULATION_DELAUNAY_DISCREPANCY. // // Discussion: // // TRIANGULATION_DELAUNAY_DISCREPANCY measures the amount (possibly zero) // by which a triangulation fails the local Delaunay test. // // The local Delaunay considers pairs of neighboring triangles. // The two triangles form a quadrilateral, and their common edge is one // diagonal of that quadrilateral. The program considers the effect of // replacing that diagonal with the other one. If the minimum angle // of the original configuration is smaller than in the new configuration, // then the pair of triangles has failed the local Delaunay test. // The amount by which the minimum angle would have increased is the // local discrepancy. // // This program searches all pairs of triangles, and records the maximum // discrepancy found. If this discrepancy is essentially zero, then the // triangulation is a Delaunay triangulation. Otherwise, it is not a // Delaunay triangulation. // // The user supplies a node file and a triangle file, containing // the coordinates of the nodes, and the indices of the nodes that // make up each triangle. Either 3-node or 6-node triangles may // be used. // // The program reads the node and triangle data, computes the triangle // neighbor information, and writes it to a file. // // Usage: // // triangulation_delaunay_discrepancy prefix // // where 'prefix' is the common filename prefix: // // * prefix_nodes.txt contains the node coordinates, // * prefix_elements.txt contains the element definitions. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 06 May 2020 // // Author: // // John Burkardt // { double angle_max = 0; int angle_max_triangle = 0; double angle_min = 0; int angle_min_triangle = 0; string prefix; Console.WriteLine(""); Console.WriteLine("TRIANGULATION_DELAUNAY_DISCREPANCY:"); Console.WriteLine(""); Console.WriteLine(" Read a node dataset of NODE_NUM points in 2 dimensions."); Console.WriteLine(" Read an associated triangulation dataset of "); Console.WriteLine(" TRIANGLE_NUM triangles using 3 or 6 nodes."); Console.WriteLine(""); Console.WriteLine(" Determine the Delaunay discrepancy, that is, the amount"); Console.WriteLine(" by which the minimum angle in the triangulation could be"); Console.WriteLine(" changed by a single adjustment of a pair of triangles."); Console.WriteLine(""); Console.WriteLine(" If this discrepancy is negative, "); Console.WriteLine(" then the triangulation is not a Delaunay triangulation."); Console.WriteLine(""); Console.WriteLine(" If this discrepancy is 0 or essentially so, "); Console.WriteLine(" then the triangulation is a Delaunay triangulation."); // // Get the filename prefix. // try { prefix = args[0]; } catch { Console.WriteLine(""); Console.WriteLine("TRIANGULATION_DELAUNAY_DISCREPANCY:"); Console.WriteLine(" Please enter the filename prefix."); prefix = Console.ReadLine(); } // // Create the filenames. // string node_filename = prefix + "_nodes.txt"; string element_filename = prefix + "_elements.txt"; // // Read the node data. // TableHeader h = typeMethods.r8mat_header_read(node_filename); int dim_num = h.m; int node_num = h.n; Console.WriteLine(""); Console.WriteLine(" Read the header of \"" + node_filename + "\"."); Console.WriteLine(""); Console.WriteLine(" Spatial dimension DIM_NUM = " + dim_num + ""); Console.WriteLine(" Number of nodes NODE_NUM = " + node_num + ""); double[] node_xy = typeMethods.r8mat_data_read(node_filename, dim_num, node_num); Console.WriteLine(""); Console.WriteLine(" Read the data in \"" + node_filename + "\"."); typeMethods.r8mat_transpose_print_some(dim_num, node_num, node_xy, 1, 1, dim_num, 5, " First 5 nodes:"); // // Read the triangulation data. // h = typeMethods.i4mat_header_read(element_filename); int triangle_order = h.m; int triangle_num = h.n; Console.WriteLine(""); Console.WriteLine(" Read the header of \"" + element_filename + "\"."); Console.WriteLine(""); Console.WriteLine(" Triangle order TRIANGLE_ORDER = " + triangle_order + ""); Console.WriteLine(" Number of triangles TRIANGLE_NUM = " + triangle_num + ""); int[] triangle_node = typeMethods.i4mat_data_read(element_filename, triangle_order, triangle_num); Console.WriteLine(""); Console.WriteLine(" Read the data in \"" + element_filename + "\"."); typeMethods.i4mat_transpose_print_some(triangle_order, triangle_num, triangle_node, 1, 1, triangle_order, 10, " First 10 triangles:"); // // Detect and correct 1-based node indexing. // Mesh.mesh_base_zero(node_num, triangle_order, triangle_num, ref triangle_node); // // Create the triangle neighbors. // int[] triangle_neighbor = NeighborElements.triangulation_neighbor_triangles(triangle_order, triangle_num, triangle_node); // // Convert to 0-based index. // for (int j = 0; j < triangle_num; j++) { for (int i = 0; i < 3; i++) { triangle_neighbor[i + 3 * j] -= 1; } } typeMethods.i4mat_transpose_print_some(3, triangle_num, triangle_neighbor, 1, 1, 3, 10, " First 10 triangle neighbors:"); // // Now we are ready to check. // double discrepancy = Delauney.triangulation_delaunay_discrepancy_compute(node_num, node_xy, triangle_order, triangle_num, triangle_node, triangle_neighbor, ref angle_min, ref angle_min_triangle, ref angle_max, ref angle_max_triangle); Console.WriteLine(""); Console.WriteLine(" Discrepancy (degrees) = " + discrepancy + ""); Console.WriteLine(" Minimum angle (degrees) = " + angle_min + ""); Console.WriteLine(" occurred in triangle " + angle_min_triangle + ""); Console.WriteLine(" Maximum angle (degrees) = " + angle_max + ""); Console.WriteLine(" occurred in triangle " + angle_max_triangle + ""); Console.WriteLine(""); Console.WriteLine("TRIANGULATION_DELAUNAY_DISCREPANCY:"); Console.WriteLine(" Normal end of execution."); Console.WriteLine(""); }
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 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 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(""); }
/** * Inserts a split from each selected vertex to the center of the face */ private static bool PokeFace_Internal(pb_Object pb, pb_Face face, int[] indices_nonFaceSpecific, out pb_Face[] splitFaces, out Vector3[][] splitVertices, out int[][] splitSharedIndices) { splitFaces = null; splitVertices = null; splitSharedIndices = null; pb_IntArray[] sharedIndices = pb.sharedIndices; ///** Sort index array such that it only uses indices local to the passed face int[] indices = new int[indices_nonFaceSpecific.Length]; int[] dist_ind_si = new int[face.distinctIndices.Length]; // figure out sharedIndices index of distinct Indices for (int i = 0; i < face.distinctIndices.Length; i++) { dist_ind_si[i] = sharedIndices.IndexOf(face.distinctIndices[i]); } // now do the same for non-face specific indices, assigning matching groups for (int i = 0; i < indices.Length; i++) { int ind = System.Array.IndexOf(dist_ind_si, sharedIndices.IndexOf(indices_nonFaceSpecific[i])); if (ind < 0) { return(false); } indices[i] = face.distinctIndices[ind]; } ///** Sort index array such that it only uses indices local to the passed face Vector3 cen3d = pb_Math.Average(pb.GetVertices(face)); Vector3[] verts = pb.GetVertices(face.distinctIndices); Vector3 nrm = pb_Math.Normal(pb.GetVertices(face.indices)); Vector2[] plane = pb_Math.VerticesTo2DPoints(verts, nrm); Vector2[] indPlane = pb_Math.VerticesTo2DPoints(pb.GetVertices(indices), nrm); Vector2 cen2d = pb_Math.VerticesTo2DPoints(new Vector3[1] { cen3d }, nrm)[0]; // Get the directions from which to segment this face Vector2[] dividers = new Vector2[indices.Length]; for (int i = 0; i < indices.Length; i++) { dividers[i] = (indPlane[i] - cen2d).normalized; } List <Vector2>[] quadrants2d = new List <Vector2> [indices.Length]; List <Vector3>[] quadrants3d = new List <Vector3> [indices.Length]; List <int>[] sharedIndex = new List <int> [indices.Length]; for (int i = 0; i < quadrants2d.Length; i++) { quadrants2d[i] = new List <Vector2>(1) { cen2d }; quadrants3d[i] = new List <Vector3>(1) { cen3d }; sharedIndex[i] = new List <int>(1) { -2 }; // any negative value less than -1 will be treated as a new group } for (int i = 0; i < face.distinctIndices.Length; i++) { // if this index is a divider, it needs to belong to the leftmost and // rightmost quadrant int indexInPokeVerts = System.Array.IndexOf(indices, face.distinctIndices[i]); int ignore = -1; if (indexInPokeVerts > -1) { // Add vert to this quadrant quadrants2d[indexInPokeVerts].Add(plane[i]); quadrants3d[indexInPokeVerts].Add(verts[i]); sharedIndex[indexInPokeVerts].Add(pb.sharedIndices.IndexOf(face.distinctIndices[i])); // And also the one closest counter clockwise ignore = indexInPokeVerts; } Vector2 dir = (plane[i] - cen2d).normalized; // plane corresponds to distinctIndices float largestClockwiseDistance = 0f; int quad = -1; for (int j = 0; j < dividers.Length; j++) { if (j == ignore) { continue; // this is a dividing vertex - ignore } float dist = Vector2.Angle(dividers[j], dir); if (Vector2.Dot(pb_Math.Perpendicular(dividers[j]), dir) < 0f) { dist = 360f - dist; } if (dist > largestClockwiseDistance) { largestClockwiseDistance = dist; quad = j; } } quadrants2d[quad].Add(plane[i]); quadrants3d[quad].Add(verts[i]); sharedIndex[quad].Add(pb.sharedIndices.IndexOf(face.distinctIndices[i])); } int len = quadrants2d.Length; // Triangulate int[][] tris = new int[len][]; for (int i = 0; i < len; i++) { tris[i] = Delauney.Triangulate(quadrants2d[i]).ToIntArray(); if (tris[i].Length < 3) { return(false); } // todo - check that face normal is correct } splitFaces = new pb_Face[len]; splitVertices = new Vector3[len][]; splitSharedIndices = new int[len][]; for (int i = 0; i < len; i++) { // triangles, material, pb_UV, smoothing group, shared index splitFaces[i] = new pb_Face(tris[i], face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, -1, face.color); splitVertices[i] = quadrants3d[i].ToArray(); splitSharedIndices[i] = sharedIndex[i].ToArray(); } return(true); }
// todo - there's a lot of duplicate code between this and poke face. /** * Inserts a vertex at the center of each edge, then connects the new vertices to another new * vertex placed at the center of the face. */ // internal method - so it's allow to be messy, right? private static bool SubdivideFace_Internal(pb_Object pb, EdgeConnection edgeConnection, out Vector3?[] appendedVertices, out pb_Face[] splitFaces, out Vector3[][] splitVertices, out int[][] splitSharedIndices) { splitFaces = null; splitVertices = null; splitSharedIndices = null; appendedVertices = new Vector3?[edgeConnection.edges.Count]; // cache all the things pb_Face face = edgeConnection.face; pb_IntArray[] sharedIndices = pb.sharedIndices; Vector3[] vertices = pb.vertices; List <Vector3> edgeCenters3d = new List <Vector3>(); //pb.GetVertices(edgeConnection.face)); // filter duplicate edges int u = 0; List <int> usedEdgeIndices = new List <int>(); foreach (pb_Edge edge in edgeConnection.edges) { int ind = face.edges.IndexOf(edge, sharedIndices); if (!usedEdgeIndices.Contains(ind)) { Vector3 cen = (vertices[edge.x] + vertices[edge.y]) / 2f; edgeCenters3d.Add(cen); usedEdgeIndices.Add(ind); appendedVertices[u] = cen; } else { appendedVertices[u] = null; } u++; } // now we have all the vertices of the old face, plus the new edge center vertices Vector3[] verts3d = pb.GetVertices(face.distinctIndices); Vector3 nrm = pb_Math.Normal(pb.GetVertices(face.indices)); Vector2[] verts2d = pb_Math.VerticesTo2DPoints(verts3d, nrm); Vector2[] edgeCenters2d = pb_Math.VerticesTo2DPoints(edgeCenters3d.ToArray(), nrm); Vector3 cen3d = pb_Math.Average(verts3d); Vector2 cen2d = pb_Math.VerticesTo2DPoints(new Vector3[1] { cen3d }, nrm)[0]; // Get the directions from which to segment this face Vector2[] dividers = new Vector2[edgeCenters2d.Length]; for (int i = 0; i < edgeCenters2d.Length; i++) { dividers[i] = (edgeCenters2d[i] - cen2d).normalized; } List <Vector2>[] quadrants2d = new List <Vector2> [edgeCenters2d.Length]; List <Vector3>[] quadrants3d = new List <Vector3> [edgeCenters2d.Length]; List <int>[] sharedIndex = new List <int> [edgeCenters2d.Length]; for (int i = 0; i < quadrants2d.Length; i++) { quadrants2d[i] = new List <Vector2>(1) { cen2d }; quadrants3d[i] = new List <Vector3>(1) { cen3d }; sharedIndex[i] = new List <int>(1) { -2 }; // any negative value less than -1 will be treated as a new group } // add the divisors for (int i = 0; i < edgeCenters2d.Length; i++) { quadrants2d[i].Add(edgeCenters2d[i]); quadrants3d[i].Add(edgeCenters3d[i]); sharedIndex[i].Add(-1); // -(i+2) to group new vertices in AppendFace // and add closest in the counterclockwise direction Vector2 dir = (edgeCenters2d[i] - cen2d).normalized; float largestClockwiseDistance = 0f; int quad = -1; for (int j = 0; j < dividers.Length; j++) { if (j == i) { continue; // this is a dividing vertex - ignore } float dist = Vector2.Angle(dividers[j], dir); if (Vector2.Dot(pb_Math.Perpendicular(dividers[j]), dir) < 0f) { dist = 360f - dist; } if (dist > largestClockwiseDistance) { largestClockwiseDistance = dist; quad = j; } } quadrants2d[quad].Add(edgeCenters2d[i]); quadrants3d[quad].Add(edgeCenters3d[i]); sharedIndex[quad].Add(-1); } // distribute the existing vertices for (int i = 0; i < face.distinctIndices.Length; i++) { Vector2 dir = (verts2d[i] - cen2d).normalized; // plane corresponds to distinctIndices float largestClockwiseDistance = 0f; int quad = -1; for (int j = 0; j < dividers.Length; j++) { float dist = Vector2.Angle(dividers[j], dir); if (Vector2.Dot(pb_Math.Perpendicular(dividers[j]), dir) < 0f) { dist = 360f - dist; } if (dist > largestClockwiseDistance) { largestClockwiseDistance = dist; quad = j; } } quadrants2d[quad].Add(verts2d[i]); quadrants3d[quad].Add(verts3d[i]); sharedIndex[quad].Add(pb.sharedIndices.IndexOf(face.distinctIndices[i])); } int len = quadrants2d.Length; // Triangulate int[][] tris = new int[len][]; for (int i = 0; i < len; i++) { if (quadrants2d[i].Count < 3) { Debug.LogError("Insufficient points to triangulate - bailing on subdivide operation. This is probably due to a concave face, or maybe the compiler just doesn't like you today. 50/50 odds really."); return(false); } tris[i] = Delauney.Triangulate(quadrants2d[i]).ToIntArray(); Vector3[] nrm_check = new Vector3[3] { quadrants3d[i][tris[i][0]], quadrants3d[i][tris[i][1]], quadrants3d[i][tris[i][2]] }; if (Vector3.Dot(nrm, pb_Math.Normal(nrm_check)) < 0) { System.Array.Reverse(tris[i]); } } splitFaces = new pb_Face[len]; splitVertices = new Vector3[len][]; splitSharedIndices = new int[len][]; for (int i = 0; i < len; i++) { // triangles, material, pb_UV, smoothing group, shared index splitFaces[i] = new pb_Face(tris[i], face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.color); splitVertices[i] = quadrants3d[i].ToArray(); splitSharedIndices[i] = sharedIndex[i].ToArray(); } return(true); }
/** * This method assumes that the split selection edges share a common face and have already been sanity checked. Will return * the variables necessary to compose a new face from the split, or null if the split is invalid. */ private static bool SplitFace_Internal(SplitSelection splitSelection, out pb_Face[] splitFaces, out Vector3[][] splitVertices, out int[][] splitSharedIndices) { splitFaces = null; splitVertices = null; splitSharedIndices = null; pb_Object pb = splitSelection.pb; // we'll be using this a lot pb_Face face = splitSelection.face; // likewise int[] indices = face.distinctIndices; pb_IntArray[] sharedIndices = pb.sharedIndices; int[] sharedIndex = new int[indices.Length]; for (int i = 0; i < indices.Length; i++) { sharedIndex[i] = sharedIndices.IndexOf(indices[i]); } // First order of business is to translate the face to 2D plane. Vector3[] verts = pb.GetVertices(face.distinctIndices); Vector3 projAxis = pb_Math.GetProjectionAxis(pb_Math.Normal(pb.GetVertices(face.indices))).ToVector3(); Vector2[] plane = pb_Math.VerticesTo2DPoints(verts, projAxis); // Split points Vector3 splitPointA_3d = splitSelection.pointA; Vector3 splitPointB_3d = splitSelection.pointB; Vector2 splitPointA_2d = pb_Math.VerticesTo2DPoints(new Vector3[1] { splitPointA_3d }, projAxis)[0]; Vector2 splitPointB_2d = pb_Math.VerticesTo2DPoints(new Vector3[1] { splitPointB_3d }, projAxis)[0]; List <Vector3> v_polyA = new List <Vector3>(); // point in object space List <Vector2> v_polyA_2d = new List <Vector2>(); // point in 2d space - used to triangulate List <Vector3> v_polyB = new List <Vector3>(); // point in object space List <Vector2> v_polyB_2d = new List <Vector2>(); // point in 2d space - used to triangulate List <int> i_polyA = new List <int>(); // sharedIndices array index List <int> i_polyB = new List <int>(); // sharedIndices array index List <int> nedgeA = new List <int>(); List <int> nedgeB = new List <int>(); // Sort points into two separate polygons for (int i = 0; i < indices.Length; i++) { // is this point (a) a vertex to split or (b) on the negative or positive side of this split line if ((splitSelection.aIsVertex && splitSelection.indexA == indices[i]) || (splitSelection.bIsVertex && splitSelection.indexB == indices[i])) { v_polyA.Add(verts[i]); v_polyB.Add(verts[i]); v_polyA_2d.Add(plane[i]); v_polyB_2d.Add(plane[i]); i_polyA.Add(sharedIndex[i]); i_polyB.Add(sharedIndex[i]); } else { // split points across the division line Vector2 perp = pb_Math.Perpendicular(splitPointB_2d, splitPointA_2d); Vector2 origin = (splitPointA_2d + splitPointB_2d) / 2f; if (Vector2.Dot(perp, plane[i] - origin) > 0) { v_polyA.Add(verts[i]); v_polyA_2d.Add(plane[i]); i_polyA.Add(sharedIndex[i]); } else { v_polyB.Add(verts[i]); v_polyB_2d.Add(plane[i]); i_polyB.Add(sharedIndex[i]); } } } if (!splitSelection.aIsVertex) { v_polyA.Add(splitPointA_3d); v_polyA_2d.Add(splitPointA_2d); v_polyB.Add(splitPointA_3d); v_polyB_2d.Add(splitPointA_2d); i_polyA.Add(-1); i_polyB.Add(-1); // neg 1 because it's a new vertex point nedgeA.Add(v_polyA.Count); nedgeB.Add(v_polyB.Count); } if (!splitSelection.bIsVertex) { v_polyA.Add(splitPointB_3d); v_polyA_2d.Add(splitPointB_2d); v_polyB.Add(splitPointB_3d); v_polyB_2d.Add(splitPointB_2d); i_polyA.Add(-1); i_polyB.Add(-1); // neg 1 because it's a new vertex point nedgeA.Add(v_polyA.Count); nedgeB.Add(v_polyB.Count); } if (v_polyA_2d.Count < 3 || v_polyB_2d.Count < 3) { splitFaces = null; splitVertices = null; splitSharedIndices = null; return(false); } // triangulate new polygons int[] t_polyA = Delauney.Triangulate(v_polyA_2d).ToIntArray(); int[] t_polyB = Delauney.Triangulate(v_polyB_2d).ToIntArray(); if (t_polyA.Length < 3 || t_polyB.Length < 3) { return(false); } // figure out the face normals for the new faces and check to make sure they match the original face Vector2[] pln = pb_Math.VerticesTo2DPoints(pb.GetVertices(face.indices), projAxis); Vector3 nrm = Vector3.Cross(pln[2] - pln[0], pln[1] - pln[0]); Vector3 nrmA = Vector3.Cross(v_polyA_2d[t_polyA[2]] - v_polyA_2d[t_polyA[0]], v_polyA_2d[t_polyA[1]] - v_polyA_2d[t_polyA[0]]); Vector3 nrmB = Vector3.Cross(v_polyB_2d[t_polyB[2]] - v_polyB_2d[t_polyB[0]], v_polyB_2d[t_polyB[1]] - v_polyB_2d[t_polyB[0]]); if (Vector3.Dot(nrm, nrmA) < 0) { System.Array.Reverse(t_polyA); } if (Vector3.Dot(nrm, nrmB) < 0) { System.Array.Reverse(t_polyB); } // triangles, material, pb_UV, smoothing group, shared index pb_Face faceA = new pb_Face(t_polyA, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.color); pb_Face faceB = new pb_Face(t_polyB, face.material, new pb_UV(face.uv), face.smoothingGroup, face.textureGroup, face.elementGroup, face.color); splitFaces = new pb_Face[2] { faceA, faceB }; splitVertices = new Vector3[2][] { v_polyA.ToArray(), v_polyB.ToArray() }; splitSharedIndices = new int[2][] { i_polyA.ToArray(), i_polyB.ToArray() }; return(true); }
private static void test03(int prob) //****************************************************************************80 // // Purpose: // // TEST03 tests PWL_INTERP_2D_SCATTERED_VALUE. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 October 2012 // // Author: // // John Burkardt // { int element_num = 0; int i; int j; const int ni = 25; double[] xi = new double[25]; double[] xyi = new double[2 * 25]; double[] yi = new double[25]; const int g = 2; int nd = Data_2D.g00_size(g); Console.WriteLine(""); Console.WriteLine("TEST03"); Console.WriteLine(" PWL_INTERP_2D_SCATTERED_VALUE evaluates a"); Console.WriteLine(" piecewise linear interpolant to scattered data."); Console.WriteLine(" Here, we use grid number " + g + ""); Console.WriteLine(" with " + nd + " scattered points in the unit square"); Console.WriteLine(" on problem " + prob + ""); // // Get the data points and evaluate the function there. // double[] xd = new double[nd]; double[] yd = new double[nd]; Data_2D.g00_xy(g, nd, ref xd, ref yd); double[] zd = new double[nd]; Data_2D.f00_f0(prob, nd, xd, yd, ref zd); double[] xyd = new double[2 * nd]; for (i = 0; i < nd; i++) { xyd[0 + i * 2] = xd[i]; xyd[1 + i * 2] = yd[i]; } // // Set up the Delaunay triangulation. // int[] element_neighbor = new int[3 * 2 * nd]; int[] triangle = new int[3 * 2 * nd]; Delauney.r8tris2(nd, ref xyd, ref element_num, ref triangle, ref element_neighbor); for (j = 0; j < element_num; j++) { for (i = 0; i < 3; i++) { switch (element_neighbor[i + j * 3]) { case > 0: element_neighbor[i + j * 3] -= 1; break; } } } // // Define the interpolation points. // int k = 0; for (i = 1; i <= 5; i++) { for (j = 1; j <= 5; j++) { xyi[0 + k * 2] = (2 * i - 1) / 10.0; xyi[1 + k * 2] = (2 * j - 1) / 10.0; k += 1; } } for (k = 0; k < ni; k++) { xi[k] = xyi[0 + k * 2]; yi[k] = xyi[1 + k * 2]; } double[] ze = new double[ni]; Data_2D.f00_f0(prob, ni, xi, yi, ref ze); // // Evaluate the interpolant. // double[] zi = Interp2D.pwl_interp_2d_scattered_value(nd, xyd, zd, element_num, triangle, element_neighbor, ni, xyi); double rms = 0.0; for (k = 0; k < ni; k++) { rms += Math.Pow(zi[k] - ze[k], 2); } rms = Math.Sqrt(rms / ni); Console.WriteLine(""); Console.WriteLine(" RMS error is " + rms + ""); Console.WriteLine(""); Console.WriteLine(" K Xi(K) Yi(K) Zi(K) Z(X,Y)"); Console.WriteLine(""); for (k = 0; k < ni; k++) { Console.WriteLine(" " + k.ToString().PadLeft(4) + " " + xyi[0 + k * 2].ToString(CultureInfo.InvariantCulture).PadLeft(10) + " " + xyi[1 + k * 2].ToString(CultureInfo.InvariantCulture).PadLeft(10) + " " + zi[k].ToString(CultureInfo.InvariantCulture).PadLeft(10) + " " + ze[k].ToString(CultureInfo.InvariantCulture).PadLeft(10) + ""); } }
private static void test02() //****************************************************************************80 // // Purpose: // // TEST02 tests PWL_INTERP_2D_SCATTERED_VALUE. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 October 2012 // // Author: // // John Burkardt // { int[] element_neighbor = new int[3 * 2 * 9]; int element_num = 0; int i; int j; const int ni = 25; const int node_num = 9; double[] node_xy = { 0.0, 0.0, 0.0, 1.0, 0.2, 0.5, 0.3, 0.6, 0.4, 0.5, 0.6, 0.4, 0.6, 0.5, 1.0, 0.0, 1.0, 1.0 }; int[] triangle = new int[3 * 2 * 9]; double[] xyi = new double[2 * 25]; double[] zd = new double[9]; Console.WriteLine(""); Console.WriteLine("TEST02"); Console.WriteLine(" PWL_INTERP_2D_SCATTERED_VALUE evaluates a"); Console.WriteLine(" piecewise linear interpolant to scattered data."); // // Set up the Delaunay triangulation. // Delauney.r8tris2(node_num, ref node_xy, ref element_num, ref triangle, ref element_neighbor); for (j = 0; j < element_num; j++) { for (i = 0; i < 3; i++) { switch (element_neighbor[i + j * 3]) { case > 0: element_neighbor[i + j * 3] -= 1; break; } } } Print.triangulation_order3_print(node_num, element_num, node_xy, triangle, element_neighbor); // // Define the Z data. // for (i = 0; i < node_num; i++) { double x = node_xy[0 + i * 2]; double y = node_xy[1 + i * 2]; zd[i] = x + 2.0 * y; } // // Define the interpolation points. // int k = 0; for (i = 0; i <= 4; i++) { for (j = 0; j <= 4; j++) { xyi[0 + k * 2] = (i - 1) / 4.0; xyi[1 + k * 2] = (j - 1) / 4.0; k += 1; } } // // Evaluate the interpolant. // double[] zi = Interp2D.pwl_interp_2d_scattered_value(node_num, node_xy, zd, element_num, triangle, element_neighbor, ni, xyi); Console.WriteLine(""); Console.WriteLine(" K Xi(K) Yi(K) Zi(K) Z(X,Y)"); Console.WriteLine(""); for (k = 0; k < ni; k++) { double ze = xyi[0 + k * 2] + 2.0 * xyi[1 + k * 2]; Console.WriteLine(" " + k.ToString().PadLeft(4) + " " + xyi[0 + k * 2].ToString(CultureInfo.InvariantCulture).PadLeft(10) + " " + xyi[1 + k * 2].ToString(CultureInfo.InvariantCulture).PadLeft(10) + " " + zi[k].ToString(CultureInfo.InvariantCulture).PadLeft(10) + " " + ze.ToString(CultureInfo.InvariantCulture).PadLeft(10) + ""); } }
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); }