#ifndef SCALER_H #define SCALER_H #include #include struct Rect { float x0; float y0; float x1; float y1; }; /** * - scale between map- and screen-space. * - inverts y-axis (for openGL) */ class Scaler { private: int w; int h; float _scale = 50; float _snap = 0.1; Point3 _offset; public: /** map->screen (no offset) */ float ms(const float m) const {return m*_scale;} /** x map->screen */ float xms(const float x) const {return w/2+(x+_offset.x)*_scale;} /** x map->screen */ float yms(const float y) const {return h/2-(y-_offset.y)*_scale;} /** screen->map (no offset) */ float sm(const float s) const {return (s/_scale);} /** x screen->map */ float xsm(const float x) const {return ((x-w/2)/_scale)-_offset.x;} /** y screen->map */ float ysm(const float y) const {return ((h/2-y)/_scale)+_offset.y;} void setScale(const float s) {_scale = s;} float getScale() const {return _scale;} void setOffset(Point3 p) {_offset = p;} Point3 getOffset() const {return _offset;} void addOffset(int px, int py) {_offset.x += sm(px); _offset.y += sm(py);} float getLODstep() const { float step = 0.01; if (_scale <= 1000) {step = 0.1;} if (_scale <= 500) {step = 0.5;} if (_scale <= 100) {step = 1.0;} if (_scale <= 50) {step = 5.0;} if (_scale <= 10) {step = 10.0;} if (_scale <= 1) {step = 100.0;} return step; } /** get the currently visible map-region given the provided screen-size */ Rect getMapVisible(const int screenW, const int screenH) const { Rect r; r.x0 = xsm(0); r.x1 = xsm(screenW); r.y0 = ysm(screenH); r.y1 = ysm(0); return r; } /** get the currently visible map-region given the provided screen-size, SNAPED to the given grid-size */ Rect getMapVisible(const int screenW, const int screenH, const float mapGridSize) const { Rect r = getMapVisible(screenW, screenH); r.x0 = snapFloor(r.x0, mapGridSize); r.y0 = snapFloor(r.y0, mapGridSize); r.x1 = snapCeil(r.x1, mapGridSize); r.y1 = snapCeil(r.y1, mapGridSize); return r; } //Point2 getOffset() const {return _offset.xy();} Point2 getCenter() const {return Point2(-_offset.x, _offset.y);} void setScreenSize(const int w, const int h) {this->w = w; this->h = h;} public: static float snap(const float v, const float grid) { return std::round(v/grid)*grid; } static Point2 snap(const Point2 p, const float grid) { return Point2(snap(p.x, grid), snap(p.y, grid)); } static Point3 snap(const Point3 p, const float grid) { return Point3(snap(p.x, grid), snap(p.y, grid), snap(p.z, grid)); } static float snapCeil(const float v, const float grid) { return std::ceil(v/grid) * grid; } static float snapFloor(const float v, const float grid) { return std::floor(v/grid) * grid; } //float snap(const float v) const { return v; } }; #endif // SCALER_H