예제 #1
0
        private static Dictionary <SimpleEdge, List <FaceEdge> > BuildEdgeFacesDictionary(List <TriangleWrapper> triangleList)
        {
            var edgeFaces = new Dictionary <SimpleEdge, List <FaceEdge> >();

            foreach (var triangle in triangleList)
            {
                Vector3 center = triangle.Triangle.GetCenter();

                for (int i = 0; i < 3; i++)
                {
                    var simpleEdge = new SimpleEdge(triangle.TriangleEdges[i]);
                    var oppVert    = triangle.Vertices[(i + 2) % 3].Position;
                    if (!edgeFaces.ContainsKey(simpleEdge))
                    {
                        edgeFaces.Add(simpleEdge, new List <FaceEdge>());
                    }

                    var faceEdge = new FaceEdge(triangle.Triangle, triangle.TriangleEdges[i])
                    {
                        PerpVec  = Vector3.GetPerpendicular(simpleEdge.P1, simpleEdge.P2, center),
                        Altitude = Vector3.GetPerpendicularDistance(simpleEdge.P1, simpleEdge.P2, oppVert)
                    };
                    triangle.FaceEdges[i] = faceEdge;
                    edgeFaces[simpleEdge].Add(faceEdge);

                    triangle.Indices[i].RoundEdgeData.Reset();
                }
            }

            return(edgeFaces);
        }
예제 #2
0
 public EdgeLine(FaceEdge edge, Vector2 p1, Vector2 p2)
 {
     Edge = edge;
     P1   = p1;
     P2   = p2;
     //Equation = Maths.Line.FromPoints(p1, p2);
 }
예제 #3
0
 private void CreateRenderData(Mesh meshToBuildListFor, double nonPlanarAngleRequired = 0)
 {
     edgeLinesData = new VectorPOD <WireVertexData>();
     // first make sure all the textures are created
     foreach (MeshEdge meshEdge in meshToBuildListFor.MeshEdges)
     {
         if (nonPlanarAngleRequired > 0)
         {
             if (meshEdge.GetNumFacesSharingEdge() == 2)
             {
                 FaceEdge firstFaceEdge = meshEdge.firstFaceEdge;
                 FaceEdge nextFaceEdge  = meshEdge.firstFaceEdge.radialNextFaceEdge;
                 double   angle         = Vector3.CalculateAngle(firstFaceEdge.containingFace.normal, nextFaceEdge.containingFace.normal);
                 if (angle > MathHelper.Tau * .1)
                 {
                     edgeLinesData.Add(AddVertex(meshEdge.VertexOnEnd[0].Position, meshEdge.VertexOnEnd[1].Position));
                 }
             }
             else
             {
                 edgeLinesData.Add(AddVertex(meshEdge.VertexOnEnd[0].Position, meshEdge.VertexOnEnd[1].Position));
             }
         }
         else
         {
             edgeLinesData.Add(AddVertex(meshEdge.VertexOnEnd[0].Position, meshEdge.VertexOnEnd[1].Position));
         }
     }
 }
예제 #4
0
 /// <summary>
 /// Pivots the edge forward around its near face, such that it targets the next far face around the next vertex.
 /// </summary>
 /// <param name="edge">The edge to be pivoted.</param>
 public void PivotEdgeForward(FaceEdge edge)
 {
     if (!CanPivotEdgeForward(edge))
     {
         throw new InvalidOperationException("Cannot pivot a face edge backward when either its far face or next vertex has only two neighbors.");
     }
     PivotEdgeForwardUnchecked(edge);
 }
예제 #5
0
 /// <summary>
 /// Spins the edge forward, such that it faces toward the next far face around the next vertex, and it
 /// faces away from the next near face along the previous vertex.
 /// </summary>
 /// <param name="edge">The edge to spin.</param>
 /// <remarks><para>This is equivalent to pivoting both the specified edge and its twin.</para></remarks>
 public void SpinEdgeForward(FaceEdge edge)
 {
     if (!CanSpinEdgeForward(edge))
     {
         throw new InvalidOperationException("Cannot spin a face edge forward when either its far face or near face has only two neighbors.");
     }
     PivotEdgeForwardUnchecked(edge);
     PivotEdgeForwardUnchecked(edge.twin);
 }
