예제 #1
0
        public Section(float[] points, int[] tri, int xyz, float value, Vector3 maxVer, Vector3 minVer)
        {
            //xyz截面方向,value截面值
            direction    = xyz;
            sectionValue = value;
            vMax         = maxVer;
            vMin         = minVer;
            if (vMax.x - vMin.x > vMax.y - vMin.y)
            {
                if (vMax.x - vMin.x > vMax.z - vMin.z)
                {
                    Max = vMax.x;
                    Min = vMin.x;
                }
                else
                {
                    Max = vMax.z;
                    Min = vMin.z;
                }
            }
            else
            {
                if (vMax.y - vMin.y > vMax.z - vMin.z)
                {
                    Max = vMax.y;
                    Min = vMin.y;
                }
                else
                {
                    Max = vMax.z;
                    Min = vMin.z;
                }
            }


            int pointNum = points.Length / 3;
            int triNum   = tri.Length / 3;
            //int[] mark = new int[pointNum * pointNum];
            List <long>    mark = new List <long>();
            List <int>     n0   = new List <int>();
            List <int>     n1   = new List <int>();
            List <float>   frac = new List <float>();
            List <Vector2> v2   = new List <Vector2>();
            List <Vector3> v3   = new List <Vector3>();

            int[] pointIndex = new int[] { 0, 1, 1, 2, 2, 0 };
            int   ni0 = 0, ni1 = 0;
            float f = 0;

            for (int i = 0; i < triNum; ++i)
            {
                for (int pointIndexI = 0; pointIndexI < 3; ++pointIndexI)
                {
                    int  triPoint0 = tri[3 * i + pointIndex[2 * pointIndexI]];
                    int  triPoint1 = tri[3 * i + pointIndex[2 * pointIndexI + 1]];
                    bool isSection = false;
                    if (points[3 * triPoint0 + xyz] < value)
                    {
                        if (points[3 * triPoint1 + xyz] > value)
                        {
                            ni0       = triPoint0;
                            ni1       = triPoint1;
                            f         = (value - points[3 * ni0 + xyz]) / (points[3 * ni1 + xyz] - points[3 * ni0 + xyz]);
                            isSection = true;
                        }
                        else if (points[3 * triPoint1 + xyz] == value)
                        {
                            ni0       = triPoint1;
                            ni1       = triPoint1;
                            f         = 0;
                            isSection = true;
                        }
                    }
                    else if (points[3 * triPoint0 + xyz] > value)
                    {
                        if (points[3 * triPoint1 + xyz] < value)
                        {
                            ni0       = triPoint1;
                            ni1       = triPoint0;
                            f         = (value - points[3 * ni0 + xyz]) / (points[3 * ni1 + xyz] - points[3 * ni0 + xyz]);
                            isSection = true;
                        }
                        else if (points[3 * triPoint1 + xyz] == value)
                        {
                            ni0       = triPoint1;
                            ni1       = triPoint1;
                            f         = 0;
                            isSection = true;
                        }
                    }
                    else if (points[3 * triPoint0 + xyz] == value)
                    {
                        if (points[3 * triPoint1 + xyz] < value)
                        {
                            ni0       = triPoint0;
                            ni1       = triPoint0;
                            f         = 0;
                            isSection = true;
                        }
                        else if (points[3 * triPoint1 + xyz] > value)
                        {
                            ni0       = triPoint0;
                            ni1       = triPoint0;
                            f         = 0;
                            isSection = true;
                        }
                    }
                    if (isSection && !mark.Contains(ni0 * pointNum + ni1))
                    {
                        n0.Add(ni0);
                        n1.Add(ni1);
                        frac.Add(f);
                        float xx, yy;
                        switch (xyz)
                        {
                        case 0:
                            xx = points[3 * ni0 + 1] + f * (points[3 * ni1 + 1] - points[3 * ni0 + 1]);
                            yy = points[3 * ni0 + 2] + f * (points[3 * ni1 + 2] - points[3 * ni0 + 2]);
                            v2.Add(new Vector2(xx, yy));
                            v3.Add(new Vector3(10 * (value - vMin.x) / (Max - Min) - 5
                                               , 5 - 10 * (xx - vMin.y) / (Max - Min), 10 * (yy - vMin.z) / (Max - Min) - 5));
                            break;

                        case 1:
                            xx = points[3 * ni0] + f * (points[3 * ni1] - points[3 * ni0]);
                            yy = points[3 * ni0 + 2] + f * (points[3 * ni1 + 2] - points[3 * ni0 + 2]);
                            v2.Add(new Vector2(xx, yy));
                            v3.Add(new Vector3(10 * (xx - vMin.x) / (Max - Min) - 5
                                               , 5 - 10 * (value - vMin.y) / (Max - Min), 10 * (yy - vMin.z) / (Max - Min) - 5));
                            break;

                        case 2:
                            xx = points[3 * ni0] + f * (points[3 * ni1] - points[3 * ni0]);
                            yy = points[3 * ni0 + 1] + f * (points[3 * ni1 + 1] - points[3 * ni0 + 1]);
                            v2.Add(new Vector2(xx, yy));
                            v3.Add(new Vector3(10 * (xx - vMin.x) / (Max - Min) - 5
                                               , 5 - 10 * (yy - vMin.y) / (Max - Min), 10 * (value - vMin.z) / (Max - Min) - 5));
                            break;
                        }
                        mark.Add(ni0 * pointNum + ni1);
                    }
                }
            }
            node0    = n0.ToArray();
            node1    = n1.ToArray();
            nodeNum  = node0.Length;
            fraction = frac.ToArray();
            vertices = v3.ToArray();
            // Delaunay 三角剖分
            DelaunayTriangulation delaunayTriangulation = null;
            DelaunayCalculator    delaunayCalculator    = new DelaunayCalculator();

            if (vertices.Length > 0)
            {
                delaunayCalculator.CalculateTriangulation(v2, ref delaunayTriangulation);
                triangles = delaunayTriangulation.Triangles.ToArray();
            }
        }
