コード例 #1
0
        /// <summary>
        /// Generate the Voronoi diagram from given triangle mesh..
        /// </summary>
        /// <param name="triangleNetMesh"></param>
        /// <param name="bounded"></param>
        protected void Generate(TriangleNetMesh triangleNetMesh)
        {
            triangleNetMesh.Renumber();

            base.edges = new List <HalfEdge>();
            this.rays  = new List <HalfEdge>();

            // Allocate space for Voronoi diagram.
            var vertices = new Vertex[triangleNetMesh.triangles.Count + triangleNetMesh.hullsize];
            var faces    = new Face[triangleNetMesh.vertices.Count];

            if (factory == null)
            {
                factory = new DefaultVoronoiFactory();
            }

            factory.Initialize(vertices.Length, 2 * triangleNetMesh.NumberOfEdges, faces.Length);

            // Compute triangles circumcenters.
            var map = ComputeVertices(triangleNetMesh, vertices);

            // Create all Voronoi faces.
            foreach (var vertex in triangleNetMesh.vertices.Values)
            {
                faces[vertex.id] = factory.CreateFace(vertex);
            }

            ComputeEdges(triangleNetMesh, vertices, faces, map);

            // At this point all edges are computed, but the (edge.next) pointers aren't set.
            ConnectEdges(map);

            base.vertices = new List <Vertex>(vertices);
            base.faces    = new List <Face>(faces);
        }
