示例#1
0
    // Start is called before the first frame update
    void Start()
    {
        var SPoints = new List <Point2D>()
        {
            MakePoint(-20, -10), MakePoint(0, 30), MakePoint(20, -10)
        };
        var SuperTriangle = MakeTriangle(SPoints[0], SPoints[1], SPoints[2]);

        List <Point2D> ListOfPoints = new List <Point2D>();

        for (int i = 0; i < 75; i++)
        {
            ListOfPoints.Add(gameObject.MakeRandomPoint(Prefab));
        }

        DelaunayTriangulator      DelaOBJ   = new DelaunayTriangulator(Prefab, SPoints, ListOfPoints);
        HashSet <VirtualTriangle> Triangles = DelaOBJ.BowyerWatson();

        foreach (VirtualTriangle vtrs in Triangles)
        {
            if (!vtrs.ISPointExists(SPoints))
            {
                MakeTriangle(vtrs.Vertices[0], vtrs.Vertices[1], vtrs.Vertices[2]);
            }
        }
    }
        /// <summary>
        ///     Performs Delaunay triangulation over the specified collection of <see cref="Minutia"/>.
        /// </summary>
        /// <param name="minutiae">The collection of <see cref="Minutia"/> to triangulate.</param>
        /// <returns>The Delaunay triangles.</returns>
        public static IntegerTriangle[] Triangulate(ICollection<Minutia> minutiae)
        {
            ICollection<PointF> pointsCollection = new List<PointF>(minutiae.Count);
            foreach (var minutia in minutiae)
            {
                pointsCollection.Add(new PointF(minutia.X, minutia.Y));
            }
            DelaunayTriangulator edges = new DelaunayTriangulator();
            if (edges.Initialize(pointsCollection, 0.00001f))
                edges.Process();

            return edges.ToArray();
        }
示例#3
0
        /// <summary>
        ///     Performs Delaunay triangulation over the specified collection of <see cref="Minutia"/>.
        /// </summary>
        /// <param name="minutiae">The collection of <see cref="Minutia"/> to triangulate.</param>
        /// <returns>The Delaunay triangles.</returns>
        public static IntegerTriangle[] Triangulate(ICollection <Minutia> minutiae)
        {
            ICollection <PointF> pointsCollection = new List <PointF>(minutiae.Count);

            foreach (var minutia in minutiae)
            {
                pointsCollection.Add(new PointF(minutia.X, minutia.Y));
            }
            DelaunayTriangulator edges = new DelaunayTriangulator();

            if (edges.Initialize(pointsCollection, 0.00001f))
            {
                edges.Process();
            }

            return(edges.ToArray());
        }
    void DelaunayTriangulation(List <Point2D> RandomPoints)
    {
        List <Point2D> SPoints = new List <Point2D>()
        {
            MakePoint(-2100, -1100), MakePoint(0, 3100), MakePoint(2100, -1100)
        };
        DelaunayTriangulator      Triangulator = new DelaunayTriangulator(Prefab, SPoints, RandomPoints);
        HashSet <VirtualTriangle> Triangles    = Triangulator.BowyerWatson();

        foreach (VirtualTriangle tr in Triangles)
        {
            if (!tr.ISPointExists(SPoints))
            {
                MakeTriangle(tr.Vertices[0], tr.Vertices[1], tr.Vertices[2]);
            }
        }
    }
示例#5
0
        public VoronoiDiagram(DelaunayTriangulator triangulation)
        {
            sites = new HashSet <Point>();
            edges = new HashSet <Edge>();

            foreach (Vertex vertex in triangulation.triangles)
            {
                foreach (Vertex neighbor in vertex.neighbors)
                {
                    if (neighbor != null)
                    {
                        Point a = vertex.center;
                        Point b = neighbor.center;
                        this.edges.Add(new Edge(a, b));
                    }
                }
                this.sites.UnionWith(vertex.points);
            }
        }
示例#6
0
        static void Main(string[] args)
        {
            var delaunay      = new DelaunayTriangulator();
            var points        = delaunay.GeneratePoints(2500, 512, 512);
            var triangulation = delaunay.BowyerWatson(points);

            newBitmap();
            var image = new Bitmap(Image.FromFile("map.png"));

            using (var g = Graphics.FromImage(image)) {
                foreach (var var in triangulation)
                {
                    g.DrawLines(White, var.Vertices.Select(var2 => new Point((int)var2.X, (int)var2.Y)).ToArray());
                }

                image.Save("map.png");
                image.Dispose();
                Console.WriteLine("world generated!");
            }
        }
