Beispiel #1
0
        private static bool FaceShouldBeOwnedFace(Edge edge, PolygonalFace face)
        {
            var otherEdgeVector = face.OtherVertex(edge.From, edge.To).Position.subtract(edge.To.Position, 3);
            var isThisNormal    = edge.Vector.crossProduct(otherEdgeVector);

            return(face.Normal.dotProduct(isThisNormal, 3) > 0);
        }
        /// <summary>
        ///     Combines the vertices of edge.
        /// </summary>
        /// <param name="edge">The edge.</param>
        /// <param name="removedVertexOut">The removed vertex out.</param>
        /// <param name="removedEdge1Out">The removed edge1 out.</param>
        /// <param name="removedEdge2Out">The removed edge2 out.</param>
        /// <param name="removedFace1">The removed face1.</param>
        /// <param name="removedFace2">The removed face2.</param>
        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
        private static bool CombineVerticesOfEdge(Edge edge, out Vertex removedVertexOut, out Edge removedEdge1Out,
                                                  out Edge removedEdge2Out, out PolygonalFace removedFace1, out PolygonalFace removedFace2)
        {
            var keepVertex    = edge.To;   // arbitrarily choose the To as the keep vertex, but this may be swapped below
            var removedVertex = edge.From; // if the To has some missing faces

            if (keepVertex == removedVertex)
            {
                removedVertexOut = null;
                removedEdge2Out  = removedEdge1Out = null;
                removedFace1     = removedFace2 = null;
                return(false);
            }
            removedFace1 = edge.OwnedFace;
            removedFace2 = edge.OtherFace;
            var removedEdge1 = removedFace1 == null ? null : removedFace1.OtherEdge(keepVertex, true);
            var removedEdge2 = removedFace2 == null ? null : removedFace2.OtherEdge(keepVertex, true);
            var keepEdge1    = removedFace1 == null ? null : removedFace1.OtherEdge(removedVertex, true);
            var keepEdge2    = removedFace2 == null ? null : removedFace2.OtherEdge(removedVertex, true);

            if (removedEdge1 != null && removedEdge2 != null && (keepEdge1 == null || keepEdge2 == null))
            {
                // swap with removed.
                var tempVertex = keepVertex;
                keepVertex    = removedVertex;
                removedVertex = tempVertex;
                var tempEdge = keepEdge1;
                keepEdge1    = removedEdge1;
                removedEdge1 = tempEdge;
                tempEdge     = keepEdge2;
                keepEdge2    = removedEdge2;
                removedEdge2 = tempEdge;
            }
            var otherEdgesOnTheKeepSide =
                keepVertex.Edges.Where(e => e != edge && e != keepEdge1 && e != keepEdge2).ToList();
            var otherEdgesOnTheRemoveSide =
                removedVertex.Edges.Where(e => e != edge && e != removedEdge1 && e != removedEdge2).ToList();

            if ( // this is a topologically important check. It ensures that the edge is not deleted if
                 // it serves an important role in ensuring the proper topology of the solid
                otherEdgesOnTheKeepSide.Select(e => e.OtherVertex(keepVertex))
                .Intersect(otherEdgesOnTheRemoveSide.Select(e => e.OtherVertex(removedVertex)))
                .Any())
            {
                removedVertexOut = null;
                removedEdge2Out  = removedEdge1Out = null;
                removedFace1     = removedFace2 = null;
                return(false);
            }
            // move edges connected to removeVertex to the keepVertex and let keepVertex link back to these edges
            foreach (var e in otherEdgesOnTheRemoveSide)
            {
                keepVertex.Edges.Add(e);
                if (e.From == removedVertex)
                {
                    e.From = keepVertex;
                }
                else
                {
                    e.To = keepVertex;
                }
            }
            // move faces connected to removeVertex to the keepVertex and let keepVertex link back to these edges.
            foreach (var face in removedVertex.Faces)
            {
                if (face == removedFace1 || face == removedFace2)
                {
                    continue;
                }
                keepVertex.Faces.Add(face);
                face.Vertices[face.Vertices.IndexOf(removedVertex)] = keepVertex;
            }
            // conversely keepVertex should forget about the edge and the remove faces
            keepVertex.Edges.Remove(edge);
            keepVertex.Faces.Remove(removedFace1);
            keepVertex.Faces.Remove(removedFace2);
            var farVertex = removedFace1 == null ? null : removedFace1.OtherVertex(edge, true);

            if (farVertex != null)
            {
                farVertex.Edges.Remove(removedEdge1);
                farVertex.Faces.Remove(removedFace1);
            }
            farVertex = removedFace2 == null ? null : removedFace2.OtherVertex(edge, true);
            if (farVertex != null)
            {
                farVertex.Edges.Remove(removedEdge2);
                farVertex.Faces.Remove(removedFace2);
            }
            // for the winged edges (removedEdge1 and removedEdge2) that are removed, connected their faces to
            // the new edge
            // first on the "owned side of edge"
            var fromFace = removedEdge1 == null
                ? null
                : removedEdge1.OwnedFace == removedFace1 ? removedEdge1.OtherFace : removedEdge1.OwnedFace;

            if (fromFace != null)
            {
                var index = fromFace.Edges.IndexOf(removedEdge1);
                if (index >= 0 && index < fromFace.Edges.Count)
                {
                    fromFace.Edges[index] = keepEdge1;
                }
            }
            if (keepEdge1 != null && keepEdge1.OwnedFace == removedFace1)
            {
                keepEdge1.OwnedFace = fromFace;
            }
            else if (keepEdge1 != null)
            {
                keepEdge1.OtherFace = fromFace;
            }
            // second on the "other side of edge"
            fromFace = removedEdge2 == null
                ? null
                : removedEdge2.OwnedFace == removedFace2 ? removedEdge2.OtherFace : removedEdge2.OwnedFace;
            if (fromFace != null)
            {
                var index = fromFace.Edges.IndexOf(removedEdge2);
                if (index >= 0 && index < fromFace.Edges.Count)
                {
                    fromFace.Edges[index] = keepEdge2;
                }
            }
            if (keepEdge2 != null && keepEdge2.OwnedFace == removedFace2)
            {
                keepEdge2.OwnedFace = fromFace;
            }
            else if (keepEdge2 != null)
            {
                keepEdge2.OtherFace = fromFace;
            }
            keepVertex.Position = DetermineIntermediateVertexPosition(keepVertex, removedVertex);
            foreach (var e in keepVertex.Edges)
            {
                e.Update();
            }
            foreach (var f in keepVertex.Faces)
            {
                f.Update();
            }
            removedVertexOut = removedVertex;
            removedEdge1Out  = removedEdge1;
            removedEdge2Out  = removedEdge2;
            return(true);
        }