private void CreateVoronoi(List <FlowStructure> flowStructures)
        {
            // Get the starts from everything
            var allStartPoints = flowStructures.Select(x => x.start).ToList();
            // Make a 2d list of all the start points
            var nodes = new Node2List(allStartPoints);

            // Create a 2d list that forms the boundary
            var outline = new List <Node2>();
            // Get sorted lists of coordinates to guestimate a boundary rectangle

            var sortedX = allStartPoints.OrderByDescending(item => item.X);
            var sortedY = allStartPoints.OrderByDescending(item => item.Y);

            outline.Add(new Node2(sortedX.First().X, sortedY.First().Y));
            outline.Add(new Node2(sortedX.First().X, sortedY.Last().Y));
            outline.Add(new Node2(sortedX.Last().X, sortedY.Last().Y));
            outline.Add(new Node2(sortedX.Last().X, sortedY.First().Y));

            // TODO: a delauney first so the brute force isn't needed, and the topology can be used to group

            var voronoiCells = Solver.Solve_BruteForce(nodes, outline);

            // Cells are order as the nodes were; so we can loop through both
            for (var i = 0; i < voronoiCells.Count; i++)
            {
                flowStructures[i].catchment = voronoiCells[i].ToPolyline();
            }
        }
Beispiel #2
0
        /*
         * /// <summary>Delaunay mesher.</summary>
         * /// <param name="nodes">Nodes to triangulate</param>
         * /// <param name="jitter_amount">Amount of random noise. Make sure there is at least some noise
         * /// if your input nodes are structured.</param>
         * /// <param name="faces">Face list output</param>
         * /// <returns>Mesh instance</returns>
         * public static Mesh Solve_Mesh(Node2List nodes, double jitter_amount, ref List<Face> faces)
         * {
         *  faces = Solver.Solve_Faces(nodes, jitter_amount);
         *  Mesh mesh1;
         *  if (faces == null)
         *      mesh1 = (Mesh)null;
         *  else if (faces.Count == 0)
         *  {
         *      mesh1 = (Mesh)null;
         *  }
         *  else
         *  {
         *      Mesh mesh2 = new Mesh();
         *      int num1 = nodes.Count - 1;
         *      for (int index = 0; index <= num1; ++index)
         *          mesh2.Vertices.Add(nodes[index].x, nodes[index].y, 0.0);
         *      int num2 = faces.Count - 1;
         *      for (int index = 0; index <= num2; ++index)
         *          mesh2.Faces.AddFace(faces[index].A, faces[index].B, faces[index].C);
         *      mesh2.Normals.ComputeNormals();
         *      mesh1 = mesh2;
         *  }
         *  return mesh1;
         * }
         */

        /// <summary>Connectivity solver. Returns a topological edge diagram of delaunay faces.</summary>
        /// <param name="nodes">Nodes to connect</param>
        /// <param name="jitter_amount">Amount of random motion.</param>
        /// <param name="include_convex_hull_edges">If true, the edges of the convex hull are included in the connectivity diagram.</param>
        /// <returns>Connectivity diagram for [nodes]</returns>
        public static Connectivity Solve_Connectivity(
            Node2List nodes,
            double jitter_amount,
            bool include_convex_hull_edges)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException(nameof(nodes));
            }
            if (nodes.Count < 2)
            {
                throw new InvalidOperationException("Insufficient nodes for a Connectivity diagram");
            }
            List <Face> faces = (List <Face>)null;

            if (nodes.Count > 2)
            {
                faces = Solver.Solve_Faces(nodes, jitter_amount);
            }
            if (faces == null)
            {
                faces = new List <Face>();
            }
            Connectivity connectivity = new Connectivity();

            connectivity.SolveConnectivity(nodes, faces, include_convex_hull_edges);
            return(connectivity);
        }
        public void AddFace(int A, int B, int C, Node2List Nodes)
        {
            FaceEx faceEx = new FaceEx(A, B, C);

            faceEx.ComputeBC(Nodes);
            AddFace(faceEx);
        }
