Ejemplo n.º 1
0
        /// <summary>
        /// Adds a new face to the kernel
        /// </summary>
        /// <param name="positions"></param>
        public bool AddFace(IEnumerable <Vec3d> positions)
        {
            // No bad faces please :(
            if (positions.Count() < 3)
            {
                return(false);
            }

            // convert positions to vertices inside the mesh
            var vertices = VertexQuery.GetVerticesForPositions(_vertices, positions);

            // if the positions had stacked vertices, we might not be able to continue
            if (vertices.Count() < 3)
            {
                // iterate over position vertices
                foreach (var vertex in vertices)
                {
                    // if the vertex was old, it will have an outgoing
                    if (vertex.Outgoing != null)
                    {
                        continue;
                    }

                    // if it was new we need to remove it to restore state
                    Remove(vertex);
                }

                return(false);
            }

            var edges = new List <HalfEdge>();

            // iterate over all positions
            foreach (var vertex in vertices)
            {
                // create a new halfedge originating from the current vertex and linked to the new face
                var halfEdge = new HalfEdge
                {
                    Origin = vertex,
                };

                // test if the vertex already has an outgoing edge assigned
                if (vertex.Outgoing is null)
                {
                    vertex.Outgoing = halfEdge;
                }

                edges.Add(halfEdge);
            }

            // Insert a face from the edges
            Insert(edges);

            // iterate over all edges and insert them
            foreach (var edge in edges)
            {
                // TODO: Maybe we should NOT skip linking checks here
                _halfEdges.Add(edge);
            }

            // test if first face
            if (this.FaceCount == 1)
            {
                var outerRing = new EdgeIterator(
                    _halfEdges[0])
                                .Select(h => h.Pair)
                                .Reverse()
                                .ToList();

                // establish circular link between outside half-edges
                EdgeLinker.LinkOrderedEdgeCollection(outerRing);
            }

            // TODO: Should be method of edgelinker instead
            // Make sure edge pairs either have a starting face or the ghost face
            // Iterators are lazy, calling `Count()` will execute the select body
            _ = edges.Where(e => e.Pair.Face == null).Select(e => e.Pair.Face = Kernel.Outside).Count();

            return(true);

            // TODO: Make sure outer halfEdges are linked,too
            // TODO: Right now only inner halfEdges are linked circularly
            // TODO: This leads to crashes on faces with too many naked edges when creating vertexringiterators
            // TODO: For this we will need a 'ghost' face that encompasses all the space outside of the mesh faces
            // TODO: CLosed meshes will have an empty ghost face
        }