Loading...
Searching...
No Matches
Spline/GeneratorDialog.hpp
1#pragma once
2#include <Process/Script/ScriptEditor.hpp>
3
4#include <ossia/math/math_expression.hpp>
5
6#include <QDialog>
7#include <QDoubleSpinBox>
8#include <QFormLayout>
9#include <QHBoxLayout>
10
11#include <cmath>
12
13#include <Spline/Commands.hpp>
14
15namespace Spline
16{
18{
19public:
21 const ProcessModel& model, const score::DocumentContext& ctx, QWidget* parent)
22 : Process::ScriptDialog{"exprtk", ctx, parent}
23 , m_model{model}
24 {
25 auto step = new QDoubleSpinBox{this};
26 step->setRange(0.0001, 0.3);
27 step->setValue(m_step);
28 step->setSingleStep(0.001);
29 step->setDecimals(8);
30 // step->setStepType(QSpinBox::AdaptiveDecimalStepType);
31 auto lay = static_cast<QBoxLayout*>(this->layout());
32 auto controls = new QFormLayout;
33 controls->addRow("Step (smaller is more precise)", step);
34 lay->insertLayout(2, controls);
35 connect(
36 step, qOverload<double>(&QDoubleSpinBox::valueChanged), this,
37 [this](double step) { m_step = step; });
38
39 expr.add_variable("t", t);
40 expr.add_variable("x", x);
41 expr.add_variable("y", y);
42 expr.add_constants();
43 expr.register_symbol_table();
44
45 setText(R"_(x := cos(2 * pi * t);
46y := sin(2 * pi * t);
47)_");
48 }
49
50 void on_accepted() override
51 {
52 this->setError(0, QString{});
53 auto txt = this->text().toStdString();
54 bool ok = expr.set_expression(txt);
55 if(!ok)
56 {
57 setError(0, QString::fromStdString(expr.error()));
58 return;
59 }
60 else
61 {
62 ossia::spline_data data;
63 QString error;
64 auto add_point = [&] {
65 expr.value();
66 if(expr.interrupted())
67 error = tr("The expression runs for too long (a loop does not end)");
68 else if(!(std::isfinite(x) && std::isfinite(y)))
69 error = tr("The expression gives an undefined point at t = %1").arg(t);
70 else
71 data.points.push_back({x, y});
72 return error.isEmpty();
73 };
74 bool complete = true;
75 for(t = 0.; t < 1. && complete; t += m_step)
76 complete = add_point();
77 if(complete)
78 {
79 t = 1.;
80 complete = add_point();
81 }
82 if(!complete)
83 {
84 setError(0, error);
85 return;
86 }
87
88 CommandDispatcher<>{m_context.commandStack}.submit<ChangeSpline>(
89 m_model, std::move(data));
90 }
91 }
92 double t{}, x{}, y{};
93 double m_step{0.03};
94 ossia::math_expression expr;
95
96 const ProcessModel& m_model;
97};
98
99}
The CommandDispatcher class.
Definition CommandDispatcher.hpp:13
Definition ScriptEditor.hpp:22
Definition plugins/score-plugin-spline/Spline/commands.hpp:14
Definition Spline/GeneratorDialog.hpp:18
Definition score-plugin-spline/Spline/Model.hpp:20
Definition DocumentContext.hpp:18