Beispiel #4
0
        /// <summary>Core Delaunay solver.</summary>
        /// <param name="nodes">Nodes to triangulate</param>
        /// <param name="jitter_amount">Amount of random noise. Make sure there is at least some noise
        /// if your input nodes are structured.</param>
        /// <returns>A list of triangular faces that connect indices in the [nodes] parameter.</returns>
        public static List <Face> Solve_Faces(Node2List nodes, double jitter_amount)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException(nameof(nodes));
            }
            if (nodes.Count < 3)
            {
                throw new InvalidOperationException("Insufficient nodes for a triangulation");
            }
            Solver solver = new Solver();

            solver.m_nodes = new Node2List(nodes);
            solver.m_nodes.RenumberNodes();
            if (jitter_amount != 0.0)
            {
                solver.m_nodes.JitterNodes(jitter_amount);
            }
            List <Face> faceList;

            if (!solver.Triangulate())
            {
                faceList = (List <Face>)null;
            }
            else
            {
                solver.RemapFaceIndices();
                faceList = solver.m_faces;
            }
            return(faceList);
        }
Beispiel #5
0
 /// <summary>This class cannot be constructed.</summary>
 private Solver()
 {
     this.m_nodes       = new Node2List();
     this.m_faces       = new List <Face>();
     this.m_box_corners = new int[4] {
         -1, -1, -1, -1
     };
 }
        public void InsertFaces(Node2List nodes)
        {
            int num = m_F.Count - 1;

            for (int i = 0; i <= num; i++)
            {
                FaceEx faceEx = m_F[i];
                if (faceEx != null)
                {
                    Polyline polyline = new Polyline();
                    polyline.Add(nodes[faceEx.A].x, nodes[faceEx.A].y, 0.0);
                    polyline.Add(nodes[faceEx.B].x, nodes[faceEx.B].y, 0.0);
                    polyline.Add(nodes[faceEx.C].x, nodes[faceEx.C].y, 0.0);
                    polyline.Add(nodes[faceEx.A].x, nodes[faceEx.A].y, 0.0);
                }
            }
        }
Beispiel #7
0
        public static Polyline ComputeHull(Node2List pts)
        {
            List <int> list = new List <int>();

            if (!Compute(pts, list))
            {
                return(null);
            }
            Polyline polyline = new Polyline(list.Count);
            int      num      = list.Count - 1;

            for (int i = 0; i <= num; i++)
            {
                polyline.Add(pts[list[i]].x, pts[list[i]].y, 0.0);
            }
            polyline.Add(polyline[0]);
            return(polyline);
        }
        public void SolveConnectivity(Node2List nodes, List <Face> faces, bool include_convex_hull_edges)
        {
            m_map = new List <List <int> >(nodes.Count);
            int num = nodes.Count - 1;

            for (int i = 0; i <= num; i++)
            {
                m_map.Add(new List <int>(6));
            }
            int num2 = faces.Count - 1;

            for (int j = 0; j <= num2; j++)
            {
                Face face = faces[j];
                m_map[face.A].Add(face.B);
                m_map[face.A].Add(face.C);
                m_map[face.B].Add(face.A);
                m_map[face.B].Add(face.C);
                m_map[face.C].Add(face.A);
                m_map[face.C].Add(face.B);
            }
            if (include_convex_hull_edges)
            {
                List <int> list = new List <int>();
                if (Diagrams.ConvexHull.Solver.Compute(nodes, list))
                {
                    int num3 = list.Count - 1;
                    for (int k = 0; k <= num3; k++)
                    {
                        int num4 = k + 1;
                        if (num4 == list.Count)
                        {
                            num4 = 0;
                        }
                        m_map[list[k]].Add(list[num4]);
                        m_map[list[num4]].Add(list[k]);
                    }
                }
            }
            RemoveDuplicates();
        }
