From 94a9c8dae519b090cc064eac13a60f4c5f4c57e1 Mon Sep 17 00:00:00 2001
From: Dmitri Naumov <github@naumov.de>
Date: Mon, 20 Jul 2020 18:10:24 +0200
Subject: [PATCH] [ParL] Pass curves to FunctionParameter.

Allows usage of curves in Function type parameters.
---
 ParameterLib/FunctionParameter.cpp |  8 ++++--
 ParameterLib/FunctionParameter.h   | 40 ++++++++++++++++++++++++++++--
 ParameterLib/Parameter.cpp         |  2 +-
 3 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/ParameterLib/FunctionParameter.cpp b/ParameterLib/FunctionParameter.cpp
index 11da80a7580..2c3511be564 100644
--- a/ParameterLib/FunctionParameter.cpp
+++ b/ParameterLib/FunctionParameter.cpp
@@ -15,7 +15,10 @@
 namespace ParameterLib
 {
 std::unique_ptr<ParameterBase> createFunctionParameter(
-    std::string const& name, BaseLib::ConfigTree const& config)
+    std::string const& name, BaseLib::ConfigTree const& config,
+    std::map<std::string,
+             std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
+        curves)
 {
     //! \ogs_file_param{prj__parameters__parameter__type}
     config.checkConfigParameter("type", "Function");
@@ -29,7 +32,8 @@ std::unique_ptr<ParameterBase> createFunctionParameter(
         vec_expressions.emplace_back(expression_str);
     }
 
-    return std::make_unique<FunctionParameter<double>>(name, vec_expressions);
+    return std::make_unique<FunctionParameter<double>>(name, vec_expressions,
+                                                       curves);
 }
 
 }  // namespace ParameterLib
diff --git a/ParameterLib/FunctionParameter.h b/ParameterLib/FunctionParameter.h
index 812fdeac365..8a316c5f1fe 100644
--- a/ParameterLib/FunctionParameter.h
+++ b/ParameterLib/FunctionParameter.h
@@ -28,6 +28,23 @@ namespace ParameterLib
 template <typename T>
 struct FunctionParameter final : public Parameter<T>
 {
+    class CurveWrapper : public exprtk::ifunction<T>
+    {
+    public:
+        CurveWrapper(MathLib::PiecewiseLinearInterpolation const& curve)
+            : exprtk::ifunction<T>(1), _curve(curve)
+        {
+            exprtk::disable_has_side_effects(*this);
+        }
+        double operator()(double const& t) override
+        {
+            return _curve.getValue(t);
+        }
+
+    private:
+        MathLib::PiecewiseLinearInterpolation const& _curve;
+    };
+
     using symbol_table_t = exprtk::symbol_table<T>;
     using expression_t = exprtk::expression<T>;
     using parser_t = exprtk::parser<T>;
@@ -40,16 +57,34 @@ struct FunctionParameter final : public Parameter<T>
      * @param vec_expression_str  a vector of mathematical expressions
      * The vector size specifies the number of components of the parameter.
      */
-    FunctionParameter(std::string const& name,
-                      std::vector<std::string> const& vec_expression_str)
+    FunctionParameter(
+        std::string const& name,
+        std::vector<std::string> const& vec_expression_str,
+        std::map<std::string,
+                 std::unique_ptr<MathLib::PiecewiseLinearInterpolation>> const&
+            curves)
         : Parameter<T>(name, nullptr), _vec_expression_str(vec_expression_str)
     {
+        // Convert curves to function objects callable by the exprtk.
+        _curves.reserve(curves.size());
+        std::transform(
+            begin(curves), end(curves), std::back_inserter(_curves),
+            [](auto const& curve) -> std::pair<std::string, CurveWrapper> {
+                return {curve.first, CurveWrapper(*curve.second)};
+            });
+
+        // Create symbol table for variables and functions.
         _symbol_table.add_constants();
         _symbol_table.create_variable("x");
         _symbol_table.create_variable("y");
         _symbol_table.create_variable("z");
         _symbol_table.create_variable("t");
+        for (auto& curve : _curves)
+        {
+            _symbol_table.add_function(curve.first, curve.second);
+        }
 
+        // Compile expressions.
         _vec_expression.resize(_vec_expression_str.size());
         for (unsigned i = 0; i < _vec_expression_str.size(); i++)
         {
@@ -108,6 +143,7 @@ private:
     std::vector<std::string> const _vec_expression_str;
     symbol_table_t _symbol_table;
     std::vector<expression_t> _vec_expression;
+    std::vector<std::pair<std::string, CurveWrapper>> _curves;
 };
 
 std::unique_ptr<ParameterBase> createFunctionParameter(
diff --git a/ParameterLib/Parameter.cpp b/ParameterLib/Parameter.cpp
index cd39a7309d7..3bafd8cde75 100644
--- a/ParameterLib/Parameter.cpp
+++ b/ParameterLib/Parameter.cpp
@@ -59,7 +59,7 @@ std::unique_ptr<ParameterBase> createParameter(
     if (type == "Function")
     {
         INFO("FunctionParameter: {:s}", name);
-        return createFunctionParameter(name, config);
+        return createFunctionParameter(name, config, curves);
     }
     if (type == "Group")
     {
-- 
GitLab