コード例 #2
0
        /// <summary>
        /// Gets the Voronoi diagram as raw output data.
        /// </summary>
        /// <param name="mesh"></param>
        /// <returns></returns>
        /// <remarks>
        /// The Voronoi diagram is the geometric dual of the Delaunay triangulation.
        /// Hence, the Voronoi vertices are listed by traversing the Delaunay
        /// triangles, and the Voronoi edges are listed by traversing the Delaunay
        /// edges.
        ///</remarks>
        private void Generate()
        {
            _TriangleNetMesh.Renumber();
            _TriangleNetMesh.MakeVertexMap();

            // Allocate space for voronoi diagram
            points  = new Point[_TriangleNetMesh.triangles.Count + _TriangleNetMesh.hullsize];
            regions = new Dictionary <int, VoronoiRegion>(_TriangleNetMesh.vertices.Count);

            rayPoints = new Dictionary <int, Point>();
            rayIndex  = 0;

            bounds = new Rectangle();

            // Compute triangles circumcenters and setup bounding box
            ComputeCircumCenters();

            // Add all Voronoi regions to the map.
            foreach (var vertex in _TriangleNetMesh.vertices.Values)
            {
                regions.Add(vertex.id, new VoronoiRegion(vertex));
            }

            // Loop over the mesh vertices (Voronoi generators).
            foreach (var region in regions.Values)
            {
                //if (item.Boundary == 0)
                {
                    ConstructCell(region);
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Gets the permutation vector for the Reverse Cuthill-McKee numbering.
        /// </summary>
        /// <param name="triangleNetMesh">The mesh.</param>
        /// <returns>Permutation vector.</returns>
        public int[] Renumber(TriangleNetMesh triangleNetMesh)
        {
            // Algorithm needs linear numbering of the nodes.
            triangleNetMesh.Renumber(NodeNumbering.Linear);

            return(Renumber(new AdjacencyMatrix(triangleNetMesh)));
        }
コード例 #4
0
        /// <summary>
        /// Number the vertices and write them to a .node file.
        /// </summary>
        private void WriteNodes(StreamWriter writer, TriangleNetMesh triangleNetMesh)
        {
            int outvertices = triangleNetMesh.vertices.Count;
            int nextras     = triangleNetMesh.nextras;

            Behavior behavior = triangleNetMesh.behavior;

            if (behavior.Jettison)
            {
                outvertices = triangleNetMesh.vertices.Count - triangleNetMesh.undeads;
            }

            if (writer != null)
            {
                // Number of vertices, number of dimensions, number of vertex attributes,
                // and number of boundary markers (zero or one).
                writer.WriteLine("{0} {1} {2} {3}", outvertices, triangleNetMesh.mesh_dim, nextras,
                                 behavior.UseBoundaryMarkers ? "1" : "0");

                if (triangleNetMesh.numbering == NodeNumbering.None)
                {
                    // If the mesh isn't numbered yet, use linear node numbering.
                    triangleNetMesh.Renumber();
                }

                if (triangleNetMesh.numbering == NodeNumbering.Linear)
                {
                    // If numbering is linear, just use the dictionary values.
                    WriteNodes(writer, triangleNetMesh.vertices.Values, behavior.UseBoundaryMarkers,
                               nextras, behavior.Jettison);
                }
                else
                {
                    // If numbering is not linear, a simple 'foreach' traversal of the dictionary
                    // values doesn't reflect the actual numbering. Use an array instead.

                    // TODO: Could use a custom sorting function on dictionary values instead.
                    Vertex[] nodes = new Vertex[triangleNetMesh.vertices.Count];

                    foreach (var node in triangleNetMesh.vertices.Values)
                    {
                        nodes[node.id] = node;
                    }

                    WriteNodes(writer, nodes, behavior.UseBoundaryMarkers,
                               nextras, behavior.Jettison);
                }
            }
        }
コード例 #5
0
        /// <summary>
        /// Computes the bounded voronoi diagram.
        /// </summary>
        private void Generate()
        {
            _TriangleNetMesh.Renumber();
            _TriangleNetMesh.MakeVertexMap();

            // Allocate space for voronoi diagram
            regions = new List <VoronoiRegion>(_TriangleNetMesh.vertices.Count);

            points    = new Point[_TriangleNetMesh.triangles.Count];
            segPoints = new List <Point>(_TriangleNetMesh.subsegs.Count * 4);

            ComputeCircumCenters();

            TagBlindTriangles();

            foreach (var v in _TriangleNetMesh.vertices.Values)
            {
                // TODO: Need a reliable way to check if a vertex is on a segment
                if (v.type == VertexType.FreeVertex || v.label == 0)
                {
                    ConstructCell(v);
                }
                else if (includeBoundary)
                {
                    ConstructBoundaryCell(v);
                }
            }

            // Add the new points on segments to the point array.
            int length = points.Length;

            Array.Resize <Point>(ref points, length + segPoints.Count);

            for (int i = 0; i < segPoints.Count; i++)
            {
                points[length + i] = segPoints[i];
            }

            segPoints.Clear();
            segPoints = null;
        }
コード例 #6
0
        public static DcelMesh ToDCEL(TriangleNetMesh triangleNetMesh)
        {
            var dcel = new DcelMesh();

            var vertices = new HVertex[triangleNetMesh.vertices.Count];
            var faces    = new Face[triangleNetMesh.triangles.Count];

            dcel.HalfEdges.Capacity = 2 * triangleNetMesh.NumberOfEdges;

            triangleNetMesh.Renumber();

            HVertex vertex;

            foreach (var v in triangleNetMesh.vertices.Values)
            {
                vertex       = new HVertex(v.x, v.y);
                vertex.id    = v.id;
                vertex.label = v.label;

                vertices[v.id] = vertex;
            }

            // Maps a triangle to its 3 edges (used to set next pointers).
            var map = new List <HalfEdge> [triangleNetMesh.triangles.Count];

            Face face;

            foreach (var t in triangleNetMesh.triangles)
            {
                face    = new Face(null);
                face.id = t.id;

                faces[t.id] = face;

                map[t.id] = new List <HalfEdge>(3);
            }

            Otri tri = default(Otri), neighbor = default(Otri);

            TriangleNet.Geometry.Vertex org, dest;

            int id, nid, count = triangleNetMesh.triangles.Count;

            HalfEdge edge, twin, next;

            var edges = dcel.HalfEdges;

            // Count half-edges (edge ids).
            int k = 0;

            // Maps a vertex to its leaving boundary edge.
            var boundary = new Dictionary <int, HalfEdge>();

            foreach (var t in triangleNetMesh.triangles)
            {
                id = t.id;

                tri.tri = t;

                for (int i = 0; i < 3; i++)
                {
                    tri.orient = i;
                    tri.Sym(ref neighbor);

                    nid = neighbor.tri.id;

                    if (id < nid || nid < 0)
                    {
                        face = faces[id];

                        // Get the endpoints of the current triangle edge.
                        org  = tri.Org();
                        dest = tri.Dest();

                        // Create half-edges.
                        edge = new HalfEdge(vertices[org.id], face);
                        twin = new HalfEdge(vertices[dest.id], nid < 0 ? Face.Empty : faces[nid]);

                        map[id].Add(edge);

                        if (nid >= 0)
                        {
                            map[nid].Add(twin);
                        }
                        else
                        {
                            boundary.Add(dest.id, twin);
                        }

                        // Set leaving edges.
                        edge.origin.leaving = edge;
                        twin.origin.leaving = twin;

                        // Set twin edges.
                        edge.twin = twin;
                        twin.twin = edge;

                        edge.id = k++;
                        twin.id = k++;

                        edges.Add(edge);
                        edges.Add(twin);
                    }
                }
            }

            // Set next pointers for each triangle face.
            foreach (var t in map)
            {
                edge = t[0];
                next = t[1];

                if (edge.twin.origin.id == next.origin.id)
                {
                    edge.next = next;
                    next.next = t[2];
                    t[2].next = edge;
                }
                else
                {
                    edge.next = t[2];
                    next.next = edge;
                    t[2].next = next;
                }
            }

            // Resolve boundary edges.
            foreach (var e in boundary.Values)
            {
                e.next = boundary[e.twin.origin.id];
            }

            dcel.Vertices.AddRange(vertices);
            dcel.Faces.AddRange(faces);

            return(dcel);
        }