diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2016-12-16 11:58:02 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2016-12-16 11:58:02 +0100 |
commit | 8cd2a4ee13a086759740dde22d03ab281fa55886 (patch) | |
tree | bc5f7ffab761ee5769aeb99b5fec27ce43be4c2a | |
parent | d37bed91649d2acdd9a548cd52730a87d0a28d6d (diff) |
tracker/tobii: flush, but still broken
Needs the spline class to allow initializing itself from a function. Even if the
passed control points are correct, it still looks like shit. Presently they
aren't correct though. Need to work on linear approximation.
-rw-r--r-- | tracker-tobii-eyex/tobii-eyex-dialog.cpp | 2 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-eyex-dialog.ui | 195 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-settings.cpp | 74 | ||||
-rw-r--r-- | tracker-tobii-eyex/tobii-settings.hpp | 5 |
4 files changed, 106 insertions, 170 deletions
diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.cpp b/tracker-tobii-eyex/tobii-eyex-dialog.cpp index 0388ddfb..8997c6c2 100644 --- a/tracker-tobii-eyex/tobii-eyex-dialog.cpp +++ b/tracker-tobii-eyex/tobii-eyex-dialog.cpp @@ -20,9 +20,7 @@ tobii_eyex_dialog::tobii_eyex_dialog() tie_setting(rs.expt_len, ui.exponent_len); tie_setting(rs.expt_norm, ui.exponent_norm); - tie_setting(rs.log_slope, ui.log_base); tie_setting(rs.log_len, ui.log_len); - tie_setting(rs.log_norm, ui.log_norm); connect(rs.b.get(), &bundle_::changed, this, [this]() { rs.make_spline(); }, Qt::QueuedConnection); diff --git a/tracker-tobii-eyex/tobii-eyex-dialog.ui b/tracker-tobii-eyex/tobii-eyex-dialog.ui index 1e622f93..b6138514 100644 --- a/tracker-tobii-eyex/tobii-eyex-dialog.ui +++ b/tracker-tobii-eyex/tobii-eyex-dialog.ui @@ -192,19 +192,22 @@ </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLabel" name="speed_label"> - <property name="minimumSize"> - <size> - <width>24</width> - <height>0</height> - </size> + <item row="1" column="2"> + <widget class="QSlider" name="deadzone"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> </property> - <property name="text"> - <string>0</string> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + <property name="tickPosition"> + <enum>QSlider::TicksAbove</enum> + </property> + <property name="tickInterval"> + <number>25</number> </property> </widget> </item> @@ -224,25 +227,6 @@ </property> </widget> </item> - <item row="1" column="2"> - <widget class="QSlider" name="deadzone"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="tickPosition"> - <enum>QSlider::TicksAbove</enum> - </property> - <property name="tickInterval"> - <number>25</number> - </property> - </widget> - </item> <item row="2" column="2"> <widget class="QSlider" name="exponent"> <property name="sizePolicy"> @@ -262,8 +246,8 @@ </property> </widget> </item> - <item row="1" column="1"> - <widget class="QLabel" name="deadzone_label"> + <item row="0" column="1"> + <widget class="QLabel" name="speed_label"> <property name="minimumSize"> <size> <width>24</width> @@ -291,6 +275,22 @@ </property> </widget> </item> + <item row="1" column="1"> + <widget class="QLabel" name="deadzone_label"> + <property name="minimumSize"> + <size> + <width>24</width> + <height>0</height> + </size> + </property> + <property name="text"> + <string>0</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> <item row="5" column="0"> <widget class="QLabel" name="label_8"> <property name="sizePolicy"> @@ -333,19 +333,6 @@ </property> </widget> </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_5"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Exponent segment length</string> - </property> - </widget> - </item> <item row="5" column="2"> <widget class="QSlider" name="log_len"> <property name="sizePolicy"> @@ -365,8 +352,8 @@ </property> </widget> </item> - <item row="6" column="0"> - <widget class="QLabel" name="label_9"> + <item row="3" column="0"> + <widget class="QLabel" name="label_5"> <property name="sizePolicy"> <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> <horstretch>0</horstretch> @@ -374,42 +361,7 @@ </sizepolicy> </property> <property name="text"> - <string>Log slope</string> - </property> - </widget> - </item> - <item row="6" column="1"> - <widget class="QLabel" name="log_base_label"> - <property name="minimumSize"> - <size> - <width>24</width> - <height>0</height> - </size> - </property> - <property name="text"> - <string>0</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="6" column="2"> - <widget class="QSlider" name="log_base"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="tickPosition"> - <enum>QSlider::TicksAbove</enum> - </property> - <property name="tickInterval"> - <number>25</number> + <string>Exponent segment length</string> </property> </widget> </item> @@ -448,19 +400,6 @@ </property> </widget> </item> - <item row="4" column="0"> - <widget class="QLabel" name="label_6"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Exponent norm</string> - </property> - </widget> - </item> <item row="4" column="2"> <widget class="QSlider" name="exponent_norm"> <property name="sizePolicy"> @@ -480,6 +419,19 @@ </property> </widget> </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Exponent norm</string> + </property> + </widget> + </item> <item row="3" column="2"> <widget class="QSlider" name="exponent_len"> <property name="sizePolicy"> @@ -515,53 +467,18 @@ </property> </widget> </item> - <item row="7" column="1"> - <widget class="QLabel" name="log_norm_label"> - <property name="minimumSize"> + <item row="6" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> <size> - <width>24</width> + <width>20</width> <height>0</height> </size> </property> - <property name="text"> - <string>0</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="7" column="2"> - <widget class="QSlider" name="log_norm"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="tickPosition"> - <enum>QSlider::TicksAbove</enum> - </property> - <property name="tickInterval"> - <number>25</number> - </property> - </widget> - </item> - <item row="7" column="0"> - <widget class="QLabel" name="label_12"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Log norm</string> - </property> - </widget> + </spacer> </item> </layout> </widget> diff --git a/tracker-tobii-eyex/tobii-settings.cpp b/tracker-tobii-eyex/tobii-settings.cpp index fb5bb8f6..0dcb377f 100644 --- a/tracker-tobii-eyex/tobii-settings.cpp +++ b/tracker-tobii-eyex/tobii-settings.cpp @@ -28,14 +28,45 @@ void rel_settings::make_spline() { - const double log_c = 1./std::log(log_slope()); + const double dz_len_ = dz_len(), + expt_len_ = expt_len(), + expt_norm_ = expt_norm(), + expt_slope_ = expt_slope(), + log_len_ = log_len(); + + const double expt_deriv_at_end = expt_norm_ * expt_slope_ * std::pow(expt_len_, expt_slope_ - 1); // cnx^(n-1) + const double expt_at_end = expt_norm_ * std::pow(expt_len_, expt_slope_); // cx^n + + const double lin_len = 1 - dz_len_ - expt_len_ - log_len_; + + // this isn't correct but works. + // we use exponentiation of the linear part to get logarithmic approximation of the linear + // part rather than linear approximation of the linear part + + const double lin_at_end = std::pow(M_E, lin_len * expt_deriv_at_end - expt_at_end); // e^(cx + a) + const double lin_deriv_at_end = expt_deriv_at_end * std::exp(-expt_at_end + expt_deriv_at_end * lin_len); // ce^(a + cx) + + // this was all derived by the awesome linear approximation + // calculator <http://www.emathhelp.net/calculators/calculus-1/linear-approximation-calculator/> + + auto expt_part = [=](double x) { return expt_norm_ * std::pow(x, expt_slope_); }; + const double expt_inv_norm = expt_norm_/expt_part(expt_len_); + + auto lin_part = [=](double x) { return expt_inv_norm * (expt_at_end + expt_deriv_at_end * (x - expt_len_)); }; + const double lin_inv_norm = (1 - expt_norm_ - .25)/lin_part(lin_len); + + // TODO needs norm for log/lin parts + auto log_part = [=](double x) { return expt_inv_norm * lin_inv_norm * std::log(lin_at_end + lin_deriv_at_end * (x - lin_len)); }; + const double log_inv_norm = .25/log_part(expt_len_); + + qDebug() << "lin" << expt_deriv_at_end << lin_inv_norm; part functors[] { - { 1, dz_len(), 0, [](double) { return 0; } }, - { 5, expt_len(), expt_norm(), [=](double x) { return std::pow(x, expt_slope()); } }, - { 7, 1 - dz_len() - expt_len() - log_len(), std::max(0., 1 - expt_norm() - log_norm()), [](double x) { return x; } }, - { 7, log_len(), log_norm(), [=](double x) { return std::log(1+x)*log_c; } }, + { dz_len_, [](double) { return 0; } }, + { expt_len_, [=](double x) { return expt_inv_norm * expt_part(x); } }, // cx^n + { lin_len, [=](double x) { return lin_inv_norm * lin_part(x); } }, // cx + a + { log_len_, [=](double x) { return log_inv_norm * log_part(x); } }, // ln(cx + a) }; make_spline_(functors, std::distance(std::begin(functors), std::end(functors))); @@ -45,12 +76,10 @@ rel_settings::rel_settings() : opts("tobii-eyex-relative-mode"), speed(b, "speed", s(3, .1, 10)), dz_len(b, "deadzone-length", s(.04, 0, .2)), - expt_slope(b, "exponent-slope", s(1.75, 1.25, 3)), - expt_len(b, "exponent-length", s(.25, 0, .5)), - expt_norm(b, "exponent-norm", s(.3, .1, .5)), - log_slope(b, "log-slope", s(2.75, 1.25, 10)), + expt_slope(b, "exponent-slope", s(1.75, 1.5, 3)), + expt_len(b, "exponent-length", s(.2, 0, .5)), + expt_norm(b, "exponent-norm", s(.4, .1, .5)), log_len(b, "log-len", s(.1, 0, .2)), - log_norm(b, "log-norm", s(.1, .05, .3)), acc_mode_spline(100, 100, "") { make_spline(); @@ -68,30 +97,23 @@ void rel_settings::make_spline_(part* functors, unsigned len) { acc_mode_spline.removeAllPoints(); - double lastx = 0, lasty = 0; - - using std::accumulate; - - const double inv_norm_y = 1./accumulate(functors, functors + len, 1e-4, [](double acc, const part& functor) { return acc + functor.norm; }); - const double inv_norm_x = 1./accumulate(functors, functors + len, 1e-4, [](double acc, const part& functor) { return acc + functor.len; }); + double lastx = 0; for (unsigned k = 0; k < len; k++) { part& fun = functors[k]; - const double xscale = fun.len * spline_max * inv_norm_x; - const double maxx = fun.f(1); - const double yscale = fun.norm * spline_max * inv_norm_y * (maxx < 1e-3 ? 0 : 1./maxx); + static constexpr unsigned nparts = 7; - for (unsigned i = 0; i <= fun.nparts; i++) + for (unsigned i = 1; i <= nparts; i++) { - const double x = lastx + (fun.nparts == 0 ? 1 : i) / (1.+fun.nparts) * xscale; - const double y = lasty + clamp(fun.f(x) * yscale, 0, spline_max); - qDebug() << k << i << x << y; - acc_mode_spline.addPoint(x, y); + const double x = i*fun.len/nparts; + const double y = clamp(fun.f(x), 0, 1); + if (i == nparts/2) + qDebug() << k << i << x << y; + acc_mode_spline.addPoint((lastx + x) * spline_max, y * spline_max); } - lastx += xscale; - lasty += yscale; + lastx += fun.len; } } diff --git a/tracker-tobii-eyex/tobii-settings.hpp b/tracker-tobii-eyex/tobii-settings.hpp index 4346a156..5c09b201 100644 --- a/tracker-tobii-eyex/tobii-settings.hpp +++ b/tracker-tobii-eyex/tobii-settings.hpp @@ -24,8 +24,7 @@ class rel_settings final : public QObject, public opts struct part { - int nparts; - double len, norm; + double len; functor f; }; @@ -33,7 +32,7 @@ class rel_settings final : public QObject, public opts public: using s = slider_value; - value<slider_value> speed, dz_len, expt_slope, expt_len, expt_norm, log_slope, log_len, log_norm; + value<slider_value> speed, dz_len, expt_slope, expt_len, expt_norm, log_len; spline acc_mode_spline; rel_settings(); double gain(double value); |