From 23c17fd6d6137aaf23125730887d9202194c0928 Mon Sep 17 00:00:00 2001 From: BillSenior Date: Mon, 2 Dec 2024 12:09:31 +0100 Subject: [PATCH] GRIDEDIT-1546 Small refactoring after review and discussion --- .../include/MeshKernel/Definitions.hpp | 23 +++++ libs/MeshKernel/include/MeshKernel/Mesh2D.hpp | 3 +- .../include/MeshKernel/SampleInterpolator.hpp | 4 +- .../include/MeshKernelApi/MeshKernel.hpp | 17 ++-- .../MeshKernelApi/PropertyCalculator.hpp | 31 +++++-- .../include/MeshKernelApi/State.hpp | 3 - libs/MeshKernelApi/src/MeshKernel.cpp | 85 +++++++++++++------ libs/MeshKernelApi/src/PropertyCalculator.cpp | 48 +++++------ .../tests/src/MeshPropertyTests.cpp | 67 +++++++-------- 9 files changed, 178 insertions(+), 103 deletions(-) diff --git a/libs/MeshKernel/include/MeshKernel/Definitions.hpp b/libs/MeshKernel/include/MeshKernel/Definitions.hpp index e272c2ec4..34cc731a8 100644 --- a/libs/MeshKernel/include/MeshKernel/Definitions.hpp +++ b/libs/MeshKernel/include/MeshKernel/Definitions.hpp @@ -119,6 +119,12 @@ namespace meshkernel { array[i] } -> std::convertible_to; }; + /// @brief The concept specifies that the array type must have an access operator returning a reference to the array element type + template + concept ArrayNonConstAccessConcept = requires(ArrayType& array, const size_t i) { + { array[i] } -> std::same_as; + }; + /// @brief A concept that specifies that the array must have a size function return the number of elements in the array template concept ArraySizeConcept = requires(const ArrayType& array) { @@ -136,10 +142,27 @@ namespace meshkernel { array.end() }; }; + /// @brief A concept that specifies that the array must have a begin and end function. + /// + /// Would like to also specify the return type here, but span needs some c++23 functionality here. + /// Then change all iterator usage to cbegin and cend returning a const_iterator + /// std::same_as + template + concept ArrayNonConstIteratorsConcept = requires(ArrayType& array) { + { array.begin() } -> std::same_as; + { array.end() } -> std::same_as; + }; + /// @brief A concept that specifies all the functionality required to be usable as a constant array of doubles. template concept ValidConstDoubleArray = ArrayConstAccessConcept && ArrayConstIteratorsConcept && ArraySizeConcept; + /// @brief A concept that specifies all the functionality required to be usable as a constant array of doubles. + template + concept ValidNonConstDoubleArray = ArrayNonConstAccessConcept && + ArrayNonConstIteratorsConcept && + ArraySizeConcept; + } // namespace meshkernel diff --git a/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp b/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp index ba0745dd7..a302040b4 100644 --- a/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp +++ b/libs/MeshKernel/include/MeshKernel/Mesh2D.hpp @@ -80,8 +80,7 @@ namespace meshkernel enum class Property { Orthogonality = 0, - EdgeLength = 1, - Bathymetry = 2 + EdgeLength = 1 }; /// @brief Default destructor diff --git a/libs/MeshKernel/include/MeshKernel/SampleInterpolator.hpp b/libs/MeshKernel/include/MeshKernel/SampleInterpolator.hpp index d4a8dd4a0..e5048569c 100644 --- a/libs/MeshKernel/include/MeshKernel/SampleInterpolator.hpp +++ b/libs/MeshKernel/include/MeshKernel/SampleInterpolator.hpp @@ -56,9 +56,7 @@ namespace meshkernel SampleInterpolator(const VectorType& xNodes, const VectorType& yNodes, const Projection projection) - : m_triangulation(xNodes, yNodes, projection) - { - } + : m_triangulation(xNodes, yNodes, projection) {} /// @brief Get the number of nodes of size of the sample data. UInt Size() const; diff --git a/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp b/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp index d879c496a..d8dfdb97c 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp @@ -685,6 +685,11 @@ namespace meshkernelapi double regionControlPointX = mkernel_get_separator(), double regionControlPointY = mkernel_get_separator()); + /// @brief Deallocate property calculator + /// @param[in] propertyId The id of the property + /// @returns Error code + MKERNEL_API int mkernel_deallocate_property(int propertyId); + /// @brief Deallocate mesh state /// @param[in] meshKernelId The id of the mesh state /// @returns Error code @@ -1344,7 +1349,7 @@ namespace meshkernelapi /// /// @param[in] meshKernelId The id of the mesh state /// @param[in] propertyValue The value representing the specific property - /// @param[in] geometrylist A reference to a GeometryList object that will be populated with the values of the requested property + /// @param[in/out] geometrylist A reference to a GeometryList object that will be populated with the values of the requested property /// @returns Error code MKERNEL_API int mkernel_mesh2d_get_property(int meshKernelId, int propertyValue, const GeometryList& geometrylist); @@ -1352,7 +1357,7 @@ namespace meshkernelapi /// /// @param[in] meshKernelId The id of the mesh state /// @param[in] propertyValue The value representing the specific property - /// @param[in] dimension The dimension of the specified property + /// @param[out] dimension The dimension of the specified property /// @returns Error code MKERNEL_API int mkernel_mesh2d_get_property_dimension(int meshKernelId, int propertyValue, int& dimension); @@ -1448,7 +1453,7 @@ namespace meshkernelapi /// @brief Determine if the property data for the mesh can be computed /// @param[in] meshKernelId The id of the mesh state /// @param[in] propertyId The id of the property - /// @param[out] propertyIsAvailable Indicate (true or false) is the property can be calculated. + /// @param[out] propertyIsAvailable Indicate (true or false) if the property can be calculated. /// @returns Error code MKERNEL_API int mkernel_mesh2d_is_valid_property(int meshKernelId, const int propertyId, bool& propertyIsAvailable); @@ -1603,11 +1608,11 @@ namespace meshkernelapi MKERNEL_API int mkernel_mesh2d_set(int meshKernelId, const Mesh2D& mesh2d); /// @brief Sets the property data for the mesh, the sample data points do not have to match the mesh2d nodes. - /// @param[in] meshKernelId The id of the mesh state - /// @param[in] propertyId The id of the property + /// @param[in] projectionType The projection type used by the sample data /// @param[in] sampleData The sample data and associated sample data points. + /// @param[out] propertyId The id of the property /// @returns Error code - MKERNEL_API int mkernel_mesh2d_set_property(int meshKernelId, const int propertyId, const GeometryList& sampleData); + MKERNEL_API int mkernel_mesh2d_set_property(int projectionType, const GeometryList& sampleData, int& propertyId); /// @brief Snaps a mesh to a land boundary. /// @param[in] meshKernelId The id of the mesh state diff --git a/libs/MeshKernelApi/include/MeshKernelApi/PropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/PropertyCalculator.hpp index 543cc9001..d563bae33 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/PropertyCalculator.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/PropertyCalculator.hpp @@ -27,6 +27,8 @@ #pragma once +#include "MeshKernel/SampleInterpolator.hpp" + #include "MeshKernelApi/GeometryList.hpp" #include "MeshKernelApi/State.hpp" @@ -43,10 +45,10 @@ namespace meshkernelapi /// @brief Determine is the calculator can compute the desired results correctly. /// /// This has a default of checking that the mesh2d is not null and the number of nodes is greater than zero. - virtual bool IsValid(const MeshKernelState& state, const int propertyId) const; + virtual bool IsValid(const MeshKernelState& state) const; /// @brief Calculate the property - virtual void Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const = 0; + virtual void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const = 0; /// @brief Determine the size of the vector required to store the calculated properties virtual int Size(const MeshKernelState& state) const = 0; @@ -57,7 +59,7 @@ namespace meshkernelapi { public: /// @brief Calculate the orthogonality for a mesh - void Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; /// @brief Determine the size of the orthogonality vector required int Size(const MeshKernelState& state) const override; @@ -68,24 +70,39 @@ namespace meshkernelapi { public: /// @brief Calculate the edge-length for a mesh - void Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; /// @brief Determine the size of the edge-length vector required int Size(const MeshKernelState& state) const override; }; /// @brief Interpolate the depths at the mesh node points. - class DepthSamplePropertyCalculator : public PropertyCalculator + class InterpolatedSamplePropertyCalculator : public PropertyCalculator { public: + /// @brief Constructor + InterpolatedSamplePropertyCalculator(const GeometryList& sampleData, + const meshkernel::Projection projection, + const int propertyId); + /// @brief Determine is the calculator can interpolate depth values correctly - bool IsValid(const MeshKernelState& state, const int propertyId) const override; + bool IsValid(const MeshKernelState& state) const override; /// @brief Calculate the edge-length for a mesh - void Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; /// @brief Determine the size of the edge-length vector required int Size(const MeshKernelState& state) const override; + + private: + /// @brief Interpolator for the samples + std::unique_ptr m_sampleInterpolator; + + /// @brief Projection sued for sample data. + meshkernel::Projection m_projection; + + /// @brief Property id. + int m_propertyId = -1; }; } // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/State.hpp b/libs/MeshKernelApi/include/MeshKernelApi/State.hpp index 3fab9de7d..d662b132e 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/State.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/State.hpp @@ -37,7 +37,6 @@ #include #include #include -#include #include "MeshKernelApi/ApiCache/BoundariesAsPolygonCache.hpp" #include "MeshKernelApi/ApiCache/CachedPointValues.hpp" @@ -84,8 +83,6 @@ namespace meshkernelapi // Exclusively owned state meshkernel::Projection m_projection{meshkernel::Projection::cartesian}; ///< Projection used by the meshes - std::shared_ptr m_sampleInterpolator; ///< Associated samples and interpolator - // Cached values, used when dimensions are computed first, followed by values being retrieved in a separate call std::shared_ptr m_facePropertyCache; ///< face property cache std::shared_ptr m_boundariesAsPolygonCache; ///< boundaries as polygon cache diff --git a/libs/MeshKernelApi/src/MeshKernel.cpp b/libs/MeshKernelApi/src/MeshKernel.cpp index 59eb9b52b..a31b7f04e 100644 --- a/libs/MeshKernelApi/src/MeshKernel.cpp +++ b/libs/MeshKernelApi/src/MeshKernel.cpp @@ -127,6 +127,15 @@ namespace meshkernelapi /// @brief Stack of undo actions static meshkernel::UndoActionStack meshKernelUndoStack; + int GeneratePropertyId() + { + // The current property id, initialised with a number larger than the Mesh2D:::Property enum values + static int currentPropertyId = static_cast(meshkernel::Mesh2D::Property::EdgeLength); + + // Increment and return the current property id value. + return ++currentPropertyId; + } + std::map> allocatePropertyCalculators() { std::map> propertyMap; @@ -137,9 +146,6 @@ namespace meshkernelapi propertyId = static_cast(meshkernel::Mesh2D::Property::EdgeLength); propertyMap.emplace(propertyId, std::make_unique()); - propertyId = static_cast(meshkernel::Mesh2D::Property::Bathymetry); - propertyMap.emplace(propertyId, std::make_unique()); - return propertyMap; } @@ -505,6 +511,26 @@ namespace meshkernelapi return lastExitCode; } + MKERNEL_API int mkernel_deallocate_property(int propertyId) + { + lastExitCode = meshkernel::ExitCode::Success; + try + { + + if (!propertyCalculators.contains(propertyId) || propertyCalculators[propertyId] == nullptr) + { + throw meshkernel::MeshKernelError("The property id does not exist: {}.", propertyId); + } + + propertyCalculators.erase(propertyId); + } + catch (...) + { + lastExitCode = HandleException(); + } + return lastExitCode; + } + MKERNEL_API int mkernel_mesh2d_is_valid_property(int meshKernelId, const int propertyId, bool& propertyIsAvailable) { lastExitCode = meshkernel::ExitCode::Success; @@ -514,7 +540,7 @@ namespace meshkernelapi propertyIsAvailable = meshKernelState.contains(meshKernelId) && propertyCalculators.contains(propertyId) && propertyCalculators[propertyId] != nullptr && - propertyCalculators[propertyId]->IsValid(meshKernelState.at(meshKernelId), propertyId); + propertyCalculators[propertyId]->IsValid(meshKernelState.at(meshKernelId)); } catch (...) { @@ -523,32 +549,25 @@ namespace meshkernelapi return lastExitCode; } - MKERNEL_API int mkernel_mesh2d_set_property(int meshKernelId, const int propertyId, const GeometryList& sampleData) + MKERNEL_API int mkernel_mesh2d_set_property(int projectionType, const GeometryList& sampleData, int& propertyId) { lastExitCode = meshkernel::ExitCode::Success; + propertyId = -1; + try { - if (!meshKernelState.contains(meshKernelId)) - { - throw meshkernel::MeshKernelError("The selected mesh kernel id does not exist."); - } + meshkernel::range_check::CheckOneOf(projectionType, meshkernel::GetValidProjections(), "Projection"); + auto const projection = static_cast(projectionType); - if (meshKernelState[meshKernelId].m_mesh2d == nullptr) - { - throw meshkernel::MeshKernelError("The selected mesh not exist."); - } + int localPropertyId = GeneratePropertyId(); - if (propertyCalculators[propertyId] != nullptr && propertyCalculators[propertyId]->IsValid(meshKernelState.at(meshKernelId), propertyId)) + if (propertyCalculators.contains(localPropertyId)) { - throw meshkernel::MeshKernelError("The property, {}, has already been defined.", propertyId); + throw meshkernel::ConstraintError("The pproperty id already exists: id = {}.", localPropertyId); } - std::span xNodes(sampleData.coordinates_x, sampleData.num_coordinates); - std::span yNodes(sampleData.coordinates_y, sampleData.num_coordinates); - meshKernelState[meshKernelId].m_sampleInterpolator = std::make_shared(xNodes, yNodes, meshKernelState[meshKernelId].m_projection); - - std::span dataSamples(sampleData.values, sampleData.num_coordinates); - meshKernelState[meshKernelId].m_sampleInterpolator->SetData(propertyId, dataSamples); + propertyCalculators.try_emplace(localPropertyId, std::make_unique(sampleData, projection, localPropertyId)); + propertyId = localPropertyId; } catch (...) { @@ -1573,6 +1592,7 @@ namespace meshkernelapi MKERNEL_API int mkernel_mesh2d_get_property(int meshKernelId, int propertyValue, const GeometryList& geometryList) { lastExitCode = meshkernel::ExitCode::Success; + try { if (!meshKernelState.contains(meshKernelId)) @@ -1585,9 +1605,26 @@ namespace meshkernelapi return lastExitCode; } - if (propertyCalculators.contains(propertyValue) && propertyCalculators[propertyValue] != nullptr && propertyCalculators[propertyValue]->IsValid(meshKernelState.at(meshKernelId), propertyValue)) + if (!propertyCalculators.contains(propertyValue) || propertyCalculators[propertyValue] == nullptr) + { + throw meshkernel::MeshKernelError("The property calculator does not exist."); + } + + if (geometryList.num_coordinates < propertyCalculators[propertyValue]->Size(meshKernelState.at(meshKernelId))) + { + throw meshkernel::ConstraintError("Array size too small to store property values {} < {}.", + geometryList.num_coordinates, + propertyCalculators[propertyValue]->Size(meshKernelState.at(meshKernelId))); + } + + if (geometryList.values == nullptr) + { + throw meshkernel::ConstraintError("The property values are null."); + } + + if (propertyCalculators[propertyValue]->IsValid(meshKernelState[meshKernelId])) { - propertyCalculators[propertyValue]->Calculate(meshKernelState.at(meshKernelId), propertyValue, geometryList); + propertyCalculators[propertyValue]->Calculate(meshKernelState[meshKernelId], geometryList); } else { @@ -1620,7 +1657,7 @@ namespace meshkernelapi if (propertyCalculators.contains(propertyValue) && propertyCalculators[propertyValue] != nullptr) { - dimension = propertyCalculators[propertyValue]->Size(meshKernelState.at(meshKernelId)); + dimension = propertyCalculators[propertyValue]->Size(meshKernelState[meshKernelId]); } else { diff --git a/libs/MeshKernelApi/src/PropertyCalculator.cpp b/libs/MeshKernelApi/src/PropertyCalculator.cpp index 6629bb49c..48d8a072b 100644 --- a/libs/MeshKernelApi/src/PropertyCalculator.cpp +++ b/libs/MeshKernelApi/src/PropertyCalculator.cpp @@ -1,20 +1,16 @@ #include "MeshKernelApi/PropertyCalculator.hpp" #include +#include -bool meshkernelapi::PropertyCalculator::IsValid(const MeshKernelState& state, const int propertyId [[maybe_unused]]) const +bool meshkernelapi::PropertyCalculator::IsValid(const MeshKernelState& state) const { return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; } -void meshkernelapi::OrthogonalityPropertyCalculator::Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const +void meshkernelapi::OrthogonalityPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { - if (propertyId != static_cast(meshkernel::Mesh2D::Property::Orthogonality)) - { - throw meshkernel::ConstraintError("Incorrect property id, expected = {}, actual = {}", static_cast(meshkernel::Mesh2D::Property::Orthogonality), propertyId); - } - std::vector values = state.m_mesh2d->GetOrthogonality(); if (static_cast(geometryList.num_coordinates) < values.size()) @@ -31,14 +27,9 @@ int meshkernelapi::OrthogonalityPropertyCalculator::Size(const MeshKernelState& return static_cast(state.m_mesh2d->GetNumEdges()); } -void meshkernelapi::EdgeLengthPropertyCalculator::Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const +void meshkernelapi::EdgeLengthPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { - if (propertyId != static_cast(meshkernel::Mesh2D::Property::EdgeLength)) - { - throw meshkernel::ConstraintError("Incorrect property id, expected = {}, actual = {}", static_cast(meshkernel::Mesh2D::Property::EdgeLength), propertyId); - } - state.m_mesh2d->ComputeEdgesLengths(); std::vector values = state.m_mesh2d->m_edgeLengths; @@ -56,25 +47,34 @@ int meshkernelapi::EdgeLengthPropertyCalculator::Size(const MeshKernelState& sta return static_cast(state.m_mesh2d->GetNumEdges()); } -bool meshkernelapi::DepthSamplePropertyCalculator::IsValid(const MeshKernelState& state, const int propertyId) const +meshkernelapi::InterpolatedSamplePropertyCalculator::InterpolatedSamplePropertyCalculator(const GeometryList& sampleData, const meshkernel::Projection projection, const int propertyId) + : m_projection(projection), + m_propertyId(propertyId) { - return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0 && state.m_sampleInterpolator != nullptr && state.m_sampleInterpolator->Contains(propertyId); + std::span xNodes(sampleData.coordinates_x, sampleData.num_coordinates); + std::span yNodes(sampleData.coordinates_y, sampleData.num_coordinates); + + m_sampleInterpolator = std::make_unique(xNodes, yNodes, m_projection); + + std::span dataSamples(sampleData.values, sampleData.num_coordinates); + m_sampleInterpolator->SetData(m_propertyId, dataSamples); } -void meshkernelapi::DepthSamplePropertyCalculator::Calculate(const MeshKernelState& state, const int propertyId, const GeometryList& geometryList) const +bool meshkernelapi::InterpolatedSamplePropertyCalculator::IsValid(const MeshKernelState& state) const { + return state.m_mesh2d != nullptr && + state.m_mesh2d->GetNumNodes() > 0 && + m_sampleInterpolator->Contains(m_propertyId) && + m_projection == state.m_projection; +} - if (geometryList.num_coordinates < Size(state)) - { - throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", - geometryList.num_coordinates, Size(state)); - } - +void meshkernelapi::InterpolatedSamplePropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const +{ std::span interpolatedSampleData(geometryList.values, geometryList.num_coordinates); - state.m_sampleInterpolator->Interpolate(propertyId, state.m_mesh2d->Nodes(), interpolatedSampleData); + m_sampleInterpolator->Interpolate(m_propertyId, state.m_mesh2d->Nodes(), interpolatedSampleData); } -int meshkernelapi::DepthSamplePropertyCalculator::Size(const MeshKernelState& state) const +int meshkernelapi::InterpolatedSamplePropertyCalculator::Size(const MeshKernelState& state) const { return static_cast(state.m_mesh2d->GetNumNodes()); } diff --git a/libs/MeshKernelApi/tests/src/MeshPropertyTests.cpp b/libs/MeshKernelApi/tests/src/MeshPropertyTests.cpp index 358457a34..4e7101ac6 100644 --- a/libs/MeshKernelApi/tests/src/MeshPropertyTests.cpp +++ b/libs/MeshKernelApi/tests/src/MeshPropertyTests.cpp @@ -16,6 +16,8 @@ namespace mkapi = meshkernelapi; TEST(MeshPropertyTests, BathymetryTest) { + const int projectionType = 0; + const int numXCoords = 4; const int numYCoords = 4; const int numberOfCoordinates = numXCoords * numYCoords; @@ -27,7 +29,7 @@ TEST(MeshPropertyTests, BathymetryTest) const double origin = 0.0; const double delta = 1.0; - const int BathymetryPropertyId = static_cast(meshkernel::Mesh2D::Property::Bathymetry); + int bathymetryPropertyId = -1; int meshKernelId = meshkernel::constants::missing::intValue; int errorCode; @@ -108,7 +110,7 @@ TEST(MeshPropertyTests, BathymetryTest) sampleData.coordinates_x = bathymetryXNodes.data(); sampleData.coordinates_y = bathymetryYNodes.data(); - errorCode = mkapi::mkernel_mesh2d_set_property(meshKernelId, BathymetryPropertyId, sampleData); + errorCode = mkapi::mkernel_mesh2d_set_property(projectionType, sampleData, bathymetryPropertyId); ASSERT_EQ(mk::ExitCode::Success, errorCode); const double tolerance = 1.0e-13; @@ -119,7 +121,7 @@ TEST(MeshPropertyTests, BathymetryTest) 0.0, 1.0, 2.0, 3.0}; int sampleDataSize = -1; - errorCode = mkapi::mkernel_mesh2d_get_property_dimension(meshKernelId, BathymetryPropertyId, sampleDataSize); + errorCode = mkapi::mkernel_mesh2d_get_property_dimension(meshKernelId, bathymetryPropertyId, sampleDataSize); ASSERT_EQ(mk::ExitCode::Success, errorCode); ASSERT_EQ(sampleDataSize, numberOfCoordinates); @@ -128,7 +130,7 @@ TEST(MeshPropertyTests, BathymetryTest) propertyData.num_coordinates = numberOfCoordinates; propertyData.values = retrievedPropertyData.data(); - errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, BathymetryPropertyId, propertyData); + errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, bathymetryPropertyId, propertyData); ASSERT_EQ(mk::ExitCode::Success, errorCode); for (size_t i = 0; i < retrievedPropertyData.size(); ++i) @@ -136,12 +138,20 @@ TEST(MeshPropertyTests, BathymetryTest) EXPECT_NEAR(retrievedPropertyData[i], expectedInterpolatedData[i], tolerance); } + //-------------------------------- + // Remove kernel and property id from state. + errorCode = mkapi::mkernel_expunge_state(meshKernelId); ASSERT_EQ(mk::ExitCode::Success, errorCode); + + errorCode = mkapi::mkernel_deallocate_property(bathymetryPropertyId); + ASSERT_EQ(mk::ExitCode::Success, errorCode); } TEST(MeshPropertyTests, PropertyFailureTest) { + const int projectionType = 0; + const int numXCoords = 4; const int numYCoords = 4; const int numberOfCoordinates = numXCoords * numYCoords; @@ -153,7 +163,7 @@ TEST(MeshPropertyTests, PropertyFailureTest) const double origin = 0.0; const double delta = 1.0; - const int BathymetryPropertyId = static_cast(meshkernel::Mesh2D::Property::Bathymetry); + int bathymetryPropertyId = -1; int meshKernelId = meshkernel::constants::missing::intValue; int errorCode; @@ -236,14 +246,14 @@ TEST(MeshPropertyTests, PropertyFailureTest) bool hasBathymetryData = false; - errorCode = mkapi::mkernel_mesh2d_is_valid_property(meshKernelId, BathymetryPropertyId, hasBathymetryData); + errorCode = mkapi::mkernel_mesh2d_is_valid_property(meshKernelId, bathymetryPropertyId, hasBathymetryData); ASSERT_EQ(mk::ExitCode::Success, errorCode); EXPECT_FALSE(hasBathymetryData); - errorCode = mkapi::mkernel_mesh2d_set_property(meshKernelId, BathymetryPropertyId, sampleData); + errorCode = mkapi::mkernel_mesh2d_set_property(projectionType, sampleData, bathymetryPropertyId); ASSERT_EQ(mk::ExitCode::Success, errorCode); - errorCode = mkapi::mkernel_mesh2d_is_valid_property(meshKernelId, BathymetryPropertyId, hasBathymetryData); + errorCode = mkapi::mkernel_mesh2d_is_valid_property(meshKernelId, bathymetryPropertyId, hasBathymetryData); ASSERT_EQ(mk::ExitCode::Success, errorCode); EXPECT_TRUE(hasBathymetryData); @@ -252,51 +262,40 @@ TEST(MeshPropertyTests, PropertyFailureTest) int sampleDataSize = -1; - // Invalid meshkernel id - errorCode = mkapi::mkernel_mesh2d_get_property_dimension(meshKernelId + 100, BathymetryPropertyId, sampleDataSize); + // Expected test failure due to invalid meshkernel id + errorCode = mkapi::mkernel_mesh2d_get_property_dimension(meshKernelId + 100, bathymetryPropertyId, sampleDataSize); ASSERT_EQ(mk::ExitCode::MeshKernelErrorCode, errorCode); mkapi::GeometryList propertyData{}; std::vector retrievedPropertyData(numberOfCoordinates, -1.0); propertyData.num_coordinates = numberOfCoordinates; + + // Expected test failure due to values set to null + propertyData.values = nullptr; + errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, bathymetryPropertyId, propertyData); + ASSERT_EQ(mk::ExitCode::ConstraintErrorCode, errorCode); + propertyData.values = retrievedPropertyData.data(); - // Invalid property id - errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, BathymetryPropertyId + 100, propertyData); + // Expected test failure due to invalid property id + errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, bathymetryPropertyId + 100, propertyData); ASSERT_EQ(mk::ExitCode::MeshKernelErrorCode, errorCode); // Expected test failure due to incorrect size propertyData.num_coordinates = numberOfCoordinates - 1; - - errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, BathymetryPropertyId, propertyData); + errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId, bathymetryPropertyId, propertyData); ASSERT_EQ(mk::ExitCode::ConstraintErrorCode, errorCode); //-------------------------------- - // Try with kernel id that has not had data set - - int meshKernelId2 = meshkernel::constants::missing::intValue; + // Remove kernel and property id from state. - errorCode = mkapi::mkernel_allocate_state(0, meshKernelId2); + errorCode = mkapi::mkernel_deallocate_property(bathymetryPropertyId); ASSERT_EQ(mk::ExitCode::Success, errorCode); - // Generate curvilinear grid. - errorCode = mkapi::mkernel_curvilinear_compute_rectangular_grid(meshKernelId2, makeGridParameters); - ASSERT_EQ(mk::ExitCode::Success, errorCode); - - // Convert the curvilinear grid to an unstructured grid. - errorCode = mkapi::mkernel_curvilinear_convert_to_mesh2d(meshKernelId2); + errorCode = mkapi::mkernel_mesh2d_is_valid_property(meshKernelId, bathymetryPropertyId, hasBathymetryData); ASSERT_EQ(mk::ExitCode::Success, errorCode); - - // Try to get properties that have not been initalised - errorCode = mkapi::mkernel_mesh2d_get_property(meshKernelId2, BathymetryPropertyId, propertyData); - ASSERT_EQ(mk::ExitCode::MeshKernelErrorCode, errorCode); - - //-------------------------------- - // Remove kernel ids from state. + EXPECT_FALSE(hasBathymetryData); errorCode = mkapi::mkernel_expunge_state(meshKernelId); ASSERT_EQ(mk::ExitCode::Success, errorCode); - - errorCode = mkapi::mkernel_expunge_state(meshKernelId2); - ASSERT_EQ(mk::ExitCode::Success, errorCode); }