Skip to content

Commit

Permalink
GRIDEDIT-1499 Added simple mechanis for bypassing the undo info colle…
Browse files Browse the repository at this point in the history
…ction
  • Loading branch information
BillSenior committed Nov 25, 2024
1 parent f05be4e commit 3ae3d68
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 40 deletions.
1 change: 1 addition & 0 deletions libs/MeshKernel/include/MeshKernel/CasulliRefinement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#pragma once

#include <array>
#include <memory>
#include <vector>

#include "MeshKernel/Mesh2D.hpp"
Expand Down
9 changes: 6 additions & 3 deletions libs/MeshKernel/include/MeshKernel/Mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<UInt, std::unique_ptr<AddEdgeAction>> ConnectNodes(UInt startNode, UInt endNode);
[[nodiscard]] std::tuple<UInt, std::unique_ptr<AddEdgeAction>> 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<DeleteNodeAction> DeleteNode(UInt node);
[[nodiscard]] std::unique_ptr<DeleteNodeAction> DeleteNode(UInt node, const bool collectUndo = true);

/// @brief Find the edge sharing two nodes
/// @param[in] firstNodeIndex The index of the first node
Expand Down Expand Up @@ -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<DeleteEdgeAction> DeleteEdge(UInt edge);
[[nodiscard]] std::unique_ptr<DeleteEdgeAction> 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
Expand Down
45 changes: 26 additions & 19 deletions libs/MeshKernel/src/CasulliRefinement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
//------------------------------------------------------------------------------

#include <algorithm>
#include <tuple>

#include "MeshKernel/CasulliRefinement.hpp"
#include "MeshKernel/Exceptions.hpp"
Expand Down Expand Up @@ -210,7 +211,8 @@ void meshkernel::CasulliRefinement::Administrate(Mesh2D& mesh, const UInt numNod
{
if (nodeMask[i] > NodeMask::Unassigned && nodeMask[i] < NodeMask::CornerNode)
{
[[maybe_unused]] auto undoAction = 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 */);
}
}

Expand Down Expand Up @@ -262,23 +264,24 @@ void meshkernel::CasulliRefinement::ConnectNodes(Mesh2D& mesh, const std::vector
// 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);
// 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);
[[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);
[[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);
[[maybe_unused]] auto ignore = mesh.ConnectNodes(node2, node4, false /* collectUndo info */);
}
}
}
Expand Down Expand Up @@ -338,29 +341,30 @@ void meshkernel::CasulliRefinement::ConnectFaceNodes(Mesh2D& mesh, const UInt cu
// 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);
// 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]);
[[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]);
[[maybe_unused]] auto ignore = mesh.ConnectNodes(node1, newIndex[nextNextIndex], false /* collectUndo info */);
break;
}
}
}

