public void SplitMeshEdge(MeshEdge meshEdgeToSplit, out Vertex vertexCreatedDuringSplit, out MeshEdge meshEdgeCreatedDuringSplit) { // create our new Vertex and MeshEdge { // make a new vertex between the existing ones // TODO: make this create an interpolated vertex, check if it exits and add it or use the right one. //vertexCreatedDuringSplit = meshEdgeToSplit.edgeEndVertex[0].CreateInterpolated(meshEdgeToSplit.edgeEndVertex[1], .5); vertexCreatedDuringSplit = CreateVertex((meshEdgeToSplit.VertexOnEnd[0].Position + meshEdgeToSplit.VertexOnEnd[1].Position) / 2); // TODO: check if the mesh edge exits and use the existing one (or not) meshEdgeCreatedDuringSplit = new MeshEdge(); } // Set the new firstMeshEdge on the new Vertex vertexCreatedDuringSplit.firstMeshEdge = meshEdgeCreatedDuringSplit; Vertex existingVertexToConectTo = meshEdgeToSplit.VertexOnEnd[1]; // fix the Vertex references on the MeshEdges { // and set the edges to point to this new one meshEdgeCreatedDuringSplit.VertexOnEnd[0] = vertexCreatedDuringSplit; meshEdgeCreatedDuringSplit.VertexOnEnd[1] = existingVertexToConectTo; meshEdgeToSplit.VertexOnEnd[1] = vertexCreatedDuringSplit; } // fix the MeshEdgeLinks on the MeshEdges { // set the created edge to be connected to the old edges other mesh edges meshEdgeCreatedDuringSplit.NextMeshEdgeFromEnd[0] = meshEdgeToSplit; // make anything that pointed to the split edge point to the new mesh edge meshEdgeToSplit.NextMeshEdgeFromEnd[1] = meshEdgeCreatedDuringSplit; } // if the MeshEdge is part of a face than we have to fix the face up FaceEdge faceEdgeToSplit = meshEdgeToSplit.firstFaceEdge; if (faceEdgeToSplit != null) { foreach (FaceEdge faceEdge in meshEdgeToSplit.FaceEdgesSharingMeshEdge()) { Face currentFace = faceEdge.containingFace; FaceEdge newFaceEdge = new FaceEdge(currentFace, meshEdgeCreatedDuringSplit, vertexCreatedDuringSplit); newFaceEdge.AddToRadialLoop(meshEdgeCreatedDuringSplit); // and inject it into the face loop for this face newFaceEdge.prevFaceEdge = faceEdge; newFaceEdge.nextFaceEdge = faceEdge.nextFaceEdge; faceEdge.nextFaceEdge.prevFaceEdge = newFaceEdge; faceEdge.nextFaceEdge = newFaceEdge; } } }
/// <summary> /// Unsplit (merge) the edgeToJoin and the edge that it is connected to through vertexToDelete. /// Only unsplit the edge if we are reversing what would have been a split (a single vertex connecting only two edges). /// </summary> /// <param name="edgeToJoin"></param> /// <param name="vertexToDelete"></param> /// <returns></returns> public void UnsplitMeshEdge(MeshEdge edgeToJoin, Vertex vertexToDelete) { int endToJoinIndex = edgeToJoin.GetVertexEndIndex(vertexToDelete); MeshEdge edgeToDelete = edgeToJoin.GetNextMeshEdgeConnectedTo(vertexToDelete); if (edgeToDelete.GetNextMeshEdgeConnectedTo(vertexToDelete) != edgeToJoin) { // make sure the edgeToJoin is a valid unsplit (only one connection) throw new Exception("The edge that is being unsplit must be connected to only one other MeshEdge across the vertexToDelete."); } int otherEndOfEdgeToDelete = edgeToDelete.GetOpositeVertexEndIndex(vertexToDelete); MeshEdge edgeToJoinTo = edgeToDelete.NextMeshEdgeFromEnd[otherEndOfEdgeToDelete]; // if the MeshEdge is part of any faces than we have to fix the faces. if (edgeToJoin.firstFaceEdge != null) { // The edge we split was part of one or more faces, we need to fix the FaceEdge loops foreach (FaceEdge faceEdge in edgeToJoin.FaceEdgesSharingMeshEdge()) { FaceEdge faceEdgeToDelete = null; if (faceEdge.nextFaceEdge.meshEdge == edgeToDelete) { faceEdgeToDelete = faceEdge.nextFaceEdge; FaceEdge newNextFaceEdge = faceEdgeToDelete.nextFaceEdge; newNextFaceEdge.prevFaceEdge = faceEdge; faceEdge.nextFaceEdge = newNextFaceEdge; } else if (faceEdge.prevFaceEdge.meshEdge == edgeToDelete) { faceEdgeToDelete = faceEdge.prevFaceEdge; FaceEdge newPrevFaceEdge = faceEdgeToDelete.prevFaceEdge; newPrevFaceEdge.nextFaceEdge = faceEdge; faceEdge.prevFaceEdge = newPrevFaceEdge; } else { throw new Exception("Either the next or prev edge must be the same as the edge to delete."); } // if the FaceEdge we are deleting is the one that the face was using as its firstFaceEdge, change it. if (faceEdge.containingFace.firstFaceEdge == faceEdgeToDelete) { faceEdge.containingFace.firstFaceEdge = faceEdge; } // and clear out the FaceEdge we are deleting to help debugging and other references to it. faceEdgeToDelete.nextFaceEdge = null; faceEdgeToDelete.prevFaceEdge = null; faceEdgeToDelete.radialNextFaceEdge = null; faceEdgeToDelete.radialPrevFaceEdge = null; faceEdgeToDelete.meshEdge = null; faceEdgeToDelete.containingFace = null; faceEdgeToDelete.firstVertex = null; } } // fix the MeshEdgeLinks on the edgeToJoin { edgeToJoin.VertexOnEnd[endToJoinIndex] = edgeToDelete.VertexOnEnd[otherEndOfEdgeToDelete]; edgeToJoin.NextMeshEdgeFromEnd[endToJoinIndex] = edgeToDelete.NextMeshEdgeFromEnd[otherEndOfEdgeToDelete]; } // Clear all the data on the deleted vertex and edge so we have less code that will work if it continues to use them. vertexToDelete.firstMeshEdge = null; edgeToDelete.firstFaceEdge = null; edgeToDelete.VertexOnEnd[0] = null; edgeToDelete.NextMeshEdgeFromEnd[0] = null; edgeToDelete.VertexOnEnd[1] = null; edgeToDelete.NextMeshEdgeFromEnd[1] = null; }