예제 #2
0
    public VolumeticMesh2D generateMesh()
    {
        var mesh = new VolumeticMesh2D();

        Mesh rawMesh = GetComponent <MeshFilter>().mesh;

        var vertices = rawMesh.vertices;

        foreach (var vertex in vertices)
        {
            mesh.nodes.Add(new Vector2(vertex.x, vertex.y));
        }

        var calculator = new GK.DelaunayCalculator();
        var result     = calculator.CalculateTriangulation(mesh.nodes);
        var triangles  = result.Triangles;

        for (int i = 0; i < triangles.Count; i += 3)
        {
            var edgeA = new Edge2D(triangles[i], triangles[i + 2]);
            var edgeB = new Edge2D(triangles[i + 2], triangles[i + 1]);
            var edgeC = new Edge2D(triangles[i + 1], triangles[i]);

            int edgeIndexA, edgeIndexB, edgeIndexC;

            if (!mesh.edges.Contains(edgeA))
            {
                mesh.edges.Add(edgeA);
                edgeIndexA = mesh.edges.Count - 1;
            }
            else
            {
                edgeIndexA = mesh.edges.FindIndex(edge => edge == edgeA);
            }

            if (!mesh.edges.Contains(edgeB))
            {
                mesh.edges.Add(edgeB);
                edgeIndexB = mesh.edges.Count - 1;
            }
            else
            {
                edgeIndexB = mesh.edges.FindIndex(edge => edge == edgeB);
            }

            if (!mesh.edges.Contains(edgeC))
            {
                mesh.edges.Add(edgeC);
                edgeIndexC = mesh.edges.Count - 1;
            }
            else
            {
                edgeIndexC = mesh.edges.FindIndex(edge => edge == edgeC);
            }

            mesh.nodeJointIndexes.Add(new TriangleNodes2D(triangles[i], triangles[i + 2], triangles[i + 1]));
            mesh.edgeJointIndexes.Add(new TriangleEdges2D(edgeIndexA, edgeIndexB, edgeIndexC));
        }

        return(mesh);
    }
예제 #3
0
 /// <summary>
 /// Create new Voronoi calculator.
 /// </summary>
 public VoronoiCalculator()
 {
     pts     = new List <PointTriangle>();
     delCalc = new DelaunayCalculator();
     cmp     = new PTComparer();
 }