Beispiel #9
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            string path     = "";
            int    lineSkip = 1;

            if (!DA.GetData(0, ref path))
            {
                return;
            }
            DA.GetData(1, ref recursive);
            DA.GetData(2, ref asMesh);
            DA.GetData(3, ref lineSkip);

            if (lineSkip < 1)
            {
                lineSkip = 1;
            }

            try
            {
                if (oldPath != path)
                {
                    oldPath  = path;
                    geometry = GetGeometricData(path);
                }

                DataTree <IGH_GeometricGoo> geo = new DataTree <IGH_GeometricGoo>();

                foreach (Tuple <int, ConcurrentQueue <IGH_GeometricGoo>, FileTypes> tuple in geometry)
                {
                    switch (tuple.Item3)
                    {
                    case FileTypes.XYZ:

                        if (asMesh)
                        {
                            ConcurrentQueue <Point3d> pp = new ConcurrentQueue <Point3d>();
                            Parallel.ForEach(tuple.Item2, (item, _, iNum) =>
                            {
                                if (iNum % lineSkip == 0)
                                {
                                    GH_Point p = new GH_Point();
                                    if (GH_Convert.ToGHPoint(item, GH_Conversion.Both, ref p))
                                    {
                                        pp.Enqueue(p.Value);
                                    }
                                }
                            });
                            Mesh mesh = new Mesh();
                            mesh.Vertices.AddVertices(pp);
                            try
                            {
                                Node2List              nodes     = new Node2List(pp);
                                List <Face>            faces     = Solver.Solve_Faces(nodes, 1);
                                IEnumerable <MeshFace> meshFaces = faces.Select(x => new MeshFace(x.A, x.B, x.C));
                                mesh.Faces.AddFaces(meshFaces);

                                ConcurrentQueue <IGH_GeometricGoo> goo = new ConcurrentQueue <IGH_GeometricGoo>();
                                goo.Enqueue(GH_Convert.ToGeometricGoo(mesh));
                                geo.AddRange(goo, new GH_Path(tuple.Item1));
                            }
                            catch (Exception e)
                            {
                                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message);
                            }
                        }
                        else
                        {
                            ConcurrentQueue <IGH_GeometricGoo> goo = new ConcurrentQueue <IGH_GeometricGoo>();
                            Parallel.ForEach(tuple.Item2, (item, _, iNum) =>
                            {
                                if (iNum % lineSkip == 0)
                                {
                                    goo.Enqueue(item);
                                }
                            });
                            geo.AddRange(goo, new GH_Path(tuple.Item1));
                        }
                        break;
                    }
                }
                DA.SetDataTree(0, geo);
            }
            catch (Exception e)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message);
            }
        }
Beispiel #10
0
 public void ComputeBC(Node2List Nodes)
 {
     ComputeBC(Nodes[A], Nodes[B], Nodes[C]);
 }
Beispiel #11
0
        /// <summary>
        /// Compute the convex hull of list of nodes.
        /// </summary>
        /// <param name="nodes">Nodes to wrap. May not contain null references.</param>
        /// <param name="hull">Index list describing the convex hull (closing segment not included)</param>
        public static bool Compute(Node2List nodes, List <int> hull)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (hull == null)
            {
                throw new ArgumentNullException("hull");
            }
            List <bool> list = new List <bool>();

            hull.Clear();
            list.Clear();
            hull.Capacity = nodes.Count;
            list.Capacity = nodes.Count;
            if (nodes.Count == 0)
            {
                return(false);
            }
            if (nodes.Count == 1)
            {
                return(false);
            }
            if (nodes.Count == 2)
            {
                hull.Add(0);
                hull.Add(1);
                return(true);
            }
            int num = nodes.Count - 1;

            for (int i = 0; i <= num; i++)
            {
                list.Add(item: false);
            }
            int num2 = -1;
            int num3 = -1;
            int num4 = nodes.Count - 1;

            for (int j = 0; j <= num4; j++)
            {
                if (nodes[j] != null)
                {
                    num2 = j;
                    num3 = j;
                    break;
                }
            }
            if (num2 < 0)
            {
                return(false);
            }
            int num5 = nodes.Count - 1;

            for (int k = 1; k <= num5; k++)
            {
                if (nodes[k] != null)
                {
                    if (nodes[k].x < nodes[num2].x)
                    {
                        num2 = k;
                    }
                    else if (nodes[k].x == nodes[num2].x && nodes[k].y < nodes[num2].y)
                    {
                        num2 = k;
                    }
                }
            }
            num3 = num2;
            do
            {
                int num6 = -1;
                int num7 = nodes.Count - 1;
                for (int l = 0; l <= num7; l++)
                {
                    if (nodes[l] == null || list[l] || l == num3)
                    {
                        continue;
                    }
                    if (num6 == -1)
                    {
                        num6 = l;
                        continue;
                    }
                    double num8 = CrossProduct(nodes[l], nodes[num3], nodes[num6]);
                    if (num8 == 0.0)
                    {
                        if (DotProduct(nodes[num3], nodes[l], nodes[l]) > DotProduct(nodes[num3], nodes[num6], nodes[num6]))
                        {
                            num6 = l;
                        }
                    }
                    else if (num8 < 0.0)
                    {
                        num6 = l;
                    }
                }
                num3       = num6;
                list[num3] = true;
                hull.Add(num3);
            }while (num3 != num2);
            return(true);
        }
