Skip to content

Commit 57f68d4

Browse files
committed
GRIDEDIT-704 Added setting of nodes outside a box to invalid.
1 parent 19af3c4 commit 57f68d4

File tree

3 files changed

+177
-0
lines changed

3 files changed

+177
-0
lines changed

libs/MeshKernel/include/MeshKernel/CurvilinearGrid/CurvilinearGrid.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,10 @@ namespace meshkernel
210210
/// @note If any index is the null value or is out of range a ConstraintError will be thrown
211211
void DeleteInterior(const CurvilinearGridNodeIndices& firstNode, const CurvilinearGridNodeIndices& secondNode);
212212

213+
/// @brief Set all the nodes oustide of the block to be invalid.
214+
/// @note If any index is the null value or is out of range a ConstraintError will be thrown
215+
void DeleteExterior(const CurvilinearGridNodeIndices& firstNode, const CurvilinearGridNodeIndices& secondNode);
216+
213217
/// @brief Moves a node from one position to another
214218
/// @param[in] fromPoint The input position, the closest node will be used
215219
/// @param[in] toPoint The coordinates of the new position

libs/MeshKernel/src/CurvilinearGrid/CurvilinearGrid.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,69 @@ void CurvilinearGrid::DeleteInterior(const CurvilinearGridNodeIndices& firstNode
905905
}
906906
}
907907

