Ejemplo n.º 1
0
 public bool IsValid(decimal epsilon = 0.5m)
 {
     return(!GetCoplanarFaces().Any() && // Check coplanar faces
            !GetBackwardsFaces(epsilon).Any() && // Check faces are pointing outwards
            !Faces.Any(x => x.GetNonPlanarVertices(epsilon).Any()) && // Check face vertices are all on the plane
            Faces.All(x => x.IsConvex()));   // Check all faces are convex
 }
Ejemplo n.º 2
0
 public bool IsRectangularPrism()
 {
     return(Faces.Count == 6 &&
            Edges.Count == 12 &&
            Vertices.Count == 8 &&
            Faces.All(face => face.IsRectangle()));
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Determines whether the mesh is a valid triangle mesh.
        /// </summary>
        /// <returns>
        /// <see langword="true"/> if the mesh is a valid triangle mesh; otherwise,
        /// <see langword="false"/>.
        /// </returns>
        /// <remarks>
        /// <para>
        /// This method checks if the mesh consists only of triangle faces without edges or vertices
        /// that are not connected to a face.
        /// </para>
        /// <para>
        /// This method does not check whether the mesh <see cref="IsValid()"/>.
        /// </para>
        /// </remarks>
        public bool IsTriangleMesh()
        {
            if (Vertices.Count > 0 && Faces.Count == 0)
            {
                return(false);
            }

            return(Faces.All(f => f.Holes == null) &&       // No holes allowed.
                   Edges.All(e => e.Face == null ||
                             e.Next != null &&              // Face boundary consists of exactly 3 edges.
                             e.Next.Next == e.Previous &&
                             e.Next != e.Previous));
        }
Ejemplo n.º 4
0
        public override void Transform(Transformations.IUnitTransformation transform, TransformFlags flags)
        {
            Faces.ForEach(f => f.Transform(transform, flags));

            // Handle flip transforms / negative scales
            var origin = GetOrigin();

            if (Faces.All(x => x.Plane.OnPlane(origin) >= 0))
            {
                // All planes are facing inwards - flip them all
                Faces.ForEach(x => x.Flip());
            }

            base.Transform(transform, flags);
        }
Ejemplo n.º 5
0
        // TODO: ORDER the resulting vertices (clockwise)!
        private void InitializeVertices()
        {
            if (Faces.All(face => face.Vertices.Count > 0))
            {
                return;
            }

            foreach (var face in Faces)
            {
                face.Vertices.Clear();
            }

            // TODO: This is probably O(n^3) or so!
            //       Would it be more efficient to, for each face, use all other faces to cut it down to a polygon?
            //       That would be O(n^2) I think??
            for (int i = 0; i < Faces.Count; i++)
            {
                for (int j = i + 1; j < Faces.Count; j++)
                {
                    for (int k = j + 1; k < Faces.Count; k++)
                    {
                        var face1 = Faces[i];
                        var face2 = Faces[j];
                        var face3 = Faces[k];
                        if (Plane.IntersectionPoint(face1.Plane, face2.Plane, face3.Plane) is Vector3D point &&
                            this.Contains(point, epsilon: 1f))  // TODO: Figure out what a reasonable epsilon is, and whether this can cause any problems... (a 0 epsilon will sometimes omit vertices!)
                        {
                            // TODO: Look into ORDERING these vertices (CCW or CW) -- it matters for some use-cases!
                            if (!face1.Vertices.Contains(point))
                            {
                                face1.Vertices.Add(point);
                            }
                            if (!face2.Vertices.Contains(point))
                            {
                                face2.Vertices.Add(point);
                            }
                            if (!face3.Vertices.Contains(point))
                            {
                                face3.Vertices.Add(point);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Determines whether this mesh is a closed mesh.
        /// </summary>
        /// <returns>
        /// <see langword="true"/> if this instance is a closed mesh; otherwise, <see langword="false"/>.
        /// </returns>
        /// <remarks>
        /// <para>
        /// In a closed mesh all edges are connected to 2 faces. For example: The mesh of a sphere is a
        /// closed mesh. An object with holes, like a pullover, is not closed. A flat object, like a
        /// curtain, is closed if both sides are modeled with faces. It is not closed if only a one side
        /// is modeled with faces. (A single vertex is considered as closed. A single edge-pair is also
        /// considered as closed.)
        /// </para>
        /// <para>
        /// This method does not check whether the mesh <see cref="IsValid()"/>.
        /// </para>
        /// </remarks>
        public bool IsClosed()
        {
            // Empty mesh is not closed.
            if (Vertex == null)
            {
                return(false);
            }

            // A single edge-pair is closed.
            if (Faces.Count == 0 && Edges.Count <= 2)
            {
                return(true);
            }

            return(Faces.All(f => f.Holes == null) &&   // No holes allowed.
                   Edges.All(e => e.Face != null &&     // Faces on both sides of the edge.
                             e.Twin != null &&
                             e.Twin.Face != null));
        }
Ejemplo n.º 7
0
        public override void Transform(Transformations.IUnitTransformation transform, TransformFlags flags)
        {
            Coordinate newStart = transform.Transform(BoundingBox.Start);
            Coordinate newEnd   = transform.Transform(BoundingBox.End);

            if ((newStart - newEnd).VectorMagnitude() > 1000000m)
            {
                return;
            }

            Faces.ForEach(f => f.Transform(transform, flags));

            // Handle flip transforms / negative scales
            var origin = GetOrigin();

            if (Faces.All(x => x.Plane.OnPlane(origin) >= 0))
            {
                // All planes are facing inwards - flip them all
                Faces.ForEach(x => x.Flip());
            }

            base.Transform(transform, flags);
        }
Ejemplo n.º 8
0
        // TODO: Add error messages to IsXxx method, so that users see where the problem is.

        /// <summary>
        /// Gets a value indicating whether the tags of all components in the mesh are equal to the
        /// given tag value.
        /// </summary>
        /// <param name="tag">The reference tag value.</param>
        /// <returns>
        /// <see langword="true"/> if the tags of all components are equal to <paramref name="tag"/>;
        /// otherwise, <see langword="false"/>.
        /// </returns>
        public bool AreTagsEqualTo(int tag)
        {
            return(Vertices.All(vertex => vertex.Tag == tag) &&
                   Edges.All(edge => edge.Tag == tag) &&
                   Faces.All(face => face.Tag == tag));
        }