summaryrefslogtreecommitdiff
path: root/include/llmr/map/transform.hpp
blob: dbef17c1a15f2f095f87618aa04c7bbcbc95aa6c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#ifndef LLMR_MAP_TRANSFORM
#define LLMR_MAP_TRANSFORM

#include <llmr/util/vec.hpp>
#include <llmr/util/mat4.hpp>
#include <llmr/util/animation.hpp>
#include <llmr/util/noncopyable.hpp>
#include <llmr/map/tile.hpp>

#include <forward_list>

namespace llmr {

struct box;

    class Transform : private util::noncopyable {
public:
    Transform();

    // Animations
    bool needsAnimation() const;
    void updateAnimations();
    void cancelAnimations();

    void resize(uint16_t width, uint16_t height, uint16_t fb_width, uint16_t fb_height);

    // Relative changes
    void moveBy(double dx, double dy, double duration = 0);
    void scaleBy(double ds, double cx = -1, double cy = -1, double duration = 0);
    void rotateBy(double cx, double cy, double sx, double sy, double ex, double ey, double duration = 0);

    // Absolute changes
    void setScale(double scale, double cx = -1, double cy = -1, double duration = 0);
    void setAngle(double angle, double duration = 0);
    void setZoom(double zoom, double duration = 0);
    void setLonLat(double lon, double lat, double duration = 0);
    void setLonLatZoom(double lon, double lat, double zoom, double duration = 0);

    // Getters
    void matrixFor(mat4& matrix, const Tile::ID& id) const;
    float getZoom() const;
    float getNormalizedZoom() const;
    int32_t getIntegerZoom() const;
    double getScale() const;
    double getAngle() const;
    void getLonLat(double& lon, double& lat) const;
    void getLonLatZoom(double& lon, double& lat, double& zoom) const;

    // Animations
    void startPanning();
    void stopPanning();
    void startRotating();
    void stopRotating();
    void startScaling();
    void stopScaling();

    // Temporary
    box mapCornersToBox(uint32_t z) const;

    // More getters
    inline uint16_t getWidth() const { return width; }
    inline uint16_t getHeight() const { return height; }
    inline uint16_t getFramebufferWidth() const { return fb_width; }
    inline uint16_t getFramebufferHeight() const { return fb_height; }
    inline float getPixelRatio() const { return pixelRatio; }

private:
    void setScaleXY(double new_scale, double xn, double yn, double duration = 0);
    double pixel_x() const;
    double pixel_y() const;

private:
    // logical dimensions
    uint16_t width = 0;
    uint16_t height = 0;

    // physical (framebuffer) dimensions
    uint16_t fb_width = 0;
    uint16_t fb_height = 0;

    float pixelRatio = 1;

public:
    bool rotating = false;
    bool scaling = false;
    bool panning = false;

private:
    double x = 0, y = 0; // pixel values of the map center in the current scale
    double angle = 0;
    double scale = 1;

    double min_scale = pow(2, 0);
    double max_scale = pow(2, 20);

    // cache values for spherical mercator math
    double zc, Bc, Cc;

    std::forward_list<std::shared_ptr<util::animation>> animations;
    std::shared_ptr<util::animation> scale_timeout;
    std::shared_ptr<util::animation> rotate_timeout;
    std::shared_ptr<util::animation> pan_timeout;
};

}

#endif