diff --git a/libs/MeshKernel/include/MeshKernel/Definitions.hpp b/libs/MeshKernel/include/MeshKernel/Definitions.hpp index 503c86dd8..5ff28770e 100644 --- a/libs/MeshKernel/include/MeshKernel/Definitions.hpp +++ b/libs/MeshKernel/include/MeshKernel/Definitions.hpp @@ -160,7 +160,9 @@ namespace meshkernel EdgeLength = 1, FaceCircumcenter = 2, NetlinkContourPolygon = 3, - FaceBounds = 4 + FaceBounds = 4, + Smoothness = 5, + LastValue }; /// \brief Describe how the circumcentre should be computed. diff --git a/libs/MeshKernelApi/CMakeLists.txt b/libs/MeshKernelApi/CMakeLists.txt index 56beb6522..fbea30f64 100644 --- a/libs/MeshKernelApi/CMakeLists.txt +++ b/libs/MeshKernelApi/CMakeLists.txt @@ -31,6 +31,7 @@ set(SRC_LIST ${SRC_DIR}/Mesh2DFaceBoundsPropertyCalculator.cpp ${SRC_DIR}/NetlinkContourPolygonPropertyCalculator.cpp ${SRC_DIR}/OrthogonalityPropertyCalculator.cpp + ${SRC_DIR}/MeshSmoothnessPropertyCalculator.cpp ${SRC_DIR}/InterpolatedSamplePropertyCalculator.cpp ) @@ -64,11 +65,13 @@ set( ${DOMAIN_INC_DIR}/Mesh2D.hpp ${DOMAIN_INC_DIR}/MeshKernel.hpp ${DOMAIN_INC_DIR}/PropertyCalculator.hpp + ${DOMAIN_INC_DIR}/PredefinedPropertyCalculator.hpp ${DOMAIN_INC_DIR}/EdgeLengthPropertyCalculator.hpp ${DOMAIN_INC_DIR}/FaceCircumcenterPropertyCalculator.hpp ${DOMAIN_INC_DIR}/Mesh2DFaceBoundsPropertyCalculator.hpp ${DOMAIN_INC_DIR}/NetlinkContourPolygonPropertyCalculator.hpp ${DOMAIN_INC_DIR}/OrthogonalityPropertyCalculator.hpp + ${DOMAIN_INC_DIR}/MeshSmoothnessPropertyCalculator.hpp ${DOMAIN_INC_DIR}/InterpolatedSamplePropertyCalculator.hpp ${DOMAIN_INC_DIR}/State.hpp ${DOMAIN_INC_DIR}/Utils.hpp diff --git a/libs/MeshKernelApi/include/MeshKernelApi/EdgeLengthPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/EdgeLengthPropertyCalculator.hpp index 666c83ae7..98b0f940f 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/EdgeLengthPropertyCalculator.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/EdgeLengthPropertyCalculator.hpp @@ -32,27 +32,32 @@ #include "MeshKernel/SampleInterpolator.hpp" #include "MeshKernelApi/GeometryList.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" namespace meshkernelapi { /// @brief Calculator for the edge lengths for a mesh - class EdgeLengthPropertyCalculator : public PropertyCalculator + class EdgeLengthPropertyCalculator : public PredefinedPropertyCalculator { public: /// @brief Determine is the calculator can compute the desired results correctly. /// - /// This has a default of checking that the mesh2d is valid and the location is at edges - bool IsValid(const MeshKernelState& state, const meshkernel::Location location) const override; + /// This has a default of checking that the mesh2d is valid + bool IsValid(const MeshKernelState& state) const override; /// @brief Calculate the edge-length for a mesh /// /// \note This calculator is for mesh edges only - void Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; + + /// @brief Get the location at which the property can be evaluated + /// + /// Can be evaluated only at Location::Edges + meshkernel::Location EvaluationLocation() const override; /// @brief Determine the size of the edge-length vector required - int Size(const MeshKernelState& state, const meshkernel::Location location) const override; + int Size(const MeshKernelState& state) const override; }; } // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/FaceCircumcenterPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/FaceCircumcenterPropertyCalculator.hpp index 84ab9f057..0b0412719 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/FaceCircumcenterPropertyCalculator.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/FaceCircumcenterPropertyCalculator.hpp @@ -32,27 +32,32 @@ #include "MeshKernel/SampleInterpolator.hpp" #include "MeshKernelApi/GeometryList.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" namespace meshkernelapi { /// @brief Calculator for the face circumcenter for a mesh - class FaceCircumcenterPropertyCalculator : public PropertyCalculator + class FaceCircumcenterPropertyCalculator : public PredefinedPropertyCalculator { public: /// @brief Determine is the calculator can compute the desired results correctly. /// - /// This has a default of checking that the mesh2d is valid and the location is at faces - bool IsValid(const MeshKernelState& state, const meshkernel::Location location) const override; + /// This has a default of checking that the mesh2d is valid + bool IsValid(const MeshKernelState& state) const override; /// @brief Calculate the face circumcentres for a mesh /// /// \note This calculator is for mesh faces only - void Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; + + /// @brief Get the location at which the property can be evaluated + /// + /// Can be evaluated only at Location::Faces + meshkernel::Location EvaluationLocation() const override; /// @brief Determine the size of the face circumcentre vector required - int Size(const MeshKernelState& state, const meshkernel::Location location) const override; + int Size(const MeshKernelState& state) const override; }; } // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/Mesh2DFaceBoundsPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/Mesh2DFaceBoundsPropertyCalculator.hpp index 5671e7a4b..ffd53f6bb 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/Mesh2DFaceBoundsPropertyCalculator.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/Mesh2DFaceBoundsPropertyCalculator.hpp @@ -32,25 +32,30 @@ #include "MeshKernel/SampleInterpolator.hpp" #include "MeshKernelApi/GeometryList.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" namespace meshkernelapi { /// @brief Calculator for the face bounds values for a mesh - class Mesh2DFaceBoundsPropertyCalculator : public PropertyCalculator + class Mesh2DFaceBoundsPropertyCalculator : public PredefinedPropertyCalculator { public: /// @brief Determine is the calculator can compute the desired results correctly. /// - /// This has a default of checking that the mesh2d is valid and the location is at faces - bool IsValid(const MeshKernelState& state, const meshkernel::Location location) const override; + /// This has a default of checking that the mesh2d is valid + bool IsValid(const MeshKernelState& state) const override; /// @brief Calculate the face bounds values for a mesh - void Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; + + /// @brief Get the location at which the property can be evaluated + /// + /// Can be evaluated only at Location::Faces + meshkernel::Location EvaluationLocation() const override; /// @brief Determine the size of the face bounds array (for all faces) required - int Size(const MeshKernelState& state, const meshkernel::Location location) const override; + int Size(const MeshKernelState& state) const override; }; } // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp b/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp index 34d57f7f0..7de85ee79 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/MeshKernel.hpp @@ -1255,6 +1255,11 @@ namespace meshkernelapi /// @returns Error code MKERNEL_API int mkernel_mesh2d_get_face_bounds_property_type(int& type); + /// @brief Gets an int indicating the mesh smoothness property type for mesh2d + /// @param[out] type The int indicating the mesh smoothness property type + /// @returns Error code + MKERNEL_API int mkernel_mesh2d_get_mesh_smoothness_property_type(int& type); + /// @brief Gets the Mesh2D inner boundary polygons data /// /// @param[in] meshKernelId The id of the mesh state @@ -1451,6 +1456,22 @@ namespace meshkernelapi /// @returns Error code MKERNEL_API int mkernel_mesh2d_get_property_dimension(int meshKernelId, int propertyValue, int locationId, int& dimension); + /// @brief Retrieves a specified predefined property of a 2D mesh. + /// + /// @param[in] meshKernelId The id of the mesh state + /// @param[in] propertyId The identifier representing the specific 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_predefined_property(int meshKernelId, int propertyId, const GeometryList& geometrylist); + + /// @brief The dimension of a specified property of a 2D mesh. + /// + /// @param[in] meshKernelId The id of the mesh state + /// @param[in] propertyId The identifier representing the specific property + /// @param[out] dimension The dimension of the specified property + /// @returns Error code + MKERNEL_API int mkernel_mesh2d_get_predefined_property_dimension(int meshKernelId, int propertyId, int& dimension); + /// @brief Gets the small mesh2d flow edges. The flow edges are the edges connecting faces circumcenters. /// @param[in] meshKernelId The id of the mesh state /// @param[in] smallFlowEdgesThreshold The configurable threshold for detecting a small flow edge diff --git a/libs/MeshKernelApi/include/MeshKernelApi/MeshSmoothnessPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/MeshSmoothnessPropertyCalculator.hpp new file mode 100644 index 000000000..489ceb34f --- /dev/null +++ b/libs/MeshKernelApi/include/MeshKernelApi/MeshSmoothnessPropertyCalculator.hpp @@ -0,0 +1,61 @@ +//---- GPL --------------------------------------------------------------------- +// +// Copyright (C) Stichting Deltares, 2011-2025. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// contact: delft3d.support@deltares.nl +// Stichting Deltares +// P.O. Box 177 +// 2600 MH Delft, The Netherlands +// +// All indications and logos of, and references to, "Delft3D" and "Deltares" +// are registered trademarks of Stichting Deltares, and remain the property of +// Stichting Deltares. All rights reserved. +// +//------------------------------------------------------------------------------ + +#pragma once + +#include "MeshKernel/Definitions.hpp" + +#include "MeshKernelApi/GeometryList.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" + +namespace meshkernelapi +{ + + /// @brief Calculator for the mesh smoothness (edge size ratio) for a mesh + class MeshSmoothnessPropertyCalculator : public PredefinedPropertyCalculator + { + public: + /// @brief Determine if the calculator can compute the desired results correctly. + /// + /// This has a default of checking that the mesh2d is valid + bool IsValid(const MeshKernelState& state) const override; + + /// @brief Calculate the mesh smoothness for a mesh + /// + /// \note This calculator is for mesh edges only + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; + + /// @brief Get the location at which the property can be evaluated + /// + /// Can be evaluated only at Location::Edges + meshkernel::Location EvaluationLocation() const override; + + /// @brief Determine the size of the smoothness vector required + int Size(const MeshKernelState& state) const override; + }; + +} // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/NetlinkContourPolygonPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/NetlinkContourPolygonPropertyCalculator.hpp index 2edaaa984..3c298bce4 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/NetlinkContourPolygonPropertyCalculator.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/NetlinkContourPolygonPropertyCalculator.hpp @@ -32,25 +32,30 @@ #include "MeshKernel/SampleInterpolator.hpp" #include "MeshKernelApi/GeometryList.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" namespace meshkernelapi { /// @brief Calculator for the netlink contour polygons for a mesh - class NetlinkContourPolygonPropertyCalculator : public PropertyCalculator + class NetlinkContourPolygonPropertyCalculator : public PredefinedPropertyCalculator { public: /// @brief Determine is the calculator can compute the desired results correctly. /// - /// This has a default of checking that the mesh2d is valid and the location is at edges - bool IsValid(const MeshKernelState& state, const meshkernel::Location location) const override; + /// This has a default of checking that the mesh2d is valid + bool IsValid(const MeshKernelState& state) const override; /// @brief Calculate the netlink contour polygons for a mesh - void Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; + + /// @brief Get the location at which the property can be evaluated + /// + /// Can be evaluated only at Location::Edges + meshkernel::Location EvaluationLocation() const override; /// @brief Determine the size of the netlink contour polygon array (for all edges) required - int Size(const MeshKernelState& state, const meshkernel::Location location) const override; + int Size(const MeshKernelState& state) const override; }; } // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/OrthogonalityPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/OrthogonalityPropertyCalculator.hpp index 5e2b48939..b0b411196 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/OrthogonalityPropertyCalculator.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/OrthogonalityPropertyCalculator.hpp @@ -32,25 +32,30 @@ #include "MeshKernel/SampleInterpolator.hpp" #include "MeshKernelApi/GeometryList.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" namespace meshkernelapi { /// @brief Calculator for orthogonality of a mesh. - class OrthogonalityPropertyCalculator : public PropertyCalculator + class OrthogonalityPropertyCalculator : public PredefinedPropertyCalculator { public: /// @brief Determine is the calculator can compute the desired results correctly. /// - /// This has a default of checking that the mesh2d is valid and the location is at edges - bool IsValid(const MeshKernelState& state, const meshkernel::Location location) const override; + /// This has a default of checking that the mesh2d is valid + bool IsValid(const MeshKernelState& state) const override; /// @brief Calculate the orthogonality for a mesh - void Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const override; + void Calculate(const MeshKernelState& state, const GeometryList& geometryList) const override; + + /// @brief Get the location at which the property can be evaluated + /// + /// Can be evaluated only at Location::Edges + meshkernel::Location EvaluationLocation() const override; /// @brief Determine the size of the orthogonality vector required - int Size(const MeshKernelState& state, const meshkernel::Location location) const override; + int Size(const MeshKernelState& state) const override; }; } // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/PredefinedPropertyCalculator.hpp b/libs/MeshKernelApi/include/MeshKernelApi/PredefinedPropertyCalculator.hpp new file mode 100644 index 000000000..ff5e1e6cf --- /dev/null +++ b/libs/MeshKernelApi/include/MeshKernelApi/PredefinedPropertyCalculator.hpp @@ -0,0 +1,64 @@ +//---- GPL --------------------------------------------------------------------- +// +// Copyright (C) Stichting Deltares, 2011-2024. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// contact: delft3d.support@deltares.nl +// Stichting Deltares +// P.O. Box 177 +// 2600 MH Delft, The Netherlands +// +// All indications and logos of, and references to, "Delft3D" and "Deltares" +// are registered trademarks of Stichting Deltares, and remain the property of +// Stichting Deltares. All rights reserved. +// +//------------------------------------------------------------------------------ + +#pragma once + +#include "MeshKernel/Definitions.hpp" + +#include "MeshKernelApi/GeometryList.hpp" + +namespace meshkernelapi +{ + + /// @brief Forward declaration of MeshKernelState + struct MeshKernelState; + + /// @brief Base class for property calculators with a predefined (fixed) evaluation location + /// + /// PredefinedPropertyCalculator has a fixed location determined by EvaluationLocation(). + class PredefinedPropertyCalculator + { + public: + /// @brief Destructor + virtual ~PredefinedPropertyCalculator() = default; + + /// @brief Get the location at which the property can be evaluated + /// + /// Must return a specific location (Nodes, Edges, or Faces), not Unknown + virtual meshkernel::Location EvaluationLocation() const = 0; + + /// @brief Determine if the calculator can compute the desired results correctly + virtual bool IsValid(const MeshKernelState& state) const = 0; + + /// @brief Calculate the property + 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; + }; + +} // namespace meshkernelapi diff --git a/libs/MeshKernelApi/include/MeshKernelApi/State.hpp b/libs/MeshKernelApi/include/MeshKernelApi/State.hpp index f593ebf6f..423596e0b 100644 --- a/libs/MeshKernelApi/include/MeshKernelApi/State.hpp +++ b/libs/MeshKernelApi/include/MeshKernelApi/State.hpp @@ -49,6 +49,7 @@ #include "MeshKernelApi/ApiCache/PolygonRefinementCache.hpp" #include "MeshKernelApi/ApiCache/SmallFlowEdgeCentreCache.hpp" #include "MeshKernelApi/ApiCache/SplineIntersectionCache.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" #include "MeshKernelApi/PropertyCalculator.hpp" #include "ApiCache/MeshBoundariesAsPolygonCache.hpp" @@ -87,6 +88,7 @@ namespace meshkernelapi std::shared_ptr m_curvilinearGridLineShift; ///< Shared pointer to meshkernel::CurvilinearGridLineShift instance std::shared_ptr m_curvilinearGridOrthogonalization; ///< Shared pointer to meshkernel::CurvilinearGridOrthogonalization instance std::map> m_propertyCalculators; ///< Property calculators for the mesh2d + std::map> m_predefinedPropertyCalculators; ///< Predefined property calculators for the mesh2d std::unordered_map> m_frozenLines; ///< Map for string the frozen lines meshkernel::UInt m_frozenLinesCounter = 0; ///< An increasing counter for returning the id of frozen lines to the client diff --git a/libs/MeshKernelApi/src/EdgeLengthPropertyCalculator.cpp b/libs/MeshKernelApi/src/EdgeLengthPropertyCalculator.cpp index 41f0f0595..e76537d11 100644 --- a/libs/MeshKernelApi/src/EdgeLengthPropertyCalculator.cpp +++ b/libs/MeshKernelApi/src/EdgeLengthPropertyCalculator.cpp @@ -26,7 +26,7 @@ //------------------------------------------------------------------------------ #include "MeshKernelApi/EdgeLengthPropertyCalculator.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" #include "MeshKernelApi/State.hpp" #include "MeshKernel/Mesh2D.hpp" @@ -35,18 +35,18 @@ #include #include -bool meshkernelapi::EdgeLengthPropertyCalculator::IsValid(const MeshKernelState& state, const meshkernel::Location location) const +bool meshkernelapi::EdgeLengthPropertyCalculator::IsValid(const MeshKernelState& state) const { - return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0 && location == meshkernel::Location::Edges; + return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; } -void meshkernelapi::EdgeLengthPropertyCalculator::Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const +void meshkernelapi::EdgeLengthPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { if (static_cast(geometryList.num_coordinates) < state.m_mesh2d->GetNumEdges()) { throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", - geometryList.num_coordinates, Size(state, location)); + geometryList.num_coordinates, Size(state)); } std::span edgeLengths(geometryList.values, state.m_mesh2d->GetNumEdges()); @@ -73,14 +73,12 @@ void meshkernelapi::EdgeLengthPropertyCalculator::Calculate(const MeshKernelStat } } -int meshkernelapi::EdgeLengthPropertyCalculator::Size(const MeshKernelState& state, const meshkernel::Location location) const +int meshkernelapi::EdgeLengthPropertyCalculator::Size(const MeshKernelState& state) const { - int size = -1; - - if (location == meshkernel::Location::Edges) - { - size = static_cast(state.m_mesh2d->GetNumEdges()); - } + return static_cast(state.m_mesh2d->GetNumEdges()); +} - return size; +meshkernel::Location meshkernelapi::EdgeLengthPropertyCalculator::EvaluationLocation() const +{ + return meshkernel::Location::Edges; } diff --git a/libs/MeshKernelApi/src/FaceCircumcenterPropertyCalculator.cpp b/libs/MeshKernelApi/src/FaceCircumcenterPropertyCalculator.cpp index 23b5c8a31..c4725d594 100644 --- a/libs/MeshKernelApi/src/FaceCircumcenterPropertyCalculator.cpp +++ b/libs/MeshKernelApi/src/FaceCircumcenterPropertyCalculator.cpp @@ -26,7 +26,7 @@ //------------------------------------------------------------------------------ #include "MeshKernelApi/FaceCircumcenterPropertyCalculator.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" #include "MeshKernelApi/State.hpp" #include "MeshKernel/MeshFaceCenters.hpp" @@ -34,18 +34,18 @@ #include #include -bool meshkernelapi::FaceCircumcenterPropertyCalculator::IsValid(const MeshKernelState& state, const meshkernel::Location location) const +bool meshkernelapi::FaceCircumcenterPropertyCalculator::IsValid(const MeshKernelState& state) const { - return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0 && location == meshkernel::Location::Faces; + return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; } -void meshkernelapi::FaceCircumcenterPropertyCalculator::Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const +void meshkernelapi::FaceCircumcenterPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { if (static_cast(geometryList.num_coordinates) < state.m_mesh2d->GetNumFaces()) { throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", - geometryList.num_coordinates, Size(state, location)); + geometryList.num_coordinates, Size(state)); } std::vector faceCircumcentres(state.m_mesh2d->GetNumFaces()); @@ -68,14 +68,12 @@ void meshkernelapi::FaceCircumcenterPropertyCalculator::Calculate(const MeshKern } } -int meshkernelapi::FaceCircumcenterPropertyCalculator::Size(const MeshKernelState& state, const meshkernel::Location location) const +int meshkernelapi::FaceCircumcenterPropertyCalculator::Size(const MeshKernelState& state) const { - int size = -1; - - if (location == meshkernel::Location::Faces) - { - size = static_cast(state.m_mesh2d->GetNumFaces()); - } + return static_cast(state.m_mesh2d->GetNumFaces()); +} - return size; +meshkernel::Location meshkernelapi::FaceCircumcenterPropertyCalculator::EvaluationLocation() const +{ + return meshkernel::Location::Faces; } diff --git a/libs/MeshKernelApi/src/Mesh2DFaceBoundsPropertyCalculator.cpp b/libs/MeshKernelApi/src/Mesh2DFaceBoundsPropertyCalculator.cpp index c103dfdf2..c13b642a5 100644 --- a/libs/MeshKernelApi/src/Mesh2DFaceBoundsPropertyCalculator.cpp +++ b/libs/MeshKernelApi/src/Mesh2DFaceBoundsPropertyCalculator.cpp @@ -26,27 +26,27 @@ //------------------------------------------------------------------------------ #include "MeshKernelApi/Mesh2DFaceBoundsPropertyCalculator.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" #include "MeshKernelApi/State.hpp" #include "MeshKernel/Mesh2DFaceBounds.hpp" -bool meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::IsValid(const MeshKernelState& state, const meshkernel::Location location) const +bool meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::IsValid(const MeshKernelState& state) const { - return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0 && location == meshkernel::Location::Faces; + return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; } -void meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const +void meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { if (geometryList.num_coordinates < static_cast(meshkernel::constants::geometric::maximumNumberOfNodesPerFace * state.m_mesh2d->GetNumFaces())) { throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", - geometryList.num_coordinates, Size(state, location)); + geometryList.num_coordinates, Size(state)); } std::vector faceBounds(meshkernel::algo::Mesh2DFaceBounds::Compute(*state.m_mesh2d)); - size_t size = static_cast(Size(state, location)); + size_t size = static_cast(Size(state)); std::span xCoord(geometryList.coordinates_x, size); std::span yCoord(geometryList.coordinates_y, size); @@ -63,14 +63,12 @@ void meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::Calculate(const MeshKern } } -int meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::Size(const MeshKernelState& state, const meshkernel::Location location) const +int meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::Size(const MeshKernelState& state) const { - int size = -1; - - if (location == meshkernel::Location::Faces) - { - size = meshkernel::constants::geometric::maximumNumberOfNodesPerFace * static_cast(state.m_mesh2d->GetNumFaces()); - } + return meshkernel::constants::geometric::maximumNumberOfNodesPerFace * static_cast(state.m_mesh2d->GetNumFaces()); +} - return size; +meshkernel::Location meshkernelapi::Mesh2DFaceBoundsPropertyCalculator::EvaluationLocation() const +{ + return meshkernel::Location::Faces; } diff --git a/libs/MeshKernelApi/src/MeshKernel.cpp b/libs/MeshKernelApi/src/MeshKernel.cpp index ea006071d..b2f234944 100644 --- a/libs/MeshKernelApi/src/MeshKernel.cpp +++ b/libs/MeshKernelApi/src/MeshKernel.cpp @@ -109,6 +109,7 @@ #include "MeshKernelApi/FaceCircumcenterPropertyCalculator.hpp" #include "MeshKernelApi/InterpolatedSamplePropertyCalculator.hpp" #include "MeshKernelApi/Mesh2DFaceBoundsPropertyCalculator.hpp" +#include "MeshKernelApi/MeshSmoothnessPropertyCalculator.hpp" #include "MeshKernelApi/NetlinkContourPolygonPropertyCalculator.hpp" #include "MeshKernelApi/OrthogonalityPropertyCalculator.hpp" #include "MeshKernelApi/PropertyCalculator.hpp" @@ -124,12 +125,10 @@ namespace meshkernelapi { - std::map> allocateDefaultPropertyCalculators(); + std::map> allocatePredefinedPropertyCalculators(); // The state held by MeshKernel static std::unordered_map meshKernelState; - /// @brief Map of property calculators, from an property identifier to the calculator. - static std::map> propertyCalculators = allocateDefaultPropertyCalculators(); static int meshKernelStateCounter = 0; // Error state @@ -146,15 +145,15 @@ namespace meshkernelapi int GeneratePropertyId() { // The current property id, initialised with a value equal to the last enum in Mesh2D:::Property enum values - static int currentPropertyId = static_cast(meshkernel::Property::FaceBounds); + static int currentPropertyId = static_cast(meshkernel::Property::LastValue); // Increment and return the current property id value. return ++currentPropertyId; } - std::map> allocateDefaultPropertyCalculators() + std::map> allocatePredefinedPropertyCalculators() { - std::map> propertyMap; + std::map> propertyMap; int propertyId = static_cast(meshkernel::Property::Orthogonality); propertyMap.emplace(propertyId, std::make_shared()); @@ -171,6 +170,9 @@ namespace meshkernelapi propertyId = static_cast(meshkernel::Property::FaceBounds); propertyMap.emplace(propertyId, std::make_shared()); + propertyId = static_cast(meshkernel::Property::Smoothness); + propertyMap.emplace(propertyId, std::make_shared()); + return propertyMap; } @@ -213,7 +215,7 @@ namespace meshkernelapi meshkernel::range_check::CheckOneOf(projectionType, meshkernel::GetValidProjections(), "Projection"); auto const projection = static_cast(projectionType); meshKernelState.insert({meshKernelId, MeshKernelState(projection)}); - meshKernelState[meshKernelId].m_propertyCalculators = allocateDefaultPropertyCalculators(); + meshKernelState[meshKernelId].m_predefinedPropertyCalculators = allocatePredefinedPropertyCalculators(); } catch (...) { @@ -1037,6 +1039,13 @@ namespace meshkernelapi return lastExitCode; } + MKERNEL_API int mkernel_mesh2d_get_mesh_smoothness_property_type(int& type) + { + lastExitCode = meshkernel::ExitCode::Success; + type = static_cast(meshkernel::Property::Smoothness); + return lastExitCode; + } + MKERNEL_API int mkernel_mesh1d_get_dimensions(int meshKernelId, Mesh1D& mesh1d) { lastExitCode = meshkernel::ExitCode::Success; @@ -1356,8 +1365,9 @@ namespace meshkernelapi meshkernel::ProjectionToString(targetProjection)); } + meshKernelState[meshKernelId].m_predefinedPropertyCalculators.clear(); + meshKernelState[meshKernelId].m_predefinedPropertyCalculators = allocatePredefinedPropertyCalculators(); meshKernelState[meshKernelId].m_propertyCalculators.clear(); - meshKernelState[meshKernelId].m_propertyCalculators = allocateDefaultPropertyCalculators(); } } catch (...) @@ -1819,6 +1829,84 @@ namespace meshkernelapi return lastExitCode; } + MKERNEL_API int mkernel_mesh2d_get_predefined_property(int meshKernelId, int propertyId, const GeometryList& geometryList) + { + lastExitCode = meshkernel::ExitCode::Success; + + try + { + if (!meshKernelState.contains(meshKernelId)) + { + throw meshkernel::MeshKernelError("The selected mesh kernel id does not exist."); + } + + if (const auto& mesh2d = meshKernelState.at(meshKernelId).m_mesh2d; mesh2d == nullptr || mesh2d->GetNumNodes() <= 0) + { + return lastExitCode; + } + + if (!meshKernelState[meshKernelId].m_predefinedPropertyCalculators.contains(propertyId) || + meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId] == nullptr) + { + throw meshkernel::MeshKernelError("The predefined property calculator does not exist."); + } + + if (geometryList.num_coordinates < meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId]->Size(meshKernelState.at(meshKernelId))) + { + throw meshkernel::ConstraintError("Array size too small to store property values {} < {}.", + geometryList.num_coordinates, + meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId]->Size(meshKernelState.at(meshKernelId))); + } + + if (meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId]->IsValid(meshKernelState[meshKernelId])) + { + meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId]->Calculate(meshKernelState[meshKernelId], geometryList); + } + else + { + throw meshkernel::MeshKernelError("Unknown predefined property"); + } + } + catch (...) + { + lastExitCode = HandleException(); + } + return lastExitCode; + } + + MKERNEL_API int mkernel_mesh2d_get_predefined_property_dimension(int meshKernelId, int propertyId, int& dimension) + { + lastExitCode = meshkernel::ExitCode::Success; + dimension = -1; + + try + { + if (!meshKernelState.contains(meshKernelId)) + { + throw meshkernel::MeshKernelError("The selected mesh kernel id does not exist."); + } + + if (const auto& mesh2d = meshKernelState.at(meshKernelId).m_mesh2d; !mesh2d || mesh2d->GetNumNodes() <= 0) + { + return lastExitCode; + } + + if (meshKernelState[meshKernelId].m_predefinedPropertyCalculators.contains(propertyId) && meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId] != nullptr) + { + dimension = meshKernelState[meshKernelId].m_predefinedPropertyCalculators[propertyId]->Size(meshKernelState[meshKernelId]); + } + else + { + throw meshkernel::MeshKernelError("Predefined property not supported"); + } + } + catch (...) + { + lastExitCode = HandleException(); + } + return lastExitCode; + } + MKERNEL_API int mkernel_mesh2d_get_smoothness(int meshKernelId, GeometryList& geometryList) { lastExitCode = meshkernel::ExitCode::Success; diff --git a/libs/MeshKernelApi/src/MeshSmoothnessPropertyCalculator.cpp b/libs/MeshKernelApi/src/MeshSmoothnessPropertyCalculator.cpp new file mode 100644 index 000000000..84d5ba9a5 --- /dev/null +++ b/libs/MeshKernelApi/src/MeshSmoothnessPropertyCalculator.cpp @@ -0,0 +1,75 @@ +//---- GPL --------------------------------------------------------------------- +// +// Copyright (C) Stichting Deltares, 2011-2025. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation version 3. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// +// contact: delft3d.support@deltares.nl +// Stichting Deltares +// P.O. Box 177 +// 2600 MH Delft, The Netherlands +// +// All indications and logos of, and references to, "Delft3D" and "Deltares" +// are registered trademarks of Stichting Deltares, and remain the property of +// Stichting Deltares. All rights reserved. +// +//------------------------------------------------------------------------------ + +#include "MeshKernelApi/MeshSmoothnessPropertyCalculator.hpp" +#include "MeshKernelApi/State.hpp" + +#include "MeshKernel/Constants.hpp" +#include "MeshKernel/Mesh2D.hpp" +#include "MeshKernel/MeshSmoothness.hpp" + +#include +#include + +bool meshkernelapi::MeshSmoothnessPropertyCalculator::IsValid(const MeshKernelState& state) const +{ + return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; +} + +void meshkernelapi::MeshSmoothnessPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const +{ + if (static_cast(geometryList.num_coordinates) < state.m_mesh2d->GetNumEdges()) + { + throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", + geometryList.num_coordinates, Size(state)); + } + + std::span smoothness(geometryList.values, state.m_mesh2d->GetNumEdges()); + meshkernel::MeshSmoothness::Compute(*state.m_mesh2d, smoothness); + + if (geometryList.coordinates_x != nullptr) + { + std::span xCoord(geometryList.coordinates_x, state.m_mesh2d->GetNumEdges()); + std::ranges::fill(xCoord, meshkernel::constants::missing::doubleValue); + } + + if (geometryList.coordinates_y != nullptr) + { + std::span yCoord(geometryList.coordinates_y, state.m_mesh2d->GetNumEdges()); + std::ranges::fill(yCoord, meshkernel::constants::missing::doubleValue); + } +} + +int meshkernelapi::MeshSmoothnessPropertyCalculator::Size(const MeshKernelState& state) const +{ + return static_cast(state.m_mesh2d->GetNumEdges()); +} + +meshkernel::Location meshkernelapi::MeshSmoothnessPropertyCalculator::EvaluationLocation() const +{ + return meshkernel::Location::Edges; +} diff --git a/libs/MeshKernelApi/src/NetlinkContourPolygonPropertyCalculator.cpp b/libs/MeshKernelApi/src/NetlinkContourPolygonPropertyCalculator.cpp index 7e5adb0d2..c00b29e29 100644 --- a/libs/MeshKernelApi/src/NetlinkContourPolygonPropertyCalculator.cpp +++ b/libs/MeshKernelApi/src/NetlinkContourPolygonPropertyCalculator.cpp @@ -26,28 +26,28 @@ //------------------------------------------------------------------------------ #include "MeshKernelApi/NetlinkContourPolygonPropertyCalculator.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" #include "MeshKernelApi/State.hpp" #include "MeshKernel/NetlinkContourPolygons.hpp" -bool meshkernelapi::NetlinkContourPolygonPropertyCalculator::IsValid(const MeshKernelState& state, const meshkernel::Location location) const +bool meshkernelapi::NetlinkContourPolygonPropertyCalculator::IsValid(const MeshKernelState& state) const { - return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0 && location == meshkernel::Location::Edges; + return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; } -void meshkernelapi::NetlinkContourPolygonPropertyCalculator::Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const +void meshkernelapi::NetlinkContourPolygonPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { if (static_cast(geometryList.num_coordinates) < 4u * state.m_mesh2d->GetNumEdges()) { throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", - geometryList.num_coordinates, Size(state, location)); + geometryList.num_coordinates, Size(state)); } std::vector netlinkContourPolygons(meshkernel::algo::NetlinkContourPolygons::Compute(*state.m_mesh2d)); - size_t size = static_cast(Size(state, location)); + size_t size = static_cast(Size(state)); std::span xCoord(geometryList.coordinates_x, size); std::span yCoord(geometryList.coordinates_y, size); @@ -64,14 +64,12 @@ void meshkernelapi::NetlinkContourPolygonPropertyCalculator::Calculate(const Mes } } -int meshkernelapi::NetlinkContourPolygonPropertyCalculator::Size(const MeshKernelState& state, const meshkernel::Location location) const +int meshkernelapi::NetlinkContourPolygonPropertyCalculator::Size(const MeshKernelState& state) const { - int size = -1; - - if (location == meshkernel::Location::Edges) - { - size = 4 * static_cast(state.m_mesh2d->GetNumEdges()); - } + return 4 * static_cast(state.m_mesh2d->GetNumEdges()); +} - return size; +meshkernel::Location meshkernelapi::NetlinkContourPolygonPropertyCalculator::EvaluationLocation() const +{ + return meshkernel::Location::Edges; } diff --git a/libs/MeshKernelApi/src/OrthogonalityPropertyCalculator.cpp b/libs/MeshKernelApi/src/OrthogonalityPropertyCalculator.cpp index 797b693e9..12146ac8c 100644 --- a/libs/MeshKernelApi/src/OrthogonalityPropertyCalculator.cpp +++ b/libs/MeshKernelApi/src/OrthogonalityPropertyCalculator.cpp @@ -26,7 +26,7 @@ //------------------------------------------------------------------------------ #include "MeshKernelApi/OrthogonalityPropertyCalculator.hpp" -#include "MeshKernelApi/PropertyCalculator.hpp" +#include "MeshKernelApi/PredefinedPropertyCalculator.hpp" #include "MeshKernelApi/State.hpp" #include "MeshKernel/MeshOrthogonality.hpp" @@ -34,18 +34,18 @@ #include #include -bool meshkernelapi::OrthogonalityPropertyCalculator::IsValid(const MeshKernelState& state, const meshkernel::Location location) const +bool meshkernelapi::OrthogonalityPropertyCalculator::IsValid(const MeshKernelState& state) const { - return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0 && location == meshkernel::Location::Edges; + return state.m_mesh2d != nullptr && state.m_mesh2d->GetNumNodes() > 0; } -void meshkernelapi::OrthogonalityPropertyCalculator::Calculate(const MeshKernelState& state, const meshkernel::Location location, const GeometryList& geometryList) const +void meshkernelapi::OrthogonalityPropertyCalculator::Calculate(const MeshKernelState& state, const GeometryList& geometryList) const { if (geometryList.num_coordinates < static_cast(state.m_mesh2d->GetNumEdges())) { throw meshkernel::ConstraintError("GeometryList with wrong dimensions, {} must be greater than or equal to {}", - geometryList.num_coordinates, Size(state, location)); + geometryList.num_coordinates, Size(state)); } std::span orthogonality(geometryList.values, geometryList.num_coordinates); @@ -72,14 +72,12 @@ void meshkernelapi::OrthogonalityPropertyCalculator::Calculate(const MeshKernelS } } -int meshkernelapi::OrthogonalityPropertyCalculator::Size(const MeshKernelState& state, const meshkernel::Location location) const +int meshkernelapi::OrthogonalityPropertyCalculator::Size(const MeshKernelState& state) const { - int size = -1; - - if (location == meshkernel::Location::Edges) - { - size = static_cast(state.m_mesh2d->GetNumEdges()); - } + return static_cast(state.m_mesh2d->GetNumEdges()); +} - return size; +meshkernel::Location meshkernelapi::OrthogonalityPropertyCalculator::EvaluationLocation() const +{ + return meshkernel::Location::Edges; } diff --git a/libs/MeshKernelApi/tests/src/Mesh2DTests.cpp b/libs/MeshKernelApi/tests/src/Mesh2DTests.cpp index 5b8174bf6..093553d5a 100644 --- a/libs/MeshKernelApi/tests/src/Mesh2DTests.cpp +++ b/libs/MeshKernelApi/tests/src/Mesh2DTests.cpp @@ -200,9 +200,8 @@ TEST(Mesh2DTests, Mesh2DGetPropertyTest) errorCode = meshkernelapi::mkernel_mesh2d_get_orthogonality_property_type(orthogonalityId); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); - int locationId = static_cast(meshkernel::Location::Edges); int geometryListDimension = -1; - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, orthogonalityId, locationId, geometryListDimension); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property_dimension(meshKernelId, orthogonalityId, geometryListDimension); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Execute @@ -211,7 +210,7 @@ TEST(Mesh2DTests, Mesh2DGetPropertyTest) propertyvalues.geometry_separator = meshkernel::constants::missing::doubleValue; std::vector values(geometryListDimension); propertyvalues.values = values.data(); - errorCode = mkernel_mesh2d_get_property(meshKernelId, orthogonalityId, locationId, propertyvalues); + errorCode = mkernel_mesh2d_get_predefined_property(meshKernelId, orthogonalityId, propertyvalues); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Assert @@ -260,9 +259,8 @@ TEST(Mesh2DTests, Mesh2DGetCircumcenterPropertyTest) errorCode = meshkernelapi::mkernel_mesh2d_get_face_circumcenter_property_type(circumcenterId); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); - int locationId = static_cast(meshkernel::Location::Faces); int geometryListDimension = -1; - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, circumcenterId, locationId, geometryListDimension); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property_dimension(meshKernelId, circumcenterId, geometryListDimension); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Execute @@ -273,7 +271,7 @@ TEST(Mesh2DTests, Mesh2DGetCircumcenterPropertyTest) std::vector yCoords(geometryListDimension); propertyvalues.coordinates_x = xCoords.data(); propertyvalues.coordinates_y = yCoords.data(); - errorCode = mkernel_mesh2d_get_property(meshKernelId, circumcenterId, locationId, propertyvalues); + errorCode = mkernel_mesh2d_get_predefined_property(meshKernelId, circumcenterId, propertyvalues); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Assert @@ -291,16 +289,6 @@ TEST(Mesh2DTests, Mesh2DGetCircumcenterPropertyTest) EXPECT_NEAR(yCoords[2], 10.35, tolerance); EXPECT_NEAR(yCoords[3], 11.548206664537, tolerance); EXPECT_NEAR(yCoords[4], 15.241823309923, tolerance); - - // Try to access the dimension for an invalid location id (nodes in this case) for circumcentres, should return non-success error code - int nodesLocation = static_cast(meshkernel::Location::Nodes); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, circumcenterId, nodesLocation, geometryListDimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); - - // Try to access the dimension for an invalid location id (edges in this case) for circumcentres, should return non-success error code - int edgesLocation = static_cast(meshkernel::Location::Edges); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, circumcenterId, edgesLocation, geometryListDimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); } TEST(Mesh2DTests, Mesh2DGetEdgeLengthPropertyTest) @@ -339,9 +327,8 @@ TEST(Mesh2DTests, Mesh2DGetEdgeLengthPropertyTest) errorCode = meshkernelapi::mkernel_mesh2d_get_edge_length_property_type(edgeLengthId); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); - int locationId = static_cast(meshkernel::Location::Edges); int geometryListDimension = -1; - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, edgeLengthId, locationId, geometryListDimension); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property_dimension(meshKernelId, edgeLengthId, geometryListDimension); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Execute @@ -350,7 +337,7 @@ TEST(Mesh2DTests, Mesh2DGetEdgeLengthPropertyTest) propertyvalues.geometry_separator = meshkernel::constants::missing::doubleValue; std::vector edgeLengths(geometryListDimension); propertyvalues.values = edgeLengths.data(); - errorCode = mkernel_mesh2d_get_property(meshKernelId, edgeLengthId, locationId, propertyvalues); + errorCode = mkernel_mesh2d_get_predefined_property(meshKernelId, edgeLengthId, propertyvalues); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Assert @@ -369,16 +356,6 @@ TEST(Mesh2DTests, Mesh2DGetEdgeLengthPropertyTest) EXPECT_NEAR(edgeLengths[9], 8.10555365166, tolerance); EXPECT_NEAR(edgeLengths[10], 9.80204060387, tolerance); EXPECT_NEAR(edgeLengths[11], 7.3, tolerance); - - // Try to access the dimension for an invalid location id (faces in this case) for edge length, should return non-success error code - int facesLocation = static_cast(meshkernel::Location::Faces); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, edgeLengthId, facesLocation, geometryListDimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); - - // Try to access the dimension for an invalid location id (nodes in this case) for edge length, should return non-success error code - int nodesLocation = static_cast(meshkernel::Location::Nodes); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshKernelId, edgeLengthId, nodesLocation, geometryListDimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); } TEST(Mesh2DTests, GetPolygonsOfDeletedFaces_WithPolygon_ShouldGetPolygonOfDeletedFaces) @@ -1784,8 +1761,7 @@ TEST(Mesh2DTests, Mesh2D_ShouldComputeNetlinkPolygon) ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Execute - int edgesLocation = static_cast(meshkernel::Location::Edges); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshkernelId, propertyId, edgesLocation, dimension); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property_dimension(meshkernelId, propertyId, dimension); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Each polygon has exactly 4 points @@ -1800,7 +1776,7 @@ TEST(Mesh2DTests, Mesh2D_ShouldComputeNetlinkPolygon) polygons.coordinates_x = xCoords.data(); polygons.coordinates_y = yCoords.data(); - errorCode = meshkernelapi::mkernel_mesh2d_get_property(meshkernelId, propertyId, edgesLocation, polygons); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property(meshkernelId, propertyId, polygons); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); std::vector expectedX{1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 2, 1, 1, 2, 1, 2, 2, 1, 1, 2, 2, 1, 3, 2, 2, 3, 2, 3, 3, 2, 2, 3, 3, 2, 0.5, 0.5, 0, 0, 0.5, 0.5, 0, 0, 0.5, 0.5, 1.5, 1.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 3, 3, 2.5, 2.5, 3, 3}; @@ -1814,16 +1790,6 @@ TEST(Mesh2DTests, Mesh2D_ShouldComputeNetlinkPolygon) EXPECT_NEAR(xCoords[i], expectedX[i], tolerance); EXPECT_NEAR(yCoords[i], expectedY[i], tolerance); } - - // Try to access the dimension for an invalid location id (faces in this case) for netlink contours, should return non-success error code - int facesLocation = static_cast(meshkernel::Location::Faces); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshkernelId, propertyId, facesLocation, dimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); - - // Try to access the dimension for an invalid location id (node in this case) for netlink contours, should return non-success error code - int nodesLocation = static_cast(meshkernel::Location::Nodes); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshkernelId, propertyId, nodesLocation, dimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); } TEST(Mesh2DTests, Mesh2D_ShouldComputeFaceBounds) @@ -1840,8 +1806,7 @@ TEST(Mesh2DTests, Mesh2D_ShouldComputeFaceBounds) ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); // Execute - int facesLocation = static_cast(meshkernel::Location::Faces); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshkernelId, propertyId, facesLocation, dimension); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property_dimension(meshkernelId, propertyId, dimension); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); ASSERT_EQ(dimension, 6 * 6); // 2x3 quadrilateral elements => 6 * 6 nodes (the maximum number of nodes an element can have is 6) @@ -1855,7 +1820,7 @@ TEST(Mesh2DTests, Mesh2D_ShouldComputeFaceBounds) polygons.coordinates_x = xCoords.data(); polygons.coordinates_y = yCoords.data(); - errorCode = meshkernelapi::mkernel_mesh2d_get_property(meshkernelId, propertyId, facesLocation, polygons); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property(meshkernelId, propertyId, polygons); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); std::vector expectedX{0.0, 1.0, 1.0, 0.0, -999.0, -999.0, 0.0, 1.0, 1.0, 0.0, -999.0, -999.0, 1.0, 2.0, 2.0, 1.0, -999.0, -999.0, 1.0, 2.0, 2.0, 1.0, -999.0, -999.0, 2.0, 3.0, 3.0, 2.0, -999.0, -999.0, 2.0, 3.0, 3.0, 2.0, -999.0, -999.0}; @@ -1868,14 +1833,4 @@ TEST(Mesh2DTests, Mesh2D_ShouldComputeFaceBounds) EXPECT_NEAR(xCoords[i], expectedX[i], tolerance); EXPECT_NEAR(yCoords[i], expectedY[i], tolerance); } - - // Try to access the dimension for an invalid location id (faces in this case) for netlink contours, should return non-success error code - int edgesLocation = static_cast(meshkernel::Location::Edges); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshkernelId, propertyId, edgesLocation, dimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); - - // Try to access the dimension for an invalid location id (node in this case) for netlink contours, should return non-success error code - int nodesLocation = static_cast(meshkernel::Location::Nodes); - errorCode = meshkernelapi::mkernel_mesh2d_get_property_dimension(meshkernelId, propertyId, nodesLocation, dimension); - ASSERT_EQ(meshkernel::ExitCode::MeshKernelErrorCode, errorCode); } diff --git a/libs/MeshKernelApi/tests/src/SmoothnessOrthogonalisationTests.cpp b/libs/MeshKernelApi/tests/src/SmoothnessOrthogonalisationTests.cpp index 0d72d7573..183ab5f2f 100644 --- a/libs/MeshKernelApi/tests/src/SmoothnessOrthogonalisationTests.cpp +++ b/libs/MeshKernelApi/tests/src/SmoothnessOrthogonalisationTests.cpp @@ -206,17 +206,21 @@ TEST_F(CartesianApiTestFixture, GetSmoothnessMesh2D_OnMesh2D_ShouldGetSmoothness MakeMesh(); auto const meshKernelId = GetMeshKernelId(); - meshkernelapi::Mesh2D mesh2d{}; - auto errorCode = mkernel_mesh2d_get_dimensions(meshKernelId, mesh2d); + int smoothnessPropertyId = -1; + auto errorCode = meshkernelapi::mkernel_mesh2d_get_mesh_smoothness_property_type(smoothnessPropertyId); ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); - meshkernelapi::GeometryList edgeSmoothness; - std::vector values(mesh2d.num_edges); + int dimension = -1; + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property_dimension(meshKernelId, smoothnessPropertyId, dimension); + ASSERT_EQ(meshkernel::ExitCode::Success, errorCode); + + meshkernelapi::GeometryList edgeSmoothness{}; + std::vector values(dimension); edgeSmoothness.values = values.data(); - edgeSmoothness.num_coordinates = mesh2d.num_edges; + edgeSmoothness.num_coordinates = dimension; // Execute - errorCode = mkernel_mesh2d_get_smoothness(meshKernelId, edgeSmoothness); + errorCode = meshkernelapi::mkernel_mesh2d_get_predefined_property(meshKernelId, smoothnessPropertyId, edgeSmoothness); // Assert ASSERT_EQ(meshkernel::ExitCode::Success, errorCode);