示例#7
0
    void Start()
    {
        Cursor.lockState = CursorLockMode.None;
        Cursor.visible   = true;

        float minDistance             = pointPrefab.GetComponent <CircleCollider2D>().radius * 2;
        DelaunayTriangulator delaunay = new DelaunayTriangulator();
        var points        = delaunay.GeneratePoints(numberOfPoints, spawnArea, minDistance);
        var triangulation = delaunay.BowyerWatson(points);
        //remove junctions that are subjectively too long
        float maxDistanceBetweenPoints = Player.Instance.maxTravelDistance / 3;

        SpawnPOIs(pointPrefab, points, maxDistanceBetweenPoints, parentCanvas);
        Vector2 southernPoint = FindStartingPosition(points);

        playerToken.transform.SetPositionAndRotation(southernPoint, Quaternion.identity);
        playerToken.GetComponent <PlayerToken>().OnReachedDestination
            += GetComponent <RandomEventController>().StartEvent;

        OnPlayerReady?.Invoke(playerToken.transform.position);
    }
示例#8
0
            internal bool Initialize(ICollection <PointF> pointsCollection, float tolerance)
            {
                this.points        = null;
                this.pointsIndices = null;
                this.edgesBuckets  = null;
                this.edgesEntries  = null;
                this.Triangles     = null;
                this.Triangles     = null;

                // Initialize triangle table

                this.TrianglesFirst = -1;
                this.TrianglesLast  = -1;
                this.TrianglesCount = 0;

                this.firstNonCompletedTriangle = -1;
                this.lastNonCompletedTriangle  = -1;

                // Initialize edge table

                this.edgesGeneration = 1;
                this.edgesCount      = 0;

                this.tolerance = tolerance > 0 ? tolerance : float.Epsilon; // Ensure tolerance is valid

                this.pointsCount = pointsCollection == null ? 0 : pointsCollection.Count;

                if (pointsCollection.Count < 3)
                {
                    return(false); // We need a non null collection with at least 3 vertices!
                }
                // Create the array of points.
                // We need 3 more items to add supertriangle vertices

                this.points = new PointF[this.pointsCount + 3];
                pointsCollection.CopyTo(points, 0);

                // Create an array of indices to points sorted by Y (firstly), X (secondly) and insertion order (thirdly)
                this.pointsIndices = DelaunayTriangulator.GetSortedPointIndices(points, this.pointsCount, tolerance);

                // Calculate min and max X and Y coomponents of points

                PointF pointsMin, pointsMax;
                PointF d = new PointF();

                DelaunayTriangulator.GetMinMaxPointCoordinates(points, this.pointsCount, out pointsMin, out pointsMax);

                // Create supertriangle vertices
                d.X = pointsMax.X - pointsMin.X;
                d.Y = pointsMax.Y - pointsMin.Y;

                float  dmax = (d.X > d.Y) ? d.X : d.Y;
                PointF mid  = new PointF();

                mid.X = (pointsMax.X + pointsMin.X) * 0.5f;
                mid.Y = (pointsMax.Y + pointsMin.Y) * 0.5f;

                points[this.pointsCount]     = new PointF(mid.X - 2 * dmax, mid.Y - dmax);
                points[this.pointsCount + 1] = new PointF(mid.X, mid.Y + 2 * dmax);
                points[this.pointsCount + 2] = new PointF(mid.X + 2 * dmax, mid.Y - dmax);

                // Initialize triangle array

                this.Triangles = new Triangle[this.pointsCount * 4 + 1];

                Triangle triangleEntry = new Triangle();

                triangleEntry.prevNonCompleted = -1;
                triangleEntry.nextNonCompleted = -1;

                // Initialized free triangles

                this.Triangles = new Triangle[this.Triangles.Length];

                this.firstFreeTriangle = 0;
                for (int i = 0; i < this.Triangles.Length; ++i)
                {
                    triangleEntry.Previous = i - 1;
                    triangleEntry.Next     = i + 1;

                    this.Triangles[i] = triangleEntry;
                }
                this.Triangles[this.Triangles.Length - 1].Next = -1;

                // Initialize edge table

                int size = SPMath.GetPrime(this.Triangles.Length * 3 + 1);

                this.edgesBuckets = new EdgeBucketEntry[size];
                this.edgesEntries = new EdgeEntry[size];

                // Add supertriangle

                this.AddTriangle(this.pointsCount, this.pointsCount + 1, this.pointsCount + 2);

                return(true);
            }
