diff --git a/libs/MeshKernel/include/MeshKernel/CasulliRefinement.hpp b/libs/MeshKernel/include/MeshKernel/CasulliRefinement.hpp index 8214699c3..428848ab7 100644 --- a/libs/MeshKernel/include/MeshKernel/CasulliRefinement.hpp +++ b/libs/MeshKernel/include/MeshKernel/CasulliRefinement.hpp @@ -28,6 +28,7 @@ #pragma once #include +#include #include #include "MeshKernel/Mesh2D.hpp" @@ -104,14 +105,14 @@ namespace meshkernel /// @param [in, out] mesh The Mesh /// @param [in, out] newNodes List of new nodes and connectivity /// @param [in, out] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr ComputeNewNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask); + static void ComputeNewNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask); /// @brief Connect newly generated nodes /// /// @param [in, out] mesh The mesh being refined /// @param [in] newNodes List of new nodes and connectivity /// @param [in] numEdges Number of edges in original mesh, before refinement. - [[nodiscard]] static std::unique_ptr ConnectNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numEdges); + static void ConnectNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numEdges); /// @brief Compute new edges required for refinement /// @@ -119,14 +120,14 @@ namespace meshkernel /// @param [in] numNodes Number of nodes in original mesh, before refinement. /// @param [in] newNodes List of new nodes and connectivity /// @param [in, out] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr CreateMissingBoundaryEdges(Mesh2D& mesh, const UInt numNodes, const std::vector& newNodes, std::vector& nodeMask); + static void CreateMissingBoundaryEdges(Mesh2D& mesh, const UInt numNodes, const std::vector& newNodes, std::vector& nodeMask); /// @brief Compute new nodes on faces /// /// @param [in, out] mesh The mesh being refined /// @param [in, out] newNodes List of new nodes and connectivity /// @param [in, out] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr ComputeNewFaceNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask); + static void ComputeNewFaceNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask); /// @brief Compute new nodes on edges /// @@ -134,7 +135,7 @@ namespace meshkernel /// @param [in] numEdges Number of edges in original mesh, before refinement. /// @param [in, out] newNodes List of new nodes and connectivity /// @param [in, out] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr ComputeNewEdgeNodes(Mesh2D& mesh, const UInt numEdges, std::vector& newNodes, std::vector& nodeMask); + static void ComputeNewEdgeNodes(Mesh2D& mesh, const UInt numEdges, std::vector& newNodes, std::vector& nodeMask); /// @brief Connect edges /// @@ -143,11 +144,11 @@ namespace meshkernel /// @param [in] newNodes List of new nodes and connectivity /// @param [out] edgeCount Number of edges created /// @param [in, out] newEdges Identifiers of edges created - [[nodiscard]] static std::unique_ptr ConnectEdges(Mesh2D& mesh, - const UInt currentNode, - const std::vector& newNodes, - UInt& edgeCount, - std::vector& newEdges); + static void ConnectEdges(Mesh2D& mesh, + const UInt currentNode, + const std::vector& newNodes, + UInt& edgeCount, + std::vector& newEdges); /// @brief Connect face node /// @@ -155,10 +156,10 @@ namespace meshkernel /// @param [in] currentFace The face being connected /// @param [in, out] newNodes List of new nodes and connectivity /// @param [in, out] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr ConnectFaceNodes(Mesh2D& mesh, - const UInt currentFace, - const std::vector& newNodes, - std::vector& nodeMask); + static void ConnectFaceNodes(Mesh2D& mesh, + const UInt currentFace, + const std::vector& newNodes, + std::vector& nodeMask); /// @brief Connect newly generated nodes /// @@ -168,7 +169,7 @@ namespace meshkernel /// @param [in] numEdges Number of edges in original mesh, before refinement. /// @param [in] numFaces Number of faces in original mesh, before refinement. /// @param [in, out] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr ConnectNewNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numNodes, const UInt numEdges, const UInt numFaces, std::vector& nodeMask); + static void ConnectNewNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numNodes, const UInt numEdges, const UInt numFaces, std::vector& nodeMask); /// @brief Add newly generated nodes to the newNodes list. /// @@ -198,7 +199,7 @@ namespace meshkernel /// @param [in, out] mesh The mesh /// @param [in] numNodes The original number of nodes in the mesh /// @param [in] nodeMask Node mask information - [[nodiscard]] static std::unique_ptr Administrate(Mesh2D& mesh, const UInt numNodes, const std::vector& nodeMask); + static void Administrate(Mesh2D& mesh, const UInt numNodes, const std::vector& nodeMask); }; } // namespace meshkernel diff --git a/libs/MeshKernel/include/MeshKernel/Mesh.hpp b/libs/MeshKernel/include/MeshKernel/Mesh.hpp index e9a5636b9..edcdc45b8 100644 --- a/libs/MeshKernel/include/MeshKernel/Mesh.hpp +++ b/libs/MeshKernel/include/MeshKernel/Mesh.hpp @@ -244,13 +244,15 @@ namespace meshkernel /// If the nodes are not connected a new edge is formed, otherwise UInt invalid value is returned. (connectdbn) /// @param[in] startNode The start node index /// @param[in] endNode The end node index + /// @param[in] collectUndo Indicate whether or not an undo action should be created, if false then the undo result will be nullptr /// @return The index of the new edge and the undoAction to connect two nodes - [[nodiscard]] std::tuple> ConnectNodes(UInt startNode, UInt endNode); + [[nodiscard]] std::tuple> ConnectNodes(UInt startNode, UInt endNode, const bool collectUndo = true); /// @brief Deletes a node and removes any connected edges /// @param[in] node The node index + /// @param[in] collectUndo Indicate whether or not an undo action should be created, if false then the undo result will be nullptr. /// @return The undoAction to delete the node and any connecting edges - [[nodiscard]] std::unique_ptr DeleteNode(UInt node); + [[nodiscard]] std::unique_ptr DeleteNode(UInt node, const bool collectUndo = true); /// @brief Find the edge sharing two nodes /// @param[in] firstNodeIndex The index of the first node @@ -288,8 +290,9 @@ namespace meshkernel /// @brief Deletes an edge /// @param[in] edge The edge index + /// @param[in] collectUndo Indicate whether or not an undo action should be created, if false then the undo result will be nullptr. /// @return The undoAction to delete the edge - [[nodiscard]] std::unique_ptr DeleteEdge(UInt edge); + [[nodiscard]] std::unique_ptr DeleteEdge(UInt edge, const bool collectUndo = true); /// @brief Find the common node two edges share /// This method uses return parameters since the success is evaluated in a hot loop diff --git a/libs/MeshKernel/src/CasulliRefinement.cpp b/libs/MeshKernel/src/CasulliRefinement.cpp index ccace28f3..ae1e1242a 100644 --- a/libs/MeshKernel/src/CasulliRefinement.cpp +++ b/libs/MeshKernel/src/CasulliRefinement.cpp @@ -26,11 +26,11 @@ //------------------------------------------------------------------------------ #include +#include #include "MeshKernel/CasulliRefinement.hpp" #include "MeshKernel/Exceptions.hpp" -#include "MeshKernel/UndoActions/AddNodeAction.hpp" -#include "MeshKernel/UndoActions/CompoundUndoAction.hpp" +#include "MeshKernel/UndoActions/FullUnstructuredGridUndo.hpp" std::unique_ptr meshkernel::CasulliRefinement::Compute(Mesh2D& mesh) { @@ -42,15 +42,16 @@ std::unique_ptr meshkernel::CasulliRefinement::Compute(M { std::vector newNodes(mesh.GetNumEdges(), {constants::missing::uintValue, constants::missing::uintValue, constants::missing::uintValue, constants::missing::uintValue}); std::vector nodeMask(InitialiseNodeMask(mesh, polygon)); - std::unique_ptr refinementAction = CompoundUndoAction::Create(); + + std::unique_ptr refinementAction = FullUnstructuredGridUndo::Create(mesh); const UInt numNodes = mesh.GetNumNodes(); const UInt numEdges = mesh.GetNumEdges(); const UInt numFaces = mesh.GetNumFaces(); - refinementAction->Add(ComputeNewNodes(mesh, newNodes, nodeMask)); - refinementAction->Add(ConnectNewNodes(mesh, newNodes, numNodes, numEdges, numFaces, nodeMask)); - refinementAction->Add(Administrate(mesh, numNodes, nodeMask)); + ComputeNewNodes(mesh, newNodes, nodeMask); + ConnectNewNodes(mesh, newNodes, numNodes, numEdges, numFaces, nodeMask); + Administrate(mesh, numNodes, nodeMask); return refinementAction; } @@ -203,22 +204,19 @@ std::vector meshkernel::CasulliRefineme return nodeMask; } -std::unique_ptr meshkernel::CasulliRefinement::Administrate(Mesh2D& mesh, const UInt numNodes, const std::vector& nodeMask) +void meshkernel::CasulliRefinement::Administrate(Mesh2D& mesh, const UInt numNodes, const std::vector& nodeMask) { - - std::unique_ptr administrateAction = CompoundUndoAction::Create(); - // Need check only the original nodes in the mesh, hence use of numNodes. for (UInt i = 0; i < numNodes; ++i) { if (nodeMask[i] > NodeMask::Unassigned && nodeMask[i] < NodeMask::CornerNode) { - administrateAction->Add(mesh.DeleteNode(i)); + // With passing false for the collectUndo, DeleteNode should return a null pointer + [[maybe_unused]] auto undoAction = mesh.DeleteNode(i, false /* collectUndo info */); } } - mesh.Administrate(administrateAction.get()); - return administrateAction; + mesh.Administrate(); } void meshkernel::CasulliRefinement::FindPatchIds(const Mesh2D& mesh, @@ -253,10 +251,8 @@ void meshkernel::CasulliRefinement::FindPatchIds(const Mesh2D& mesh, mesh.FindNodesSharedByFaces(currentNode, sharedFaces, connectedNodes, faceNodeMapping); } -std::unique_ptr meshkernel::CasulliRefinement::ConnectNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numEdges) +void meshkernel::CasulliRefinement::ConnectNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numEdges) { - std::unique_ptr connectNodeAction = CompoundUndoAction::Create(); - // make the original-edge based new edges for (UInt i = 0; i < numEdges; ++i) { @@ -268,37 +264,31 @@ std::unique_ptr meshkernel::CasulliRefinement::ConnectNo // Parallel edges, these are the start-end connections if (node1 != constants::missing::uintValue && node2 != constants::missing::uintValue && node1 != node2) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(node1, node2); - connectNodeAction->Add(std::move(connectionAction)); + // With passing false for the collectUndo, ConnectNodes should return a null pointer + [[maybe_unused]] auto ignore = mesh.ConnectNodes(node1, node2, false /* collectUndo info */); } if (node3 != constants::missing::uintValue && node4 != constants::missing::uintValue && node3 != node4) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(node3, node4); - connectNodeAction->Add(std::move(connectionAction)); + [[maybe_unused]] auto ignore = mesh.ConnectNodes(node3, node4, false /* collectUndo info */); } // normal edges, these are the left-right connections if (node1 != constants::missing::uintValue && node3 != constants::missing::uintValue && node1 != node3) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(node1, node3); - connectNodeAction->Add(std::move(connectionAction)); + [[maybe_unused]] auto ignore = mesh.ConnectNodes(node1, node3, false /* collectUndo info */); } if (node2 != constants::missing::uintValue && node4 != constants::missing::uintValue && node2 != node4) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(node2, node4); - connectNodeAction->Add(std::move(connectionAction)); + [[maybe_unused]] auto ignore = mesh.ConnectNodes(node2, node4, false /* collectUndo info */); } } - - return connectNodeAction; } -std::unique_ptr meshkernel::CasulliRefinement::ConnectFaceNodes(Mesh2D& mesh, const UInt currentFace, const std::vector& newNodes, - std::vector& nodeMask) +void meshkernel::CasulliRefinement::ConnectFaceNodes(Mesh2D& mesh, const UInt currentFace, const std::vector& newNodes, + std::vector& nodeMask) { - std::unique_ptr connectFacesAction = CompoundUndoAction::Create(); // Perhaps change quads to maximum number of edges for any shape std::array oldIndex{constants::missing::uintValue, constants::missing::uintValue, @@ -351,35 +341,30 @@ std::unique_ptr meshkernel::CasulliRefinement::ConnectFa // only one new node: new diagonal edge connects new node with one old node if (nodeMask[node1] < NodeMask::Unassigned && nodeMask[node2] == NodeMask::Unassigned && nodeMask[node3] == NodeMask::Unassigned && nodeMask[node4] == NodeMask::Unassigned) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(node1, node4); - connectFacesAction->Add(std::move(connectionAction)); + // With passing false for the collectUndo, ConnectNodes should return a null pointer + [[maybe_unused]] auto ignore = mesh.ConnectNodes(node1, node4, false /* collectUndo info */); break; } // only one old node: new diagonal edge connects new nodes only (i.e. perpendicular to previous one) if (nodeMask[node1] < NodeMask::Unassigned && nodeMask[node2] > NodeMask::Unassigned && nodeMask[node3] > NodeMask::Unassigned && nodeMask[node4] == NodeMask::Unassigned) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(newIndex[previousIndex], newIndex[nextIndex]); - connectFacesAction->Add(std::move(connectionAction)); + [[maybe_unused]] auto ignore = mesh.ConnectNodes(newIndex[previousIndex], newIndex[nextIndex], false /* collectUndo info */); break; } // two new and opposing nodes: new diagonal edge connects the new nodes if (nodeMask[node1] < NodeMask::Unassigned && nodeMask[node2] == NodeMask::Unassigned && nodeMask[node3] == NodeMask::Unassigned && nodeMask[node4] == NodeMask::RegisteredNode) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(node1, newIndex[nextNextIndex]); - connectFacesAction->Add(std::move(connectionAction)); + [[maybe_unused]] auto ignore = mesh.ConnectNodes(node1, newIndex[nextNextIndex], false /* collectUndo info */); break; } } - - return connectFacesAction; } -std::unique_ptr meshkernel::CasulliRefinement::ConnectEdges(Mesh2D& mesh, const UInt currentNode, const std::vector& newNodes, UInt& edgeCount, std::vector& newEdges) +void meshkernel::CasulliRefinement::ConnectEdges(Mesh2D& mesh, const UInt currentNode, const std::vector& newNodes, UInt& edgeCount, std::vector& newEdges) { - std::unique_ptr connectEdgesAction = CompoundUndoAction::Create(); - std::fill(newEdges.begin(), newEdges.end(), constants::missing::uintValue); + std::ranges::fill(newEdges, constants::missing::uintValue); edgeCount = 0; for (UInt j = 0; j < mesh.m_nodesNumEdges[currentNode]; ++j) @@ -400,29 +385,21 @@ std::unique_ptr meshkernel::CasulliRefinement::ConnectEd { if (mesh.GetEdge(edgeId).first == currentNode) { - auto [edgeId1, connectionAction1] = mesh.ConnectNodes(currentNode, newNodes[edgeId][0]); - connectEdgesAction->Add(std::move(connectionAction1)); - - auto [edgeId2, connectionAction2] = mesh.ConnectNodes(currentNode, newNodes[edgeId][2]); - connectEdgesAction->Add(std::move(connectionAction2)); + // With passing false for the collectUndo, ConnectNodes should return a null pointer + [[maybe_unused]] auto ignore1 = mesh.ConnectNodes(currentNode, newNodes[edgeId][0], false /* collectUndo info */); + [[maybe_unused]] auto ignore2 = mesh.ConnectNodes(currentNode, newNodes[edgeId][2], false /* collectUndo info */); } else { - auto [edgeId1, connectionAction1] = mesh.ConnectNodes(currentNode, newNodes[edgeId][1]); - connectEdgesAction->Add(std::move(connectionAction1)); - - auto [edgeId2, connectionAction2] = mesh.ConnectNodes(currentNode, newNodes[edgeId][3]); - connectEdgesAction->Add(std::move(connectionAction2)); + [[maybe_unused]] auto ignore1 = mesh.ConnectNodes(currentNode, newNodes[edgeId][1], false /* collectUndo info */); + [[maybe_unused]] auto ignore2 = mesh.ConnectNodes(currentNode, newNodes[edgeId][3], false /* collectUndo info */); } } } - - return connectEdgesAction; } -std::unique_ptr meshkernel::CasulliRefinement::CreateMissingBoundaryEdges(Mesh2D& mesh, const UInt numNodes, const std::vector& newNodes, std::vector& nodeMask) +void meshkernel::CasulliRefinement::CreateMissingBoundaryEdges(Mesh2D& mesh, const UInt numNodes, const std::vector& newNodes, std::vector& nodeMask) { - std::unique_ptr missingBoundariesAction = CompoundUndoAction::Create(); std::vector newEdges(InitialEdgeArraySize); // make the missing boundary edges @@ -435,7 +412,7 @@ std::unique_ptr meshkernel::CasulliRefinement::CreateMis } UInt edgeCount = 0; - missingBoundariesAction->Add(ConnectEdges(mesh, i, newNodes, edgeCount, newEdges)); + ConnectEdges(mesh, i, newNodes, edgeCount, newEdges); if (edgeCount == 0) { @@ -477,8 +454,8 @@ std::unique_ptr meshkernel::CasulliRefinement::CreateMis { if (nodesToConnect[0] != constants::missing::uintValue && nodesToConnect[1] != constants::missing::uintValue && nodesToConnect[0] != nodesToConnect[1]) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(nodesToConnect[0], nodesToConnect[1]); - missingBoundariesAction->Add(std::move(connectionAction)); + // With passing false for the collectUndo, ConnectNodes should return a null pointer + [[maybe_unused]] auto ignore = mesh.ConnectNodes(nodesToConnect[0], nodesToConnect[1], false /* collectUndo info */); } } } @@ -488,21 +465,16 @@ std::unique_ptr meshkernel::CasulliRefinement::CreateMis { if (nodesToConnect[j] != constants::missing::uintValue && nodesToConnect[j] != i) { - auto [edgeId, connectionAction] = mesh.ConnectNodes(i, nodesToConnect[j]); - missingBoundariesAction->Add(std::move(connectionAction)); + [[maybe_unused]] auto ignore = mesh.ConnectNodes(i, nodesToConnect[j], false /* collectUndo info */); } } } } - - return missingBoundariesAction; } -std::unique_ptr meshkernel::CasulliRefinement::ConnectNewNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numNodes, const UInt numEdges, const UInt numFaces, std::vector& nodeMask) +void meshkernel::CasulliRefinement::ConnectNewNodes(Mesh2D& mesh, const std::vector& newNodes, const UInt numNodes, const UInt numEdges, const UInt numFaces, std::vector& nodeMask) { - std::unique_ptr connectNodesAction = CompoundUndoAction::Create(); - - connectNodesAction->Add(ConnectNodes(mesh, newNodes, numEdges)); + ConnectNodes(mesh, newNodes, numEdges); // create the diagonal edges in quads that connect the new mesh with the old mesh for (UInt i = 0; i < numFaces; ++i) @@ -527,11 +499,11 @@ std::unique_ptr meshkernel::CasulliRefinement::ConnectNe // Check for active nodes if (faceIsActive) { - connectNodesAction->Add(ConnectFaceNodes(mesh, i, newNodes, nodeMask)); + ConnectFaceNodes(mesh, i, newNodes, nodeMask); } } - connectNodesAction->Add(CreateMissingBoundaryEdges(mesh, numNodes, newNodes, nodeMask)); + CreateMissingBoundaryEdges(mesh, numNodes, newNodes, nodeMask); for (UInt i = 0; i < numNodes; ++i) { @@ -546,30 +518,21 @@ std::unique_ptr meshkernel::CasulliRefinement::ConnectNe if (mesh.GetEdge(edgeId).first == i) { - auto [edgeId1, connectionAction1] = mesh.ConnectNodes(i, newNodes[edgeId][0]); - connectNodesAction->Add(std::move(connectionAction1)); - - auto [edgeId2, connectionAction2] = mesh.ConnectNodes(i, newNodes[edgeId][2]); - connectNodesAction->Add(std::move(connectionAction2)); + // With passing false for the collectUndo, ConnectNodes should return a null pointer + [[maybe_unused]] auto ignore1 = mesh.ConnectNodes(i, newNodes[edgeId][0], false /* collectUndo info */); + [[maybe_unused]] auto ignore2 = mesh.ConnectNodes(i, newNodes[edgeId][2], false /* collectUndo info */); } else { - auto [edgeId1, connectionAction1] = mesh.ConnectNodes(i, newNodes[edgeId][1]); - connectNodesAction->Add(std::move(connectionAction1)); - - auto [edgeId2, connectionAction2] = mesh.ConnectNodes(i, newNodes[edgeId][3]); - connectNodesAction->Add(std::move(connectionAction2)); + [[maybe_unused]] auto ignore1 = mesh.ConnectNodes(i, newNodes[edgeId][1], false /* collectUndo info */); + [[maybe_unused]] auto ignore2 = mesh.ConnectNodes(i, newNodes[edgeId][3], false /* collectUndo info */); } } } - - return connectNodesAction; } -std::unique_ptr meshkernel::CasulliRefinement::ComputeNewFaceNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask) +void meshkernel::CasulliRefinement::ComputeNewFaceNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask) { - std::unique_ptr newFacesAction = CompoundUndoAction::Create(); - for (UInt i = 0; i < mesh.GetNumFaces(); ++i) { const Point elementCentre = mesh.m_facesCircumcenters[i]; @@ -612,7 +575,6 @@ std::unique_ptr meshkernel::CasulliRefinement::ComputeNe Point newNode = 0.5 * (elementCentre + mesh.Node(elementNode)); std::tie(newNodeId, nodeInsertionAction) = mesh.InsertNode(newNode); - newFacesAction->Add(std::move(nodeInsertionAction)); nodeMask[newNodeId] = NodeMask::NewAssignedNode; } @@ -624,13 +586,10 @@ std::unique_ptr meshkernel::CasulliRefinement::ComputeNe StoreNewNode(mesh, elementNode, firstEdgeId, secondEdgeId, newNodeId, newNodes); } } - - return newFacesAction; } -std::unique_ptr meshkernel::CasulliRefinement::ComputeNewEdgeNodes(Mesh2D& mesh, const UInt numEdges, std::vector& newNodes, std::vector& nodeMask) +void meshkernel::CasulliRefinement::ComputeNewEdgeNodes(Mesh2D& mesh, const UInt numEdges, std::vector& newNodes, std::vector& nodeMask) { - std::unique_ptr newEdgeNodesAction = CompoundUndoAction::Create(); for (UInt i = 0; i < numEdges; ++i) { @@ -657,7 +616,6 @@ std::unique_ptr meshkernel::CasulliRefinement::ComputeNe const Point newNode = 0.5 * (edgeCentre + mesh.Node(node1)); std::tie(newNodeId, nodeInsertionAction) = mesh.InsertNode(newNode); - newEdgeNodesAction->Add(std::move(nodeInsertionAction)); nodeMask[newNodeId] = NodeMask::NewGeneralNode; } else @@ -672,7 +630,6 @@ std::unique_ptr meshkernel::CasulliRefinement::ComputeNe const Point newNode = 0.5 * (edgeCentre + mesh.Node(node2)); std::tie(newNodeId, nodeInsertionAction) = mesh.InsertNode(newNode); - newEdgeNodesAction->Add(std::move(nodeInsertionAction)); nodeMask[newNodeId] = NodeMask::NewGeneralNode; } else @@ -682,19 +639,15 @@ std::unique_ptr meshkernel::CasulliRefinement::ComputeNe StoreNewNode(mesh, node2, i, i, newNodeId, newNodes); } - - return newEdgeNodesAction; } -std::unique_ptr meshkernel::CasulliRefinement::ComputeNewNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask) +void meshkernel::CasulliRefinement::ComputeNewNodes(Mesh2D& mesh, std::vector& newNodes, std::vector& nodeMask) { - std::unique_ptr newNodesAction = CompoundUndoAction::Create(); // Keep copy of number of edges in mesh before any nodes are added. const UInt numEdges = mesh.GetNumEdges(); - newNodesAction->Add(ComputeNewFaceNodes(mesh, newNodes, nodeMask)); - newNodesAction->Add(ComputeNewEdgeNodes(mesh, numEdges, newNodes, nodeMask)); - return newNodesAction; + ComputeNewFaceNodes(mesh, newNodes, nodeMask); + ComputeNewEdgeNodes(mesh, numEdges, newNodes, nodeMask); } void meshkernel::CasulliRefinement::StoreNewNode(const Mesh2D& mesh, const UInt nodeId, const UInt edge1Index, const UInt edge2Index, const UInt newNodeId, std::vector& newNodes) diff --git a/libs/MeshKernel/src/Mesh.cpp b/libs/MeshKernel/src/Mesh.cpp index 7dfe03527..4b255ef0d 100644 --- a/libs/MeshKernel/src/Mesh.cpp +++ b/libs/MeshKernel/src/Mesh.cpp @@ -489,7 +489,7 @@ std::tuple> Mesh::I return {newNodeIndex, std::move(undoAction)}; } -std::tuple> Mesh::ConnectNodes(UInt startNode, UInt endNode) +std::tuple> Mesh::ConnectNodes(UInt startNode, UInt endNode, const bool collectUndo) { if (FindEdge(startNode, endNode) != constants::missing::uintValue) { @@ -499,11 +499,20 @@ std::tuple> Mesh::C // increment the edges container const auto newEdgeIndex = GetNumEdges(); m_edges.resize(newEdgeIndex + 1); - - std::unique_ptr undoAction = AddEdgeAction::Create(*this, newEdgeIndex, startNode, endNode); - CommitAction(*undoAction); SetAdministrationRequired(true); - return {newEdgeIndex, std::move(undoAction)}; + + if (collectUndo) + { + std::unique_ptr undoAction = AddEdgeAction::Create(*this, newEdgeIndex, startNode, endNode); + CommitAction(*undoAction); + return {newEdgeIndex, std::move(undoAction)}; + } + else + { + AddEdgeAction undoAction(*this, newEdgeIndex, startNode, endNode); + CommitAction(undoAction); + return {newEdgeIndex, nullptr}; + } } std::unique_ptr Mesh::ResetNode(const UInt nodeId, const Point& newValue) @@ -530,38 +539,64 @@ void Mesh::SetNode(const UInt nodeId, const Point& newValue) m_nodes[nodeId] = newValue; } -std::unique_ptr Mesh::DeleteEdge(UInt edge) +std::unique_ptr Mesh::DeleteEdge(UInt edge, const bool collectUndo) { if (edge == constants::missing::uintValue) [[unlikely]] { throw std::invalid_argument("Mesh::DeleteEdge: The index of the edge to be deleted does not exist."); } - std::unique_ptr undoAction = DeleteEdgeAction::Create(*this, edge, m_edges[edge].first, m_edges[edge].second); - - CommitAction(*undoAction); SetAdministrationRequired(true); - return undoAction; + + if (collectUndo) + { + std::unique_ptr undoAction = DeleteEdgeAction::Create(*this, edge, m_edges[edge].first, m_edges[edge].second); + + CommitAction(*undoAction); + return undoAction; + } + else + { + DeleteEdgeAction undoAction(*this, edge, m_edges[edge].first, m_edges[edge].second); + + CommitAction(undoAction); + return nullptr; + } } -std::unique_ptr Mesh::DeleteNode(UInt node) +std::unique_ptr Mesh::DeleteNode(UInt node, const bool collectUndo) { if (node >= GetNumNodes()) [[unlikely]] { throw std::invalid_argument("Mesh::DeleteNode: The index of the node to be deleted does not exist."); } - std::unique_ptr undoAction = DeleteNodeAction::Create(*this, node, m_nodes[node]); + SetAdministrationRequired(true); - for (UInt e = 0; e < m_nodesEdges[node].size(); e++) + if (collectUndo) { - const auto edgeIndex = m_nodesEdges[node][e]; - undoAction->Add(DeleteEdge(edgeIndex)); + std::unique_ptr undoAction = DeleteNodeAction::Create(*this, node, m_nodes[node]); + + for (UInt e = 0; e < m_nodesEdges[node].size(); e++) + { + undoAction->Add(DeleteEdge(m_nodesEdges[node][e], true)); + } + + CommitAction(*undoAction); + return undoAction; } + else + { + DeleteNodeAction undoAction(*this, node, m_nodes[node]); - SetAdministrationRequired(true); - CommitAction(*undoAction); - return undoAction; + for (UInt e = 0; e < m_nodesEdges[node].size(); e++) + { + [[maybe_unused]] auto nullUndo = DeleteEdge(m_nodesEdges[node][e], false); + } + + CommitAction(undoAction); + return nullptr; + } } void Mesh::ComputeEdgesLengths()