public void RemoveFromMeshEdgeLinksOfVertex(IVertex vertexToRemoveFrom) { // lets first fix up the MeshEdge pointed to by the vertexToRemoveFrom if (vertexToRemoveFrom.FirstMeshEdge == this) { MeshEdge nextMeshEdgeConnectedToThisVertex = vertexToRemoveFrom.FirstMeshEdge.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); // if this is a radial loop if (nextMeshEdgeConnectedToThisVertex == vertexToRemoveFrom.FirstMeshEdge) { // the vertex is connected to no edges vertexToRemoveFrom.FirstMeshEdge = null; return; } else { // hook it up to the next connected mesh edge vertexToRemoveFrom.FirstMeshEdge = nextMeshEdgeConnectedToThisVertex; } } // now lets clean up the edge links on the mesh edges that are still connected to the vertexToRemoveFrom MeshEdge nextEdgeThisConnectedTo = GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); if (nextEdgeThisConnectedTo == this) { throw new Exception("You can't disconnect when you are the only mesh edge."); } MeshEdge edgeAfterEdgeWeAreConnectedTo = nextEdgeThisConnectedTo.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); if (edgeAfterEdgeWeAreConnectedTo == this) { // if only 2 edges (this and other) then set the other one to a circular reference to itself int indexOnEdgeWeAreConnectedTo = nextEdgeThisConnectedTo.GetVertexEndIndex(vertexToRemoveFrom); nextEdgeThisConnectedTo.NextMeshEdgeFromEnd[indexOnEdgeWeAreConnectedTo] = nextEdgeThisConnectedTo; } else { // we need to find the edge that has a reference to this one MeshEdge edgeConnectedToThis = edgeAfterEdgeWeAreConnectedTo; while (edgeConnectedToThis.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom) != this) { edgeConnectedToThis = edgeConnectedToThis.GetNextMeshEdgeConnectedTo(vertexToRemoveFrom); } int indexOfThisOnOther = edgeConnectedToThis.GetVertexEndIndex(vertexToRemoveFrom); edgeConnectedToThis.NextMeshEdgeFromEnd[indexOfThisOnOther] = nextEdgeThisConnectedTo; } // and set this one to null (it has no vertices) VertexOnEnd[GetVertexEndIndex(vertexToRemoveFrom)] = null; }
/// <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; }