예제 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Face" /> class.
        /// </summary>
        /// <param name="generator">The generator of this face (for Voronoi diagram)</param>
        /// <param name="edge">The half-edge connected to this face.</param>
        public Face(Point generator, HalfEdge edge)
        {
            this.generator = generator;
            this.edge = edge;
            this.bounded = true;

            if (generator != null)
            {
                this.id = generator.ID;
            }
        }
예제 #2
0
        /// <summary>
        /// Case 1: edge origin lies inside the domain.
        /// </summary>
        private void HandleCase1(HalfEdge edge, TVertex v1, TVertex v2)
        {
            //int mark = GetBoundaryMark(v1);

            // The infinite vertex.
            var v = (Point)edge.twin.origin;

            // The half-edge is the bisector of v1 and v2, so the projection onto the
            // boundary segment is actually its midpoint.
            v.x = (v1.x + v2.x) / 2.0;
            v.y = (v1.y + v2.y) / 2.0;

            // Close the cell connected to edge.
            var gen = factory.CreateVertex(v1.x, v1.y);

            var h1 = factory.CreateHalfEdge(edge.twin.origin, edge.face);
            var h2 = factory.CreateHalfEdge(gen, edge.face);

            edge.next = h1;
            h1.next = h2;
            h2.next = edge.face.edge;

            gen.leaving = h2;

            // Let the face edge point to the edge leaving at generator.
            edge.face.edge = h2;

            base.edges.Add(h1);
            base.edges.Add(h2);

            int count = base.edges.Count;

            h1.id = count;
            h2.id = count + 1;

            gen.id = offset++;
            base.vertices.Add(gen);
        }
예제 #3
0
        public static DcelMesh ToDCEL(Mesh mesh)
        {
            var dcel = new DcelMesh();

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

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

            mesh.Renumber();

            HVertex vertex;

            foreach (var v in mesh.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>[mesh.triangles.Count];

            Face face;

            foreach (var t in mesh.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 = mesh.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 mesh.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;
        }
예제 #4
0
        /// <summary>
        /// Enumerates all half-edges of the face boundary.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<HalfEdge> EnumerateEdges()
        {
            var edge = this.Edge;
            int first = edge.ID;

            do
            {
                yield return edge;

                edge = edge.Next;
            } while (edge.ID != first);
        }
예제 #5
0
        /// <summary>
        /// Case 2: edge origin lies outside the domain.
        /// </summary>
        private void HandleCase2(HalfEdge edge, TVertex v1, TVertex v2)
        {
            // The vertices of the infinite edge.
            var p1 = (Point)edge.origin;
            var p2 = (Point)edge.twin.origin;

            // The two edges leaving p1, pointing into the mesh.
            var e1 = edge.twin.next;
            var e2 = e1.twin.next;

            // Find the two intersections with boundary edge.
            IntersectionHelper.IntersectSegments(v1, v2, e1.origin, e1.twin.origin, ref p2);
            IntersectionHelper.IntersectSegments(v1, v2, e2.origin, e2.twin.origin, ref p1);

            // The infinite edge will now lie on the boundary. Update pointers:
            e1.twin.next = edge.twin;
            edge.twin.next = e2;
            edge.twin.face = e2.face;

            e1.origin = edge.twin.origin;

            edge.twin.twin = null;
            edge.twin = null;

            // Close the cell.
            var gen = factory.CreateVertex(v1.x, v1.y);
            var he = factory.CreateHalfEdge(gen, edge.face);

            edge.next = he;
            he.next = edge.face.edge;

            // Let the face edge point to the edge leaving at generator.
            edge.face.edge = he;

            base.edges.Add(he);

            he.id = base.edges.Count;

            gen.id = offset++;
            base.vertices.Add(gen);
        }
예제 #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Vertex" /> class.
 /// </summary>
 /// <param name="x">The x coordinate.</param>
 /// <param name="y">The y coordinate.</param>
 /// <param name="leaving">A half-edge leaving this vertex.</param>
 public Vertex(double x, double y, HalfEdge leaving)
     : base(x, y)
 {
     this.leaving = leaving;
 }
예제 #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Vertex" /> class.
 /// </summary>
 /// <param name="x">The x coordinate.</param>
 /// <param name="y">The y coordinate.</param>
 /// <param name="leaving">A half-edge leaving this vertex.</param>
 public Vertex(float x, float y, HalfEdge leaving)
     : base(x, y)
 {
     this.leaving = leaving;
 }
예제 #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Vertex" /> class.
 /// </summary>
 /// <param name="x">The x coordinate.</param>
 /// <param name="y">The y coordinate.</param>
 /// <param name="leaving">A half-edge leaving this vertex.</param>
 public Vertex(double x, double y, HalfEdge leaving)
     : base(x, y)
 {
     this.leaving = leaving;
 }