copy rotation behavior from js version
This commit is contained in:
@@ -21,7 +21,7 @@ public:
|
||||
bool render();
|
||||
void moveBy(double dx, double dy);
|
||||
void scaleBy(double ds, double cx, double cy);
|
||||
void rotateBy(double cx, double cy, double dx, double dy);
|
||||
void rotateBy(double cx, double cy, double sx, double sy, double ex, double ey);
|
||||
void tileLoaded(tile *tile);
|
||||
void tileFailed(tile *tile);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
// Relative changes
|
||||
void moveBy(double dx, double dy);
|
||||
void scaleBy(double ds, double cx, double cy);
|
||||
void rotateBy(double cx, double cy, double dx, double dy);
|
||||
void rotateBy(double cx, double cy, double sx, double sy, double ex, double ey);
|
||||
|
||||
// Absolute changes
|
||||
void setScale(double scale);
|
||||
|
||||
16
include/llmr/util/math.hpp
Normal file
16
include/llmr/util/math.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef LLMR_UTIL_MATH
|
||||
#define LLMR_UTIL_MATH
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace llmr {
|
||||
namespace util {
|
||||
|
||||
inline double angle_between(double ax, double ay, double bx, double by) {
|
||||
return atan2((ax * by - ay * bx), ax * bx + ay * by);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -75,7 +75,13 @@ public:
|
||||
static void mouseclick(GLFWwindow *window, int button, int action, int modifiers) {
|
||||
MapView *view = (MapView *)glfwGetWindowUserPointer(window);
|
||||
|
||||
if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||
if (button == GLFW_MOUSE_BUTTON_RIGHT || (button == GLFW_MOUSE_BUTTON_LEFT && modifiers & GLFW_MOD_CONTROL)) {
|
||||
view->rotating = action == GLFW_PRESS;
|
||||
if (view->rotating) {
|
||||
view->start_x = view->last_x;
|
||||
view->start_y = view->last_y;
|
||||
}
|
||||
} else if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||
view->tracking = action == GLFW_PRESS;
|
||||
|
||||
if (action == GLFW_RELEASE) {
|
||||
@@ -85,14 +91,7 @@ public:
|
||||
}
|
||||
view->last_click = now;
|
||||
}
|
||||
} else if (button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
view->rotating = action == GLFW_PRESS;
|
||||
if (view->rotating) {
|
||||
view->start_x = view->last_x;
|
||||
view->start_y = view->last_y;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void mousemove(GLFWwindow *window, double x, double y) {
|
||||
@@ -100,7 +99,7 @@ public:
|
||||
if (view->tracking) {
|
||||
view->map->moveBy(x - view->last_x, y - view->last_y);
|
||||
} else if (view->rotating) {
|
||||
view->map->rotateBy(view->start_x, view->start_y, x - view->last_x, y - view->last_y);
|
||||
view->map->rotateBy(view->start_x, view->start_y, view->last_x, view->last_y, x, y);
|
||||
}
|
||||
view->last_x = x;
|
||||
view->last_y = y;
|
||||
|
||||
@@ -52,8 +52,8 @@ void map::scaleBy(double ds, double cx, double cy) {
|
||||
platform->restart();
|
||||
}
|
||||
|
||||
void map::rotateBy(double cx, double cy, double dx, double dy) {
|
||||
transform->rotateBy(cx, cy, dx, dy);
|
||||
void map::rotateBy(double cx, double cy, double sx, double sy, double ex, double ey) {
|
||||
transform->rotateBy(cx, cy, sx, sy, ex, ey);
|
||||
platform->restart();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <llmr/map/transform.hpp>
|
||||
|
||||
#include <llmr/util/mat4.h>
|
||||
#include <llmr/util/math.hpp>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -42,9 +43,32 @@ void transform::scaleBy(double ds, double cx, double cy) {
|
||||
y = (y * ds) + fy;
|
||||
}
|
||||
|
||||
void transform::rotateBy(double cx, double cy, double dx, double dy) {
|
||||
const double distance = copysign(sqrt(dx * dx + dy * dy), dx);
|
||||
setAngle(angle + D2R * distance);
|
||||
|
||||
void transform::rotateBy(double anchor_x, double anchor_y, double start_x, double start_y, double end_x, double end_y) {
|
||||
double center_x = width / 2, center_y = height / 2;
|
||||
|
||||
const double begin_center_x = start_x - center_x;
|
||||
const double begin_center_y = start_y - center_y;
|
||||
|
||||
const double beginning_center_dist = sqrt(begin_center_x * begin_center_x + begin_center_y * begin_center_y);
|
||||
|
||||
// If the first click was too close to the center, move the center of rotation by 200 pixels
|
||||
// in the direction of the click.
|
||||
if (beginning_center_dist < 200) {
|
||||
const double offset_x = -200, offset_y = 0;
|
||||
const double rotate_angle = atan2(begin_center_y, begin_center_x);
|
||||
const double rotate_angle_sin = sin(rotate_angle);
|
||||
const double rotate_angle_cos = cos(rotate_angle);
|
||||
center_x = start_x + rotate_angle_cos * offset_x - rotate_angle_sin * offset_y;
|
||||
center_y = start_y + rotate_angle_sin * offset_x + rotate_angle_cos * offset_y;
|
||||
}
|
||||
|
||||
const double first_x = start_x - center_x, first_y = start_y - center_y;
|
||||
const double second_x = end_x - center_x, second_y = end_y - center_y;
|
||||
|
||||
const double ang = angle + util::angle_between(first_x, first_y, second_x, second_y);
|
||||
|
||||
setAngle(ang);
|
||||
}
|
||||
|
||||
void transform::setAngle(double new_angle) {
|
||||
|
||||
Reference in New Issue
Block a user