diff --git a/libs/MeshKernel/include/MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp b/libs/MeshKernel/include/MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp index 721adafeb..94e9f6992 100644 --- a/libs/MeshKernel/include/MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp +++ b/libs/MeshKernel/include/MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp @@ -95,8 +95,8 @@ namespace meshkernel /// @brief Move assignment operator for CurvilinearGrid CurvilinearGrid& operator=(CurvilinearGrid&& copy) noexcept; - /// @brief Delete copy assignment operator for CurvilinearGrid - CurvilinearGrid& operator=(const CurvilinearGrid& copy) = delete; + /// @brief Ccopy assignment operator for CurvilinearGrid + CurvilinearGrid& operator=(const CurvilinearGrid& copy); /// @brief Set the grid nodes of a curvilinear grid instance /// @details The matrix row index corresponds to the CurvilinearGrid n index, the matrix column index corresponds to the CurvilinearGrid m index diff --git a/libs/MeshKernel/include/MeshKernel/Mesh.hpp b/libs/MeshKernel/include/MeshKernel/Mesh.hpp index 457ee2f8c..bfb1da220 100644 --- a/libs/MeshKernel/include/MeshKernel/Mesh.hpp +++ b/libs/MeshKernel/include/MeshKernel/Mesh.hpp @@ -362,8 +362,6 @@ namespace meshkernel /// @returns The undo action std::unique_ptr Join(const Mesh& rhs); - // std::unique_ptr Join(nodes, edges); - /// @brief Get the mapping/indexing from the node array mapped to valid nodes std::vector GetValidNodeMapping() const; diff --git a/libs/MeshKernel/include/MeshKernel/UndoActions/NoActionUndo.hpp b/libs/MeshKernel/include/MeshKernel/UndoActions/NoActionUndo.hpp index f9aff1829..58acbddb7 100644 --- a/libs/MeshKernel/include/MeshKernel/UndoActions/NoActionUndo.hpp +++ b/libs/MeshKernel/include/MeshKernel/UndoActions/NoActionUndo.hpp @@ -46,10 +46,10 @@ namespace meshkernel private: /// @brief Perform the undo action, does not change anything - void DoCommit(); + void DoCommit() override; /// @brief Perform the redo action, does not change anything - void DoRestore(); + void DoRestore() override; }; } // namespace meshkernel diff --git a/libs/MeshKernel/src/CurvilinearGrid/CurvilinearGrid.cpp b/libs/MeshKernel/src/CurvilinearGrid/CurvilinearGrid.cpp index 2f429eba3..2eb8a666f 100644 --- a/libs/MeshKernel/src/CurvilinearGrid/CurvilinearGrid.cpp +++ b/libs/MeshKernel/src/CurvilinearGrid/CurvilinearGrid.cpp @@ -105,6 +105,37 @@ CurvilinearGrid& CurvilinearGrid::operator=(CurvilinearGrid&& copy) noexcept return *this; } +CurvilinearGrid& CurvilinearGrid::operator=(const CurvilinearGrid& copy) +{ + if (this != ©) + { + m_projection = copy.m_projection; + m_gridNodes = copy.m_gridNodes; + m_gridFacesMask = copy.m_gridFacesMask; + m_gridNodesTypes = copy.m_gridNodesTypes; + m_gridIndices = copy.m_gridIndices; + + m_nodesRTreeRequiresUpdate = true; + m_edgesRTreeRequiresUpdate = true; + m_facesRTreeRequiresUpdate = true; + + m_RTrees.emplace(Location::Nodes, RTreeFactory::Create(m_projection)); + m_RTrees.emplace(Location::Edges, RTreeFactory::Create(m_projection)); + m_RTrees.emplace(Location::Faces, RTreeFactory::Create(m_projection)); + + m_boundingBoxCache = copy.m_boundingBoxCache; + + m_edges = copy.m_edges; + + m_startOffset = copy.m_startOffset; + m_endOffset = copy.m_endOffset; + + SetGridNodes(m_gridNodes); + } + + return *this; +} + void CurvilinearGrid::SetGridNodes(const lin_alg::Matrix& gridNodes) { if (gridNodes.rows() <= 1 || gridNodes.cols() <= 1) diff --git a/libs/MeshKernel/tests/src/UndoStackTests.cpp b/libs/MeshKernel/tests/src/UndoStackTests.cpp index e1868249c..b49c549df 100644 --- a/libs/MeshKernel/tests/src/UndoStackTests.cpp +++ b/libs/MeshKernel/tests/src/UndoStackTests.cpp @@ -552,7 +552,6 @@ TEST(UndoStackTests, RemovingUndoActionsRandomised) for (mk::UInt i = 0; i < totalActionCount; ++i) { mk::UInt randomNum = static_cast(generator()) % NumberOfUndoActions; - // int randomNum = rand() % NumberOfUndoActions; undoActionStack.Add(std::make_unique(), actionIds[randomNum]); ++actionCounts[randomNum]; } diff --git a/libs/MeshKernelApi/include/MeshKernelApi/State.hpp b/libs/MeshKernelApi/include/MeshKernelApi/State.hpp index 02ee8d358..4d2794f0b 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/State.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/State.hpp @@ -55,61 +55,7 @@ namespace meshkernelapi /// @brief Default constructor MeshKernelState() = default; - // MeshKernelState(MeshKernelState& mk) : m_mesh1d(mk.m_mesh1d), - // m_network1d(mk.m_network1d), - // m_mesh2d(mk.m_mesh2d), - // m_contacts(mk.m_contacts), - // m_curvilinearGrid(mk.m_curvilinearGrid), - // m_meshOrthogonalization(mk.m_meshOrthogonalization), - // m_curvilinearGridFromSplines(mk.m_curvilinearGridFromSplines), - // m_curvilinearGridOrthogonalization(mk.m_curvilinearGridOrthogonalization), - // m_curvilinearGridLineShift(mk.m_curvilinearGridLineShift), - // m_projection(mk.m_projection), - // m_state(mk.m_state) - - // { - // } - - // MeshKernelState(MeshKernelState&& mk) : m_mesh1d(std::move(mk.m_mesh1d)), - // m_network1d(std::move(mk.m_network1d)), - // m_mesh2d(std::move(mk.m_mesh2d)), - // m_contacts(std::move(mk.m_contacts)), - // m_curvilinearGrid(std::move(mk.m_curvilinearGrid)), - // m_meshOrthogonalization(std::move(mk.m_meshOrthogonalization)), - // m_curvilinearGridFromSplines(std::move(mk.m_curvilinearGridFromSplines)), - // m_curvilinearGridOrthogonalization(std::move(mk.m_curvilinearGridOrthogonalization)), - // m_curvilinearGridLineShift(std::move(mk.m_curvilinearGridLineShift)), - // m_projection(mk.m_projection), - // m_state(mk.m_state) - - // { - // } - - // /// @brief Constructor initializing mesh and contacts classes - // /// @param[in] projection The projection to use - // MeshKernelState(meshkernel::Projection projection) : m_projection(projection) - // { - // m_mesh1d = std::make_unique(projection); - // m_mesh2d = std::make_unique(projection); - // m_network1d = std::make_unique(projection); - // m_contacts = std::make_unique(*m_mesh1d, *m_mesh2d); - // m_curvilinearGrid = std::make_unique(projection); - // } - - // // Geometrical entities instances - // std::unique_ptr m_mesh1d; ///< Unique pointer to meshkernel::Mesh1D instance - // std::unique_ptr m_network1d; ///< Unique pointer to meshkernel::Network1D instance - // std::unique_ptr m_mesh2d; ///< Unique pointer to meshkernel::Mesh2D instance - // std::unique_ptr m_contacts; ///< Unique pointer to meshkernel::Contacts instance - // std::unique_ptr m_curvilinearGrid; ///< Unique pointer to meshkernel::CurvilinearGrid instance - - // // Algorithms instances (interactivity) - // std::unique_ptr m_meshOrthogonalization; ///< Unique pointer to meshkernel::OrthogonalizationAndSmoothing instance - // std::unique_ptr m_curvilinearGridFromSplines; ///< Unique pointer to meshkernel::CurvilinearGridFromSplines instance - // std::unique_ptr m_curvilinearGridOrthogonalization; ///< Unique pointer to meshkernel::CurvilinearGridOrthogonalization instance - // std::unique_ptr m_curvilinearGridLineShift; ///< Unique pointer to meshkernel::CurvilinearGridLineShift instance - - MeshKernelState(meshkernel::Projection projection) : m_projection(projection) + explicit MeshKernelState(meshkernel::Projection projection) : m_projection(projection) { m_mesh1d = std::make_shared(projection); m_mesh2d = std::make_shared(projection); @@ -119,17 +65,17 @@ namespace meshkernelapi } // Geometrical entities instances - std::shared_ptr m_mesh1d; ///< Unique pointer to meshkernel::Mesh1D instance - std::shared_ptr m_network1d; ///< Unique pointer to meshkernel::Network1D instance - std::shared_ptr m_mesh2d; ///< Unique pointer to meshkernel::Mesh2D instance - std::shared_ptr m_contacts; ///< Unique pointer to meshkernel::Contacts instance - std::shared_ptr m_curvilinearGrid; ///< Unique pointer to meshkernel::CurvilinearGrid instance + std::shared_ptr m_mesh1d; ///< Shared pointer to meshkernel::Mesh1D instance + std::shared_ptr m_network1d; ///< Shared pointer to meshkernel::Network1D instance + std::shared_ptr m_mesh2d; ///< Shared pointer to meshkernel::Mesh2D instance + std::shared_ptr m_contacts; ///< Shared pointer to meshkernel::Contacts instance + std::shared_ptr m_curvilinearGrid; ///< Shared pointer to meshkernel::CurvilinearGrid instance // Algorithms instances (interactivity) - std::shared_ptr m_meshOrthogonalization; ///< Unique pointer to meshkernel::OrthogonalizationAndSmoothing instance - std::shared_ptr m_curvilinearGridFromSplines; ///< Unique pointer to meshkernel::CurvilinearGridFromSplines instance - std::shared_ptr m_curvilinearGridOrthogonalization; ///< Unique pointer to meshkernel::CurvilinearGridOrthogonalization instance - std::shared_ptr m_curvilinearGridLineShift; ///< Unique pointer to meshkernel::CurvilinearGridLineShift instance + std::shared_ptr m_meshOrthogonalization; ///< Shared pointer to meshkernel::OrthogonalizationAndSmoothing instance + std::shared_ptr m_curvilinearGridFromSplines; ///< Shared pointer to meshkernel::CurvilinearGridFromSplines instance + std::shared_ptr m_curvilinearGridOrthogonalization; ///< Shared pointer to meshkernel::CurvilinearGridOrthogonalization instance + std::shared_ptr m_curvilinearGridLineShift; ///< Shared pointer to meshkernel::CurvilinearGridLineShift instance // Exclusively owned state meshkernel::Projection m_projection{meshkernel::Projection::cartesian}; ///< Projection used by the meshes @@ -141,7 +87,7 @@ namespace meshkernelapi } // namespace meshkernelapi -inline const std::string& meshkernelapi::toString(const MeshKernelState::CurrentState state) +inline static const std::string& meshkernelapi::toString(const MeshKernelState::CurrentState state) { static std::string uninitialisedStr = "Uninitialised"; static std::string validMeshStr = "ValidMesh"; @@ -161,5 +107,5 @@ inline const std::string& meshkernelapi::toString(const MeshKernelState::Current return deletedMeshStr; default: return unknown; - }; + } } diff --git a/libs/MeshKernelApi/src/MeshKernel.cpp b/libs/MeshKernelApi/src/MeshKernel.cpp index b41f8c888..c30532f79 100644 --- a/libs/MeshKernelApi/src/MeshKernel.cpp +++ b/libs/MeshKernelApi/src/MeshKernel.cpp @@ -429,12 +429,11 @@ namespace meshkernelapi { throw meshkernel::ConstraintError("The 2d mesh contains no nodes."); } + meshkernel::range_check::CheckOneOf(deletionOption, meshkernel::GetValidDeletionOptions(), "Deletion"); const std::vector polygonPoints = ConvertGeometryListToPointVector(polygon); - // if (polygonPoints.size () > 0) - // { const bool invertDeletionBool = invertDeletion == 1; const meshkernel::Polygons meshKernelPolygon(polygonPoints, meshKernelState[meshKernelId].m_mesh2d->m_projection); const auto deletionOptionEnum = static_cast(deletionOption); @@ -4213,7 +4212,8 @@ namespace meshkernelapi } auto undoAction = MKStateUndoAction::Create(meshKernelState[meshKernelId]); - *meshKernelState[meshKernelId].m_curvilinearGrid = std::move(meshkernel::CurvilinearGridGenerateCircularGrid::Compute(parameters, meshKernelState[meshKernelId].m_projection)); + *meshKernelState[meshKernelId].m_curvilinearGrid = meshkernel::CurvilinearGridGenerateCircularGrid::Compute(parameters, + meshKernelState[meshKernelId].m_projection); meshKernelUndoStack.Add(std::move(undoAction), meshKernelId); meshKernelState[meshKernelId].m_state = MeshKernelState::CurrentState::ValidMesh; diff --git a/libs/MeshKernelApi/tests/src/ApiTest.cpp b/libs/MeshKernelApi/tests/src/ApiTest.cpp index f3eaf599b..761e3eaaa 100644 --- a/libs/MeshKernelApi/tests/src/ApiTest.cpp +++ b/libs/MeshKernelApi/tests/src/ApiTest.cpp @@ -2994,6 +2994,7 @@ TEST(Mesh2D, Mesh2DSetAndAdd) // allocate state int mk_id = 0; errorCode = mkernel_allocate_state(0, mk_id); + ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // first initialise using the first mesh, mesh2d_1 errorCode = mkernel_mesh2d_set(mk_id, mesh2d_1); diff --git a/libs/MeshKernelApi/tests/src/UndoTests.cpp b/libs/MeshKernelApi/tests/src/UndoTests.cpp index 2831bb872..e0bb1508c 100644 --- a/libs/MeshKernelApi/tests/src/UndoTests.cpp +++ b/libs/MeshKernelApi/tests/src/UndoTests.cpp @@ -86,6 +86,11 @@ bool CompareCurvilinearGrids(const int meshKernelId1, const int meshKernelId2) errorCode = mkapi::mkernel_curvilinear_get_data(meshKernelId2, curvilinearGrid2); + if (mk::ExitCode::Success != errorCode) + { + return false; + } + size_t count = 0; for (int i = 0; i < curvilinearGrid1.num_n; ++i) @@ -153,6 +158,11 @@ bool CompareUnstructuredGrids(const int meshKernelId1, const int meshKernelId2) errorCode = mkapi::mkernel_mesh2d_get_node_edge_data(meshKernelId2, grid2); + if (mk::ExitCode::Success != errorCode) + { + return false; + } + size_t count = 0; for (int i = 0; i < grid1.num_nodes; ++i) @@ -464,10 +474,13 @@ TEST(UndoTests, UnstructuredGrid) ASSERT_EQ(mk::ExitCode::Success, errorCode); // Generate the curvilinear grids, later to be converted to unstructured grids - errorCode = GenerateCurvilinearMesh(meshKernelId4, clg2Size, delta, 0.0); errorCode = GenerateCurvilinearMesh(meshKernelId2, clg2Size, delta, 0.0); ASSERT_EQ(mk::ExitCode::Success, errorCode); + // Generate an identical copy of meshKernelId2 to enable easy comparing later + errorCode = GenerateCurvilinearMesh(meshKernelId4, clg2Size, delta, 0.0); + ASSERT_EQ(mk::ExitCode::Success, errorCode); + // Convert the curvilinear grid id2 to an unstructured grid. errorCode = mkapi::mkernel_curvilinear_convert_to_mesh2d(meshKernelId2); ASSERT_EQ(mk::ExitCode::Success, errorCode); @@ -628,7 +641,7 @@ TEST(UndoTests, UnstructuredGridConnection) const double clg2DeltaX = 1.0; const double clg2DeltaY = 1.0; - const double fraction = 2.0 * 0.015625; + const double fraction = 0.03125; const double clg1OriginX = 0.0; const double clg1OriginY = 0.0; @@ -674,6 +687,9 @@ TEST(UndoTests, UnstructuredGridConnection) ASSERT_EQ(mk::ExitCode::Success, errorCode); //-------------------------------- + // Insert node in middle of an element and connect the surrounding 4 nodes to it. + // The undo these actions. + // This is to create some unused data in the node and edge lists. // insert node to mesh1 int newNodeId; @@ -725,7 +741,7 @@ TEST(UndoTests, UnstructuredGridConnection) errorCode = mkapi::mkernel_mesh2d_insert_edge(meshKernelId1, node4, newNodeId, edge4); ASSERT_EQ(mk::ExitCode::Success, errorCode); - // now, 5 undos to remove the added edges and inserted nodes. + // now, 5 undos to remove the adding of 4 edges and 1 inserted node. for (int i = 1; i <= 5; ++i) { @@ -741,6 +757,7 @@ TEST(UndoTests, UnstructuredGridConnection) //-------------------------------- // Now the nodes and edges of meshKernelId1, should contain holes from the undoing above. + // Connect the meshes, overwriting meshKernelId2 and check the connected mesh is correct. mkapi::Mesh2D mesh2d{}; errorCode = mkapi::mkernel_mesh2d_get_dimensions(meshKernelId1, mesh2d); @@ -757,6 +774,7 @@ TEST(UndoTests, UnstructuredGridConnection) errorCode = mkapi::mkernel_mesh2d_get_node_edge_data(meshKernelId1, mesh2d); ASSERT_EQ(mk::ExitCode::Success, errorCode); + // Connect the meshes. errorCode = mkapi::mkernel_mesh2d_connect_meshes(meshKernelId2, mesh2d, 0.1); ASSERT_EQ(mk::ExitCode::Success, errorCode); @@ -776,6 +794,7 @@ TEST(UndoTests, UnstructuredGridConnection) const double nullValue = mk::constants::missing::doubleValue; + // The null values are from the three common nodes of the two meshes being connected. std::vector expectedNodesConnectedX{12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 12.0, 13.0, 14.0, 0.0, 4.0, 8.0, nullValue, 0.0, 4.0, 8.0, nullValue, 0.0, 4.0, 8.0, nullValue, 0.0, 4.0, 8.0, 12.0, 8.0, 8.0}; @@ -800,7 +819,7 @@ TEST(UndoTests, UnstructuredGridConnection) } //-------------------------------- - // Undo the connection + // Undo the connection of the meshes bool didUndo = false; int undoId = mkapi::mkernel_get_null_identifier();