示例#9
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            iPoints = new List <Point3d>();
            DA.GetDataList <Point3d>("Points", iPoints);
            iApicals = new List <Circle>();
            DA.GetDataList <Circle>("Apicals", iApicals);
            iMasses = new List <double>();
            DA.GetDataList <double>("Masses", iMasses);
            DA.GetData <Curve>("Boundary Curve", ref iBoundaryCurve);
            DA.GetData <double>("Rest Length Scale", ref iRestLengthScale);
            DA.GetData <double>("Rest Length Offset", ref iRestLengthOffset);
            DA.GetData <double>("Stiffness", ref iStiffness);
            DA.GetData <double>("Bending Stiffness", ref iBendingStiffness);
            DA.GetData <bool>("In/Out Switch", ref iInOutSwitch);
            DA.GetData <double>("In/Out Threshold", ref iInOutThreshold);
            DA.GetData <double>("Fixed Point Threshold", ref iFixedPointThreshold);
            iFixedPointExclusion = new List <Curve>();
            DA.GetDataList <Curve>("Fixed Point Exclusion", iFixedPointExclusion);
            iFixedPointInclusion = new List <Curve>();
            DA.GetDataList <Curve>("Fixed Point Inclusion", iFixedPointInclusion);


            // ===========================================================================================
            // Compute Delaunay Triangulation
            // ===========================================================================================

            List <DelaunayVertex> delaunayVertices = new List <DelaunayVertex>();

            foreach (Point3d point in iPoints)
            {
                delaunayVertices.Add(new DelaunayVertex(point.X, point.Y));
            }

            List <Triad> triads = new DelaunayTriangulator().Triangulation(delaunayVertices);

            HashSet <Tuple <int, int> > delaunayEdgeTuples = new HashSet <Tuple <int, int> >();


            for (int i = 0; i < triads.Count; i++)
            {
                Triad triad = triads[i];
                delaunayEdgeTuples.Add(triad.a < triad.b ? new Tuple <int, int>(triad.a, triad.b) : new Tuple <int, int>(triad.b, triad.a));
                delaunayEdgeTuples.Add(triad.b < triad.c ? new Tuple <int, int>(triad.b, triad.c) : new Tuple <int, int>(triad.c, triad.b));
                delaunayEdgeTuples.Add(triad.c < triad.a ? new Tuple <int, int>(triad.c, triad.a) : new Tuple <int, int>(triad.a, triad.c));
            }


            // ===========================================================================================
            // Convert Delaunay mesh to particle-spring mesh
            // ===========================================================================================

            oSpringMesh = new SpringMesh();

            // Create edge list -----------------------------------------------------------------------------------------------

            foreach (Tuple <int, int> delaunayEdgeTuple in delaunayEdgeTuples)
            {
                Point3d A = iPoints[delaunayEdgeTuple.Item1];
                Point3d B = iPoints[delaunayEdgeTuple.Item2];
                Point3d M = 0.5 * (A + B);

                // Skip if the edge lies outside of the boundary
                double t;
                iBoundaryCurve.ClosestPoint(M, out t);
                Point3d N = iBoundaryCurve.PointAt(t);
                if (Vector3d.CrossProduct(iBoundaryCurve.TangentAt(t), M - N).Z *(iInOutSwitch ? -1.0 : 1.0) < 0.0 &&
                    Utils.DistanceSquared(M, N) > iInOutThreshold * iInOutThreshold)
                {
                    continue;
                }

                double edgeLength = Utils.Distance(A, B);
                double restLength = iRestLengthScale * edgeLength + iRestLengthOffset;
                oSpringMesh.Edges.Add(new Edge(delaunayEdgeTuple.Item1, delaunayEdgeTuple.Item2, restLength, iStiffness, Math.PI, iBendingStiffness));
            }

            // Create vertex list -----------------------------------------------------------------------------------------------

            List <HashSet <int> > neighborVerticesSets = new List <HashSet <int> >();

            for (int i = 0; i < iPoints.Count; i++)
            {
                neighborVerticesSets.Add(new HashSet <int>());
            }

            foreach (Edge edge in oSpringMesh.Edges)
            {
                neighborVerticesSets[edge.FirstVertexIndex].Add(edge.SecondVertexIndex);
                neighborVerticesSets[edge.SecondVertexIndex].Add(edge.FirstVertexIndex);
            }

            for (int i = 0; i < iPoints.Count; i++)
            {
                Point3d p = iPoints[i];
                double  t;
                iBoundaryCurve.ClosestPoint(p, out t);

                bool vertexFixedness = true;

                if (Utils.Distance(p, iBoundaryCurve.PointAt(t)) > iFixedPointThreshold)
                {
                    vertexFixedness = false;
                }
                else
                {
                    foreach (Curve curve in iFixedPointExclusion)
                    {
                        if (curve.Contains(p) == PointContainment.Inside)
                        {
                            vertexFixedness = false;
                            break;
                        }
                    }
                }

                foreach (Curve curve in iFixedPointInclusion)
                {
                    if (curve.Contains(p) == PointContainment.Inside)
                    {
                        vertexFixedness = true;
                        break;
                    }
                }

                Vertex vertex = new Vertex(p, Vector3d.Zero, neighborVerticesSets[i].ToList <int>(), iMasses.Count == 1 ? iMasses[0] : iMasses[i], vertexFixedness);
                oSpringMesh.Vertices.Add(vertex);
            }


            // Set boundary edge -----------------------------------------------------------------------------------------------

            foreach (Edge edge in oSpringMesh.Edges)
            {
                if (oSpringMesh.Vertices[edge.FirstVertexIndex].IsFixed && oSpringMesh.Vertices[edge.SecondVertexIndex].IsFixed)
                {
                    edge.IsBoundaryEdge = true;
                }
            }


            // Create triangle list ------------------------------------------------------------------------------------------------

            Dictionary <Tuple <int, int, int>, int> tripletDict = new Dictionary <Tuple <int, int, int>, int>();

            for (int k = 0; k < oSpringMesh.Edges.Count; k++)
            {
                Edge   edge = oSpringMesh.Edges[k];
                Vertex A    = oSpringMesh.Vertices[edge.FirstVertexIndex];
                Vertex B    = oSpringMesh.Vertices[edge.SecondVertexIndex];

                for (int i = 0; i < A.NeighborVertexIndices.Count; i++)
                {
                    for (int j = 0; j < B.NeighborVertexIndices.Count; j++)
                    {
                        if (A.NeighborVertexIndices[i] == B.NeighborVertexIndices[j])
                        {
                            Tuple <int, int, int> triplet = sortTriplet(edge.FirstVertexIndex, edge.SecondVertexIndex, A.NeighborVertexIndices[i]);

                            if (tripletDict.ContainsKey(triplet))
                            {
                                if (edge.FirstTriangleIndex < 0)
                                {
                                    edge.FirstTriangleIndex       = tripletDict[triplet];
                                    edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }
                                else
                                {
                                    edge.SecondTriangleIndex       = tripletDict[triplet];
                                    edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }
                            }
                            else
                            {
                                oSpringMesh.Triangles.Add(new Triangle(triplet.Item1, triplet.Item2, triplet.Item3));

                                int triangleIndex = oSpringMesh.Triangles.Count - 1;

                                if (edge.FirstTriangleIndex < 0)
                                {
                                    edge.FirstTriangleIndex       = triangleIndex;
                                    edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }
                                else
                                {
                                    edge.SecondTriangleIndex       = triangleIndex;
                                    edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }

                                tripletDict.Add(triplet, triangleIndex);
                            }
                        }
                    }
                }
            }

            // ===========================================================================================
            // Compute edge indices for each triangle
            // ===========================================================================================

            for (int i = 0; i < oSpringMesh.Edges.Count; i++)
            {
                Edge edge = oSpringMesh.Edges[i];

                Triangle triangle = oSpringMesh.Triangles[edge.FirstTriangleIndex];
                if (triangle.FirstEdgeIndex == -1)
                {
                    triangle.FirstEdgeIndex = i;
                }
                else if (triangle.SecondEdgeIndex == -1)
                {
                    triangle.SecondEdgeIndex = i;
                }
                else
                {
                    triangle.ThirdEdgeIndex = i;
                }

                if (edge.SecondTriangleIndex == -1)
                {
                    continue;
                }

                triangle = oSpringMesh.Triangles[edge.SecondTriangleIndex];
                if (triangle.FirstEdgeIndex == -1)
                {
                    triangle.FirstEdgeIndex = i;
                }
                else if (triangle.SecondEdgeIndex == -1)
                {
                    triangle.SecondEdgeIndex = i;
                }
                else
                {
                    triangle.ThirdEdgeIndex = i;
                }
            }


            // ===========================================================================================
            // Rearange the vertex order in each triangle so the normal calculation is consistent
            // ===========================================================================================

            for (int i = 0; i < oSpringMesh.Triangles.Count; i++)
            {
                if (oSpringMesh.ComputeTriangleNormal(i).Z < 0.0)
                {
                    int temp = oSpringMesh.Triangles[i].SecondVertexIndex;
                    oSpringMesh.Triangles[i].SecondVertexIndex = oSpringMesh.Triangles[i].ThirdVertexIndex;
                    oSpringMesh.Triangles[i].ThirdVertexIndex  = temp;
                }
            }


            // ===========================================================================================
            // Rearranging edge adjacent vertex indices for consitency
            // ===========================================================================================

            foreach (Edge edge in oSpringMesh.Edges)
            {
                if (edge.SecondAdjacentVertexIndex == -1)
                {
                    Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position;
                    Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position;
                    Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position;

                    if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstTriangleIndex) < 0.0)
                    {
                        Point3d temp = A;
                        A = B;
                        B = temp;
                    }
                }
                else
                {
                    Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position;
                    Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position;
                    Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position;
                    Point3d N = oSpringMesh.Vertices[edge.SecondAdjacentVertexIndex].Position;

                    if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstAdjacentVertexIndex) < 0.0)
                    {
                        int temp = edge.FirstAdjacentVertexIndex;
                        edge.FirstAdjacentVertexIndex  = edge.SecondAdjacentVertexIndex;
                        edge.SecondAdjacentVertexIndex = temp;

                        temp = edge.FirstTriangleIndex;
                        edge.FirstTriangleIndex  = edge.SecondTriangleIndex;
                        edge.SecondTriangleIndex = temp;
                    }
                }
            }

            // ===========================================================================================
            // Compute adjacent vertex index for each triangle
            // ===========================================================================================

            //foreach (Triangle triangle in oSpringMesh.Triangles)
            //{
            //    Vertex firstVertex = oSpringMesh.Vertices[triangle.FirstVertexIndex];
            //    Vertex secondVertex = oSpringMesh.Vertices[triangle.SecondVertexIndex];
            //    Vertex thirdVertex = oSpringMesh.Vertices[triangle.ThirdVertexIndex];

            //    foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices)
            //        foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices)
            //            if (firstNeighbourIndex == secondNeighbourIndex && firstNeighbourIndex != triangle.ThirdVertexIndex)
            //                triangle.FirstSecondAdjacentVertexIndex = firstNeighbourIndex;

            //    foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices)
            //        foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices)
            //            if (secondNeighbourIndex == thirdNeighbourIndex && secondNeighbourIndex != triangle.FirstVertexIndex)
            //                triangle.SecondThirdAdjacentVertexIndex = secondNeighbourIndex;

            //    foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices)
            //        foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices)
            //            if (thirdNeighbourIndex == firstNeighbourIndex && thirdNeighbourIndex != triangle.SecondVertexIndex)
            //                triangle.ThirdFirstAdjacentVertexIndex = thirdNeighbourIndex;
            //}


            // ===========================================================================================
            // Initial curving bias
            // ===========================================================================================

            DA.GetData <double>("Initial Curving Bias", ref iInitialCurvingBias);
            DA.GetData <bool>("Bias Apical Regions", ref iBiasApicalRegion);

            foreach (Vertex vertex in oSpringMesh.Vertices)
            {
                vertex.Position.Z = computeBiasHeight(vertex.Position, iBiasApicalRegion);
            }


            // ===========================================================================================
            // Conclusion
            // ===========================================================================================

            foreach (Edge edge in oSpringMesh.Edges)
            {
                oDebugCurves1.Add(new LineCurve(oSpringMesh.Vertices[edge.FirstVertexIndex].Position, oSpringMesh.Vertices[edge.SecondVertexIndex].Position));
            }

            DA.SetData(0, oInfo);
            DA.SetDataList(1, oDebugCurves1);
            DA.SetData(6, oSpringMesh);
        }
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            iPoints = new List<Point3d>();
            DA.GetDataList<Point3d>("Points", iPoints);
            iApicals = new List<Circle>();
            DA.GetDataList<Circle>("Apicals", iApicals);
            iMasses = new List<double>();
            DA.GetDataList<double>("Masses", iMasses);
            DA.GetData<Curve>("Boundary Curve", ref iBoundaryCurve);
            DA.GetData<double>("Rest Length Scale", ref iRestLengthScale);
            DA.GetData<double>("Rest Length Offset", ref iRestLengthOffset);
            DA.GetData<double>("Stiffness", ref iStiffness);
            DA.GetData<double>("Bending Stiffness", ref iBendingStiffness);
            DA.GetData<bool>("In/Out Switch", ref iInOutSwitch);
            DA.GetData<double>("In/Out Threshold", ref iInOutThreshold);
            DA.GetData<double>("Fixed Point Threshold", ref iFixedPointThreshold);
            iFixedPointExclusion = new List<Curve>();
            DA.GetDataList<Curve>("Fixed Point Exclusion", iFixedPointExclusion);
            iFixedPointInclusion = new List<Curve>();
            DA.GetDataList<Curve>("Fixed Point Inclusion", iFixedPointInclusion);

            // ===========================================================================================
            // Compute Delaunay Triangulation
            // ===========================================================================================

            List<DelaunayVertex> delaunayVertices = new List<DelaunayVertex>();
            foreach (Point3d point in iPoints)
                delaunayVertices.Add(new DelaunayVertex(point.X, point.Y));

            List<Triad> triads = new DelaunayTriangulator().Triangulation(delaunayVertices);

            HashSet<Tuple<int, int>> delaunayEdgeTuples = new HashSet<Tuple<int, int>>();

            for (int i = 0; i < triads.Count; i++)
            {
                Triad triad = triads[i];
                delaunayEdgeTuples.Add(triad.a < triad.b ? new Tuple<int, int>(triad.a, triad.b) : new Tuple<int, int>(triad.b, triad.a));
                delaunayEdgeTuples.Add(triad.b < triad.c ? new Tuple<int, int>(triad.b, triad.c) : new Tuple<int, int>(triad.c, triad.b));
                delaunayEdgeTuples.Add(triad.c < triad.a ? new Tuple<int, int>(triad.c, triad.a) : new Tuple<int, int>(triad.a, triad.c));
            }

            // ===========================================================================================
            // Convert Delaunay mesh to particle-spring mesh
            // ===========================================================================================

            oSpringMesh = new SpringMesh();

            // Create edge list -----------------------------------------------------------------------------------------------

            foreach (Tuple<int, int> delaunayEdgeTuple in delaunayEdgeTuples)
            {
                Point3d A = iPoints[delaunayEdgeTuple.Item1];
                Point3d B = iPoints[delaunayEdgeTuple.Item2];
                Point3d M = 0.5 * (A + B);

                // Skip if the edge lies outside of the boundary
                double t;
                iBoundaryCurve.ClosestPoint(M, out t);
                Point3d N = iBoundaryCurve.PointAt(t);
                if (Vector3d.CrossProduct(iBoundaryCurve.TangentAt(t), M - N).Z * (iInOutSwitch ? -1.0 : 1.0) < 0.0
                    && Utils.DistanceSquared(M, N) > iInOutThreshold * iInOutThreshold)
                    continue;

                double edgeLength = Utils.Distance(A, B);
                double restLength = iRestLengthScale * edgeLength + iRestLengthOffset;
                oSpringMesh.Edges.Add(new Edge(delaunayEdgeTuple.Item1, delaunayEdgeTuple.Item2, restLength, iStiffness, Math.PI, iBendingStiffness));
            }

            // Create vertex list -----------------------------------------------------------------------------------------------

            List<HashSet<int>> neighborVerticesSets = new List<HashSet<int>>();
            for (int i = 0; i < iPoints.Count; i++)
                neighborVerticesSets.Add(new HashSet<int>());

            foreach (Edge edge in oSpringMesh.Edges)
            {
                neighborVerticesSets[edge.FirstVertexIndex].Add(edge.SecondVertexIndex);
                neighborVerticesSets[edge.SecondVertexIndex].Add(edge.FirstVertexIndex);
            }

            for (int i = 0; i < iPoints.Count; i++)
            {
                Point3d p = iPoints[i];
                double t;
                iBoundaryCurve.ClosestPoint(p, out t);

                bool vertexFixedness = true;

                if (Utils.Distance(p, iBoundaryCurve.PointAt(t)) > iFixedPointThreshold)
                    vertexFixedness = false;
                else
                    foreach (Curve curve in iFixedPointExclusion)
                        if (curve.Contains(p) == PointContainment.Inside)
                        {
                            vertexFixedness = false;
                            break;
                        }

                foreach (Curve curve in iFixedPointInclusion)
                    if (curve.Contains(p) == PointContainment.Inside)
                    {
                        vertexFixedness = true;
                        break;
                    }

                Vertex vertex = new Vertex(p, Vector3d.Zero, neighborVerticesSets[i].ToList<int>(), iMasses.Count == 1 ? iMasses[0] : iMasses[i], vertexFixedness);
                oSpringMesh.Vertices.Add(vertex);
            }

            // Set boundary edge -----------------------------------------------------------------------------------------------

            foreach (Edge edge in oSpringMesh.Edges)
            {
                if (oSpringMesh.Vertices[edge.FirstVertexIndex].IsFixed && oSpringMesh.Vertices[edge.SecondVertexIndex].IsFixed)
                {
                    edge.IsBoundaryEdge = true;
                }
            }

            // Create triangle list ------------------------------------------------------------------------------------------------

            Dictionary<Tuple<int, int, int>, int> tripletDict = new Dictionary<Tuple<int, int, int>, int>();

            for (int k = 0; k < oSpringMesh.Edges.Count; k++)
            {
                Edge edge = oSpringMesh.Edges[k];
                Vertex A = oSpringMesh.Vertices[edge.FirstVertexIndex];
                Vertex B = oSpringMesh.Vertices[edge.SecondVertexIndex];

                for (int i = 0; i < A.NeighborVertexIndices.Count; i++)
                {
                    for (int j = 0; j < B.NeighborVertexIndices.Count; j++)
                    {
                        if (A.NeighborVertexIndices[i] == B.NeighborVertexIndices[j])
                        {
                            Tuple<int, int, int> triplet = sortTriplet(edge.FirstVertexIndex, edge.SecondVertexIndex, A.NeighborVertexIndices[i]);

                            if (tripletDict.ContainsKey(triplet))
                            {
                                if (edge.FirstTriangleIndex < 0)
                                {
                                    edge.FirstTriangleIndex = tripletDict[triplet];
                                    edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }
                                else
                                {
                                    edge.SecondTriangleIndex = tripletDict[triplet];
                                    edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }
                            }
                            else
                            {
                                oSpringMesh.Triangles.Add(new Triangle(triplet.Item1, triplet.Item2, triplet.Item3));

                                int triangleIndex = oSpringMesh.Triangles.Count - 1;

                                if (edge.FirstTriangleIndex < 0)
                                {
                                    edge.FirstTriangleIndex = triangleIndex;
                                    edge.FirstAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }
                                else
                                {
                                    edge.SecondTriangleIndex = triangleIndex;
                                    edge.SecondAdjacentVertexIndex = A.NeighborVertexIndices[i];
                                }

                                tripletDict.Add(triplet, triangleIndex);
                            }
                        }
                    }
                }
            }

            // ===========================================================================================
            // Compute edge indices for each triangle
            // ===========================================================================================

            for (int i = 0; i < oSpringMesh.Edges.Count; i++)
            {
                Edge edge = oSpringMesh.Edges[i];

                Triangle triangle = oSpringMesh.Triangles[edge.FirstTriangleIndex];
                if (triangle.FirstEdgeIndex == -1) triangle.FirstEdgeIndex = i;
                else if (triangle.SecondEdgeIndex == -1) triangle.SecondEdgeIndex = i;
                else triangle.ThirdEdgeIndex = i;

                if (edge.SecondTriangleIndex == -1) continue;

                triangle = oSpringMesh.Triangles[edge.SecondTriangleIndex];
                if (triangle.FirstEdgeIndex == -1) triangle.FirstEdgeIndex = i;
                else if (triangle.SecondEdgeIndex == -1) triangle.SecondEdgeIndex = i;
                else triangle.ThirdEdgeIndex = i;
            }

            // ===========================================================================================
            // Rearange the vertex order in each triangle so the normal calculation is consistent
            // ===========================================================================================

            for (int i = 0; i < oSpringMesh.Triangles.Count; i++)
            {
                if (oSpringMesh.ComputeTriangleNormal(i).Z < 0.0)
                {
                    int temp = oSpringMesh.Triangles[i].SecondVertexIndex;
                    oSpringMesh.Triangles[i].SecondVertexIndex = oSpringMesh.Triangles[i].ThirdVertexIndex;
                    oSpringMesh.Triangles[i].ThirdVertexIndex = temp;
                }
            }

            // ===========================================================================================
            // Rearranging edge adjacent vertex indices for consitency
            // ===========================================================================================

            foreach (Edge edge in oSpringMesh.Edges)
            {
                if (edge.SecondAdjacentVertexIndex == -1)
                {
                    Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position;
                    Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position;
                    Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position;

                    if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstTriangleIndex) < 0.0)
                    {
                        Point3d temp = A;
                        A = B;
                        B = temp;
                    }
                }
                else
                {
                    Point3d A = oSpringMesh.Vertices[edge.FirstVertexIndex].Position;
                    Point3d B = oSpringMesh.Vertices[edge.SecondVertexIndex].Position;
                    Point3d M = oSpringMesh.Vertices[edge.FirstAdjacentVertexIndex].Position;
                    Point3d N = oSpringMesh.Vertices[edge.SecondAdjacentVertexIndex].Position;

                    if (Vector3d.CrossProduct(B - A, M - A) * oSpringMesh.ComputeTriangleNormal(edge.FirstAdjacentVertexIndex) < 0.0)
                    {
                        int temp = edge.FirstAdjacentVertexIndex;
                        edge.FirstAdjacentVertexIndex = edge.SecondAdjacentVertexIndex;
                        edge.SecondAdjacentVertexIndex = temp;

                        temp = edge.FirstTriangleIndex;
                        edge.FirstTriangleIndex = edge.SecondTriangleIndex;
                        edge.SecondTriangleIndex = temp;
                    }
                }
            }

            // ===========================================================================================
            // Compute adjacent vertex index for each triangle
            // ===========================================================================================

            //foreach (Triangle triangle in oSpringMesh.Triangles)
            //{
            //    Vertex firstVertex = oSpringMesh.Vertices[triangle.FirstVertexIndex];
            //    Vertex secondVertex = oSpringMesh.Vertices[triangle.SecondVertexIndex];
            //    Vertex thirdVertex = oSpringMesh.Vertices[triangle.ThirdVertexIndex];

            //    foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices)
            //        foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices)
            //            if (firstNeighbourIndex == secondNeighbourIndex && firstNeighbourIndex != triangle.ThirdVertexIndex)
            //                triangle.FirstSecondAdjacentVertexIndex = firstNeighbourIndex;

            //    foreach (int secondNeighbourIndex in secondVertex.NeighborVertexIndices)
            //        foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices)
            //            if (secondNeighbourIndex == thirdNeighbourIndex && secondNeighbourIndex != triangle.FirstVertexIndex)
            //                triangle.SecondThirdAdjacentVertexIndex = secondNeighbourIndex;

            //    foreach (int thirdNeighbourIndex in thirdVertex.NeighborVertexIndices)
            //        foreach (int firstNeighbourIndex in firstVertex.NeighborVertexIndices)
            //            if (thirdNeighbourIndex == firstNeighbourIndex && thirdNeighbourIndex != triangle.SecondVertexIndex)
            //                triangle.ThirdFirstAdjacentVertexIndex = thirdNeighbourIndex;
            //}

            // ===========================================================================================
            // Initial curving bias
            // ===========================================================================================

            DA.GetData<double>("Initial Curving Bias", ref iInitialCurvingBias);
            DA.GetData<bool>("Bias Apical Regions", ref iBiasApicalRegion);

            foreach (Vertex vertex in oSpringMesh.Vertices)
            {
                vertex.Position.Z = computeBiasHeight(vertex.Position, iBiasApicalRegion);
            }

            // ===========================================================================================
            // Conclusion
            // ===========================================================================================

            foreach (Edge edge in oSpringMesh.Edges)
                oDebugCurves1.Add(new LineCurve(oSpringMesh.Vertices[edge.FirstVertexIndex].Position, oSpringMesh.Vertices[edge.SecondVertexIndex].Position));

            DA.SetData(0, oInfo);
            DA.SetDataList(1, oDebugCurves1);
            DA.SetData(6, oSpringMesh);
        }