예제 #4
0
    //subdivide our suburb into blocks
    public void GenerateBlocks(float spacing, float deviation = 0, float alignmentRotation = 0)
    {
        //set our seed for the suburb
        Random.State currentRNGState = Random.state;
        Random.InitState(seed);

        float          minX = float.MaxValue, maxX = float.MinValue, minY = float.MaxValue, maxY = float.MinValue;
        Vector2        rotationPivot = new Vector2(0, 0);
        List <Vector2> shrunkBorders = new List <Vector2>(borders);
        List <Vector2> sites         = new List <Vector2>();

        // shrink our borders so our points arnt created to close to the edge, this will result in blocks that are to small
        shrunkBorders = CityTest.Shrink(shrunkBorders, spacing / 2);
        if (shrunkBorders.Count >= 3)
        {
            for (int i = 0; i < shrunkBorders.Count; i++)//find anchorPoint
            {
                if (shrunkBorders[i].x < rotationPivot.x)
                {
                    rotationPivot.x = shrunkBorders[i].x;
                }
                if (shrunkBorders[i].y < rotationPivot.y)
                {
                    rotationPivot.y = shrunkBorders[i].y;
                }
            }

            //find rotate boarders for alignment and find bounding volume
            for (int i = 0; i < shrunkBorders.Count; i++)
            {
                shrunkBorders[i] = shrunkBorders[i].RotateAroundPoint(rotationPivot, alignmentRotation);// Vector2.MoveTowards(shrunkBorders[i].RotateAroundPoint(rotationPivot, alignmentRotation), borderCenter, spacing/2);// spacing/2);
                if (shrunkBorders[i].x > maxX)
                {
                    maxX = shrunkBorders[i].x;
                }
                else if (shrunkBorders[i].x < minX)
                {
                    minX = shrunkBorders[i].x;
                }
                if (shrunkBorders[i].y > maxY)
                {
                    maxY = shrunkBorders[i].y;
                }
                else if (shrunkBorders[i].y < minY)
                {
                    minY = shrunkBorders[i].y;
                }
            }

            //triangulate out polygon so we can check if created points are within our poly
            GK.DelaunayTriangulation triangulation = new GK.DelaunayCalculator().CalculateTriangulation(shrunkBorders);

            float xCenterOffset = ((maxX - minX) % spacing) / 2;
            float yCenterOffset = ((maxY - minY) % spacing) / 2;
            for (float x = minX - xCenterOffset; x < maxX; x += spacing)
            {
                for (float y = minY - yCenterOffset; y < maxY; y += spacing)
                {
                    Vector2 newPoint = new Vector2(x + Random.Range(-deviation, deviation), y + Random.Range(-deviation, deviation)); // generate a points i a grid

                    for (int i = 0; i < triangulation.Triangles.Count; i += 3)                                                        // if the point is contained within our polygon
                    {
                        if (GK.Geom.PointInTriangle(newPoint,
                                                    triangulation.Vertices[triangulation.Triangles[i]],
                                                    triangulation.Vertices[triangulation.Triangles[i + 1]],
                                                    triangulation.Vertices[triangulation.Triangles[i + 2]]))
                        {
                            Vector2 rotatedPoint = newPoint.RotateAroundPoint(rotationPivot, -alignmentRotation);
                            sites.Add(rotatedPoint);// rotate our aligned point to its original rotation and add it to the block site list

                            break;
                        }
                    }
                }
            }
        }

        if (sites.Count >= 3)                                                                           // we can only create a diagram if we have more then 2 verts
        {
            GK.VoronoiDiagram blockVoronoiDiagram = new GK.VoronoiCalculator().CalculateDiagram(sites); // generate our streets and blocks in our suburb

            for (int i = 0; i < blockVoronoiDiagram.Sites.Count; i++)
            {
                List <Vector2> clippedSite = null;

                if (blockVoronoiDiagram.FirstEdgeBySite.Count > 0)                                      ////THIS IS NEEDED BECAUSE THE DIAGRAM CAN BE INVALID SOMETIMES
                {
                    new GK.VoronoiClipper().ClipSite(blockVoronoiDiagram, borders, i, ref clippedSite); // clip our block by our suburb

                    if (clippedSite.Count > 0)
                    {
                        Block newBlock = new Block();// create and assign the block
                        newBlock.borders       = new List <Vector2>(clippedSite);
                        newBlock.parentSuburb  = this;
                        newBlock.seed          = Random.Range(int.MinValue, int.MaxValue);
                        newBlock.blockPosition = blockVoronoiDiagram.Sites[i];

                        newBlock.thisBlock = new GameObject("Block");
                        newBlock.thisBlock.transform.SetParent(thisSuburb.transform);
                        newBlock.thisBlock.transform.localPosition = new Vector3(newBlock.blockPosition.x, 0, newBlock.blockPosition.y);
                        myBlocks.Add(newBlock);
                    }
                    else
                    {
                        Debug.LogError("SUBURB SITE AFTER CLIPPED WASNT VALID");
                    }
                }
                else////THIS IS NEEDED BECAUSE THE DIAGRAM CAN BE INVALID SOMETIMES if its not valid make the entire subrb a block
                {
                    Debug.LogWarning("SITE COULTNT BE CREATED BECASUE DIAGRAM DOESNT HAVE STARTING EDGES");
                    Block newBlock = new Block();
                    newBlock.borders       = new List <Vector2>(borders);
                    newBlock.parentSuburb  = this;
                    newBlock.seed          = Random.Range(int.MinValue, int.MaxValue);
                    newBlock.blockPosition = sitePosition;

                    newBlock.thisBlock = new GameObject("Block");
                    newBlock.thisBlock.transform.SetParent(thisSuburb.transform);
                    newBlock.thisBlock.transform.localPosition = new Vector3(newBlock.blockPosition.x, 0, newBlock.blockPosition.y);
                    myBlocks.Add(newBlock);
                    break;
                }
            }
        }
        else// if the suburb has less then 3 verts it cant be split so we make the entire suburb a block
        {
            Block newBlock = new Block();
            newBlock.borders       = new List <Vector2>(borders);
            newBlock.parentSuburb  = this;
            newBlock.seed          = Random.Range(int.MinValue, int.MaxValue);
            newBlock.blockPosition = sitePosition;

            newBlock.thisBlock = new GameObject("Block");
            newBlock.thisBlock.transform.SetParent(thisSuburb.transform);
            newBlock.thisBlock.transform.localPosition = new Vector3(newBlock.blockPosition.x, 0, newBlock.blockPosition.y);
            myBlocks.Add(newBlock);
        }
        Random.state = currentRNGState;
    }