summaryrefslogtreecommitdiffstats
authorDon Pellegrino <don@coffee.donpellegrino.com>2009-08-18 06:10:41 (GMT)
committer Don Pellegrino <don@coffee.donpellegrino.com>2009-08-18 06:10:41 (GMT)
commit9b11713580664fea7f3f80d89b9acd42195ca8c3 (patch) (unidiff)
tree90659481e877e4060ade36986ee09e3c7e51e95e
parentd7aa70eaad644f2892c60ce85539d5439e0804b2 (diff)
downloadexp005-9b11713580664fea7f3f80d89b9acd42195ca8c3.zip
exp005-9b11713580664fea7f3f80d89b9acd42195ca8c3.tar.gz
exp005-9b11713580664fea7f3f80d89b9acd42195ca8c3.tar.bz2
Fixed bug in zooming and panning. Interactive testing of zooming by
rubber band, zooming with the mouse wheel and panning all work with the window at any size, square or non-square.
-rw-r--r--src/controller/actions/set_ortho.c13
-rw-r--r--src/controller/actions/zoom.c70
-rw-r--r--src/controller/actions/zoom.h4
-rw-r--r--src/controller/callbacks/display.c6
-rw-r--r--src/controller/callbacks/keyboard.c7
-rw-r--r--src/controller/callbacks/mouse.c49
-rw-r--r--src/controller/callbacks/mouse_wheel.c66
-rw-r--r--src/controller/callbacks/reshape.c68
-rw-r--r--src/model/geometry/density_legend_geometry.c18
-rw-r--r--src/model/state/zoom_info.h1
-rw-r--r--src/model/state/zoom_info_init.c6
11 files changed, 197 insertions, 111 deletions
diff --git a/src/controller/actions/set_ortho.c b/src/controller/actions/set_ortho.c
index 4309c76..ce66f60 100644
--- a/src/controller/actions/set_ortho.c
+++ b/src/controller/actions/set_ortho.c
@@ -7,15 +7,10 @@
7void7void
8set_ortho (void)8set_ortho (void)
9{9{
10 if (S.zoom.active)10 gluOrtho2D (S.ortho.min_x,
11 {11 S.ortho.max_x,
12 gluOrtho2D (S.zoom.coords[0],12 S.ortho.min_y,
13 S.zoom.coords[1], S.zoom.coords[2], S.zoom.coords[3]);13 S.ortho.max_y);
14 }
15 else
16 {
17 gluOrtho2D (S.ortho.min_x, S.ortho.max_x, S.ortho.min_y, S.ortho.max_y);
18 }
1914
20 return;15 return;
21}16}
diff --git a/src/controller/actions/zoom.c b/src/controller/actions/zoom.c
index b8e54cc..7209e85 100644
--- a/src/controller/actions/zoom.c
+++ b/src/controller/actions/zoom.c
@@ -11,52 +11,40 @@
11#define S state011#define S state0
1212
13void13void
14zoom (int x1, int y1, int x2, int y2)14zoom (double x1, double y1, double x2, double y2)
15{15{
16 S.zoom.active = true;
17
18 S.zoom.coords[0] = x1;
19 S.zoom.coords[1] = x2;
20 S.zoom.coords[2] = y1;
21 S.zoom.coords[3] = y2;
22
16 /*23 /*
17 * Convert the selection boundary from window coordinates to24 * Preserve the aspect ratio. First convert the selection to the
18 * world coordinates.25 * aspect ratio of the original geometry. The world is a square so
26 * convert the zoom region to a square. The reshape callback
27 * performs step two of converting the squarified zoom region to the
28 * aspect ratio of the window. This is done in reshape as the window
29 * may change while the zoom region is held the same.
19 */30 */
20 glMatrixMode (GL_MODELVIEW);31 double width = S.zoom.coords[1] - S.zoom.coords[0];
21 glLoadIdentity ();32 double height = S.zoom.coords[3] - S.zoom.coords[2];
22 GLdouble model[16];33 double difference = fabs(width - height);
23 glGetDoublev (GL_MODELVIEW_MATRIX, model);34
24 GLdouble projection[16];35 if (width > height)
25 glGetDoublev (GL_PROJECTION_MATRIX, projection);36 {
37 S.zoom.coords[2] -= 0.5 * difference;
38 S.zoom.coords[3] += 0.5 * difference;
39 }
40 else
41 {
42 S.zoom.coords[0] -= 0.5 * difference;
43 S.zoom.coords[1] += 0.5 * difference;
44 }
45
26 GLint viewport[4];46 GLint viewport[4];
27 glGetIntegerv (GL_VIEWPORT, viewport);47 glGetIntegerv (GL_VIEWPORT, viewport);
28
29 check_error (__FILE__, __LINE__);
30
31 GLdouble start_position[3];
32 gluUnProject (x1,
33 y1,
34 0,
35 model,
36 projection,
37 viewport,
38 &start_position[0],
39 &start_position[1], &start_position[2]);
40
41 check_error (__FILE__, __LINE__);
42
43 GLdouble end_position[3];
44 gluUnProject (x2,
45 y2,
46 0,
47 model,
48 projection,
49 viewport,
50 &end_position[0], &end_position[1], &end_position[2]);
51
52 check_error (__FILE__, __LINE__);
53
54 S.zoom.active = true;
55 S.zoom.coords[0] = fmin (start_position[0], end_position[0]);
56 S.zoom.coords[1] = fmax (start_position[0], end_position[0]);
57 S.zoom.coords[2] = fmin (start_position[1], end_position[1]);
58 S.zoom.coords[3] = fmax (start_position[1], end_position[1]);
59
60 reshape (viewport[2], viewport[3]);48 reshape (viewport[2], viewport[3]);
61 49
62 glutPostRedisplay ();50 glutPostRedisplay ();
diff --git a/src/controller/actions/zoom.h b/src/controller/actions/zoom.h
index bd5b852..4dc1769 100644
--- a/src/controller/actions/zoom.h
+++ b/src/controller/actions/zoom.h
@@ -2,8 +2,8 @@
2#define ZOOM_H2#define ZOOM_H
33
4/*4/*
5 * Perform a zoom operation.5 * Perform a zoom operation. Inputs are in world coordinates.
6 */6 */
7void zoom (int x1, int y1, int x2, int y2);7void zoom (double x1, double y1, double x2, double y2);
88
9#endif // ZOOM_H9#endif // ZOOM_H
diff --git a/src/controller/callbacks/display.c b/src/controller/callbacks/display.c
index b9a76a6..bee3286 100644
--- a/src/controller/callbacks/display.c
+++ b/src/controller/callbacks/display.c
@@ -1,10 +1,16 @@
1#include "display.h"1#include "display.h"
2#include "../../view/geometry.h"2#include "../../view/geometry.h"
3#include "../actions/set_ortho.h"
3#include <GL/glut.h>4#include <GL/glut.h>
45
5void6void
6display (void)7display (void)
7{8{
9 glMatrixMode (GL_PROJECTION);
10 glLoadIdentity ();
11 set_ortho ();
12
13 glMatrixMode (GL_MODELVIEW);
8 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);14 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
9 geometry (GL_RENDER);15 geometry (GL_RENDER);
10 glutSwapBuffers ();16 glutSwapBuffers ();
diff --git a/src/controller/callbacks/keyboard.c b/src/controller/callbacks/keyboard.c
index 9967ad3..9e667d8 100644
--- a/src/controller/callbacks/keyboard.c
+++ b/src/controller/callbacks/keyboard.c
@@ -4,6 +4,7 @@
4#include "reshape.h"4#include "reshape.h"
5#include "../../view/state0.h"5#include "../../view/state0.h"
6#include "../../model/state/pan_info_init.h"6#include "../../model/state/pan_info_init.h"
7#include "../../model/state/zoom_info_init.h"
7#include <GL/glut.h>8#include <GL/glut.h>
89
9#define S state010#define S state0
@@ -41,11 +42,11 @@ keyboard (unsigned char key, int x, int y)
4142
42 case 'r':43 case 'r':
43 /*44 /*
44 * Reset the view (unzoom).45 * Reset the view (unzoom, recenter).
45 */46 */
46 pan_info_init (&S.pan);47 pan_info_init (&S.pan);
47 S.zoom.active = false;48 zoom_info_init (&S.zoom);
48 49
49 GLint viewport[4];50 GLint viewport[4];
50 glGetIntegerv (GL_VIEWPORT, viewport);51 glGetIntegerv (GL_VIEWPORT, viewport);
51 reshape (viewport[2], viewport[3]);52 reshape (viewport[2], viewport[3]);
diff --git a/src/controller/callbacks/mouse.c b/src/controller/callbacks/mouse.c
index f901476..34ff290 100644
--- a/src/controller/callbacks/mouse.c
+++ b/src/controller/callbacks/mouse.c
@@ -25,7 +25,7 @@ mouse (int button, int state, int x, int y)
25 {25 {
26 // Deactive a panning event if one was happening.26 // Deactive a panning event if one was happening.
27 S.pan.active = false;27 S.pan.active = false;
2828
29 if (S.selection.active && 29 if (S.selection.active &&
30 S.selection.purpose == ZOOM &&30 S.selection.purpose == ZOOM &&
31 glutGetModifiers () == GLUT_ACTIVE_CTRL)31 glutGetModifiers () == GLUT_ACTIVE_CTRL)
@@ -35,14 +35,49 @@ mouse (int button, int state, int x, int y)
35 */35 */
36 if (x == S.selection.x || y == S.selection.y)36 if (x == S.selection.x || y == S.selection.y)
37 return;37 return;
3838
39 /*
40 * Convert the selection boundary from window coordinates to
41 * world coordinates.
42 */
43 glMatrixMode (GL_MODELVIEW);
44 glLoadIdentity ();
45 GLdouble model[16];
46 glGetDoublev (GL_MODELVIEW_MATRIX, model);
47 GLdouble projection[16];
48 glGetDoublev (GL_PROJECTION_MATRIX, projection);
39 GLint viewport[4];49 GLint viewport[4];
40 glGetIntegerv (GL_VIEWPORT, viewport);50 glGetIntegerv (GL_VIEWPORT, viewport);
4151
42 zoom (S.selection.x, 52 check_error (__FILE__, __LINE__);
43 viewport[3] - S.selection.y, 53
44 x, 54 GLdouble start_position[3];
45 viewport[3] - y);55 gluUnProject (x,
56 viewport[3] -y,
57 0,
58 model,
59 projection,
60 viewport,
61 &start_position[0],
62 &start_position[1], &start_position[2]);
63
64 check_error (__FILE__, __LINE__);
65
66 GLdouble end_position[3];
67 gluUnProject (S.selection.x,
68 viewport[3] - S.selection.y,
69 0,
70 model,
71 projection,
72 viewport,
73 &end_position[0], &end_position[1], &end_position[2]);
74
75 check_error (__FILE__, __LINE__);
76
77 zoom (fmin (start_position[0], end_position[0]),
78 fmin (start_position[1], end_position[1]),
79 fmax (start_position[0], end_position[0]),
80 fmax (start_position[1], end_position[1]));
46 }81 }
4782
48 /*83 /*
diff --git a/src/controller/callbacks/mouse_wheel.c b/src/controller/callbacks/mouse_wheel.c
index 52d3c8b..9ca73bc 100644
--- a/src/controller/callbacks/mouse_wheel.c
+++ b/src/controller/callbacks/mouse_wheel.c
@@ -1,44 +1,74 @@
1#include "mouse_wheel.h"1#include "mouse_wheel.h"
2#include "../actions/zoom.h"2#include "../actions/zoom.h"
3#include "../../view/state0.h"
3#include <GL/glut.h>4#include <GL/glut.h>
5#include <math.h>
6
7#define S state0
48
5void 9void
6mouse_wheel (int button, int dir, int x, int y)10mouse_wheel (int button, int dir, int x, int y)
7{11{
8 /*12 /*
9 * Get the current coordinates, substract some fixed amount and13 * Start at the origin of the window. An alternative would be to
10 * then perform the zoom.14 * start at the position of the mouse. Calculate a bounding box
15 * that will be the selection and zoom to it.
11 */16 */
12 GLint viewport[4];17 double width = fabs(S.ortho.max_x - S.ortho.min_x);
13 glGetIntegerv (GL_VIEWPORT, viewport);18 double height = fabs(S.ortho.max_y - S.ortho.min_y);
1419
15 /*20 /*
16 * The step size could be either a fixed number of pixels or a percentage.21 * Box the smaller of the two dimensions.
17 */22 */
18 // int step = 5;23 double box = 0.0;
19 int step = (viewport[3] - viewport[1]) * 0.10;24 if (width <= height)
25 box = width;
26 else
27 box = height;
2028
21 /*29 /*
22 * Not that the focus of the zoom is currently the center of the30 * The step size could be either a fixed number of pixels or a
23 * window but could alternatively be the mouse pointer's position.31 * percentage. Here we take 10% of the size of the box.
24 */32 */
33 double step = box * 0.10;
34
35 double x1 = 0.0;
36 double y1 = 0.0;
37 double x2 = 0.0;
38 double y2 = 0.0;
39
40 if (width < height)
41 {
42 x1 = S.ortho.min_x;
43 x2 = S.ortho.max_x;
44 y1 = ((S.ortho.max_y + S.ortho.min_y) / 2.0) - (0.5 * width);
45 y2 = ((S.ortho.max_y + S.ortho.min_y) / 2.0) + (0.5 * width);
46 }
47 else if (width > height)
48 {
49 x1 = ((S.ortho.max_x + S.ortho.min_x) / 2.0) - (0.5 * height);
50 x2 = ((S.ortho.max_x + S.ortho.min_x) / 2.0) + (0.5 * height);
51 y1 = S.ortho.min_y;
52 y2 = S.ortho.max_y;
53 }
54 else
55 {
56 x1 = S.ortho.min_x;
57 x2 = S.ortho.max_x;
58 y1 = S.ortho.min_y;
59 y2 = S.ortho.max_y;
60 }
2561
26 // Zoom in62 // Zoom in
27 if (dir > 0)63 if (dir > 0)
28 {64 {
29 zoom (step,65 zoom (x1 + step, y1 + step, x2 - step, y2 - step);
30 step,
31 viewport[3] - step,
32 viewport[3] - step);
33 }66 }
3467
35 // Zoom out68 // Zoom out
36 else69 else
37 {70 {
38 zoom (-step,71 zoom (x1 - step, y1 - step, x2 + step, y2 + step);
39 -step,
40 viewport[3] + step,
41 viewport[3] + step);
42 }72 }
4373
44 return;74 return;
diff --git a/src/controller/callbacks/reshape.c b/src/controller/callbacks/reshape.c
index 2455ea3..fec5443 100644
--- a/src/controller/callbacks/reshape.c
+++ b/src/controller/callbacks/reshape.c
@@ -3,6 +3,8 @@
3#include "../actions/set_ortho.h"3#include "../actions/set_ortho.h"
4#include "reshape.h"4#include "reshape.h"
5#include <GL/glut.h>5#include <GL/glut.h>
6#include <math.h>
7#include <stdio.h>
68
7#define S state09#define S state0
810
@@ -13,26 +15,60 @@ reshape (int w, int h)
13 glLoadIdentity ();15 glLoadIdentity ();
1416
15 /*17 /*
16 * This scaling produces an odd effect when the coordinates are not18 * Scale the zoom region to the aspect ratio of the window.
17 * centered at 0,0. When 0,0 is the lower left rather than the
18 * center this reshape is a bit unnatural since the image is not
19 * centered in the middle of the window.
20 */19 */
2120 if (S.zoom.active)
22 if (w <= h)
23 {21 {
24 S.ortho.min_x = S.ortho_min;22 if (w >= h)
25 S.ortho.max_x = S.ortho_max;23 {
26 S.ortho.min_y = S.ortho_min * (double) h / (double) w;24 double scale
27 S.ortho.max_y = S.ortho_max * (double) h / (double) w;25 = ( ( (S.zoom.coords[1] - S.zoom.coords[0]) * ((double) w / (double) h) )
26 - (S.zoom.coords[1] - S.zoom.coords[0]) )
27 * 0.5;
28
29 S.ortho.min_x = S.zoom.coords[0] - scale;
30 S.ortho.max_x = S.zoom.coords[1] + scale;
31 S.ortho.min_y = S.zoom.coords[2];
32 S.ortho.max_y = S.zoom.coords[3];
33 }
34 else
35 {
36 double scale
37 = ( ( (S.zoom.coords[3] - S.zoom.coords[2]) * ((double) h / (double) w) )
38 - (S.zoom.coords[3] - S.zoom.coords[2]) )
39 * 0.5;
40
41 S.ortho.min_x = S.zoom.coords[0];
42 S.ortho.max_x = S.zoom.coords[1];
43 S.ortho.min_y = S.zoom.coords[2] - scale;
44 S.ortho.max_y = S.zoom.coords[3] + scale;
45 }
28 }46 }
29 else47
48 else
30 {49 {
31 S.ortho.min_x = S.ortho_min * (double) w / (double) h;50 /*
32 S.ortho.max_x = S.ortho_max * (double) w / (double) h;51 * This scaling produces an odd effect when the coordinates are
33 S.ortho.min_y = S.ortho_min;52 * not centered at 0,0. When 0,0 is the lower left rather than
34 S.ortho.max_y = S.ortho_max;53 * the center this reshape is a bit unnatural since the image is
35 }54 * not centered in the middle of the window. Try chaning this
55 * to use the method used above for the zoom region scaling.
56 */
57 if (w <= h)
58 {
59 S.ortho.min_x = S.ortho_min;
60 S.ortho.max_x = S.ortho_max;
61 S.ortho.min_y = S.ortho_min * (double) h / (double) w;
62 S.ortho.max_y = S.ortho_max * (double) h / (double) w;
63 }
64 else
65 {
66 S.ortho.min_x = S.ortho_min * (double) w / (double) h;
67 S.ortho.max_x = S.ortho_max * (double) w / (double) h;
68 S.ortho.min_y = S.ortho_min;
69 S.ortho.max_y = S.ortho_max;
70 }
71 }
3672
37 set_ortho ();73 set_ortho ();
3874
diff --git a/src/model/geometry/density_legend_geometry.c b/src/model/geometry/density_legend_geometry.c
index e5baa08..ac3280c 100644
--- a/src/model/geometry/density_legend_geometry.c
+++ b/src/model/geometry/density_legend_geometry.c
@@ -27,20 +27,10 @@ density_legend_geometry (void)
27 const double *top;27 const double *top;
28 const double *bottom;28 const double *bottom;
2929
30 if (S.zoom.active)30 left = &S.ortho.min_x;
31 {31 right = &S.ortho.max_x;
32 left = &S.zoom.coords[0];32 bottom = &S.ortho.min_y;
33 right = &S.zoom.coords[1];33 top = &S.ortho.max_y;
34 bottom = &S.zoom.coords[2];
35 top = &S.zoom.coords[3];
36 }
37 else
38 {
39 left = &S.ortho.min_x;
40 right = &S.ortho.max_x;
41 bottom = &S.ortho.min_y;
42 top = &S.ortho.max_y;
43 }
4434
45 /*35 /*
46 * This value should be a percentage of the world height so that it36 * This value should be a percentage of the world height so that it
diff --git a/src/model/state/zoom_info.h b/src/model/state/zoom_info.h
index 5916b3c..83fab2c 100644
--- a/src/model/state/zoom_info.h
+++ b/src/model/state/zoom_info.h
@@ -15,6 +15,7 @@ typedef struct
1515
16 /*16 /*
17 * Left, right, bottom and top of zoom region in world coordinates.17 * Left, right, bottom and top of zoom region in world coordinates.
18 * Rubber-band zoom.
18 */19 */
19 double coords[4];20 double coords[4];
20} ZOOM_INFO;21} ZOOM_INFO;
diff --git a/src/model/state/zoom_info_init.c b/src/model/state/zoom_info_init.c
index f49dd59..aa230d8 100644
--- a/src/model/state/zoom_info_init.c
+++ b/src/model/state/zoom_info_init.c
@@ -4,6 +4,10 @@ void
4zoom_info_init (ZOOM_INFO * z)4zoom_info_init (ZOOM_INFO * z)
5{5{
6 z->active = false;6 z->active = false;
77 z->coords[0] = 0.0;
8 z->coords[1] = 0.0;
9 z->coords[2] = 0.0;
10 z->coords[3] = 0.0;
11
8 return;12 return;
9}13}

Valid XHTML 1.0 Strict

Copyright © 2009 Don Pellegrino All Rights Reserved.