示例#11
0
    public Room GenerateConnections(List <Room> rooms)
    {
        var triangulator  = new DelaunayTriangulator();
        var roomMidpoints = new List <DelaunayVoronoi.Point>();
        var minX          = float.MaxValue;
        var minY          = float.MaxValue;
        var maxX          = float.MinValue;
        var maxY          = float.MinValue;

        foreach (var room in rooms)
        {
            var x = room.position.x;
            var y = room.position.y;

            minX = Mathf.Min(x, minX);
            minY = Mathf.Min(y, minY);
            maxX = Mathf.Max(x, maxX);
            maxY = Mathf.Max(y, maxY);

            roomMidpoints.Add(new DelaunayVoronoi.Point(room.position.x, room.position.y));
        }

        // Add buffer to the sides.
        minX -= 100;
        minY -= 100;
        maxX += 100;
        maxY += 100;
        minX  = Mathf.CeilToInt(minX);
        minY  = Mathf.CeilToInt(minY);
        maxX  = Mathf.CeilToInt(maxX);
        maxY  = Mathf.CeilToInt(maxY);

        this.minX = minX;
        this.minY = minY;
        this.maxX = maxX;
        this.maxY = maxY;

        var point0          = new DelaunayVoronoi.Point(minX, minY);
        var point1          = new DelaunayVoronoi.Point(minX, maxY);
        var point2          = new DelaunayVoronoi.Point(maxX, maxY);
        var point3          = new DelaunayVoronoi.Point(maxX, minY);
        var borderTriangle1 = new Triangle(point0, point1, point2);
        var borderTriangle2 = new Triangle(point0, point2, point3);

        triangulator.border = new List <Triangle>()
        {
            borderTriangle1, borderTriangle2
        };

        var delaunayTriangles = new List <Triangle>(triangulator.BowyerWatson(roomMidpoints));

        foreach (var triangle in delaunayTriangles)
        {
            // Check if this is actually part of the delaunay triangulation, or if it's a bordering region.
            var valid = true;
            foreach (var vertex in triangle.Vertices)
            {
                if (vertex.X == minX || vertex.X == maxX || vertex.Y == minY || vertex.Y == maxY)
                {
                    valid = false;
                    break;
                }
            }

            if (!valid)
            {
                continue;
            }

            var edges = new List <System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point> >()
            {
                new System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point>(triangle.Vertices[0], triangle.Vertices[1]),
                new System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point>(triangle.Vertices[1], triangle.Vertices[2]),
                new System.Tuple <DelaunayVoronoi.Point, DelaunayVoronoi.Point>(triangle.Vertices[2], triangle.Vertices[0]),
            };

            foreach (var edge in edges)
            {
                var p1 = new Vector2((float)edge.Item1.X, (float)edge.Item1.Y);
                var p2 = new Vector2((float)edge.Item2.X, (float)edge.Item2.Y);

                var r1 = GetRoomByMidpoint(rooms, p1);
                var r2 = GetRoomByMidpoint(rooms, p2);
                if (r1 == null || r2 == null)
                {
                    continue;
                }
                r1.connectedRooms.Add(r2);
                r2.connectedRooms.Add(r1);
            }
        }

        Room spawnRoom           = null;
        var  spawnRoomDistanceSq = float.MaxValue;

        foreach (var room in rooms)
        {
            var distanceSq = room.position.x * room.position.x + room.position.y * room.position.y;
            if (distanceSq < spawnRoomDistanceSq)
            {
                spawnRoomDistanceSq = distanceSq;
                spawnRoom           = room;
            }
        }

        if (GeneratorDebugSettings.DebugStartingRoom)
        {
            Debug.DrawLine(new Vector3(spawnRoom.position.x, 0, spawnRoom.position.y),
                           new Vector3(spawnRoom.position.x, 5, spawnRoom.position.y),
                           Color.yellow, 100000f);
        }

        // Center room has no entrance; you spawn there.
        spawnRoom.DeleteConnectionsIntoSelf();

        // Remove as many connections as possible while preventing islands.
        spawnRoom.DeleteAsManyConnectionsAsPossible();

        // Remove any loops while preventing islands.
        spawnRoom.DeleteLoops();

        // Add some more connections randomly.
        var extraConnections = rooms.Count * 0.1;
        var madeConnections  = 0f;

        while (madeConnections < extraConnections)
        {
            var randomRoomA = rooms[Random.Range(0, rooms.Count - 1)];
            var randomRoomB = rooms[Random.Range(0, rooms.Count - 1)];
            if (randomRoomA == randomRoomB)
            {
                madeConnections += 0.1f;
                continue;
            }
            if (randomRoomA.connectedRooms.Contains(randomRoomB) &&
                randomRoomB.connectedRooms.Contains(randomRoomA))
            {
                madeConnections += 0.1f;
                continue;
            }
            if (randomRoomB == spawnRoom)
            {
                madeConnections += 0.1f;
                continue;
            }
            randomRoomA.connectedRooms.Add(randomRoomB);
            madeConnections++;
        }

        if (GeneratorDebugSettings.DebugGraph)
        {
            spawnRoom.DebugGraph();
        }

        foreach (var room in rooms)
        {
            room.AlignToHallwayGrid(hallwaySize, minX, minY);
            room.FinalizePosition();
        }

        return(spawnRoom);
    }
示例#12
0
 public void Test1000()
 {
     var t = DelaunayTriangulator.Triangulate(RandomPoints.Take(1000));
 }