summaryrefslogtreecommitdiffstats
Unidiff
-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.