00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008
00009
00010
00011 #include "vgui_rubberband_tableau.h"
00012
00013 #include <vcl_cassert.h>
00014 #include <vcl_cmath.h>
00015 #include <vcl_iostream.h>
00016 #include <vgl/vgl_clip.h>
00017 #include <vnl/vnl_math.h>
00018
00019 #include <vgui/vgui_matrix_state.h>
00020 #include <vgui/vgui_projection_inspector.h>
00021 #include <vgui/vgui_adaptor.h>
00022
00023 vgui_rubberband_tableau::object_type vgui_rubberband_tableau::obj_type = none_enum;
00024
00025 #ifdef __GNUC__
00026 # define function_macro { vcl_cerr << __FUNCTION__ << " not yet implemented\n"; }
00027 #else
00028 # define function_macro { vcl_cerr << __FILE__ " : " << __LINE__ << " not yet implemented\n"; }
00029 #endif
00030 void vgui_rubberband_client::add_point(float, float) function_macro
00031 void vgui_rubberband_client::add_line(float,float,float,float) function_macro
00032 void vgui_rubberband_client::add_infinite_line(float,float,float) function_macro
00033 void vgui_rubberband_client::add_circle(float,float,float) function_macro
00034 void vgui_rubberband_client::add_linestrip(int ,float const *,float const *) function_macro
00035 void vgui_rubberband_client::add_polygon(int ,float const*,float const*) function_macro
00036 void vgui_rubberband_client::add_box(float,float,float,float) function_macro
00037 void vgui_rubberband_client::clear_highlight() function_macro
00038 #undef function_macro
00039
00040
00041
00042
00043
00044 void
00045 vgui_rubberband_easy2D_client::
00046 add_point(float x, float y)
00047 {
00048 easy->add_point(x,y);
00049 }
00050
00051 void
00052 vgui_rubberband_easy2D_client::
00053 add_line(float x0, float y0, float x1, float y1)
00054 {
00055 easy->add_line(x0, y0, x1, y1);
00056 }
00057
00058 void
00059 vgui_rubberband_easy2D_client::
00060 add_infinite_line(float a, float b, float c)
00061 {
00062 easy->add_infinite_line(a, b, c);
00063 }
00064
00065 void
00066 vgui_rubberband_easy2D_client::
00067 add_circle(float x, float y, float r)
00068 {
00069 easy->add_circle(x, y, r);
00070 }
00071
00072 void
00073 vgui_rubberband_easy2D_client::
00074 add_linestrip(int n, float const* x, float const* y)
00075 {
00076 easy->add_linestrip(n, x, y);
00077 }
00078
00079 void
00080 vgui_rubberband_easy2D_client::
00081 add_polygon(int n, float const* x, float const* y)
00082 {
00083 easy->add_polygon(n, x, y);
00084 }
00085
00086
00087 void
00088 vgui_rubberband_easy2D_client::
00089 add_box(float x0, float y0, float x1, float y1)
00090 {
00091 float x[4] = {x0, x1, x1, x0};
00092 float y[4] = {y0, y0, y1, y1};
00093 this->add_polygon( 4, x, y );
00094 }
00095
00096
00097 void
00098 vgui_rubberband_easy2D_client::
00099 clear_highlight()
00100 {
00101 easy->highlight(0);
00102 }
00103
00104
00105
00106
00107 void vgui_rubberband_tableau::init(vgui_rubberband_client* the_client)
00108 {
00109 client_ = the_client;
00110 active = false;
00111 obj_type = none_enum;
00112 #ifdef HAS_MFC
00113
00114
00115 use_overlays = true;
00116 #else
00117
00118
00119
00120
00121 use_overlays = true;
00122 #endif
00123 }
00124
00125 void vgui_rubberband_tableau::rubberband_point()
00126 {
00127 obj_type = point_enum;
00128 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true );
00129 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, false);
00130 }
00131
00132 void vgui_rubberband_tableau::rubberband_line()
00133 {
00134 obj_type = line_enum;
00135 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00136 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00137 }
00138
00139 void vgui_rubberband_tableau::rubberband_infinite_line()
00140 {
00141 obj_type = infinite_line_enum;
00142 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00143 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00144 }
00145
00146 void vgui_rubberband_tableau::rubberband_circle()
00147 {
00148 obj_type = circle_enum;
00149 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00150 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00151 }
00152
00153 void vgui_rubberband_tableau::rubberband_polygon()
00154 {
00155 obj_type = polygon_enum;
00156 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00157 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00158
00159
00160 gesture2 = vgui_event_condition(vgui_MIDDLE, vgui_MODIFIER_NULL, true);
00161 }
00162
00163 void vgui_rubberband_tableau::rubberband_linestrip()
00164 {
00165 obj_type = linestrip_enum;
00166 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00167 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00168
00169 gesture2 = vgui_event_condition(vgui_MIDDLE, vgui_MODIFIER_NULL, true);
00170 }
00171
00172 void vgui_rubberband_tableau::rubberband_box()
00173 {
00174 obj_type = box_enum;
00175 gesture0 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00176 gesture1 = vgui_event_condition(vgui_LEFT, vgui_MODIFIER_NULL, true);
00177 }
00178
00179 void vgui_rubberband_tableau::rubberband_none()
00180 {
00181 active = false;
00182 obj_type = none_enum;
00183 }
00184
00185
00186 void vgui_rubberband_tableau::draw_point(float x, float y)
00187 {
00188 glColor3f(1,1,1);
00189 glBegin(GL_POINTS);
00190 #ifdef DEBUG
00191 vcl_cerr << "vgui_rubberband_tableau::draw_point(" << x << ',' << y << ")\n";
00192 #endif
00193 glVertex2f(x,y);
00194 glEnd();
00195 }
00196
00197
00198 void vgui_rubberband_tableau::draw_line(float x0, float y0, float x1, float y1)
00199 {
00200 glLineWidth(1);
00201 glColor3f(1,1,1);
00202
00203 glBegin(GL_LINES);
00204 glVertex2f(x0, y0);
00205 glVertex2f(x1, y1);
00206 glEnd();
00207 }
00208
00209
00210 void vgui_rubberband_tableau::draw_infinite_line(float a, float b, float c)
00211 {
00212
00213
00214 vgui_projection_inspector pi;
00215 float x0, y0, x1, y1;
00216 pi.image_viewport(x0,y0,x1,y1);
00217
00218 float x3, y3;
00219 float x4, y4;
00220 bool f = vgl_clip_line_to_box(a,b,c, x0, y0, x1, y1, x3, y3, x4,y4);
00221 if (!f)
00222 return;
00223
00224 glBegin(GL_LINES);
00225 glVertex2f(x3,y3);
00226 glVertex2f(x4,y4);
00227 glEnd();
00228 }
00229
00230
00231 void vgui_rubberband_tableau::draw_circle(float x, float y, float r)
00232 {
00233 glLineWidth(1);
00234 glColor3f(1,1,1);
00235 glBegin(GL_LINE_LOOP);
00236
00237
00238 for (int i=0;i<100;i++) {
00239 double angle = (2*vnl_math::pi/100.0)*i;
00240 glVertex2d(vcl_cos(angle)*r + x, vcl_sin(angle)*r + y);
00241 }
00242 glEnd();
00243 }
00244
00245
00246 void vgui_rubberband_tableau::draw_polygon(float px, float py)
00247 {
00248 unsigned n=x_coords.size(); assert(n==y_coords.size());
00249 if (n==0)
00250 return;
00251
00252 vgui_matrix_state M; M.save();
00253
00254 glLineWidth(1);
00255 glColor3f(1,1,1);
00256 if (n==1)
00257 glBegin(GL_LINES);
00258 else
00259 glBegin(GL_LINE_LOOP);
00260
00261 for (unsigned i=0; i<n; ++i)
00262 glVertex2f(x_coords[i], y_coords[i]);
00263 glVertex2f(px, py);
00264 glEnd();
00265 }
00266
00267
00268 void vgui_rubberband_tableau::draw_box(float x0,float y0,float x1,float y1)
00269 {
00270 float sx = x0>x1 ? x1:x0;
00271 float sy = y0>y1 ? y1:y0;
00272 float ex = x0>x1 ? x0:x1;
00273 float ey = y0>y1 ? y0:y1;
00274
00275 glLineWidth(1);
00276 glColor3f(1,1,1);
00277 glBegin(GL_LINE_LOOP);
00278
00279 glVertex2f(sx,sy);
00280 glVertex2f(ex,sy);
00281 glVertex2f(ex,ey);
00282 glVertex2f(sx,ey);
00283
00284 glEnd();
00285 }
00286
00287
00288 void vgui_rubberband_tableau::draw_linestrip(float px,float py)
00289 {
00290 unsigned n=x_coords.size(); assert(n==y_coords.size());
00291 if (n==0)
00292 return;
00293
00294 vgui_matrix_state M; M.save();
00295
00296 glLineWidth(1);
00297 glColor3f(1,1,1);
00298 glBegin(GL_LINE_STRIP);
00299 for (unsigned i=0; i<n; ++i)
00300 glVertex2f(x_coords[i], y_coords[i]);
00301 glVertex2f(px,py);
00302 glEnd();
00303 }
00304
00305
00306 bool vgui_rubberband_tableau::handle_point(vgui_event const &e, float ix, float iy)
00307 {
00308 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00309 {
00310 draw_point(lastx, lasty);
00311 return true;
00312 }
00313 if (gesture1(e))
00314 {
00315
00316 client_->add_point(ix,iy);
00317 active = false;
00318 obj_type = none_enum;
00319 post_redraw();
00320 return true;
00321 }
00322 return false;
00323 }
00324
00325 bool vgui_rubberband_tableau::handle_line(vgui_event const &e, float ix, float iy)
00326 {
00327 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00328 {
00329 draw_line(x_coords[0], y_coords[0], lastx, lasty);
00330 return true;
00331 }
00332 if (gesture1(e))
00333 {
00334
00335 client_->add_line(x_coords[0],y_coords[0],ix,iy);
00336 active = false;
00337 obj_type = none_enum;
00338 post_redraw();
00339 return true;
00340 }
00341 return false;
00342 }
00343
00344 bool vgui_rubberband_tableau::handle_infinite_line(vgui_event const &e, float ix, float iy)
00345 {
00346 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00347 {
00348 draw_infinite_line(-lastx+x_coords[0],y_coords[0] - lasty,
00349 -(-lastx+x_coords[0])*lastx-lasty*(y_coords[0]-lasty));
00350 return true;
00351 }
00352 if (gesture1(e))
00353 {
00354
00355 client_->add_infinite_line(-ix+x_coords[0],y_coords[0] - iy,
00356 -(-ix+x_coords[0])*lastx-iy*(y_coords[0]-lasty));
00357 active = false;
00358 obj_type = none_enum;
00359 post_redraw();
00360 return true;
00361 }
00362 return false;
00363 }
00364
00365 bool vgui_rubberband_tableau::handle_circle(vgui_event const &e, float ix, float iy)
00366 {
00367 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00368 {
00369
00370 float dx = x_coords[0] - lastx;
00371 float dy = y_coords[0] - lasty;
00372 float radi = vcl_sqrt(dx*dx + dy*dy);
00373 draw_circle(x_coords[0], y_coords[0], radi);
00374 return true;
00375 }
00376 if (gesture1(e))
00377 {
00378
00379 float dx = x_coords[0] - ix;
00380 float dy = y_coords[0] - iy;
00381 float radi = vcl_sqrt(dx*dx + dy*dy);
00382 client_->add_circle(x_coords[0],y_coords[0],radi);
00383 active = false;
00384 obj_type = none_enum;
00385 post_redraw();
00386 return true;
00387 }
00388 return false;
00389 }
00390
00391 bool vgui_rubberband_tableau::handle_polygon(vgui_event const &e, float ix, float iy)
00392 {
00393 unsigned n = x_coords.size();
00394 assert(n == y_coords.size());
00395 assert(n>0);
00396
00397 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00398 {
00399 draw_polygon(lastx, lasty);
00400 return true;
00401 }
00402 if (gesture1(e))
00403 {
00404
00405 x_coords.push_back(ix);
00406 y_coords.push_back(iy);
00407 return true;
00408 }
00409
00410 if (gesture2(e))
00411 {
00412
00413 x_coords.push_back(ix);
00414 y_coords.push_back(iy);
00415 n++;
00416
00417
00418 x_coords.push_back(x_coords[0]);
00419 y_coords.push_back(y_coords[0]);
00420 n++;
00421
00422 client_->add_polygon(n, &x_coords[0], &y_coords[0]);
00423
00424 post_redraw();
00425 active = false;
00426 obj_type = none_enum;
00427 return true;
00428 }
00429 return false;
00430 }
00431
00432 bool vgui_rubberband_tableau::handle_box(vgui_event const &e, float ix,float iy)
00433 {
00434 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00435 {
00436 draw_box(x_coords[0], y_coords[0], lastx, lasty);
00437 return true;
00438 }
00439 if (gesture1(e))
00440 {
00441 client_->add_box(x_coords[0],y_coords[0],ix,iy);
00442 active = false;
00443 obj_type = none_enum;
00444 post_redraw();
00445 return true;
00446 }
00447 return false;
00448 }
00449
00450 bool vgui_rubberband_tableau::handle_linestrip(vgui_event const &e, float ix, float iy)
00451 {
00452 unsigned n = x_coords.size();
00453 assert(n == y_coords.size());
00454 assert(n>0);
00455
00456 if ((use_overlays && e.type == vgui_DRAW_OVERLAY) || (!use_overlays && e.type == vgui_DRAW))
00457 {
00458 draw_linestrip(lastx, lasty);
00459 return true;
00460 }
00461
00462 if (gesture1(e))
00463 {
00464
00465 x_coords.push_back(ix);
00466 y_coords.push_back(iy);
00467 return true;
00468 }
00469
00470 if (gesture2(e))
00471 {
00472 client_->add_linestrip(n,&x_coords[0],&y_coords[0]);
00473 post_redraw();
00474 active = false;
00475 obj_type = none_enum;
00476 return true;
00477 }
00478 return false;
00479 }
00480
00481 bool vgui_rubberband_tableau::handle(vgui_event const &e)
00482 {
00483 if(e.origin)
00484 e.origin->make_current();
00485 else
00486 return false;
00487 float ix, iy;
00488 vgui_projection_inspector().window_to_image_coordinates(e.wx, e.wy, ix, iy);
00489
00490 if (!active) {
00491 if (obj_type != none_enum && gesture0(e))
00492 {
00493 active = true;
00494 if (use_overlays) post_overlay_redraw(); else post_redraw();
00495 client_->clear_highlight();
00496
00497 lastx = ix;
00498 lasty = iy;
00499 x_coords.clear();
00500 y_coords.clear();
00501 x_coords.push_back(ix);
00502 y_coords.push_back(iy);
00503
00504 return true;
00505 }
00506 else
00507 return false;
00508 }
00509
00510
00511 if (e.type == vgui_MOTION){
00512 lastx = ix;
00513 lasty = iy;
00514 if (use_overlays) post_overlay_redraw(); else post_redraw();
00515 client_->clear_highlight();
00516
00517 return true;
00518 }
00519
00520 if (obj_type == point_enum)
00521 return handle_point(e, ix, iy);
00522
00523 if (obj_type == line_enum)
00524 return handle_line(e, ix, iy);
00525
00526 if (obj_type == infinite_line_enum)
00527 return handle_infinite_line(e, ix, iy);
00528
00529 if (obj_type == circle_enum)
00530 return handle_circle(e, ix, iy);
00531
00532 if (obj_type == polygon_enum)
00533 return handle_polygon(e, ix, iy);
00534
00535 if (obj_type == linestrip_enum)
00536 return handle_linestrip(e,ix,iy);
00537
00538 if (obj_type == box_enum)
00539 return handle_box(e,ix,iy);
00540
00541 return false;
00542 }