예제 #1
0
    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();
    }
예제 #2
0
        /**
         *	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);
        }
예제 #3
0
    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);
    }
예제 #4
0
    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("");
    }
예제 #5
0
    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 + "");
    }
예제 #6
0
    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;
                }
            }
        }
    }
예제 #7
0
    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("");
    }
예제 #8
0
        /**
         *	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);
        }
예제 #9
0
        // 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);
        }
예제 #10
0
        /**
         *	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);
        }
예제 #11
0
    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) + "");
        }
    }
예제 #12
0
    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) + "");
        }
    }
예제 #13
0
    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);
    }