908+
void CurvilinearGrid::DeleteExterior(const CurvilinearGridNodeIndices& firstNode, const CurvilinearGridNodeIndices& secondNode)
909+
{
910+
911+
if (!firstNode.IsValid() || !secondNode.IsValid())
912+
{
913+
throw ConstraintError("Invalid index: first index - {{{}, {}}}, second index - {{{}, {}}}", firstNode.m_m, firstNode.m_n, secondNode.m_m, secondNode.m_n);
914+
}
915+
916+
if (firstNode.m_m >= m_numM || firstNode.m_n >= m_numN)
917+
{
918+
throw ConstraintError("Invalid index: first index {{{}, {}}} not in mesh limits {{{}, {}}}", firstNode.m_m, firstNode.m_n, m_numM, m_numN);
919+
}
920+
921+
if (secondNode.m_m >= m_numM || secondNode.m_n >= m_numN)
922+
{
923+
throw ConstraintError("Invalid index: second index {{{}, {}}} not in mesh limits {{{}, {}}}", secondNode.m_m, secondNode.m_n, m_numM, m_numN);
924+
}
925+
926+
UInt lowerLimitI = std::min(firstNode.m_n, secondNode.m_n);
927+
UInt upperLimitI = std::max(firstNode.m_n, secondNode.m_n);
928+
929+
UInt lowerLimitJ = std::min(firstNode.m_m, secondNode.m_m);
930+
UInt upperLimitJ = std::max(firstNode.m_m, secondNode.m_m);
931+
932+
// Split into 4 regions, setting the nodes in each region to invalid
933+
//
934+
// First region: all nodes "south" the designated box
935+
for (UInt n = 0; n < m_numN; ++n)
936+
{
937+
for (UInt m = 0; m < lowerLimitJ; ++m)
938+
{
939+
m_gridNodes(n, m).SetInvalid();
940+
}
941+
}
942+
943+
// Second region: all nodes "directly west of" the designated box
944+
for (UInt n = 0; n < lowerLimitI; ++n)
945+
{
946+
for (UInt m = lowerLimitJ; m <= upperLimitJ; ++m)
947+
{
948+
m_gridNodes(n, m).SetInvalid();
949+
}
950+
}
951+
952+
// Third region: all nodes "directly east of" the designated box
953+
for (UInt n = upperLimitI + 1; n < m_numN; ++n)
954+
{
955+
for (UInt m = lowerLimitJ; m <= upperLimitJ; ++m)
956+
{
957+
m_gridNodes(n, m).SetInvalid();
958+
}
959+
}
960+
961+
// Fourth region: all nodes "north" the designated box
962+
for (UInt n = 0; n < m_numN; ++n)
963+
{
964+
for (UInt m = upperLimitJ + 1; m < m_numM; ++m)
965+
{
966+
m_gridNodes(n, m).SetInvalid();
967+
}
968+
}
969+
}
970+
908971
void CurvilinearGrid::MoveNode(Point const& fromPoint, Point const& toPoint)
909972
{
910973
// Get the node indices of fromPoint

libs/MeshKernel/tests/src/CurvilinearUniformTests.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,3 +348,113 @@ TEST(CurvilinearGridUniform, DeleteInteriorNodesFailureTest)
348348
EXPECT_THROW(curvilinearGrid->DeleteInterior({1, 1}, {nx, ny}), meshkernel::ConstraintError);
349349
EXPECT_THROW(curvilinearGrid->DeleteInterior({nx, 1}, {4, 4}), meshkernel::ConstraintError);
350350
}
351+
352+
void TestDeleteExteriorNodes(std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid,
353+
const meshkernel::CurvilinearGridNodeIndices first,
354+
const meshkernel::CurvilinearGridNodeIndices second)
355+
{
356+
// Check first, that all nodes are valid
357+
for (meshkernel::UInt i = 0; i < curvilinearGrid->m_numN; ++i)
358+
{
359+
for (meshkernel::UInt j = 0; j < curvilinearGrid->m_numM; ++j)
360+
{
361+
EXPECT_TRUE(curvilinearGrid->GetNode(i, j).IsValid());
362+
}
363+
}
364+
365+
meshkernel::UInt lowerLimitI = std::min(first.m_n, second.m_n);
366+
meshkernel::UInt upperLimitI = std::max(first.m_n, second.m_n);
367+
368+
meshkernel::UInt lowerLimitJ = std::min(first.m_m, second.m_m);
369+
meshkernel::UInt upperLimitJ = std::max(first.m_m, second.m_m);
370+
371+
meshkernel::UInt expectedValid = (upperLimitI - lowerLimitI + 1) * (upperLimitJ - lowerLimitJ + 1);
372+
373+
// Delete the nodes outside of a block
374+
curvilinearGrid->DeleteExterior(first, second);
375+
376+
auto inRange = [](const meshkernel::UInt v, const meshkernel::UInt l, const meshkernel::UInt u)
377+
{ return l <= v && v <= u; };
378+
379+
EXPECT_EQ(expectedValid, CurvilinearGridCountValidNodes(curvilinearGrid));
380+
381+
// Check that these exterior nodes have been set to invalid.
382+
for (meshkernel::UInt i = 0; i < curvilinearGrid->m_numN; ++i)
383+
{
384+
for (meshkernel::UInt j = 0; j < curvilinearGrid->m_numM; ++j)
385+
{
386+
if (inRange(i, lowerLimitI, upperLimitI) && inRange(j, lowerLimitJ, upperLimitJ))
387+
{
388+
EXPECT_TRUE(curvilinearGrid->GetNode(i, j).IsValid()) << "node should be true: " << i << " " << j;
389+
}
390+
else
391+
{
392+
EXPECT_FALSE(curvilinearGrid->GetNode(i, j).IsValid()) << "node should be false: " << i << " " << j;
393+
}
394+
}
395+
}
396+
}
397+
398+
TEST(CurvilinearGridUniform, DeleteExteriorNodesTest)
399+
{
400+
// Basic, testing of setting nodes inside a box to invalid
401+
meshkernel::UInt nx = 10;
402+
meshkernel::UInt ny = 10;
403+
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
404+
TestDeleteExteriorNodes(curvilinearGrid, {1, 1}, {4, 4});
405+
406+
// Reset the mesh
407+
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
408+
TestDeleteExteriorNodes(curvilinearGrid, {2, 1}, {5, 4});
409+
410+
// Reset the mesh
411+
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
412+
TestDeleteExteriorNodes(curvilinearGrid, {4, 3}, {7, 8});
413+
}
414+
415+
TEST(CurvilinearGridUniform, DeleteExteriorNodesReverseTest)
416+
{
417+
// testing of setting nodes inside a box to invalid, with lower and upper reversed
418+
419+
meshkernel::UInt nx = 10;
420+
meshkernel::UInt ny = 10;
421+
422+
// Prepare
423+
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
424+
TestDeleteExteriorNodes(curvilinearGrid, {5, 6}, {1, 2});
425+
426+
// Reset the mesh
427+
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
428+
TestDeleteExteriorNodes(curvilinearGrid, {5, 6}, {0, 4});
429+
}
430+
431+
TEST(CurvilinearGridUniform, DeleteExteriorNodesMixedTest)
432+
{
433+
// testing of setting nodes inside a box to invalid, with lower and upper reversed for any of i and j index
434+
435+
meshkernel::UInt nx = 100;
436+
meshkernel::UInt ny = 100;
437+
438+
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
439+
TestDeleteExteriorNodes(curvilinearGrid, {5, 1}, {1, 6});
440+
441+
// Reset grid
442+
curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
443+
TestDeleteExteriorNodes(curvilinearGrid, {1, 6}, {5, 2});
444+
}
445+
446+
TEST(CurvilinearGridUniform, DeleteExteriorNodesFailureTest)
447+
{
448+
// testing of setting nodes inside a box to invalid with invalid or out of range indices.
449+
450+
meshkernel::UInt nx = 10;
451+
meshkernel::UInt ny = 10;
452+
453+
// Prepare
454+
std::shared_ptr<meshkernel::CurvilinearGrid> curvilinearGrid = MakeCurvilinearGrid(0.0, 0.0, 1.0, 1.0, nx, ny);
455+
456+
EXPECT_THROW(curvilinearGrid->DeleteExterior({1, meshkernel::constants::missing::uintValue}, {nx, ny}), meshkernel::ConstraintError);
457+
EXPECT_THROW(curvilinearGrid->DeleteExterior({1, 1}, {meshkernel::constants::missing::uintValue, ny}), meshkernel::ConstraintError);
458+
EXPECT_THROW(curvilinearGrid->DeleteExterior({1, 1}, {nx, ny}), meshkernel::ConstraintError);
459+
EXPECT_THROW(curvilinearGrid->DeleteExterior({nx, 1}, {4, 4}), meshkernel::ConstraintError);
460+
}

0 commit comments

Comments
 (0)