Ejemplo n.º 1
0
        /// <summary>
        /// Complexifies the tessellation so that no edge is longer than provided the maximum edge length
        /// or for adding the provided number of faces - whichever comes first
        /// </summary>
        /// <param name="ts">The ts.</param>
        /// <param name="numberOfFaces">The number of new faces to add.</param>
        /// <param name="maxLength">The maximum length.</param>
        public static void Complexify(TessellatedSolid ts, int numberOfFaces, double maxLength)
        {
            var edgeQueue = new SimplePriorityQueue <Edge, double>(new ReverseSort());

            foreach (var e in ts.Edges)
            {
                edgeQueue.Enqueue(e, e.Length);
            }
            var addedEdges    = new List <Edge>();
            var addedVertices = new List <Vertex>();
            var addedFaces    = new List <PolygonalFace>();
            var edge          = edgeQueue.Dequeue();
            var iterations    = numberOfFaces > 0 ? (int)Math.Ceiling(numberOfFaces / 2.0) : numberOfFaces;

            while (iterations-- != 0 && edge.Length >= maxLength)
            {
                var origLeftFace   = edge.OtherFace;
                var origRightFace  = edge.OwnedFace;
                var leftFarVertex  = origLeftFace.OtherVertex(edge);
                var rightFarVertex = origRightFace.OtherVertex(edge);
                var fromVertex     = edge.From;
                var toVertex       = edge.To;
                var addedVertex    = new Vertex(DetermineIntermediateVertexPosition(fromVertex, toVertex));
                // modify original faces with new intermediate vertex
                var index = origLeftFace.Vertices.IndexOf(toVertex);
                origLeftFace.Vertices[index] = addedVertex;
                origLeftFace.Update();
                addedVertex.Faces.Add(origLeftFace);
                index = origRightFace.Vertices.IndexOf(toVertex);
                origRightFace.Vertices[index] = addedVertex;
                origRightFace.Update();
                addedVertex.Faces.Add(origRightFace);

                var newLeftFace  = new PolygonalFace(new[] { toVertex, addedVertex, leftFarVertex });
                var newRightFace = new PolygonalFace(new[] { addedVertex, toVertex, rightFarVertex });
                toVertex.Faces.Remove(origLeftFace);
                toVertex.Faces.Remove(origRightFace);

                var inlineEdge = new Edge(addedVertex, toVertex, newRightFace, newLeftFace, true);
                toVertex.Edges.Remove(edge);
                edge.To = addedVertex;
                addedVertex.Edges.Add(edge);
                edge.Update();
                var newLeftEdge  = new Edge(leftFarVertex, addedVertex, origLeftFace, newLeftFace, true);
                var newRightEdge = new Edge(rightFarVertex, addedVertex, newRightFace, origRightFace, true);
                origLeftFace.AddEdge(newLeftEdge);
                origRightFace.AddEdge(newRightEdge);
                var bottomEdge = toVertex.Edges.First(e => e.OtherVertex(toVertex) == leftFarVertex);
                if (bottomEdge.OwnedFace == origLeftFace)
                {
                    bottomEdge.OwnedFace = newLeftFace;
                }
                else
                {
                    bottomEdge.OtherFace = newLeftFace;
                }
                newLeftFace.AddEdge(bottomEdge);
                bottomEdge.Update();

                bottomEdge = toVertex.Edges.First(e => e.OtherVertex(toVertex) == rightFarVertex);
                if (bottomEdge.OwnedFace == origRightFace)
                {
                    bottomEdge.OwnedFace = newRightFace;
                }
                else
                {
                    bottomEdge.OtherFace = newRightFace;
                }
                newRightFace.AddEdge(bottomEdge);
                bottomEdge.Update();


                // need to re-add the edge. It was modified in the SplitEdge function (now, half the lenght), but
                // it may still be met by this criteria
                edgeQueue.Enqueue(edge, edge.Length);
                edgeQueue.Enqueue(inlineEdge, inlineEdge.Length);
                addedEdges.Add(inlineEdge);
                edgeQueue.Enqueue(newLeftEdge, newLeftEdge.Length);
                addedEdges.Add(newLeftEdge);
                edgeQueue.Enqueue(newRightEdge, newRightEdge.Length);
                addedEdges.Add(newRightEdge);
                addedFaces.Add(newLeftFace);
                addedFaces.Add(newRightFace);
                addedVertices.Add(addedVertex);
                edge = edgeQueue.First();
            }
            ts.AddVertices(addedVertices);
            ts.AddEdges(addedEdges);
            ts.AddFaces(addedFaces);
        }
Ejemplo n.º 2
0
        /// <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);
        }