void meshkernel::CasulliRefinement::ConnectEdges(Mesh2D& mesh, const UInt currentNode, const std::vector<EdgeNodes>& newNodes, UInt& edgeCount, std::vector<UInt>& newEdges)
{
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)
Expand All @@ -381,13 +385,14 @@ void meshkernel::CasulliRefinement::ConnectEdges(Mesh2D& mesh, const UInt curren
{
if (mesh.GetEdge(edgeId).first == currentNode)
{
auto [edgeId1, connectionAction1] = mesh.ConnectNodes(currentNode, newNodes[edgeId][0]);
auto [edgeId2, connectionAction2] = mesh.ConnectNodes(currentNode, newNodes[edgeId][2]);
// 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]);
auto [edgeId2, connectionAction2] = mesh.ConnectNodes(currentNode, newNodes[edgeId][3]);
[[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 */);
}
}
}
Expand Down Expand Up @@ -449,7 +454,8 @@ void meshkernel::CasulliRefinement::CreateMissingBoundaryEdges(Mesh2D& mesh, con
{
if (nodesToConnect[0] != constants::missing::uintValue && nodesToConnect[1] != constants::missing::uintValue && nodesToConnect[0] != nodesToConnect[1])
{
auto [edgeId, connectionAction] = mesh.ConnectNodes(nodesToConnect[0], nodesToConnect[1]);
// 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 */);
}
}
}
Expand All @@ -459,7 +465,7 @@ void meshkernel::CasulliRefinement::CreateMissingBoundaryEdges(Mesh2D& mesh, con
{
if (nodesToConnect[j] != constants::missing::uintValue && nodesToConnect[j] != i)
{
auto [edgeId, connectionAction] = mesh.ConnectNodes(i, nodesToConnect[j]);
[[maybe_unused]] auto ignore = mesh.ConnectNodes(i, nodesToConnect[j], false /* collectUndo info */);
}
}
}
Expand Down Expand Up @@ -512,13 +518,14 @@ void meshkernel::CasulliRefinement::ConnectNewNodes(Mesh2D& mesh, const std::vec

if (mesh.GetEdge(edgeId).first == i)
{
auto [edgeId1, connectionAction1] = mesh.ConnectNodes(i, newNodes[edgeId][0]);
auto [edgeId2, connectionAction2] = mesh.ConnectNodes(i, newNodes[edgeId][2]);
// 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]);
auto [edgeId2, connectionAction2] = mesh.ConnectNodes(i, newNodes[edgeId][3]);
[[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 */);
}
}
}
Expand Down
71 changes: 53 additions & 18 deletions libs/MeshKernel/src/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,7 @@ std::tuple<meshkernel::UInt, std::unique_ptr<meshkernel::AddNodeAction>> Mesh::I
return {newNodeIndex, std::move(undoAction)};
}

std::tuple<meshkernel::UInt, std::unique_ptr<meshkernel::AddEdgeAction>> Mesh::ConnectNodes(UInt startNode, UInt endNode)
std::tuple<meshkernel::UInt, std::unique_ptr<meshkernel::AddEdgeAction>> Mesh::ConnectNodes(UInt startNode, UInt endNode, const bool collectUndo)
{
if (FindEdge(startNode, endNode) != constants::missing::uintValue)
{
Expand All @@ -499,11 +499,20 @@ std::tuple<meshkernel::UInt, std::unique_ptr<meshkernel::AddEdgeAction>> Mesh::C
// increment the edges container
const auto newEdgeIndex = GetNumEdges();
m_edges.resize(newEdgeIndex + 1);

std::unique_ptr<AddEdgeAction> undoAction = AddEdgeAction::Create(*this, newEdgeIndex, startNode, endNode);
CommitAction(*undoAction);
SetAdministrationRequired(true);
return {newEdgeIndex, std::move(undoAction)};

if (collectUndo)
{
std::unique_ptr<AddEdgeAction> 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<meshkernel::ResetNodeAction> Mesh::ResetNode(const UInt nodeId, const Point& newValue)
Expand All @@ -530,38 +539,64 @@ void Mesh::SetNode(const UInt nodeId, const Point& newValue)
m_nodes[nodeId] = newValue;
}

std::unique_ptr<meshkernel::DeleteEdgeAction> Mesh::DeleteEdge(UInt edge)
std::unique_ptr<meshkernel::DeleteEdgeAction> 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<meshkernel::DeleteEdgeAction> undoAction = DeleteEdgeAction::Create(*this, edge, m_edges[edge].first, m_edges[edge].second);

CommitAction(*undoAction);
SetAdministrationRequired(true);
return undoAction;

if (collectUndo)
{
std::unique_ptr<meshkernel::DeleteEdgeAction> 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<meshkernel::DeleteNodeAction> Mesh::DeleteNode(UInt node)
std::unique_ptr<meshkernel::DeleteNodeAction> 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<DeleteNodeAction> 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<DeleteNodeAction> 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()
Expand Down

0 comments on commit 3ae3d68

Please sign in to comment.