00001 #include <stdio.h>
00002 #include "agg_conv_gpc.h"
00003 #include "agg_basics.h"
00004 #include "agg_rendering_buffer.h"
00005 #include "agg_rasterizer_scanline_aa.h"
00006 #include "agg_scanline_u.h"
00007 #include "agg_scanline_p.h"
00008 #include "agg_renderer_scanline.h"
00009 #include "agg_renderer_primitives.h"
00010 #include "agg_conv_curve.h"
00011 #include "agg_conv_stroke.h"
00012 #include "agg_conv_clip_polygon.h"
00013 #include "agg_gsv_text.h"
00014 #include "agg_pixfmt_rgb.h"
00015 #include "platform/agg_platform_support.h"
00016
00017 #include "ctrl/agg_slider_ctrl.h"
00018 #include "ctrl/agg_cbox_ctrl.h"
00019 #include "ctrl/agg_rbox_ctrl.h"
00020
00021
00022 enum flip_y_e { flip_y = true };
00023
00024
00025
00026
00027 class spiral
00028 {
00029 public:
00030 spiral(double x, double y, double r1, double r2, double step, double start_angle=0) :
00031 m_x(x),
00032 m_y(y),
00033 m_r1(r1),
00034 m_r2(r2),
00035 m_step(step),
00036 m_start_angle(start_angle),
00037 m_angle(start_angle),
00038 m_da(agg::deg2rad(4.0)),
00039 m_dr(m_step / 90.0)
00040 {
00041 }
00042
00043 void rewind(unsigned)
00044 {
00045 m_angle = m_start_angle;
00046 m_curr_r = m_r1;
00047 m_start = true;
00048 }
00049
00050 unsigned vertex(double* x, double* y)
00051 {
00052 if(m_curr_r > m_r2) return agg::path_cmd_stop;
00053
00054 *x = m_x + cos(m_angle) * m_curr_r;
00055 *y = m_y + sin(m_angle) * m_curr_r;
00056 m_curr_r += m_dr;
00057 m_angle += m_da;
00058 if(m_start)
00059 {
00060 m_start = false;
00061 return agg::path_cmd_move_to;
00062 }
00063 return agg::path_cmd_line_to;
00064 }
00065
00066 private:
00067 double m_x;
00068 double m_y;
00069 double m_r1;
00070 double m_r2;
00071 double m_step;
00072 double m_start_angle;
00073
00074 double m_angle;
00075 double m_curr_r;
00076 double m_da;
00077 double m_dr;
00078 bool m_start;
00079 };
00080
00081
00082
00083 namespace agg
00084 {
00085
00086 template<class Src> struct conv_poly_counter
00087 {
00088 unsigned m_contours;
00089 unsigned m_points;
00090
00091 conv_poly_counter(Src& src) : m_src(&src), m_contours(0), m_points(0) {}
00092
00093 void rewind(unsigned path_id)
00094 {
00095 m_contours = 0;
00096 m_points = 0;
00097 m_src->rewind(path_id);
00098 }
00099
00100 unsigned vertex(double* x, double* y)
00101 {
00102 unsigned cmd = m_src->vertex(x, y);
00103 if(is_vertex(cmd)) ++m_points;
00104 if(is_move_to(cmd)) ++m_contours;
00105 return cmd;
00106 }
00107
00108 private:
00109 Src* m_src;
00110 };
00111 }
00112
00113
00114
00115
00116 void make_gb_poly(agg::path_storage& ps);
00117 void make_arrows(agg::path_storage& ps);
00118
00119
00120 class the_application : public agg::platform_support
00121 {
00122 agg::rbox_ctrl<agg::rgba8> m_polygons;
00123 agg::rbox_ctrl<agg::rgba8> m_operation;
00124 double m_x;
00125 double m_y;
00126
00127 public:
00128 the_application(agg::pix_format_e format, bool flip_y) :
00129 agg::platform_support(format, flip_y),
00130 m_polygons (5.0, 5.0, 5.0+205.0, 110.0, !flip_y),
00131 m_operation(555.0, 5.0, 555.0+80.0, 130.0, !flip_y)
00132 {
00133 m_operation.add_item("None");
00134 m_operation.add_item("OR");
00135 m_operation.add_item("AND");
00136 m_operation.add_item("XOR");
00137 m_operation.add_item("A-B");
00138 m_operation.add_item("B-A");
00139 m_operation.cur_item(2);
00140 add_ctrl(m_operation);
00141
00142 m_polygons.add_item("Two Simple Paths");
00143 m_polygons.add_item("Closed Stroke");
00144 m_polygons.add_item("Great Britain and Arrows");
00145 m_polygons.add_item("Great Britain and Spiral");
00146 m_polygons.add_item("Spiral and Glyph");
00147 m_polygons.cur_item(3);
00148 add_ctrl(m_polygons);
00149 }
00150
00151
00152 template<class Scanline, class Ras, class Ren, class Gpc>
00153 void perform_rendering(Scanline& sl, Ras& ras, Ren& ren, Gpc& gpc)
00154 {
00155 if(m_operation.cur_item() > 0)
00156 {
00157 ras.reset();
00158 switch(m_operation.cur_item())
00159 {
00160 case 1: gpc.operation(agg::gpc_or); break;
00161 case 2: gpc.operation(agg::gpc_and); break;
00162 case 3: gpc.operation(agg::gpc_xor); break;
00163 case 4: gpc.operation(agg::gpc_a_minus_b); break;
00164 case 5: gpc.operation(agg::gpc_b_minus_a); break;
00165 }
00166 agg::conv_poly_counter<Gpc> counter(gpc);
00167
00168
00169 start_timer();
00170 counter.rewind(0);
00171 double t1 = elapsed_time();
00172
00173 ras.reset();
00174 double x;
00175 double y;
00176 unsigned cmd;
00177 start_timer();
00178 while(!agg::is_stop(cmd = counter.vertex(&x, &y)))
00179 {
00180 ras.add_vertex(x, y, cmd);
00181 }
00182
00183 ren.color(agg::rgba(0.5, 0.0, 0, 0.5));
00184 agg::render_scanlines(ras, sl, ren);
00185 double t2 = elapsed_time();
00186
00187 char buf[100];
00188 sprintf(buf, "Contours: %d Points: %d", counter.m_contours, counter.m_points);
00189 agg::gsv_text txt;
00190 agg::conv_stroke<agg::gsv_text> txt_stroke(txt);
00191 txt_stroke.width(1.5);
00192 txt_stroke.line_cap(agg::round_cap);
00193 txt.size(10.0);
00194 txt.start_point(250, 5);
00195 txt.text(buf);
00196 ras.add_path(txt_stroke);
00197 ren.color(agg::rgba(0.0, 0.0, 0.0));
00198 agg::render_scanlines(ras, sl, ren);
00199
00200 sprintf(buf, "GPC=%.3fms Render=%.3fms", t1, t2);
00201 txt.start_point(250, 20);
00202 txt.text(buf);
00203 ras.add_path(txt_stroke);
00204 ren.color(agg::rgba(0.0, 0.0, 0.0));
00205 agg::render_scanlines(ras, sl, ren);
00206 }
00207 }
00208
00209
00210 template<class Scanline, class Ras>
00211 unsigned render_gpc(Scanline& sl, Ras& ras)
00212 {
00213 agg::pixfmt_bgr24 pf(rbuf_window());
00214 agg::renderer_base<agg::pixfmt_bgr24> rb(pf);
00215 agg::renderer_scanline_aa_solid<agg::renderer_base<agg::pixfmt_bgr24> > ren(rb);
00216
00217
00218 switch(m_polygons.cur_item())
00219 {
00220 case 0:
00221 {
00222
00223
00224
00225 agg::path_storage ps1;
00226 agg::path_storage ps2;
00227
00228 agg::conv_gpc<agg::path_storage, agg::path_storage> gpc(ps1, ps2);
00229
00230 double x = m_x - initial_width()/2 + 100;
00231 double y = m_y - initial_height()/2 + 100;
00232 ps1.move_to(x+140, y+145);
00233 ps1.line_to(x+225, y+44);
00234 ps1.line_to(x+296, y+219);
00235 ps1.close_polygon();
00236
00237 ps1.line_to(x+226, y+289);
00238 ps1.line_to(x+82, y+292);
00239
00240 ps1.move_to(x+220, y+222);
00241 ps1.line_to(x+363, y+249);
00242 ps1.line_to(x+265, y+331);
00243
00244 ps1.move_to(x+242, y+243);
00245 ps1.line_to(x+268, y+309);
00246 ps1.line_to(x+325, y+261);
00247
00248 ps1.move_to(x+259, y+259);
00249 ps1.line_to(x+273, y+288);
00250 ps1.line_to(x+298, y+266);
00251
00252 ps2.move_to(100+32, 100+77);
00253 ps2.line_to(100+473, 100+263);
00254 ps2.line_to(100+351, 100+290);
00255 ps2.line_to(100+354, 100+374);
00256
00257 ras.reset();
00258 ras.add_path(ps1);
00259 ren.color(agg::rgba(0, 0, 0, 0.1));
00260 agg::render_scanlines(ras, sl, ren);
00261
00262 ras.reset();
00263 ras.add_path(ps2);
00264 ren.color(agg::rgba(0, 0.6, 0, 0.1));
00265 agg::render_scanlines(ras, sl, ren);
00266
00267 perform_rendering(sl, ras, ren, gpc);
00268 }
00269 break;
00270
00271 case 1:
00272 {
00273
00274
00275
00276 agg::path_storage ps1;
00277 agg::path_storage ps2;
00278 agg::conv_stroke<agg::path_storage> stroke(ps2);
00279 stroke.width(10.0);
00280
00281 agg::conv_gpc<agg::path_storage,
00282 agg::conv_stroke<agg::path_storage> > gpc(ps1, stroke);
00283
00284
00285 double x = m_x - initial_width()/2 + 100;
00286 double y = m_y - initial_height()/2 + 100;
00287 ps1.move_to(x+140, y+145);
00288 ps1.line_to(x+225, y+44);
00289 ps1.line_to(x+296, y+219);
00290 ps1.close_polygon();
00291
00292 ps1.line_to(x+226, y+289);
00293 ps1.line_to(x+82, y+292);
00294
00295 ps1.move_to(x+220-50, y+222);
00296 ps1.line_to(x+265-50, y+331);
00297 ps1.line_to(x+363-50, y+249);
00298 ps1.close_polygon(agg::path_flags_ccw);
00299
00300 ps2.move_to(100+32, 100+77);
00301 ps2.line_to(100+473, 100+263);
00302 ps2.line_to(100+351, 100+290);
00303 ps2.line_to(100+354, 100+374);
00304 ps2.close_polygon();
00305
00306 ras.reset();
00307 ras.add_path(ps1);
00308 ren.color(agg::rgba(0, 0, 0, 0.1));
00309 agg::render_scanlines(ras, sl, ren);
00310
00311 ras.reset();
00312 ras.add_path(stroke);
00313 ren.color(agg::rgba(0, 0.6, 0, 0.1));
00314 agg::render_scanlines(ras, sl, ren);
00315
00316 perform_rendering(sl, ras, ren, gpc);
00317 }
00318 break;
00319
00320
00321 case 2:
00322 {
00323
00324
00325
00326 agg::path_storage gb_poly;
00327 agg::path_storage arrows;
00328 make_gb_poly(gb_poly);
00329 make_arrows(arrows);
00330
00331 agg::trans_affine mtx1;
00332 agg::trans_affine mtx2;
00333 mtx1 *= agg::trans_affine_translation(-1150, -1150);
00334 mtx1 *= agg::trans_affine_scaling(2.0);
00335
00336 mtx2 = mtx1;
00337 mtx2 *= agg::trans_affine_translation(m_x - initial_width()/2,
00338 m_y - initial_height()/2);
00339
00340 agg::conv_transform<agg::path_storage> trans_gb_poly(gb_poly, mtx1);
00341 agg::conv_transform<agg::path_storage> trans_arrows(arrows, mtx2);
00342
00343 agg::conv_gpc<agg::conv_transform<agg::path_storage>,
00344 agg::conv_transform<agg::path_storage> > gpc(trans_gb_poly, trans_arrows);
00345
00346 ras.add_path(trans_gb_poly);
00347 ren.color(agg::rgba(0.5, 0.5, 0, 0.1));
00348 agg::render_scanlines(ras, sl, ren);
00349
00350 agg::conv_stroke<agg::conv_transform<agg::path_storage> > stroke_gb_poly(trans_gb_poly);
00351 stroke_gb_poly.width(0.1);
00352 ras.add_path(stroke_gb_poly);
00353 ren.color(agg::rgba(0, 0, 0));
00354 agg::render_scanlines(ras, sl, ren);
00355
00356 ras.add_path(trans_arrows);
00357 ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1));
00358 agg::render_scanlines(ras, sl, ren);
00359
00360 perform_rendering(sl, ras, ren, gpc);
00361 }
00362 break;
00363
00364
00365 case 3:
00366 {
00367
00368
00369
00370 spiral sp(m_x, m_y, 10, 150, 30, 0.0);
00371 agg::conv_stroke<spiral> stroke(sp);
00372 stroke.width(15.0);
00373
00374 agg::path_storage gb_poly;
00375 make_gb_poly(gb_poly);
00376
00377 agg::trans_affine mtx;
00378 mtx *= agg::trans_affine_translation(-1150, -1150);
00379 mtx *= agg::trans_affine_scaling(2.0);
00380
00381 agg::conv_transform<agg::path_storage> trans_gb_poly(gb_poly, mtx);
00382
00383 agg::conv_gpc<agg::conv_transform<agg::path_storage>,
00384 agg::conv_stroke<spiral> > gpc(trans_gb_poly, stroke);
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 ras.add_path(trans_gb_poly);
00418 ren.color(agg::rgba(0.5, 0.5, 0, 0.1));
00419 agg::render_scanlines(ras, sl, ren);
00420
00421 agg::conv_stroke<agg::conv_transform<agg::path_storage> > stroke_gb_poly(trans_gb_poly);
00422 stroke_gb_poly.width(0.1);
00423 ras.add_path(stroke_gb_poly);
00424 ren.color(agg::rgba(0, 0, 0));
00425 agg::render_scanlines(ras, sl, ren);
00426
00427 ras.add_path(stroke);
00428 ren.color(agg::rgba(0.0, 0.5, 0.5, 0.1));
00429 agg::render_scanlines(ras, sl, ren);
00430
00431 perform_rendering(sl, ras, ren, gpc);
00432 }
00433 break;
00434
00435
00436 case 4:
00437 {
00438
00439
00440
00441 spiral sp(m_x, m_y, 10, 150, 30, 0.0);
00442 agg::conv_stroke<spiral> stroke(sp);
00443 stroke.width(15.0);
00444
00445 agg::path_storage glyph;
00446 glyph.move_to(28.47, 6.45);
00447 glyph.curve3(21.58, 1.12, 19.82, 0.29);
00448 glyph.curve3(17.19, -0.93, 14.21, -0.93);
00449 glyph.curve3(9.57, -0.93, 6.57, 2.25);
00450 glyph.curve3(3.56, 5.42, 3.56, 10.60);
00451 glyph.curve3(3.56, 13.87, 5.03, 16.26);
00452 glyph.curve3(7.03, 19.58, 11.99, 22.51);
00453 glyph.curve3(16.94, 25.44, 28.47, 29.64);
00454 glyph.line_to(28.47, 31.40);
00455 glyph.curve3(28.47, 38.09, 26.34, 40.58);
00456 glyph.curve3(24.22, 43.07, 20.17, 43.07);
00457 glyph.curve3(17.09, 43.07, 15.28, 41.41);
00458 glyph.curve3(13.43, 39.75, 13.43, 37.60);
00459 glyph.line_to(13.53, 34.77);
00460 glyph.curve3(13.53, 32.52, 12.38, 31.30);
00461 glyph.curve3(11.23, 30.08, 9.38, 30.08);
00462 glyph.curve3(7.57, 30.08, 6.42, 31.35);
00463 glyph.curve3(5.27, 32.62, 5.27, 34.81);
00464 glyph.curve3(5.27, 39.01, 9.57, 42.53);
00465 glyph.curve3(13.87, 46.04, 21.63, 46.04);
00466 glyph.curve3(27.59, 46.04, 31.40, 44.04);
00467 glyph.curve3(34.28, 42.53, 35.64, 39.31);
00468 glyph.curve3(36.52, 37.21, 36.52, 30.71);
00469 glyph.line_to(36.52, 15.53);
00470 glyph.curve3(36.52, 9.13, 36.77, 7.69);
00471 glyph.curve3(37.01, 6.25, 37.57, 5.76);
00472 glyph.curve3(38.13, 5.27, 38.87, 5.27);
00473 glyph.curve3(39.65, 5.27, 40.23, 5.62);
00474 glyph.curve3(41.26, 6.25, 44.19, 9.18);
00475 glyph.line_to(44.19, 6.45);
00476 glyph.curve3(38.72, -0.88, 33.74, -0.88);
00477 glyph.curve3(31.35, -0.88, 29.93, 0.78);
00478 glyph.curve3(28.52, 2.44, 28.47, 6.45);
00479 glyph.close_polygon();
00480
00481 glyph.move_to(28.47, 9.62);
00482 glyph.line_to(28.47, 26.66);
00483 glyph.curve3(21.09, 23.73, 18.95, 22.51);
00484 glyph.curve3(15.09, 20.36, 13.43, 18.02);
00485 glyph.curve3(11.77, 15.67, 11.77, 12.89);
00486 glyph.curve3(11.77, 9.38, 13.87, 7.06);
00487 glyph.curve3(15.97, 4.74, 18.70, 4.74);
00488 glyph.curve3(22.41, 4.74, 28.47, 9.62);
00489 glyph.close_polygon();
00490
00491 agg::trans_affine mtx;
00492 mtx *= agg::trans_affine_scaling(4.0);
00493 mtx *= agg::trans_affine_translation(220, 200);
00494 agg::conv_transform<agg::path_storage> trans(glyph, mtx);
00495 agg::conv_curve<agg::conv_transform<agg::path_storage> > curve(trans);
00496
00497 agg::conv_gpc<agg::conv_stroke<spiral>,
00498 agg::conv_curve<
00499 agg::conv_transform<
00500 agg::path_storage> > > gpc(stroke, curve);
00501
00502 ras.reset();
00503 ras.add_path(stroke);
00504 ren.color(agg::rgba(0, 0, 0, 0.1));
00505 agg::render_scanlines(ras, sl, ren);
00506
00507 ras.reset();
00508 ras.add_path(curve);
00509 ren.color(agg::rgba(0, 0.6, 0, 0.1));
00510 agg::render_scanlines(ras, sl, ren);
00511
00512 perform_rendering(sl, ras, ren, gpc);
00513 }
00514 break;
00515 }
00516
00517 return 0;
00518 }
00519
00520
00521 virtual void on_init()
00522 {
00523 m_x = width() / 2.0;
00524 m_y = height() / 2.0;
00525 }
00526
00527 virtual void on_draw()
00528 {
00529 typedef agg::renderer_base<agg::pixfmt_bgr24> base_ren_type;
00530
00531 agg::pixfmt_bgr24 pf(rbuf_window());
00532 base_ren_type ren_base(pf);
00533 ren_base.clear(agg::rgba(1,1,1));
00534
00535 agg::scanline_u8 sl;
00536 agg::rasterizer_scanline_aa<> ras;
00537
00538 render_gpc(sl, ras);
00539
00540 agg::render_ctrl(ras, sl, ren_base, m_polygons);
00541 agg::render_ctrl(ras, sl, ren_base, m_operation);
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 virtual void on_mouse_button_down(int x, int y, unsigned flags)
00637 {
00638 if(flags & agg::mouse_left)
00639 {
00640 m_x = x;
00641 m_y = y;
00642 force_redraw();
00643 }
00644
00645 if(flags & agg::mouse_right)
00646 {
00647 char buf[100];
00648 sprintf(buf, "%d %d", x, y);
00649 message(buf);
00650 }
00651 }
00652
00653
00654 virtual void on_mouse_move(int x, int y, unsigned flags)
00655 {
00656 if(flags & agg::mouse_left)
00657 {
00658 m_x = x;
00659 m_y = y;
00660 force_redraw();
00661 }
00662 }
00663
00664
00665
00666 };
00667
00668
00669
00670 int agg_main(int argc, char* argv[])
00671 {
00672 the_application app(agg::pix_format_bgr24, flip_y);
00673 app.caption("AGG Example. General Polygon Clipping (GPC)");
00674
00675 if(app.init(640, 520, agg::window_resize))
00676 {
00677 return app.run();
00678 }
00679 return 1;
00680 }
00681
00682