예제 #6
0
 /// <summary>
 /// Checks if the local topology around the given edge allows it to spin forward one step.
 /// </summary>
 /// <param name="edge">The edge to spin.</param>
 /// <returns>True if the edge can spin forward one step, and false if it cannot.</returns>
 /// <remarks><para>Spinning a face edge forward will reduce the current near and far face neighbor counts by
 /// one.  Neither of those neighbor counts are allowed to drop below two, so if either of them are already two
 /// or less, the spin should be disallowed.  Additionally, if the previous or next vertex neighbor counts are
 /// two or less (that is, they are linear vertices), then the spin modification would break down, so these
 /// neighbor counts must also be greater than two or else the spin is disallowed.</para></remarks>
 public bool CanSpinEdgeForward(FaceEdge edge)
 {
     // After spinning, the edge's old near and far faces will both have their
     // neighbor counts reduced by one.  Neither of these counts can fall below 2.
     // The previous and next vertices must also have more than 2 neighbors, or
     // else things get really weird.
     // Note that all vertex neighbor counts will remain stable.
     return(edge.farFace.neighborCount > 2 && edge.nearFace.neighborCount > 2 && edge.prevVertex.neighborCount > 2 && edge.nextVertex.neighborCount > 2);
 }
예제 #7
0
 public bool Equals(FaceEdge other)
 {
     return((
                (other.P1.Equals(P1) && other.P2.Equals(P2)) ||
                (other.P1.Equals(P2) && other.P2.Equals(P1))
                ) &&
            other.EdgeNormal.Equals(EdgeNormal) &&
            other.FaceNormal.Equals(FaceNormal));
 }
예제 #8
0
        private void PivotEdgeForwardUnchecked(FaceEdge edge)
        {
            var innerEdgeIndex1 = edge.index;
            var outerEdgeIndex1 = edgeData[innerEdgeIndex1].twin;
            var twinEdgeIndex   = edgeData[outerEdgeIndex1].vNext;
            var edgeIndex       = edgeData[twinEdgeIndex].twin;

            PivotVertexEdgeForwardUnchecked(edgeIndex, twinEdgeIndex, outerEdgeIndex1, innerEdgeIndex1);
        }
예제 #9
0
            public EdgeLine ProjectEdge2D(FaceEdge edge)
            {
                var line = new EdgeLine(edge,
                                        FacePlane.ProjectPoint2D(PlaneAxisX, edge.P1),
                                        FacePlane.ProjectPoint2D(PlaneAxisX, edge.P2));

                line.Perpendicular = FacePlane.ProjectVector2D(PlaneAxisX, edge.PerpVec);
                return(line);
            }
예제 #10
0
            public float GetNormalDiff(FaceEdge other)
            {
                float angleDiff = Vector3.AngleBetween(EdgeNormal, other.EdgeNormal);

                if (angleDiff < 0)
                {
                    angleDiff = (((float)Math.PI * 2f) + angleDiff) % ((float)Math.PI * 2f);
                }
                return(angleDiff);
            }
예제 #11
0
            public TriangleWrapper(Triangle triangle)
            {
                Triangle    = triangle;
                Normal      = triangle.Normal;
                Center      = triangle.GetCenter();
                FacePlane   = new Plane(Center, Normal);
                FaceEdges   = new FaceEdge[3];
                PlanarEdges = new EdgeLine[3];

                PlaneAxisX = (Vertices[0].Position - Center).Normalized();
            }
