From 9a886fff5bb9abd4cebff2d5f256123257aef9e1 Mon Sep 17 00:00:00 2001 From: RStolkerDeltares Date: Fri, 6 Mar 2026 20:16:33 +0100 Subject: [PATCH] GRIDEDIT-2158: Added API for retrieving 2D mesh properties --- src/MeshKernelNET/Api/IMeshKernelApi.cs | 123 ++------ src/MeshKernelNET/Api/LocationType.cs | 23 ++ src/MeshKernelNET/Api/MeshKernelApi.cs | 169 ++++------- src/MeshKernelNET/Api/PropertyType.cs | 23 ++ src/MeshKernelNET/Native/MeshKernelDll.cs | 46 ++- .../Api/MeshKernelApiTest.cs | 263 +++++++++++++----- .../Api/MeshKernelCurvilinearTest.cs | 6 +- 7 files changed, 332 insertions(+), 321 deletions(-) create mode 100644 src/MeshKernelNET/Api/LocationType.cs create mode 100644 src/MeshKernelNET/Api/PropertyType.cs diff --git a/src/MeshKernelNET/Api/IMeshKernelApi.cs b/src/MeshKernelNET/Api/IMeshKernelApi.cs index bb47065..c022bb1 100644 --- a/src/MeshKernelNET/Api/IMeshKernelApi.cs +++ b/src/MeshKernelNET/Api/IMeshKernelApi.cs @@ -246,52 +246,21 @@ int CurvilinearComputeTransfiniteFromTriangle(int meshKernelId, int CurvilinearGetBoundariesAsPolygons(int meshKernelId, int lowerLeftN, int lowerLeftM, int upperRightN, int upperRightM, out DisposableGeometryList boundaryPolygons); /// - /// Gets the index of the closest curvilinear edge + /// Gets the index of the closest curvilinear location type /// - /// /// meshKernelId The id of the mesh state + /// The location (nodes, edges, or faces) at which the index should be retrieved /// The input point coordinates /// The input point coordinates /// The input bounding box /// The location index /// Error code - int CurvilinearGetEdgeLocationIndex(int meshKernelId, - double xCoordinate, - double yCoordinate, - BoundingBox boundingBox, - ref int locationIndex); - - /// - /// Gets the index of the closest curvilinear face - /// - /// - /// meshKernelId The id of the mesh state - /// The input point coordinates - /// The input point coordinates - /// The input bounding box - /// The location index - /// Error code - int CurvilinearGetFaceLocationIndex(int meshKernelId, - double xCoordinate, - double yCoordinate, - BoundingBox boundingBox, - ref int locationIndex); - - /// - /// Gets the index of the closest curvilinear node - /// - /// - /// meshKernelId The id of the mesh state - /// The input point coordinates - /// The input point coordinates - /// The input bounding box - /// The location index - /// Error code - int CurvilinearGetNodeLocationIndex(int meshKernelId, - double xCoordinate, - double yCoordinate, - BoundingBox boundingBox, - ref int locationIndex); + int CurvilinearGetLocationIndex(int meshKernelId, + LocationType locationType, + double xCoordinate, + double yCoordinate, + BoundingBox boundingBox, + ref int locationIndex); /// /// Initializes the curvilinear line shift algorithm @@ -737,14 +706,7 @@ int CurvilinearSnapToSpline(int meshKernelId, /// The int indicating the averaging method type /// Error code int GetAveragingMethodSimpleAveraging(ref int method); - - /// - /// Gets an int indicating the edge location type - /// - /// The int indicating the edge location type - /// Error code - int GetEdgesLocationType(ref int type); - + /// /// Gets a pointer to error message /// @@ -822,13 +784,6 @@ int CurvilinearSnapToSpline(int meshKernelId, /// Error code int GetExitCodeUnknownException(ref int exitCode); - /// - /// Gets an int indicating the faces location type - /// - /// The int indicating the face location type - /// Error code - int GetFacesLocationType(ref int type); - /// /// get geometry error /// @@ -837,13 +792,6 @@ int CurvilinearSnapToSpline(int meshKernelId, /// Error code int GetGeometryError(ref int invalidIndex, ref int type); - /// - /// Gets an int indicating the node location type - /// - /// The int indicating the node location type - /// Error code - int GetNodesLocationType(ref int type); - /// /// Gets the coordinate projection of the meshkernel state /// @@ -922,7 +870,7 @@ int GetSplines(DisposableGeometryList disposableGeometryListIn, /// Error code int Mesh2dAveragingInterpolation(int meshKernelId, DisposableGeometryList samples, - int locationType, + LocationType locationType, int averagingMethodType, double relativeSearchSize, int minNumSamples, @@ -1232,48 +1180,17 @@ int Mesh2dGetEdge(int meshKernelId, double xCoordinate, double yCoordinate, doub int Mesh2dGetHangingEdges(int meshKernelId, out IntArrayWrapper hangingEdges); /// - /// Gets the index of the closest mesh edge + /// Gets the index of the closest mesh location type /// - /// /// meshKernelId The id of the mesh state + /// The location (nodes, edges, or faces) at which the index should be retrieved /// The input point coordinates /// The input point coordinates /// The input bounding box /// The location index /// Error code - int Mesh2dGetEdgeLocationIndex(int meshKernelId, - double xCoordinate, - double yCoordinate, - BoundingBox boundingBox, - ref int locationIndex); - - /// - /// Gets the index of the closest mesh face. - /// - /// - /// meshKernelId The id of the mesh state - /// The input point coordinates - /// The input point coordinates - /// The input bounding box - /// The location index - /// Error code - int Mesh2dGetFaceLocationIndex(int meshKernelId, - double xCoordinate, - double yCoordinate, - BoundingBox boundingBox, - ref int locationIndex); - - /// - /// Gets the index of the closest mesh node - /// - /// - /// meshKernelId The id of the mesh state - /// The input point coordinates - /// The input point coordinates - /// The input bounding box - /// The location index - /// Error code - int Mesh2dGetNodeLocationIndex(int meshKernelId, + int Mesh2dGetLocationIndex(int meshKernelId, + LocationType locationType, double xCoordinate, double yCoordinate, BoundingBox boundingBox, @@ -1333,6 +1250,16 @@ int GetSelectedVerticesInPolygon(int meshKernelId, DisposableGeometryList dispos /// Error code int Mesh2dGetOrthogonality(int meshKernelId, ref DisposableGeometryList disposableGeometryListOut); + /// + /// Retrieves a specified property of a 2D mesh. + /// + /// The id of the mesh state + /// The type of property values to retrieve + /// The location (nodes, edges, or faces) at which the property should be retrieved + /// The geometry list populated with the values of the requested property + /// Error code + int Mesh2dGetProperty(int meshKernelId, PropertyType propertyType, LocationType locationType, out DisposableGeometryList propertyValues); + /// /// Counts the number of polygon nodes contained in the mesh boundary polygons computed in function /// `mkernel_mesh2d_get_mesh_boundaries_as_polygons` @@ -1658,7 +1585,7 @@ int Mesh2dRefineBasedOnSamples(int meshKernelId, /// The location type /// The interpolation results with x and y coordinates /// Error code - int Mesh2dTriangulationInterpolation(int meshKernelId, DisposableGeometryList samples, int locationType, ref DisposableGeometryList results); + int Mesh2dTriangulationInterpolation(int meshKernelId, DisposableGeometryList samples, LocationType locationType, ref DisposableGeometryList results); /// Compute the network chainages from fixed point locations /// The id of the mesh state diff --git a/src/MeshKernelNET/Api/LocationType.cs b/src/MeshKernelNET/Api/LocationType.cs new file mode 100644 index 0000000..75652ca --- /dev/null +++ b/src/MeshKernelNET/Api/LocationType.cs @@ -0,0 +1,23 @@ +namespace MeshKernelNET.Api +{ + /// + /// Enum for the location type on a mesh. + /// + public enum LocationType + { + /// + /// The faces location type. + /// + Faces = 0, + + /// + /// The nodes location type. + /// + Nodes = 1, + + /// + /// The edges location type. + /// + Edges = 2 + } +} \ No newline at end of file diff --git a/src/MeshKernelNET/Api/MeshKernelApi.cs b/src/MeshKernelNET/Api/MeshKernelApi.cs index 22e1e8f..8d4ea0d 100644 --- a/src/MeshKernelNET/Api/MeshKernelApi.cs +++ b/src/MeshKernelNET/Api/MeshKernelApi.cs @@ -265,59 +265,15 @@ public int CurvilinearGetBoundariesAsPolygons(int meshKernelId, int lowerLeftN, } } - public int CurvilinearGetEdgeLocationIndex(int meshKernelId, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) + public int CurvilinearGetLocationIndex(int meshKernelId, LocationType locationType, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) { - int locationType = -1; - var exitCode = MeshKernelDll.GetEdgesLocationType(ref locationType); - if (exitCode != 0) - { - return exitCode; - } - var boundingBoxNative = boundingBox.ToBoundingBoxNative(); - exitCode = MeshKernelDll.CurvilinearGetLocationIndex(meshKernelId, - xCoordinate, - yCoordinate, - locationType, - ref boundingBoxNative, - ref locationIndex); - return exitCode; - } - - public int CurvilinearGetFaceLocationIndex(int meshKernelId, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) - { - int locationType = -1; - var exitCode = MeshKernelDll.GetFacesLocationType(ref locationType); - if (exitCode != 0) - { - return exitCode; - } - - var boundingBoxNative = boundingBox.ToBoundingBoxNative(); - exitCode = MeshKernelDll.CurvilinearGetLocationIndex(meshKernelId, - xCoordinate, - yCoordinate, - locationType, - ref boundingBoxNative, - ref locationIndex); - return exitCode; - } - - public int CurvilinearGetNodeLocationIndex(int meshKernelId, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) - { - int locationType = -1; - var exitCode = MeshKernelDll.GetNodesLocationType(ref locationType); - if (exitCode != 0) - { - return exitCode; - } var boundingBoxNative = boundingBox.ToBoundingBoxNative(); - exitCode = MeshKernelDll.CurvilinearGetLocationIndex(meshKernelId, - xCoordinate, - yCoordinate, - locationType, - ref boundingBoxNative, - ref locationIndex); - return exitCode; + return MeshKernelDll.CurvilinearGetLocationIndex(meshKernelId, + xCoordinate, + yCoordinate, + Convert.ToInt32(locationType), + ref boundingBoxNative, + ref locationIndex); } public int CurvilinearInitializeLineShift(int meshKernelId) @@ -686,11 +642,6 @@ public int GetAveragingMethodSimpleAveraging(ref int method) return MeshKernelDll.GetAveragingMethodSimpleAveraging(ref method); } - public int GetEdgesLocationType(ref int type) - { - return MeshKernelDll.GetEdgesLocationType(ref type); - } - public int GetError(out string errorMessage) { var bufferSize = 512; @@ -758,21 +709,11 @@ public int GetExitCodeUnknownException(ref int exitCode) return MeshKernelDll.GetExitCodeUnknownException(ref exitCode); } - public int GetFacesLocationType(ref int type) - { - return MeshKernelDll.GetFacesLocationType(ref type); - } - public int GetGeometryError(ref int invalidIndex, ref int type) { return MeshKernelDll.GetGeometryError(ref invalidIndex, ref type); } - public int GetNodesLocationType(ref int type) - { - return MeshKernelDll.GetNodesLocationType(ref type); - } - public int GetProjection(int meshKernelId, ref int projection) { return MeshKernelDll.GetProjection(meshKernelId, ref projection); @@ -850,7 +791,7 @@ public int Mesh1dSet(int meshKernelId, DisposableMesh1D disposableMesh1D) public int Mesh2dAveragingInterpolation(int meshKernelId, DisposableGeometryList samples, - int locationType, + LocationType locationType, int averagingMethodType, double relativeSearchSize, int minNumSamples, @@ -861,7 +802,7 @@ public int Mesh2dAveragingInterpolation(int meshKernelId, return MeshKernelDll.Mesh2dAveragingInterpolation(meshKernelId, ref samplesNative, - locationType, + Convert.ToInt32(locationType), averagingMethodType, relativeSearchSize, minNumSamples, @@ -1190,58 +1131,15 @@ public int Mesh2dGetHangingEdges(int meshKernelId, out IntArrayWrapper hangingEd return exitCode; } - public int Mesh2dGetEdgeLocationIndex(int meshKernelId, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) + public int Mesh2dGetLocationIndex(int meshKernelId, LocationType locationType, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) { - int locationType = -1; - var exitCode = MeshKernelDll.GetEdgesLocationType(ref locationType); - if (exitCode != 0) - { - return exitCode; - } var boundingBoxNative = boundingBox.ToBoundingBoxNative(); - exitCode = MeshKernelDll.Mesh2dGetLocationIndex(meshKernelId, - xCoordinate, - yCoordinate, - locationType, - ref boundingBoxNative, - ref locationIndex); - return exitCode; - } - - public int Mesh2dGetFaceLocationIndex(int meshKernelId, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) - { - int locationType = -1; - var exitCode = MeshKernelDll.GetFacesLocationType(ref locationType); - if (exitCode != 0) - { - return exitCode; - } - var boundingBoxNative = boundingBox.ToBoundingBoxNative(); - exitCode = MeshKernelDll.Mesh2dGetLocationIndex(meshKernelId, - xCoordinate, - yCoordinate, - locationType, - ref boundingBoxNative, - ref locationIndex); - return exitCode; - } - - public int Mesh2dGetNodeLocationIndex(int meshKernelId, double xCoordinate, double yCoordinate, BoundingBox boundingBox, ref int locationIndex) - { - int locationType = -1; - var exitCode = MeshKernelDll.GetNodesLocationType(ref locationType); - if (exitCode != 0) - { - return exitCode; - } - var boundingBoxNative = boundingBox.ToBoundingBoxNative(); - exitCode = MeshKernelDll.Mesh2dGetLocationIndex(meshKernelId, - xCoordinate, - yCoordinate, - locationType, - ref boundingBoxNative, - ref locationIndex); - return exitCode; + return MeshKernelDll.Mesh2dGetLocationIndex(meshKernelId, + xCoordinate, + yCoordinate, + Convert.ToInt32(locationType), + ref boundingBoxNative, + ref locationIndex); } public int Mesh2dGetMeshBoundariesAsPolygons(int meshKernelId, DisposableGeometryList selectingPolygon, ref DisposableGeometryList disposableGeometryList) @@ -1309,6 +1207,37 @@ public int Mesh2dGetOrthogonality(int meshKernelId, ref DisposableGeometryList d return MeshKernelDll.Mesh2dGetOrthogonality(meshKernelId, ref geometryListNativeIn); } + public int Mesh2dGetProperty(int meshKernelId, PropertyType propertyType, LocationType locationType, out DisposableGeometryList propertyValues) + { + propertyValues = new DisposableGeometryList(); + + var propertyId = Convert.ToInt32(propertyType); + var locationId = Convert.ToInt32(locationType); + + int dimension = -1; + int exitCode = MeshKernelDll.Mesh2dGetPropertyDimension(meshKernelId, propertyId, locationId, ref dimension); + if (exitCode != 0) + { + return exitCode; + } + + using (var exchangePropertyValues = new DisposableGeometryList(dimension)) + { + exchangePropertyValues.GeometrySeparator = GetSeparator(); + exchangePropertyValues.InnerOuterSeparator = GetInnerOuterSeparator(); + + GeometryListNative geometryListNative = exchangePropertyValues.CreateNativeObject(); + exitCode = MeshKernelDll.Mesh2dGetProperty(meshKernelId, propertyId, locationId, ref geometryListNative); + if (exitCode != 0) + { + return exitCode; + } + + propertyValues.UpdateFromNativeObject(ref geometryListNative); + return exitCode; + } + } + public int Mesh2dCountObtuseTriangles(int meshKernelId, ref int numObtuseTriangles) { return MeshKernelDll.Mesh2dCountObtuseTriangles(meshKernelId, ref numObtuseTriangles); @@ -1604,7 +1533,7 @@ public double GetInnerOuterSeparator() return MeshKernelDll.GetInnerOuterSeparator(); } - public int Mesh2dTriangulationInterpolation(int meshKernelId, DisposableGeometryList samples, int locationType, ref DisposableGeometryList results) + public int Mesh2dTriangulationInterpolation(int meshKernelId, DisposableGeometryList samples, LocationType locationType, ref DisposableGeometryList results) { if (samples.NumberOfCoordinates <= 0) { @@ -1613,7 +1542,7 @@ public int Mesh2dTriangulationInterpolation(int meshKernelId, DisposableGeometry GeometryListNative samplesNative = samples.CreateNativeObject(); GeometryListNative resultsNative = results.CreateNativeObject(); - return MeshKernelDll.Mesh2dTriangulationInterpolation(meshKernelId, ref samplesNative, locationType, ref resultsNative); + return MeshKernelDll.Mesh2dTriangulationInterpolation(meshKernelId, ref samplesNative, Convert.ToInt32(locationType), ref resultsNative); } public int Network1dComputeFixedChainages(int meshKernelId, double[] fixedChainages, double minFaceSize, double fixedChainagesOffset) diff --git a/src/MeshKernelNET/Api/PropertyType.cs b/src/MeshKernelNET/Api/PropertyType.cs new file mode 100644 index 0000000..4dea3e8 --- /dev/null +++ b/src/MeshKernelNET/Api/PropertyType.cs @@ -0,0 +1,23 @@ +namespace MeshKernelNET.Api +{ + /// + /// Enum for different properties on a 2D mesh. + /// + public enum PropertyType + { + /// + /// The orthogonality of the mesh. + /// + Orthogonality = 0, + + /// + /// The length of the mesh edges. + /// + EdgeLength = 1, + + /// + /// The circumcenter of the mesh faces. + /// + FaceCircumcenter = 2 + } +} \ No newline at end of file diff --git a/src/MeshKernelNET/Native/MeshKernelDll.cs b/src/MeshKernelNET/Native/MeshKernelDll.cs index 3e7783d..970a4e9 100644 --- a/src/MeshKernelNET/Native/MeshKernelDll.cs +++ b/src/MeshKernelNET/Native/MeshKernelDll.cs @@ -836,14 +836,6 @@ internal static extern int CurvilinearSnapToSpline([In] int meshKernelId, [DllImport(MeshKernelDllName, EntryPoint = "mkernel_get_averaging_method_simple_averaging", CallingConvention = CallingConvention.Cdecl)] internal static extern int GetAveragingMethodSimpleAveraging([In][Out] ref int method); - /// - /// Gets an int indicating the edge location type - /// - /// The int indicating the edge location type - /// Error code - [DllImport(MeshKernelDllName, EntryPoint = "mkernel_get_edges_location_type", CallingConvention = CallingConvention.Cdecl)] - internal static extern int GetEdgesLocationType([In][Out] ref int type); - /// /// Gets a pointer to error message /// @@ -932,14 +924,6 @@ internal static extern int CurvilinearSnapToSpline([In] int meshKernelId, [DllImport(MeshKernelDllName, EntryPoint = "mkernel_get_exit_code_unknown_exception", CallingConvention = CallingConvention.Cdecl)] internal static extern int GetExitCodeUnknownException([In][Out] ref int exitCode); - /// - /// Gets an int indicating the faces location type - /// - /// The int indicating the face location type - /// Error code - [DllImport(MeshKernelDllName, EntryPoint = "mkernel_get_faces_location_type", CallingConvention = CallingConvention.Cdecl)] - internal static extern int GetFacesLocationType([In][Out] ref int type); - /// /// get geometry error /// @@ -949,14 +933,6 @@ internal static extern int CurvilinearSnapToSpline([In] int meshKernelId, [DllImport(MeshKernelDllName, EntryPoint = "mkernel_get_geometry_error", CallingConvention = CallingConvention.Cdecl)] internal static extern int GetGeometryError([In][Out] ref int invalidIndex, [In][Out] ref int type); - /// - /// Gets an int indicating the node location type - /// - /// The int indicating the node location type - /// Error code - [DllImport(MeshKernelDllName, EntryPoint = "mkernel_get_nodes_location_type", CallingConvention = CallingConvention.Cdecl)] - internal static extern int GetNodesLocationType([In][Out] ref int type); - /// /// Gets the coordinate projection of the meshkernel state /// @@ -1519,6 +1495,28 @@ internal static extern int GetSelectedVerticesInPolygon([In] int meshKernelId, [DllImport(MeshKernelDllName, EntryPoint = "mkernel_mesh2d_get_orthogonality", CallingConvention = CallingConvention.Cdecl)] internal static extern int Mesh2dGetOrthogonality([In] int meshKernelId, [In][Out] ref GeometryListNative geometryListIn); + /// + /// Retrieves a specified property of a 2D mesh. + /// + /// The id of the mesh state + /// The id representing the specific property + /// The location (nodes, edge centres or face centres) at which the samples should be interpolated + /// The geometry list that will be populated with the values of the requested property + /// Error code + [DllImport(MeshKernelDllName, EntryPoint = "mkernel_mesh2d_get_property", CallingConvention = CallingConvention.Cdecl)] + internal static extern int Mesh2dGetProperty([In] int meshKernelId, [In] int propertyId, [In] int locationId, [In][Out] ref GeometryListNative geometryListNative); + + /// + /// Gets the dimension of a specified property of a 2D mesh. + /// + /// The id of the mesh state + /// The value representing the specific property + /// The location (nodes, edge centres or face centres) at which the samples should be interpolated + /// The dimension of the specified property + /// Error code + [DllImport(MeshKernelDllName, EntryPoint = "mkernel_mesh2d_get_property_dimension", CallingConvention = CallingConvention.Cdecl)] + internal static extern int Mesh2dGetPropertyDimension([In] int meshKernelId, [In] int propertyId, [In] int locationId, [In][Out] ref int dimension); + /// /// Counts the number of selected mesh node indexes /// diff --git a/test/MeshKernelNETTest/Api/MeshKernelApiTest.cs b/test/MeshKernelNETTest/Api/MeshKernelApiTest.cs index 38e8a7b..6586709 100644 --- a/test/MeshKernelNETTest/Api/MeshKernelApiTest.cs +++ b/test/MeshKernelNETTest/Api/MeshKernelApiTest.cs @@ -1624,19 +1624,6 @@ public void GetAveragingMethodSimpleAveragingThroughAPI() } } - [Test] - public void GetEdgesLocationTypeThroughAPI() - { - using (var api = new MeshKernelApi()) - { - // Execute - int locationType = -1; - Assert.That(api.GetEdgesLocationType(ref locationType), Is.EqualTo(0)); - // Assert - Assert.That(locationType, Is.EqualTo(2)); - } - } - [Test] public void GetErrorThroughAPI() { @@ -1784,20 +1771,6 @@ public void GetExitCodeUnknownExceptionThroughAPI() } } - [Test] - public void GetFacesLocationTypeThroughAPI() - { - using (var api = new MeshKernelApi()) - { - // Execute - int locationType = -1; - Assert.That(api.GetFacesLocationType(ref locationType), Is.EqualTo(0)); - - // Assert - Assert.That(locationType, Is.EqualTo(0)); - } - } - [Test] public void GetGeometryErrorThroughAPI() { @@ -1813,19 +1786,6 @@ public void GetGeometryErrorThroughAPI() } } - [Test] - public void GetNodesLocationTypeThroughAPI() - { - using (var api = new MeshKernelApi()) - { - // Execute - int type = -1; - Assert.That(api.GetNodesLocationType(ref type), Is.EqualTo(0)); - // Assert - Assert.That(type, Is.EqualTo(1)); - } - } - [Test] public void GetProjectionThroughAPI() { @@ -1956,17 +1916,16 @@ public void Mesh2dAveragingInterpolationThroughAPI() samples.Values = new[] { 3.0, 10, 4.0, 5.0 }; samples.NumberOfCoordinates = 4; - var locationType = 1; var averagingMethodType = 1; var relativeSearchSize = 1.01; - Assert.That(api.Mesh2dAveragingInterpolation(id, - samples, - locationType, - averagingMethodType, - relativeSearchSize, - 0, - ref results), Is.EqualTo(0)); + Assert.That(api.Mesh2dAveragingInterpolation(id, + samples, + LocationType.Nodes, + averagingMethodType, + relativeSearchSize, + 0, + ref results), Is.EqualTo(0)); var expectedValues = new double[results.NumberOfCoordinates]; for (var i = 0; i < results.NumberOfCoordinates; i++) expectedValues[i] = -999; @@ -2561,6 +2520,155 @@ public void Mesh2dDeleteSmallFlowEdgesAndSmallTrianglesThroughApi() } } } + + [Test] + public void Mesh2dGetPropertyOrthogonalityThroughApi() + { + // Setup + using (var api = new MeshKernelApi()) + using (var mesh = new DisposableMesh2D()) + { + var propertyValues = new DisposableGeometryList(); + try + { + // Prepare - a sheared 2-cell parallelogram mesh + // 3----4----5 + // / / / + // 0---1----2 + mesh.NumNodes = 6; + mesh.NumEdges = 7; + mesh.NodeX = new[] { 0.0, 1.0, 2.0, 0.5, 1.5, 2.5 }; + mesh.NodeY = new[] { 0.0, 0.0, 0.0, 1.0, 1.0, 1.0 }; + mesh.EdgeNodes = new[] { 0, 1, 1, 2, 3, 4, 4, 5, 0, 3, 1, 4, 2, 5 }; + + int id = api.AllocateState(0); + Assert.That(api.Mesh2dSet(id, mesh), Is.EqualTo(0)); + + // Execute + Assert.That(api.Mesh2dGetProperty(id, PropertyType.Orthogonality, LocationType.Edges, out propertyValues), Is.EqualTo(0)); + + // Assert + Assert.That(propertyValues.NumberOfCoordinates, Is.EqualTo(7)); + + // Boundary edges have missing value (-999) + Assert.That(propertyValues.Values.Where((_, i) => i != 5), Is.All.EqualTo(-999.0)); + + // Interior edge 1-4 has non-zero orthogonality due to shear (= 1/sqrt(5)) + const double tolerance = 1.0e-4; + Assert.That(propertyValues.Values[5], Is.EqualTo(0.4472).Within(tolerance)); + } + finally + { + api.ClearState(); + propertyValues.Dispose(); + } + } + } + + [Test] + public void Mesh2dGetPropertyEdgeLengthThroughApi() + { + // Setup + using (var api = new MeshKernelApi()) + using (DisposableMesh2D mesh = CreateMesh2D(4, 4, 100, 200)) + { + var propertyValues = new DisposableGeometryList(); + try + { + // Prepare + int id = api.AllocateState(0); + Assert.That(api.Mesh2dSet(id, mesh), Is.EqualTo(0)); + + // Execute + Assert.That(api.Mesh2dGetProperty(id, PropertyType.EdgeLength, LocationType.Edges, out propertyValues), Is.EqualTo(0)); + + // Assert + Assert.That(propertyValues, Is.Not.Null); + Assert.That(propertyValues.NumberOfCoordinates, Is.EqualTo(mesh.NumEdges)); + Assert.That(propertyValues.Values, Is.Not.Null); + Assert.That(propertyValues.Values.Length, Is.EqualTo(mesh.NumEdges)); + Assert.That(propertyValues.Values.Take(12), Is.All.EqualTo(200.0)); + Assert.That(propertyValues.Values.Skip(12), Is.All.EqualTo(100.0)); + } + finally + { + api.ClearState(); + propertyValues.Dispose(); + } + } + } + + [Test] + public void Mesh2dGetPropertyFaceCircumcenterThroughApi() + { + // Setup + using (var api = new MeshKernelApi()) + using (var mesh = new DisposableMesh2D()) + { + var propertyValues = new DisposableGeometryList(); + try + { + // Prepare - a 2-cell mesh with different cell widths + // 3----4------5 + // | | | + // 0----1------2 + mesh.NumNodes = 6; + mesh.NumEdges = 7; + mesh.NodeX = new[] { 0.0, 2.0, 5.0, 0.0, 2.0, 5.0 }; + mesh.NodeY = new[] { 0.0, 0.0, 0.0, 3.0, 3.0, 3.0 }; + mesh.EdgeNodes = new[] { 0, 1, 1, 2, 3, 4, 4, 5, 0, 3, 1, 4, 2, 5 }; + + int id = api.AllocateState(0); + Assert.That(api.Mesh2dSet(id, mesh), Is.EqualTo(0)); + + // Execute + Assert.That(api.Mesh2dGetProperty(id, PropertyType.FaceCircumcenter, LocationType.Faces, out propertyValues), Is.EqualTo(0)); + + // Assert + Assert.That(propertyValues.NumberOfCoordinates, Is.EqualTo(2)); + Assert.That(propertyValues.XCoordinates[0], Is.EqualTo(1.0)); + Assert.That(propertyValues.YCoordinates[0], Is.EqualTo(1.5)); + Assert.That(propertyValues.XCoordinates[1], Is.EqualTo(3.5)); + Assert.That(propertyValues.YCoordinates[1], Is.EqualTo(1.5)); + } + finally + { + api.ClearState(); + propertyValues.Dispose(); + } + } + } + + [Test] + [TestCase(PropertyType.Orthogonality, LocationType.Faces)] + [TestCase(PropertyType.Orthogonality, LocationType.Nodes)] + [TestCase(PropertyType.EdgeLength, LocationType.Faces)] + [TestCase(PropertyType.EdgeLength, LocationType.Nodes)] + [TestCase(PropertyType.FaceCircumcenter, LocationType.Nodes)] + [TestCase(PropertyType.FaceCircumcenter, LocationType.Edges)] + public void Mesh2dGetPropertyWithInvalidLocationThroughApi(PropertyType propertyType, LocationType locationType) + { + // Setup + using (var api = new MeshKernelApi()) + using (DisposableMesh2D mesh = CreateMesh2D(4, 4, 100, 200)) + { + var propertyValues = new DisposableGeometryList(); + try + { + // Prepare + int id = api.AllocateState(0); + Assert.That(api.Mesh2dSet(id, mesh), Is.EqualTo(0)); + + // Execute & Assert + Assert.That(api.Mesh2dGetProperty(id, propertyType, locationType, out propertyValues), Is.Not.EqualTo(0)); + } + finally + { + api.ClearState(); + propertyValues.Dispose(); + } + } + } [Test] public void Mesh2dGetObtuseTrianglesMassCentersThroughApi() @@ -2986,9 +3094,6 @@ public void Mesh2dTriangulationInterpolationThroughAPI() { // Setup id = api.AllocateState(0); - - int locationType = -1; - Assert.That(api.GetNodesLocationType(ref locationType), Is.EqualTo(0)); Assert.That(api.Mesh2dSet(id, mesh), Is.EqualTo(0)); Assert.That(api.Mesh2dGetData(id, out mesh2D), Is.EqualTo(0)); @@ -3003,7 +3108,7 @@ public void Mesh2dTriangulationInterpolationThroughAPI() results.NumberOfCoordinates = mesh.NumNodes; // Execute - Assert.That(api.Mesh2dTriangulationInterpolation(id, samples, locationType, ref results), Is.EqualTo(0)); + Assert.That(api.Mesh2dTriangulationInterpolation(id, samples, LocationType.Nodes, ref results), Is.EqualTo(0)); // Assert Assert.That(results.Values[4], Is.EqualTo(3)); } @@ -3307,11 +3412,12 @@ public void Mesh2dGetEdgeLocationIndexThroughApi() BoundingBox boundingBox = BoundingBox.CreateDefault(); int locationIndex = -1; - api.Mesh2dGetEdgeLocationIndex(id, - 10.0, - 0.0, - boundingBox, - ref locationIndex); + api.Mesh2dGetLocationIndex(id, + LocationType.Edges, + 10.0, + 0.0, + boundingBox, + ref locationIndex); Assert.That(locationIndex, Is.EqualTo(12)); } @@ -3338,11 +3444,12 @@ public void Mesh2dGetFaceLocationIndexThroughApi() BoundingBox boundingBox = BoundingBox.CreateDefault(); int locationIndex = -1; - api.Mesh2dGetFaceLocationIndex(id, - 10.0, - 0.0, - boundingBox, - ref locationIndex); + api.Mesh2dGetLocationIndex(id, + LocationType.Faces, + 10.0, + 0.0, + boundingBox, + ref locationIndex); Assert.That(locationIndex, Is.EqualTo(0)); } @@ -3371,11 +3478,12 @@ public void Mesh2dGetNodeLocationIndexThroughApi(double x, double y, int expecte BoundingBox boundingBox = BoundingBox.CreateDefault(); int locationIndex = -1; - api.Mesh2dGetNodeLocationIndex(id, - x, - y, - boundingBox, - ref locationIndex); + api.Mesh2dGetLocationIndex(id, + LocationType.Nodes, + x, + y, + boundingBox, + ref locationIndex); Assert.That(locationIndex, Is.EqualTo(expectedIndex)); } @@ -3412,7 +3520,7 @@ public void CurvilinearGetEdgeLocationIndexThroughApi(double x, double y, int ex BoundingBox boundingBox = BoundingBox.CreateDefault(); int actualIndex = -1; - api.CurvilinearGetEdgeLocationIndex(id, x, y, boundingBox, ref actualIndex); + api.CurvilinearGetLocationIndex(id, LocationType.Edges, x, y, boundingBox, ref actualIndex); Assert.That(actualIndex, Is.EqualTo(expectedIndex)); } @@ -3439,11 +3547,12 @@ public void CurvilinearGetFaceLocationIndexThroughApi() BoundingBox boundingBox = BoundingBox.CreateDefault(); int locationIndex = -1; - api.CurvilinearGetFaceLocationIndex(id, - 20.0, - 20.0, - boundingBox, - ref locationIndex); + api.CurvilinearGetLocationIndex(id, + LocationType.Faces, + 20.0, + 20.0, + boundingBox, + ref locationIndex); Assert.That(locationIndex, Is.EqualTo(4)); } @@ -3475,9 +3584,11 @@ public void CurvilinearGetNodeLocationIndexThroughApi(double x, double y, int ex BoundingBox boundingBox = BoundingBox.CreateDefault(); int locationIndex = -1; - api.CurvilinearGetNodeLocationIndex(id, x, y, - boundingBox, - ref locationIndex); + api.CurvilinearGetLocationIndex(id, + LocationType.Nodes, + x, y, + boundingBox, + ref locationIndex); Assert.That(locationIndex, Is.EqualTo(expectedIndex)); } diff --git a/test/MeshKernelNETTest/Api/MeshKernelCurvilinearTest.cs b/test/MeshKernelNETTest/Api/MeshKernelCurvilinearTest.cs index 309b0a2..a5a9179 100644 --- a/test/MeshKernelNETTest/Api/MeshKernelCurvilinearTest.cs +++ b/test/MeshKernelNETTest/Api/MeshKernelCurvilinearTest.cs @@ -1392,7 +1392,7 @@ public void CurvilinearGetNodeLocationIndex_AtOrCloseToVertexPositionFindsNeares yUpperRight = 6 }; int actualIndex = -1; - int returnCode = api.CurvilinearGetNodeLocationIndex(id,x,y,box, ref actualIndex); + int returnCode = api.CurvilinearGetLocationIndex(id,LocationType.Nodes,x,y,box, ref actualIndex); // Assert Assert.That(actualIndex,Is.EqualTo(expectedIndex)); @@ -1427,7 +1427,7 @@ public void CurvilinearGetNodeLocationIndex_OnOrInBoundingBox_FindsNearest(doubl yUpperRight = 3.4 }; int actualIndex = -1; - int returnCode = api.CurvilinearGetNodeLocationIndex(id,x,y,box, ref actualIndex); + int returnCode = api.CurvilinearGetLocationIndex(id,LocationType.Nodes,x,y,box, ref actualIndex); // Assert Assert.That(actualIndex,Is.EqualTo(expectedIndex)); @@ -1458,7 +1458,7 @@ public void CurvilinearGetNodeLocationIndex_DoesNotFindNearest_OutsideBoundingBo yUpperRight = 3.2 }; int actualIndex = -1; - int returnCode = api.CurvilinearGetNodeLocationIndex(id,x,y,box, ref actualIndex); + int returnCode = api.CurvilinearGetLocationIndex(id,LocationType.Nodes,x,y,box, ref actualIndex); // Assert Assert.That(actualIndex,Is.EqualTo(expectedIndex));