46 lines
1.5 KiB
C++
46 lines
1.5 KiB
C++
/* ImScale.hpp */
|
|
|
|
#pragma once
|
|
|
|
#include "imgui.h"
|
|
#include "ImSpan.hpp"
|
|
|
|
/** Linear scale for transforming between two coordinate systems.
|
|
* f(x) = m.(x - x0) + y0
|
|
* inv(f)(y) = x0 + (y - y0) / m
|
|
**/
|
|
class ImScale {
|
|
public:
|
|
ImScale(ImVec2 ref, float m) : ref_{ref}, scale_{m} {}
|
|
/** derive scale f from two reference points @p ref0 and @p ref1.
|
|
* Promise:
|
|
* @pre
|
|
* f(ref0.x) -> ref0.y
|
|
* f(ref1.x) -> ref1.y
|
|
* @endpre
|
|
**/
|
|
ImScale(ImVec2 ref0, ImVec2 ref1) : ref_{ref0}, scale_{(ref1.y - ref0.y) / (ref1.x - ref0.x)} {}
|
|
|
|
ImVec2 ref() const { return ref_; }
|
|
float scale() const { return scale_; }
|
|
|
|
/** evaluate scale f(x) at @p x **/
|
|
constexpr float at(float x) const { return scale_ * (x - ref_.x) + ref_.y; }
|
|
/** evaluate inverse inv(f)(y) at @p y **/
|
|
constexpr float inverse_at(float y) const { return 1.0 / scale_ * (y - ref_.y) + ref_.x; }
|
|
|
|
/** construct inverse function inv(f) **/
|
|
ImScale inverse() const { return ImScale(ImVec2(ref_.y, ref_.x), 1.0 / scale_); }
|
|
|
|
ImSpan map_span(ImSpan x_span) const { return ImSpan(at(x_span.lo()), at(x_span.hi())); }
|
|
ImVec2 map_span(ImVec2 x_span) const { return ImVec2(at(x_span.x), at(x_span.y)); }
|
|
ImVec2 map_span(float x1, float x2) const { return map_span(ImVec2(x1, x2)); }
|
|
|
|
constexpr float operator()(float x) const { return at(x); }
|
|
|
|
private:
|
|
/** fixed point {x0, f(x0)} **/
|
|
ImVec2 ref_ = ImVec2{0.0, 0.0};
|
|
/** scale. f(x) - f(x0) = m * (x - x0) **/
|
|
float scale_ = 1.0;
|
|
};
|