From 4676c3192b4411ee6795e26ed2b4ba9c9737440e Mon Sep 17 00:00:00 2001 From: Bill Senior Date: Tue, 11 Nov 2025 17:34:36 +0100 Subject: [PATCH 1/4] GRIDEDIT-2042 Updated comment --- meshkernel/meshkernel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshkernel/meshkernel.py b/meshkernel/meshkernel.py index 511c6796..6c6c0dfa 100644 --- a/meshkernel/meshkernel.py +++ b/meshkernel/meshkernel.py @@ -286,7 +286,7 @@ def mesh2d_delete_faces_in_polygons( self, geometry_list: GeometryList, ) -> None: - """Deletes a faces of the mesh that lie inside a polygon or polygons. + """Deletes the faces of the mesh that lie inside a polygon or polygons. Args: geometry_list (GeometryList): The GeometryList describing the polygon where to perform the deletion. From 596ac92c72ba1bc73c0dbd700b5dab050053f33b Mon Sep 17 00:00:00 2001 From: BillSenior Date: Thu, 13 Nov 2025 15:42:27 +0100 Subject: [PATCH 2/4] GRIDEDIT-2042 Use mesh.nodes_per_face instead of mesh.face_x when setting mesh.num_faces. This is then consistent with mesh.face_nodes array (both will be set or both will be null) --- meshkernel/c_structures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshkernel/c_structures.py b/meshkernel/c_structures.py index 9b74f128..742e542b 100644 --- a/meshkernel/c_structures.py +++ b/meshkernel/c_structures.py @@ -111,7 +111,7 @@ def from_mesh2d(mesh2d: Mesh2d) -> CMesh2d: # Set the sizes c_mesh2d.num_nodes = mesh2d.node_x.size c_mesh2d.num_edges = mesh2d.edge_nodes.size // 2 - c_mesh2d.num_faces = mesh2d.face_x.size + c_mesh2d.num_faces = mesh2d.nodes_per_face.size c_mesh2d.num_face_nodes = mesh2d.face_nodes.size return c_mesh2d From ddb57027a3fc03bd35730f0ffcfb0d7fb7d1086d Mon Sep 17 00:00:00 2001 From: veenstrajelmer Date: Thu, 13 Nov 2025 16:29:40 +0100 Subject: [PATCH 3/4] add testcase for mesh2d_set including holes/face_node_connectivity --- tests/test_mesh2d_basics.py | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/tests/test_mesh2d_basics.py b/tests/test_mesh2d_basics.py index 9d91feba..8f42780e 100644 --- a/tests/test_mesh2d_basics.py +++ b/tests/test_mesh2d_basics.py @@ -73,6 +73,71 @@ def test_mesh2d_set_and_mesh2d_get(): assert_array_equal(output_mesh2d.edge_y, np.array([0.0, 0.5, 1.0, 0.5])) +def test_mesh2d_set_and_mesh2d_get_with_holes(): + """ + mesh2d_set has to preserve any existing holes/illegalcells in the grid + Was not the case before resolving issue + https://github.com/Deltares/MeshKernelPy/issues/247 + """ + + # create base grid + projection = ProjectionType.SPHERICAL + make_grid_parameters = MakeGridParameters( + angle=0, + origin_x=147.75, + origin_y=-40.4, + upper_right_x=147.9, + upper_right_y=-40.25, + block_size_x=0.01, + block_size_y=0.01, + ) + + mk = MeshKernel(projection=projection) + mk.curvilinear_compute_rectangular_grid_on_extension(make_grid_parameters) + mk.curvilinear_convert_to_mesh2d() + + # this grid has 320 faces before deletion + assert len(mk.mesh2d_get().face_x) == 320 + + #cut a hole in the grid + xx, yy = np.array([[147.815, -40.282], + [147.835, -40.282], + [147.835 , -40.305], + [147.815, -40.305], + [147.815, -40.282]]).T + + delete_pol_geom = GeometryList( + x_coordinates=xx, + y_coordinates=yy, + geometry_separator=-999, + ) + mk.mesh2d_delete(geometry_list=delete_pol_geom, + delete_option=DeleteMeshOption.INSIDE_NOT_INTERSECTED, + invert_deletion=False, + ) + + mk_grid = mk.mesh2d_get() + + # recreate the grid with minimal information, specifically by leaving out + # face_x/face_y but including face_nodes and nodes_per_face since this is + # the face_node_connectivity + mk2_grid = Mesh2d( + node_x=mk_grid.node_x, + node_y=mk_grid.node_y, + edge_nodes=mk_grid.edge_nodes, + face_nodes=mk_grid.face_nodes, + nodes_per_face=mk_grid.nodes_per_face, + ) + + mk2 = MeshKernel(projection=projection) + mk2.mesh2d_set(mk2_grid) + + # assert the number of faces, if the face_node_connectivity includes a face + # at the location of the deleted cells, there will be 319 faces + assert len(mk.mesh2d_get().face_x) == 318 + assert len(mk2.mesh2d_get().face_x) == 318 + + def test_mesh2d_add(): """Test adding a 2d mesh""" mk = MeshKernel() From a10e84a199a9f3cc6afd4367e2dde971a1fe8b59 Mon Sep 17 00:00:00 2001 From: veenstrajelmer Date: Thu, 13 Nov 2025 16:31:51 +0100 Subject: [PATCH 4/4] black --- tests/test_mesh2d_basics.py | 49 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/tests/test_mesh2d_basics.py b/tests/test_mesh2d_basics.py index 8f42780e..1c6576bf 100644 --- a/tests/test_mesh2d_basics.py +++ b/tests/test_mesh2d_basics.py @@ -79,7 +79,7 @@ def test_mesh2d_set_and_mesh2d_get_with_holes(): Was not the case before resolving issue https://github.com/Deltares/MeshKernelPy/issues/247 """ - + # create base grid projection = ProjectionType.SPHERICAL make_grid_parameters = MakeGridParameters( @@ -90,34 +90,39 @@ def test_mesh2d_set_and_mesh2d_get_with_holes(): upper_right_y=-40.25, block_size_x=0.01, block_size_y=0.01, - ) - + ) + mk = MeshKernel(projection=projection) mk.curvilinear_compute_rectangular_grid_on_extension(make_grid_parameters) mk.curvilinear_convert_to_mesh2d() - + # this grid has 320 faces before deletion assert len(mk.mesh2d_get().face_x) == 320 - - #cut a hole in the grid - xx, yy = np.array([[147.815, -40.282], - [147.835, -40.282], - [147.835 , -40.305], - [147.815, -40.305], - [147.815, -40.282]]).T - + + # cut a hole in the grid + xx, yy = np.array( + [ + [147.815, -40.282], + [147.835, -40.282], + [147.835, -40.305], + [147.815, -40.305], + [147.815, -40.282], + ] + ).T + delete_pol_geom = GeometryList( x_coordinates=xx, y_coordinates=yy, geometry_separator=-999, - ) - mk.mesh2d_delete(geometry_list=delete_pol_geom, - delete_option=DeleteMeshOption.INSIDE_NOT_INTERSECTED, - invert_deletion=False, - ) - + ) + mk.mesh2d_delete( + geometry_list=delete_pol_geom, + delete_option=DeleteMeshOption.INSIDE_NOT_INTERSECTED, + invert_deletion=False, + ) + mk_grid = mk.mesh2d_get() - + # recreate the grid with minimal information, specifically by leaving out # face_x/face_y but including face_nodes and nodes_per_face since this is # the face_node_connectivity @@ -127,11 +132,11 @@ def test_mesh2d_set_and_mesh2d_get_with_holes(): edge_nodes=mk_grid.edge_nodes, face_nodes=mk_grid.face_nodes, nodes_per_face=mk_grid.nodes_per_face, - ) - + ) + mk2 = MeshKernel(projection=projection) mk2.mesh2d_set(mk2_grid) - + # assert the number of faces, if the face_node_connectivity includes a face # at the location of the deleted cells, there will be 319 faces assert len(mk.mesh2d_get().face_x) == 318