예제 #12
0
        /// <summary>
        /// Computes face adjacency for the whole mesh and stores it in the appropriate dictionaries.
        /// </summary>
        public void ComputeFaceAdjacency()
        {
            foreach (MeshFace face in mesh.Faces)
            {
                foreach (MeshVertex adjacent in face.AdjacentVertices())
                {
                    if (!FaceVertex.ContainsKey(face.Index))
                    {
                        FaceVertex.Add(face.Index, new List <int>()
                        {
                            adjacent.Index
                        });
                    }
                    else
                    {
                        FaceVertex[face.Index].Add(adjacent.Index);
                    }
                }

                foreach (MeshFace adjacent in face.AdjacentFaces())
                {
                    if (!FaceFace.ContainsKey(face.Index))
                    {
                        FaceFace.Add(face.Index, new List <int>()
                        {
                            adjacent.Index
                        });
                    }
                    else
                    {
                        FaceFace[face.Index].Add(adjacent.Index);
                    }
                }

                foreach (MeshEdge adjacent in face.AdjacentEdges())
                {
                    if (!FaceEdge.ContainsKey(face.Index))
                    {
                        FaceEdge.Add(face.Index, new List <int>()
                        {
                            adjacent.Index
                        });
                    }
                    else
                    {
                        FaceEdge[face.Index].Add(adjacent.Index);
                    }
                }
            }
        }
        public void AddFaceEdge(HEMesh mesh, ref FaceEdge faceEdge)
        {
            faceEdge.edge = id;

            if (faceEdgeHead < 0)
            {
                faceEdgeHead      = faceEdge.id;
                faceEdgeTail      = faceEdge.id;
                faceEdge.adjacent = faceEdge.id;
            }
            else
            {
                ref var tail = ref mesh.m_faceEdges[faceEdgeTail];
                tail.adjacent     = faceEdge.id;
                faceEdgeTail      = faceEdge.id;
                faceEdge.adjacent = faceEdgeHead;
            }
예제 #14
0
        private static Vector2[] GetTexCoordsForEdge(TriangleWrapper triangle, FaceEdge edge)
        {
            Vector3 axisP1 = edge.P1;

            if (edge.IsContained(triangle.Triangle))
            {
                axisP1 = triangle.Triangle.Edges.First(x => edge.Edge == x).P1.Position;
            }
            else
            {
                axisP1 = triangle.Triangle.ContainsVertex(edge.P1) ? edge.P1 : edge.P2;
            }

            axisP1 = triangle.FacePlane.ProjectPoint(axisP1);

            var localPlane = new Plane(axisP1, triangle.Normal);


            Vector3 yAxis = localPlane.ProjectVector(edge.PerpVec); //Flatten perpendicular vector to 2D plane

            Vector2[] coords = new Vector2[3];

            for (int i = 0; i < 3; i++)
            {
                var pos = localPlane.ProjectPoint2D(yAxis, triangle.Vertices[i].Position);
                coords[i] = new Vector2(pos.Y, pos.X);
            }

            var minX = coords.Min(c => c.X);

            for (int i = 0; i < 3; i++)
            {
                coords[i].X -= minX;
            }

            return(coords);
        }
예제 #15
0
        private static Vector2[] ProjectTriangle(TriangleWrapper triangle, Vector3 planeOrigin, FaceEdge edge)
        {
            var planarPerp = triangle.FacePlane.ProjectVector(edge.PerpVec);

            return(ProjectTriangle(triangle, planeOrigin, planarPerp, true));
        }
예제 #16
0
            public bool IsColinear(FaceEdge other)
            {
                var similarDir = Direction.Equals(other.Direction, 0.001f) || Direction.Equals(other.Direction * -1f, 0.001f);

                return(similarDir && (Contains(other.P1) || Contains(other.P2)));
            }
예제 #17
0
 /// <summary>
 /// Checks if the local topology around the given edge allows it to be pivoted around its near face.
 /// </summary>
 /// <param name="edge">The edge to be pivoted.</param>
 /// <returns>True if the edge can be pivoted forward, and false if it cannot.</returns>
 /// <remarks><para>Pivoting a face edge forward will reduce the current far face neighbor count by
 /// one, and the next vertex neighbor count by one.  Neither of those neighbor counts are allowed to drop
 /// below two, so if either of them are already two or less, the pivot should be disallowed.</para></remarks>
 public bool CanPivotEdgeForward(FaceEdge edge)
 {
     // After pivoting, the edge's old far face and next vertex will both have their
     // neighbor counts reduced by one.  Neither of these counts can fall below 2.
     return(edge.farFace.neighborCount > 2 && edge.nextVertex.neighborCount > 2);
 }