/// <summary>
        /// Simplifies the model by merging the eliminating edges that are closer together
        /// than double the shortest edge length
        /// </summary>
        /// <param name="ts">The ts.</param>
        public static void SimplifyFlatPatches(this TessellatedSolid ts)
        {
            //   throw new NotImplementedException();
            var edgesToRemove    = new List <Edge>();
            var edgesToAdd       = new List <Edge>();
            var facesToRemove    = new List <PolygonalFace>();
            var facesToAdd       = new List <PolygonalFace>();
            var verticesToRemove = new List <Vertex>();
            var flats            = TVGL.MiscFunctions.FindFlats(ts.Faces);

            if (ts.Primitives == null)
            {
                ts.Primitives = new List <PrimitiveSurface>();
            }
            foreach (var flat in flats)
            {
                if (flat.InnerEdges.Count < flat.Faces.Count)
                {
                    continue;
                }
                var newFaces         = new List <PolygonalFace>();
                var outerEdgeHashSet = new HashSet <Edge>(flat.OuterEdges);
                facesToRemove.AddRange(flat.Faces);
                edgesToRemove.AddRange(flat.InnerEdges);
                var innerVertices = new HashSet <Vertex>(flat.InnerEdges.Select(e => e.To));
                innerVertices.UnionWith(flat.InnerEdges.Select(e => e.From));
                innerVertices.RemoveWhere(v => outerEdgeHashSet.Overlaps(v.Edges));
                verticesToRemove.AddRange(innerVertices);
                var vertexLoops = OrganizeIntoLoop(flat.OuterEdges, flat.Normal);
                List <List <Vertex[]> > triangulatedListofLists = TriangulatePolygon.Run(new[] { vertexLoops }, flat.Normal);
                var triangulatedList  = triangulatedListofLists.SelectMany(tl => tl).ToList();
                var oldEdgeDictionary = flat.OuterEdges.ToDictionary(TessellatedSolid.SetAndGetEdgeChecksum);
                Dictionary <long, Edge> newEdgeDictionary = new Dictionary <long, Edge>();
                foreach (var triangle in triangulatedList)
                {
                    var newFace = new PolygonalFace(triangle, flat.Normal);
                    if (newFace.Area.IsNegligible() && newFace.Normal.Any(double.IsNaN))
                    {
                        continue;
                    }
                    newFaces.Add(newFace);
                    for (var j = 0; j < 3; j++)
                    {
                        var fromVertex = newFace.Vertices[j];
                        var toVertex   = newFace.NextVertexCCW(fromVertex);
                        var checksum   = TessellatedSolid.GetEdgeChecksum(fromVertex, toVertex);
                        if (oldEdgeDictionary.ContainsKey(checksum))
                        {
                            //fix up old outer edge.
                            var edge = oldEdgeDictionary[checksum];
                            if (fromVertex == edge.From)
                            {
                                edge.OwnedFace = newFace;
                            }
                            else
                            {
                                edge.OtherFace = newFace;
                            }
                            newFace.AddEdge(edge);
                            oldEdgeDictionary.Remove(checksum);
                        }
                        else if (newEdgeDictionary.ContainsKey(checksum))
                        {
                            //Finish creating edge.
                            var newEdge = newEdgeDictionary[checksum];
                            newEdge.OtherFace = newFace;
                            newFace.AddEdge(newEdge);
                            newEdgeDictionary.Remove(checksum);
                            edgesToAdd.Add(newEdge);
                        }
                        else
                        {
                            newEdgeDictionary.Add(checksum, new Edge(fromVertex, toVertex, newFace, null, false, checksum));
                        }
                    }
                }
                ts.Primitives.Add(new Flat(newFaces));
            }
            ts.RemoveVertices(verticesToRemove);  //todo: check if the order of these five commands
            ts.RemoveFaces(facesToRemove);        // matters. There may be an ordering that is more efficient
            ts.AddFaces(facesToAdd);
            ts.RemoveEdges(edgesToRemove);
            ts.AddEdges(edgesToAdd);
        }
Beispiel #2
0
        private static IEnumerable <Tuple <Edge, List <PolygonalFace> > > CreateMissingEdgesAndFaces(
            List <Tuple <List <Edge>, double[]> > loops,
            out List <PolygonalFace> newFaces, out List <Edge> remainingEdges)
        {
            var completedEdges = new List <Tuple <Edge, List <PolygonalFace> > >();

            newFaces       = new List <PolygonalFace>();
            remainingEdges = new List <Edge>();
            foreach (var tuple in loops)
            {
                var edges  = tuple.Item1;
                var normal = tuple.Item2;
                //if a simple triangle, create a new face from vertices
                if (edges.Count == 3)
                {
                    var newFace = new PolygonalFace(edges.Select(e => e.To), normal);
                    foreach (var edge in edges)
                    {
                        completedEdges.Add(new Tuple <Edge, List <PolygonalFace> >(edge,
                                                                                   new List <PolygonalFace> {
                            edge.OwnedFace, newFace
                        }));
                    }
                    newFaces.Add(newFace);
                }
                //Else, use the triangulate function
                else
                {
                    Dictionary <long, Edge> edgeDic = new Dictionary <long, Edge>();
                    foreach (var edge in edges)
                    {
                        var checksum = GetEdgeChecksum(edge.From, edge.To);
                        if (!edgeDic.ContainsKey(checksum))
                        {
                            edgeDic.Add(checksum, edge);
                        }
                    }
                    List <List <Vertex[]> > triangleFaceList = null;
                    try
                    {
                        triangleFaceList = TriangulatePolygon.Run(new List <List <Vertex> >
                        {
                            edges.Select(e => e.To).ToList()
                        }, normal);
                    }
                    catch
                    {
                        continue;
                    }
                    var triangles = triangleFaceList.SelectMany(tl => tl).ToList();
                    if (triangles.Any())
                    {
                        Message.output("loop successfully repaired with " + triangles.Count, 5);
                        foreach (var triangle in triangles)
                        {
                            var newFace = new PolygonalFace(triangle, normal);
                            if (newFace.Area.IsNegligible() && newFace.Normal.Any(double.IsNaN))
                            {
                                continue;
                            }
                            newFaces.Add(newFace);
                            for (var j = 0; j < 3; j++)
                            {
                                var fromVertex = newFace.Vertices[j];
                                var toVertex   = newFace.NextVertexCCW(fromVertex);
                                var checksum   = GetEdgeChecksum(fromVertex, toVertex);
                                if (edgeDic.ContainsKey(checksum))
                                {
                                    //Finish creating edge.
                                    var edge = edgeDic[checksum];
                                    completedEdges.Add(new Tuple <Edge, List <PolygonalFace> >(edge,
                                                                                               new List <PolygonalFace> {
                                        edge.OwnedFace, newFace
                                    }));
                                    edgeDic.Remove(checksum);
                                }
                                else
                                {
                                    edgeDic.Add(checksum, new Edge(fromVertex, toVertex, newFace, null, false, checksum));
                                }
                            }
                        }
                    }
                    else
                    {
                        remainingEdges.AddRange(edges);
                    }
                }
            }
            return(completedEdges);
        }