diff --git a/Directory.Packages.props b/Directory.Packages.props index bcd3541..6798890 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,8 +2,8 @@ true - - + + diff --git a/src/MeshKernelNET/Api/IMeshKernelApi.cs b/src/MeshKernelNET/Api/IMeshKernelApi.cs index 04d6a75..c77b0a5 100644 --- a/src/MeshKernelNET/Api/IMeshKernelApi.cs +++ b/src/MeshKernelNET/Api/IMeshKernelApi.cs @@ -86,6 +86,15 @@ public interface IMeshKernelApi : IDisposable /// Error code int ContactsGetData(int meshKernelId, out DisposableContacts disposableContacts); + /// + /// Snaps a mesh to a land boundary + /// + /// Id of the mesh state + /// The polygon where to perform the snapping + /// The input land boundaries + /// Error code + int Mesh2dSnapToLandBoundary(int meshKernelId, in DisposableGeometryList selectingPolygon, in DisposableGeometryList landBoundaries); + /// /// Make curvilinear grid from splines /// diff --git a/src/MeshKernelNET/Api/MeshKernelApi.cs b/src/MeshKernelNET/Api/MeshKernelApi.cs index 683137c..1efb389 100644 --- a/src/MeshKernelNET/Api/MeshKernelApi.cs +++ b/src/MeshKernelNET/Api/MeshKernelApi.cs @@ -82,6 +82,13 @@ public int ContactsGetData(int meshKernelId, out DisposableContacts disposableCo return exitCode; } + public int Mesh2dSnapToLandBoundary(int meshKernelId, in DisposableGeometryList selectingPolygon, in DisposableGeometryList landBoundaries) + { + var selectingPolygonNative = selectingPolygon.CreateNativeObject(); + var landBoundariesNative = landBoundaries.CreateNativeObject(); + return MeshKernelDll.Mesh2dSnapToLandBoundary(meshKernelId, ref selectingPolygonNative, ref landBoundariesNative); + } + public int CurvilinearComputeTransfiniteFromSplines(int meshKernelId, in DisposableGeometryList disposableGeometryListIn, in CurvilinearParameters curvilinearParameters) diff --git a/src/MeshKernelNET/Native/MeshKernelDll.cs b/src/MeshKernelNET/Native/MeshKernelDll.cs index 23a61d5..bf58937 100644 --- a/src/MeshKernelNET/Native/MeshKernelDll.cs +++ b/src/MeshKernelNET/Native/MeshKernelDll.cs @@ -1708,6 +1708,16 @@ internal static extern int Mesh2dTranslate([In] int meshKernelId, [DllImport(MeshKernelDllName, EntryPoint = "mkernel_mesh2d_set", CallingConvention = CallingConvention.Cdecl)] internal static extern int Mesh2dSet([In] int meshKernelId, [In] ref Mesh2DNative mesh2DNative); + /// + /// Snaps a mesh to a land boundary + /// + /// Id of the mesh state + /// The polygon where to perform the snapping + /// The input land boundaries + /// Error code + [DllImport(MeshKernelDllName, EntryPoint = "mkernel_mesh2d_snap_to_landboundary", CallingConvention = CallingConvention.Cdecl)] + internal static extern int Mesh2dSnapToLandBoundary([In] int meshKernelId, [In] ref GeometryListNative selectingPolygon, [In] ref GeometryListNative landBoundaries); + /// /// Get the double value used in the back-end library as separator and missing value /// diff --git a/test/MeshKernelNETTest/Api/MeshKernelTest.cs b/test/MeshKernelNETTest/Api/MeshKernelTest.cs index fe7850e..8ebbe11 100644 --- a/test/MeshKernelNETTest/Api/MeshKernelTest.cs +++ b/test/MeshKernelNETTest/Api/MeshKernelTest.cs @@ -3120,40 +3120,120 @@ public void CurvilinearGetNodeLocationIndexThroughApi(double x, double y, int ex } } - [Test] - public void Mesh2dConvertCurvilinearThroughApi() - { - // Setup - using (DisposableMesh2D mesh = CreateMesh2D(10, 10, 10, 10)) - using (var api = new MeshKernelApi()) - { - var id = 0; - var curvilinearGrid = new DisposableCurvilinearGrid(); - var meshOut = new DisposableMesh2D(); - try - { - id = api.AllocateState(0); - - Assert.AreEqual(0, api.Mesh2dSet(id, mesh)); - - - api.Mesh2dConvertCurvilinear(id, 5, 5); - - // Get curvilinear grid data after conversion - Assert.AreEqual(0, api.CurvilinearGridGetData(id, out curvilinearGrid)); - Assert.AreEqual((10, 10), (curvilinearGrid.NumM, curvilinearGrid.NumN)); - - // Get mesh data after conversion - Assert.AreEqual(0, api.Mesh2dGetData(id, out meshOut)); - Assert.AreEqual(0, meshOut.NumNodes); - } - finally - { - api.DeallocateState(id); - curvilinearGrid?.Dispose(); - meshOut?.Dispose(); - } - } + [Test] + public void Mesh2dConvertCurvilinearThroughApi() + { + // Setup + using (DisposableMesh2D mesh = CreateMesh2D(10, 10, 10, 10)) + using (var api = new MeshKernelApi()) + { + var id = 0; + var curvilinearGrid = new DisposableCurvilinearGrid(); + var meshOut = new DisposableMesh2D(); + try + { + id = api.AllocateState(0); + + Assert.AreEqual(0, api.Mesh2dSet(id, mesh)); + + + api.Mesh2dConvertCurvilinear(id, 5, 5); + + // Get curvilinear grid data after conversion + Assert.AreEqual(0, api.CurvilinearGridGetData(id, out curvilinearGrid)); + Assert.AreEqual((10, 10), (curvilinearGrid.NumM, curvilinearGrid.NumN)); + + // Get mesh data after conversion + Assert.AreEqual(0, api.Mesh2dGetData(id, out meshOut)); + Assert.AreEqual(0, meshOut.NumNodes); + } + finally + { + api.DeallocateState(id); + curvilinearGrid?.Dispose(); + meshOut?.Dispose(); + } + } + } + + [Test] + public void Mesh2dSnapToAnEmptyLandBoundaryThroughApi() + { + // Setup + using (DisposableMesh2D mesh = CreateMesh2D(10, 10, 10, 10)) + using (var selectingPolygon = new DisposableGeometryList()) + using (var landBoundaries = new DisposableGeometryList()) + using (var api = new MeshKernelApi()) + { + var id = 0; + var meshOut = new DisposableMesh2D(); + try + { + id = api.AllocateState(0); + + Assert.AreEqual(0, api.Mesh2dSet(id, mesh)); + + api.Mesh2dSnapToLandBoundary(id, in selectingPolygon, in landBoundaries); + + // Get mesh data after conversion + Assert.AreEqual(0, api.Mesh2dGetData(id, out meshOut)); + Assert.AreEqual(100, meshOut.NumNodes); + Assert.AreEqual(0.0, meshOut.NodeX[0]); + Assert.AreEqual(0.0, meshOut.NodeX[1]); + Assert.AreEqual(0.0, meshOut.NodeY[0]); + Assert.AreEqual(10.0, meshOut.NodeY[1]); + } + finally + { + api.DeallocateState(id); + meshOut?.Dispose(); + } + } + } + + [Test] + public void Mesh2dSnapToLandBoundaryThroughApi() + { + // Setup + using (DisposableMesh2D mesh = CreateMesh2D(10, 10, 10, 10)) + using (var selectingPolygon = new DisposableGeometryList()) + using (var landBoundaries = new DisposableGeometryList()) + using (var api = new MeshKernelApi()) + { + var id = 0; + var meshOut = new DisposableMesh2D(); + try + { + // prepare + id = api.AllocateState(0); + + Assert.AreEqual(0, api.Mesh2dSet(id, mesh)); + + selectingPolygon.XCoordinates = new[] { -10.0, 11.0, 15.0, -10.0, -10.0 }; + selectingPolygon.YCoordinates = new[] { -10.0, -10.0, 15.0, 15.0, -10.0 }; + selectingPolygon.NumberOfCoordinates = selectingPolygon.XCoordinates.Length; + + landBoundaries.XCoordinates = new[] { -1.0, 11.0 }; + landBoundaries.YCoordinates = new[] { -1.0, 11.0 }; + landBoundaries.NumberOfCoordinates = landBoundaries.XCoordinates.Length; + + // execute + api.Mesh2dSnapToLandBoundary(id, in selectingPolygon, in landBoundaries); + + // assert + Assert.AreEqual(0, api.Mesh2dGetData(id, out meshOut)); + Assert.AreEqual(100, meshOut.NumNodes); + Assert.AreEqual(0.0, meshOut.NodeX[0]); + Assert.AreEqual(0.0, meshOut.NodeX[1]); + Assert.AreEqual(0.0, meshOut.NodeY[0]); + Assert.AreEqual(10.0, meshOut.NodeY[1]); + } + finally + { + api.DeallocateState(id); + meshOut?.Dispose(); + } + } } }