Beispiel #12
0
        /// <summary>
        /// Solve the voronoi diagram using a Sorted Brute force approach.
        /// Works best with a collection of nodes which are spread along the x-direction.
        /// This function will renumber and sort the nodes.
        /// </summary>
        /// <param name="nodes">Nodes to solve for. This list will be renumbered and sorted.</param>
        /// <param name="outline">Initial boundary for every cell.</param>
        /// <returns>The voronoi cells. Order of cells is identical to the order of nodes.</returns>
        public static List <Cell2> Solve_BruteForce(Node2List nodes, IEnumerable <Node2> outline)
        {
            nodes = new Node2List(nodes);
            List <Node2> node2List;

            if (outline is List <Node2> )
            {
                node2List = (List <Node2>)outline;
            }
            else
            {
                node2List = new List <Node2>();
                node2List.AddRange(outline);
            }
            nodes.RenumberNodes();
            nodes.Sort(Node2List.NodeListSort.X);
            List <Cell2> cell2List = new List <Cell2>(nodes.Count);
            int          num1      = nodes.Count - 1;

            for (int index = 0; index <= num1; ++index)
            {
                cell2List.Add((Cell2)null);
            }
            int num2 = nodes.Count - 1;

            for (int index1 = 0; index1 <= num2; ++index1)
            {
                if (nodes[index1] != null)
                {
                    Cell2  cell2 = new Cell2(nodes[index1], (IEnumerable <Node2>)node2List);
                    double num3  = cell2.Radius();
                    for (int index2 = index1 - 1; index2 >= 0; index2 += -1)
                    {
                        if (nodes[index2] != null)
                        {
                            if (nodes[index2].x >= cell2.M.x - num3)
                            {
                                if (cell2.Slice(nodes[index2]))
                                {
                                    if (cell2.C.Count != 0)
                                    {
                                        num3 = cell2.Radius();
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    if (cell2.C.Count != 0)
                    {
                        int num4 = index1 + 1;
                        int num5 = nodes.Count - 1;
                        for (int index2 = num4; index2 <= num5; ++index2)
                        {
                            if (nodes[index2] != null)
                            {
                                if (nodes[index2].x <= cell2.M.x + num3)
                                {
                                    if (cell2.Slice(nodes[index2]))
                                    {
                                        if (cell2.C.Count != 0)
                                        {
                                            num3 = cell2.Radius();
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                        cell2List[nodes[index1].tag] = cell2;
                    }
                }
            }
            return(cell2List);
        }
Beispiel #13
0
        /// <summary>Solve the voronoi diagram using a minimal connectivity map.</summary>
        /// <param name="nodes">Nodes to solve for.</param>
        /// <param name="diagram">Connectivity diagram. Can be obtained from a Delaunay mesh.</param>
        /// <param name="outline">Initial boundary for every cell.</param>
        public static List <Cell2> Solve_Connectivity(
            Node2List nodes,
            Connectivity diagram,
            IEnumerable <Node2> outline)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException(nameof(nodes));
            }
            if (diagram == null)
            {
                throw new ArgumentNullException(nameof(diagram));
            }
            if (outline == null)
            {
                throw new ArgumentNullException("boundary");
            }
            List <Node2> node2List;

            if (outline is List <Node2> )
            {
                node2List = (List <Node2>)outline;
            }
            else
            {
                node2List = new List <Node2>();
                node2List.AddRange(outline);
            }
            nodes = new Node2List(nodes);
            nodes.RenumberNodes();
            List <Cell2> cell2List = new List <Cell2>(nodes.Count);
            int          num1      = nodes.Count - 1;

            for (int index = 0; index <= num1; ++index)
            {
                cell2List.Add((Cell2)null);
            }
            int num2 = nodes.Count - 1;

            for (int node_index = 0; node_index <= num2; ++node_index)
            {
                if (nodes[node_index] != null)
                {
                    Cell2      cell2       = new Cell2(nodes[node_index], (IEnumerable <Node2>)node2List);
                    List <int> connections = diagram.GetConnections(node_index);
                    if (connections != null)
                    {
                        int num3 = connections.Count - 1;
                        for (int index1 = 0; index1 <= num3; ++index1)
                        {
                            int index2 = connections[index1];
                            if (index2 != node_index)
                            {
                                cell2.Slice(nodes[index2]);
                            }
                        }
                        cell2List[nodes[node_index].tag] = cell2;
                    }
                }
            }
            return(cell2List);
        }