diff --git a/cmake/compiler_config.cmake b/cmake/compiler_config.cmake index ad5a12ff5..0e8a1a8e0 100644 --- a/cmake/compiler_config.cmake +++ b/cmake/compiler_config.cmake @@ -15,6 +15,13 @@ if(APPLE) message(STATUS "Configuring build for macOS with ${CMAKE_CXX_COMPILER_ID} (${CMAKE_CXX_COMPILER_VERSION}).") # Common warning and visibility flags add_compile_options("-fvisibility=hidden;-Wall;-Wextra;-pedantic;-Werror;-Wno-unused-function") + + cmake_host_system_information(RESULT os_release QUERY OS_RELEASE) + + if(os_release VERSION_GREATER_EQUAL "26.0") + add_compile_options("-Wno-character-conversion") + endif() + # Conditionally suppress unused parameter warnings (used for platform-specific compiler issues) if(SUPPRESS_UNUSED_PARAMETER_WARNING) add_compile_options("-Wno-unused-parameter") diff --git a/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp b/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp index f1f163975..c8ce399c4 100644 --- a/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp +++ b/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp @@ -448,7 +448,8 @@ namespace meshkernel void WalkBoundaryFromNode(const Polygon& polygon, std::vector& isVisited, UInt& currentNode, - std::vector& meshBoundaryPolygon) const; + std::vector& meshBoundaryPolygon, + std::vector& boundaryPolygonFaceId) const; /// @brief Constructs a polygon or polygons from the meshboundary, by walking through the mesh /// @@ -461,6 +462,18 @@ namespace meshkernel std::vector& subSequence, std::vector& illegalCells) const; + /// @brief Reconstruct the invalid cell polygons + /// + /// When constructing the invalid cell polygons, they can be computed with many smaller polygons. + /// If these smaller polygons form a single patch on the domain, then they need to be combined + void ReconstructInvalidCellsPolygon(); + + /// @brief Convert all mesh boundaries to a vector of polygon nodes, including holes (copynetboundstopol) + /// + /// @return a sequence of boundary points, which may be separated by the invalid point, and a matching sequence of Boolean values indicating which + /// polygonal sub-sequence forms a external boundary + [[nodiscard]] std::tuple, std::vector> GetAllBoundaryPolygons(const std::vector& polygon); + /// @brief Ensure that all polynomials are orientated in the ACW direction. void OrientatePolygonsAntiClockwise(std::vector& polygonNodes) const; diff --git a/libs/MeshKernel/include/MeshKernel/Operations.hpp b/libs/MeshKernel/include/MeshKernel/Operations.hpp index 8b9f5d07e..9ec570886 100644 --- a/libs/MeshKernel/include/MeshKernel/Operations.hpp +++ b/libs/MeshKernel/include/MeshKernel/Operations.hpp @@ -621,4 +621,14 @@ namespace meshkernel } } + /// @brief Determine is a polygon is comprised of multiple polygons intersecting at the control points only + /// + /// @note This currently works only for polygons that intersect at the control points + bool isMultiPolygon(std::span boundary); + + /// @brief Split a single polygon line comprised of multiple polygons into separate polygons. + /// + /// @note This currently works only for polygons that intersect at the control points + std::tuple>, std::vector> splitMultiplePolygons(std::span boundary, std::span elementIds); + } // namespace meshkernel diff --git a/libs/MeshKernel/include/MeshKernel/Point.hpp b/libs/MeshKernel/include/MeshKernel/Point.hpp index e40775df0..824c38401 100644 --- a/libs/MeshKernel/include/MeshKernel/Point.hpp +++ b/libs/MeshKernel/include/MeshKernel/Point.hpp @@ -125,6 +125,14 @@ namespace meshkernel return !isInvalid; } + + /// @brief Required by std::set + bool operator<(const Point& other) const + { + if (x != other.x) + return x < other.x; + return y < other.y; + } }; /// @brief Compute the dot product of a point with itself. diff --git a/libs/MeshKernel/include/MeshKernel/Polygon.hpp b/libs/MeshKernel/include/MeshKernel/Polygon.hpp index 2c390c295..8b7edb995 100644 --- a/libs/MeshKernel/include/MeshKernel/Polygon.hpp +++ b/libs/MeshKernel/include/MeshKernel/Polygon.hpp @@ -27,6 +27,7 @@ #pragma once +#include #include #include "MeshKernel/BoundingBox.hpp" @@ -54,6 +55,10 @@ namespace meshkernel /// @brief Default move constructor. Polygon(Polygon&& copy) = default; + /// @brief Constructor + Polygon(std::span points, + Projection projection); + /// @brief Constructor Polygon(const std::vector& points, Projection projection); diff --git a/libs/MeshKernel/src/Mesh2D.cpp b/libs/MeshKernel/src/Mesh2D.cpp index e5fa3f6c7..966eee6a6 100644 --- a/libs/MeshKernel/src/Mesh2D.cpp +++ b/libs/MeshKernel/src/Mesh2D.cpp @@ -1511,14 +1511,25 @@ std::vector Mesh2D::SortedFacesAroundNode(UInt node) const } std::vector Mesh2D::ComputeBoundaryPolygons(const std::vector& polygonNodes) +{ + Administrate(); + auto [boundaryPoints, isEnclosingBoundary] = GetAllBoundaryPolygons(polygonNodes); + return boundaryPoints; +} + +std::tuple, std::vector> Mesh2D::GetAllBoundaryPolygons(const std::vector& polygonNodes) { const Polygon polygon(polygonNodes, m_projection); - // Find faces - Administrate(); std::vector isVisited(GetNumEdges(), false); std::vector meshBoundaryPolygon; + std::vector boundaryPolygon; + // Elements connected to the boundary + std::vector boundaryPolygonFaceId; + std::vector isEnclosingBoundary; + meshBoundaryPolygon.reserve(GetNumNodes()); + boundaryPolygon.reserve(GetNumNodes()); for (UInt e = 0; e < GetNumEdges(); e++) { @@ -1527,10 +1538,10 @@ std::vector Mesh2D::ComputeBoundaryPolygons(const std::vector continue; } - const auto firstNodeIndex = m_edges[e].first; - const auto secondNodeIndex = m_edges[e].second; - const auto firstNode = m_nodes[firstNodeIndex]; - const auto secondNode = m_nodes[secondNodeIndex]; + const UInt firstNodeIndex = m_edges[e].first; + const UInt secondNodeIndex = m_edges[e].second; + const Point firstNode = m_nodes[firstNodeIndex]; + const Point secondNode = m_nodes[secondNodeIndex]; bool firstNodeInPolygon = polygon.Contains(m_nodes[firstNodeIndex]); bool secondNodeInPolygon = polygon.Contains(m_nodes[secondNodeIndex]); @@ -1541,38 +1552,77 @@ std::vector Mesh2D::ComputeBoundaryPolygons(const std::vector } // Start a new polyline - if (!meshBoundaryPolygon.empty()) - { - meshBoundaryPolygon.emplace_back(constants::missing::doubleValue, constants::missing::doubleValue); - } + boundaryPolygon.clear(); + boundaryPolygonFaceId.clear(); // Put the current edge on the mesh boundary, mark it as visited - meshBoundaryPolygon.emplace_back(firstNode); - meshBoundaryPolygon.emplace_back(secondNode); + boundaryPolygon.emplace_back(firstNode); + boundaryPolygon.emplace_back(secondNode); + boundaryPolygonFaceId.push_back(m_edgesFaces[e][0]); + isVisited[e] = true; // walk the current mesh boundary auto currentNode = secondNodeIndex; - WalkBoundaryFromNode(polygon, isVisited, currentNode, meshBoundaryPolygon); + WalkBoundaryFromNode(polygon, isVisited, currentNode, boundaryPolygon, boundaryPolygonFaceId); - const auto numNodesFirstTail = static_cast(meshBoundaryPolygon.size()); + const auto numNodesFirstTail = static_cast(boundaryPolygon.size()); // if the boundary polygon is not closed if (currentNode != firstNodeIndex) { // Now grow a polyline starting at the other side of the original link L, i.e., the second tail currentNode = firstNodeIndex; - WalkBoundaryFromNode(polygon, isVisited, currentNode, meshBoundaryPolygon); + WalkBoundaryFromNode(polygon, isVisited, currentNode, boundaryPolygon, boundaryPolygonFaceId); } // There is a nonempty second tail: reverse the second tail so that the tails connect and close the polygon. - if (meshBoundaryPolygon.size() > numNodesFirstTail) + if (boundaryPolygon.size() > numNodesFirstTail) + { + std::reverse(boundaryPolygon.begin() + numNodesFirstTail, boundaryPolygon.end()); + boundaryPolygon.push_back(boundaryPolygon.front()); + } + + std::span currentPolygonSpan(boundaryPolygon); + Polygon currentPolygon(currentPolygonSpan, m_projection); + + if (!meshBoundaryPolygon.empty()) + { + meshBoundaryPolygon.emplace_back(constants::missing::doubleValue, constants::missing::doubleValue); + } + + if (isMultiPolygon(currentPolygonSpan)) + { + + auto [multiBoundaryPolygonNodes, multiBoundaryElementIds] = (splitMultiplePolygons(currentPolygonSpan, boundaryPolygonFaceId)); + + for (size_t i = 0; i < multiBoundaryPolygonNodes.size(); ++i) + { + if (i > 0) + { + meshBoundaryPolygon.emplace_back(constants::missing::doubleValue, constants::missing::doubleValue); + } + + meshBoundaryPolygon.insert(meshBoundaryPolygon.end(), multiBoundaryPolygonNodes[i].begin(), multiBoundaryPolygonNodes[i].end()); + + std::span currentPolygonSpan(multiBoundaryPolygonNodes[i]); + Polygon currentPolygon(currentPolygonSpan, m_projection); + + isEnclosingBoundary.push_back(currentPolygon.Contains(m_facesMassCenters[multiBoundaryElementIds[i]])); + } + } + else { - std::reverse(meshBoundaryPolygon.begin() + numNodesFirstTail, meshBoundaryPolygon.end()); - meshBoundaryPolygon.push_back(meshBoundaryPolygon.front()); + meshBoundaryPolygon.insert(meshBoundaryPolygon.end(), boundaryPolygon.begin(), boundaryPolygon.end()); + + std::span currentPolygonSpan(boundaryPolygon); + Polygon currentPolygon(currentPolygonSpan, m_projection); + + isEnclosingBoundary.push_back(currentPolygon.Contains(m_facesMassCenters[boundaryPolygonFaceId[0]])); } } - return meshBoundaryPolygon; + + return {meshBoundaryPolygon, isEnclosingBoundary}; } std::vector Mesh2D::ComputeInnerBoundaryPolygons() const @@ -1778,7 +1828,8 @@ std::vector Mesh2D::RemoveOuterDomainBoundaryPolygon(const st void Mesh2D::WalkBoundaryFromNode(const Polygon& polygon, std::vector& isVisited, UInt& currentNode, - std::vector& meshBoundaryPolygon) const + std::vector& meshBoundaryPolygon, + std::vector& boundaryPolygonFaceId) const { UInt e = 0; bool currentNodeInPolygon = false; @@ -1802,6 +1853,7 @@ void Mesh2D::WalkBoundaryFromNode(const Polygon& polygon, } currentNode = OtherNodeOfEdge(m_edges[currentEdge], currentNode); + boundaryPolygonFaceId.push_back(m_edgesFaces[currentEdge][0]); e = 0; currentNodeInPolygon = false; @@ -2183,6 +2235,45 @@ std::unique_ptr Mesh2D::DeleteMeshFacesInPolygon(const P return UpdateFaceInformation(faceIndices, appendDeletedFaces); } +void Mesh2D::ReconstructInvalidCellsPolygon() +{ + auto [boundaryPoints, isEnclosingBoundary] = GetAllBoundaryPolygons(std::vector()); + + Polygons polygons(boundaryPoints, m_projection); + + if (polygons.GetNumPolygons() <= 1) + { + // There are no interior boundary polygons + return; + } + + std::vector innerBoundaryPolygons; + innerBoundaryPolygons.reserve(m_invalidCellPolygons.size()); + bool firstElement = true; + + for (UInt p = 0; p < polygons.GetNumPolygons(); ++p) + { + if (isEnclosingBoundary[p]) + { + continue; + } + + if (!firstElement) + { + innerBoundaryPolygons.push_back(Point(constants::missing::doubleValue, constants::missing::doubleValue)); + } + else + { + firstElement = false; + } + + const std::vector& polygonPoints(polygons.Enclosure(p).Outer().Nodes()); + innerBoundaryPolygons.insert(innerBoundaryPolygons.end(), polygonPoints.begin(), polygonPoints.end()); + } + + m_invalidCellPolygons = std::move(innerBoundaryPolygons); +} + std::unique_ptr Mesh2D::UpdateFaceInformation(const std::vector& faceIndices, const bool appendDeletedFaces) { std::vector facesToDelete; @@ -2273,6 +2364,8 @@ std::unique_ptr Mesh2D::UpdateFaceInformation(const std: m_faceArea.erase(m_faceArea.begin() + faceId); } + ReconstructInvalidCellsPolygon(); + return deleteMeshAction; } diff --git a/libs/MeshKernel/src/Operations.cpp b/libs/MeshKernel/src/Operations.cpp index 1ede27d7c..0fb145962 100644 --- a/libs/MeshKernel/src/Operations.cpp +++ b/libs/MeshKernel/src/Operations.cpp @@ -25,6 +25,7 @@ // //------------------------------------------------------------------------------ +#include #include #include "MeshKernel/Cartesian3DPoint.hpp" @@ -1723,4 +1724,75 @@ namespace meshkernel return (matCoefficients[0] * x[0] + matCoefficients[1] * x[1]) * y[0] + (matCoefficients[2] * x[0] + matCoefficients[3] * x[1]) * y[1]; } + bool isMultiPolygon(std::span boundary) + { + + if (boundary.size() < 4) + { + return false; + } + + std::set uniquePoints; + + for (const Point& p : boundary) + { + if (!uniquePoints.insert(p).second) + { + return true; + } + } + + return false; + } + + std::tuple>, std::vector> splitMultiplePolygons(std::span boundaryPoints, std::span elementIds) + { + std::vector> completedPolygons; + std::vector firstElementIds; + + std::vector> pointFaceStack; + // Maps a point to its current index in the pointFaceStack + std::map activePoints; + + for (size_t i = 0; i < boundaryPoints.size(); ++i) + { + const Point& current_point = boundaryPoints[i]; + + // Check if this node closes a loop with a previously visited point + if (auto it = activePoints.find(current_point); it != activePoints.end()) + { + size_t loopStartIndex = it->second; + + std::vector subPolygon; + subPolygon.reserve((pointFaceStack.size() - loopStartIndex) + 1); + + int first_edge_id = pointFaceStack[loopStartIndex].second; + + for (size_t j = loopStartIndex; j < pointFaceStack.size(); ++j) + { + subPolygon.push_back(pointFaceStack[j].first); + activePoints.erase(pointFaceStack[j].first); + } + + // close the polygon + if (!subPolygon.empty()) + { + subPolygon.push_back(subPolygon.front()); + } + + completedPolygons.push_back(subPolygon); + firstElementIds.push_back(first_edge_id); + + pointFaceStack.resize(loopStartIndex); + } + + int currentEdge = (i < elementIds.size()) ? elementIds[i] : -1; + + activePoints[current_point] = pointFaceStack.size(); + pointFaceStack.emplace_back(current_point, currentEdge); + } + + return {completedPolygons, firstElementIds}; + } + } // namespace meshkernel diff --git a/libs/MeshKernel/src/Polygon.cpp b/libs/MeshKernel/src/Polygon.cpp index f72fd156a..119a9186d 100644 --- a/libs/MeshKernel/src/Polygon.cpp +++ b/libs/MeshKernel/src/Polygon.cpp @@ -42,6 +42,12 @@ meshkernel::Polygon::Polygon(const std::vector& points, Initialise(); } +meshkernel::Polygon::Polygon(std::span points, + Projection projection) : m_nodes(points.begin(), points.end()), m_projection(projection) +{ + Initialise(); +} + meshkernel::Polygon::Polygon(std::vector&& points, Projection projection) : m_nodes(points), m_projection(projection) { diff --git a/libs/MeshKernel/src/Utilities/Utilities.cpp b/libs/MeshKernel/src/Utilities/Utilities.cpp index 28cdec407..32151435e 100644 --- a/libs/MeshKernel/src/Utilities/Utilities.cpp +++ b/libs/MeshKernel/src/Utilities/Utilities.cpp @@ -103,9 +103,6 @@ void meshkernel::SaveVtk(const std::vector& nodes, const std::vector unsavedElements; - - unsavedElements.fill(0); UInt numberOfElements = 0; @@ -115,16 +112,6 @@ void meshkernel::SaveVtk(const std::vector& nodes, const std::vector& nodesX, const std::vector unsavedElements; - - unsavedElements.fill(0); UInt numberOfElements = 0; @@ -270,16 +254,6 @@ void meshkernel::SaveVtk(const std::vector& nodesX, const std::vector innerBoundaryPoints = mesh2.GetInnerBoundaryPolygons(); // The expected number of points, should not include any land boundary points - UInt expectedNumberOfNodes = 26; + constexpr UInt expectedNumberOfNodes = 26; ASSERT_EQ(expectedNumberOfNodes, innerBoundaryPoints.size()); // The edge of one of the deleted elements lies on the boundary, so will be not be part of the // interior set of polygons - std::vector expectedXPoints{ - 95.0, - 105.0, - 100.0, - 95.0, - constants::missing::doubleValue, - 85.0, - 85.0, - 95.0, - 95.0, - 85.0, - constants::missing::doubleValue, - 80.0, - 75.0, - 85.0, - 80.0, - constants::missing::doubleValue, - 120.0, - 115.0, - 125.0, - 120.0, - constants::missing::doubleValue, - 125.0, - 125.0, - 135.0, - 135.0, - 125.0}; - - std::vector expectedYPoints{ - 15.0, - 15.0, - 0.0, - 15.0, - constants::missing::doubleValue, - 15.0, - 25.0, - 25.0, - 15.0, - 15.0, - constants::missing::doubleValue, - 0.0, - 15.0, - 15.0, - 0.0, - constants::missing::doubleValue, - 0.0, - 15.0, - 15.0, - 0.0, - constants::missing::doubleValue, - 125.0, - 135.0, - 135.0, - 125.0, - 125.0}; + std::vector expectedXPoints{95.0, 100.0, 105.0, 95.0, + constants::missing::doubleValue, + 85.0, 95.0, 95.0, 85.0, 85.0, + constants::missing::doubleValue, + 80.0, 85.0, 75.0, 80.0, + constants::missing::doubleValue, + 120.0, 125.0, 115.0, 120.0, + constants::missing::doubleValue, + 125.0, 125.0, 135.0, 135.0, 125.0}; + + std::vector expectedYPoints{15.0, 0.0, 15.0, 15.0, + constants::missing::doubleValue, + 15.0, 15.0, 25.0, 25.0, 15.0, + constants::missing::doubleValue, + 0.0, 15.0, 15.0, 0.0, + constants::missing::doubleValue, + 0.0, 15.0, 15.0, 0.0, + constants::missing::doubleValue, + 125.0, 135.0, 135.0, 125.0, 125.0}; for (size_t i = 0; i < expectedXPoints.size(); ++i) { diff --git a/libs/MeshKernelApi/tests/src/InvalidCellsPolygonsTests.cpp b/libs/MeshKernelApi/tests/src/InvalidCellsPolygonsTests.cpp index 33c5987c4..b00ad89fa 100644 --- a/libs/MeshKernelApi/tests/src/InvalidCellsPolygonsTests.cpp +++ b/libs/MeshKernelApi/tests/src/InvalidCellsPolygonsTests.cpp @@ -82,18 +82,28 @@ TEST(InvalidCellsPolygonsTests, MeshHolesAreMainainedAfterRefinement) //-------------------------------- - std::vector invalidCellsX{80.0, 85.0, 75.0, 80.0, meshkernel::constants::missing::doubleValue, - 180.0, 200.0, 200.0, 180.0, 180.0, meshkernel::constants::missing::doubleValue, - 125.0, 135.0, 135.0, 125.0, 125.0, meshkernel::constants::missing::doubleValue, - 85.0, 95.0, 95.0, 85.0, 85.0, meshkernel::constants::missing::doubleValue, - 100.0, 105.0, 95.0, 100.0, meshkernel::constants::missing::doubleValue, + std::vector invalidCellsX{80.0, 85.0, 75.0, 80.0, + meshkernel::constants::missing::doubleValue, + 180.0, 200.0, 200.0, 180.0, 180.0, + meshkernel::constants::missing::doubleValue, + 125.0, 135.0, 135.0, 125.0, 125.0, + meshkernel::constants::missing::doubleValue, + 85.0, 95.0, 95.0, 85.0, 85.0, + meshkernel::constants::missing::doubleValue, + 100.0, 105.0, 95.0, 100.0, + meshkernel::constants::missing::doubleValue, 120.0, 125.0, 115.0, 120.0}; - std::vector invalidCellsY{0.0, 15.0, 15.0, 0.0, meshkernel::constants::missing::doubleValue, - 140.0, 140.0, 160.0, 160.0, 140.0, meshkernel::constants::missing::doubleValue, - 125.0, 125.0, 135.0, 135.0, 125.0, meshkernel::constants::missing::doubleValue, - 15.0, 15.0, 25.0, 25.0, 15.0, meshkernel::constants::missing::doubleValue, - 0.0, 15.0, 15.0, 0.0, meshkernel::constants::missing::doubleValue, + std::vector invalidCellsY{0.0, 15.0, 15.0, 0.0, + meshkernel::constants::missing::doubleValue, + 140.0, 140.0, 160.0, 160.0, 140.0, + meshkernel::constants::missing::doubleValue, + 125.0, 125.0, 135.0, 135.0, 125.0, + meshkernel::constants::missing::doubleValue, + 15.0, 15.0, 25.0, 25.0, 15.0, + meshkernel::constants::missing::doubleValue, + 0.0, 15.0, 15.0, 0.0, + meshkernel::constants::missing::doubleValue, 0.0, 15.0, 15.0, 0.0}; meshkernelapi::GeometryList invalidCells; @@ -126,7 +136,7 @@ TEST(InvalidCellsPolygonsTests, MeshHolesAreMainainedAfterRefinement) ASSERT_EQ(mesh2d.num_nodes, 3130); ASSERT_EQ(mesh2d.num_edges, 6383); - ASSERT_EQ(mesh2d.num_faces, 3248); + ASSERT_EQ(mesh2d.num_faces, 3232); int whichMeshkernelId = -1; bool isUndone = false; @@ -191,15 +201,33 @@ TEST(InvalidCellsPolygonsTests, MeshHolesAreMainainedAfterRefinement) //----------------------- // Check the inner boundary polygon are correct - std::vector expectedInnerX{80.0, 85.0, 75.0, 80.0, -999.0, 100.0, 105.0, 95.0, 100.0, -999.0, 120.0, 125.0, 115.0, 120.0, -999.0, 180.0, 200.0, 200.0, 180.0, 180.0, -999.0, 95.0, 95.0, 85.0, 85.0, 95.0, -999.0, 125.0, 135.0, 135.0, 125.0, 125.0}; - std::vector expectedInnerY{0.0, 15.0, 15.0, 0.0, -999.0, 0.0, 15.0, 15.0, 0.0, -999.0, 0.0, 15.0, 15.0, 0.0, -999.0, 140.0, 140.0, 160.0, 160.0, 140.0, -999.0, 15.0, 25.0, 25.0, 15.0, 15.0, -999.0, 125.0, 125.0, 135.0, 135.0, 125.0}; + std::vector expectedInnerX{95.0, 100.0, 105.0, 95.0, + meshkernel::constants::missing::doubleValue, + 85.0, 95.0, 95.0, 85.0, 85.0, + meshkernel::constants::missing::doubleValue, + 80.0, 85.0, 75.0, 80.0, + meshkernel::constants::missing::doubleValue, + 120.0, 125.0, 115.0, 120.0, + meshkernel::constants::missing::doubleValue, + 125.0, 125.0, 135.0, 135.0, 125.0}; + + std::vector expectedInnerY{15.0, 0.0, 15.0, 15.0, + meshkernel::constants::missing::doubleValue, + 15.0, 15.0, 25.0, 25.0, 15.0, + meshkernel::constants::missing::doubleValue, + 0.0, 15.0, 15.0, 0.0, + meshkernel::constants::missing::doubleValue, + 0.0, 15.0, 15.0, 0.0, + meshkernel::constants::missing::doubleValue, + 125.0, 135.0, 135.0, 125.0, 125.0}; int innerPolygonSize = 0; meshkernelapi::GeometryList innerPolygon; errorCode = meshkernelapi::mkernel_mesh2d_get_mesh_inner_boundaries_as_polygons_dimension(meshKernelId, innerPolygonSize); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); - ASSERT_EQ(innerPolygonSize, 32); + + ASSERT_EQ(innerPolygonSize, 26); innerPolygon.num_coordinates = innerPolygonSize; std::vector xInner(innerPolygon.num_coordinates);