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); }
public EdgeLine(FaceEdge edge, Vector2 p1, Vector2 p2) { Edge = edge; P1 = p1; P2 = p2; //Equation = Maths.Line.FromPoints(p1, p2); }
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)); } } }
/// <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); }
/// <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); }
/// <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); }
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)); }
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); }
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); }
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); }
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(); }
/// <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; }
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); }
private static Vector2[] ProjectTriangle(TriangleWrapper triangle, Vector3 planeOrigin, FaceEdge edge) { var planarPerp = triangle.FacePlane.ProjectVector(edge.PerpVec); return(ProjectTriangle(triangle, planeOrigin, planarPerp, true)); }
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))); }
/// <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); }