home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / leda / prog / graphics / delaunay.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-15  |  7.4 KB  |  378 lines

  1. #include <LEDA/window.h>
  2. #include <LEDA/delaunay_tree.h>
  3.  
  4.  
  5. window* Wp;
  6.  
  7. const double R = 1000;  // "length of inifinite rays"
  8.  
  9. int ymax;
  10.  
  11. int segment_to_points(segment s, list(point)& out, double dist)
  12.   int n = int(s.length()/dist) + 2;
  13.  
  14.   double dx = (s.xcoord2() - s.xcoord1())/n;
  15.   double dy = (s.ycoord2() - s.ycoord1())/n;
  16.   double x  = s.xcoord1();
  17.   double y  = s.ycoord1();
  18.  
  19.   out.append(s.start());
  20.  
  21.   for(int i = 0; i<n; i++)
  22.   { x += dx + 0.001 * rrandom();
  23.     y += dy + 0.001 * rrandom();
  24.     out.append(point(x,y));
  25.    }
  26.  
  27.   out.permute();
  28.  
  29.   return n;
  30.  
  31. }
  32.  
  33. int circle_to_points(circle C, list(point)& out, double dist)
  34.   point c = C.center();
  35.   double r = C.radius();
  36.   int n = int(6.283 * r/dist);
  37.  
  38.   double alpha = 0;
  39.   double d = 6.283/n;
  40.  
  41.   for(int i = 0; i<n; i++)
  42.   { out.append(c.translate(alpha,r + 0.0001 * rrandom()));
  43.     alpha += d;
  44.    }
  45.  
  46.   out.permute();
  47.  
  48.  return n;
  49.  
  50. }
  51.  
  52.  
  53.  
  54.  
  55. void draw_vor_site(double x, double y)
  56. { Wp->draw_point(x,y); }
  57.  
  58. void draw_vor_seg(double x1, double y1, double x2, double y2,double,double)
  59. { Wp->draw_segment(x1,y1,x2,y2,blue); }
  60.  
  61.  
  62. void draw_triang_seg(double x1, double y1, double x2, double y2)
  63. { Wp->draw_segment(x1,y1,x2,y2,red); 
  64.  }
  65.  
  66. void infi_pt(double x1, double y1, double x2, double y2, double *x, double* y)
  67. /* retourne le point a l'infini dans la direction x2 y2 depuis x1 y1*/
  68. {
  69.   vector v(x2,y2);
  70.  
  71.   v = v.norm();
  72.  
  73.   *x = x1 + R * v[0];
  74.   *y = y1 + R * v[1];
  75.   
  76. }
  77.  
  78.  
  79. declare(DELAUNAY_TREE,int)
  80.  
  81. DELAUNAY_TREE(int) DT;
  82.  
  83. DT_item it = nil;
  84. bool vor = false;
  85. bool triang = false;
  86. list(segment) CH;
  87.  
  88. void redraw()
  89. { list(DT_item) L;
  90.   DT.all_items(L);
  91.   Wp->clear();
  92.   forall(it,L) *Wp << DT.key(it);
  93.   it = nil; 
  94.   vor = false;
  95.   triang = false;
  96.   CH.clear();
  97. }
  98.  
  99.  
  100. void interactive(window& W)
  101. {
  102.  
  103.   W.set_mode(xor_mode);
  104.  
  105.   panel P("DYNAMIC VORONOI DIAGRAMS");
  106.  
  107.   P.text_item("            based on Delaunay Trees           ");
  108.   P.text_item("             by Olivier Devillers             ");
  109.   P.text_item("             INRIA Sofia-Antipolis            ");
  110.   P.text_item("                                              ");
  111.   P.text_item("BUTTON    |  left      middle       right     ");
  112.   P.text_item("----------+-----------------------------------");
  113.   P.text_item("unshifted |  insert    voronoi      menu      ");
  114.   P.text_item("shifted   |  segment   delaunay     delete    ");
  115.   P.text_item("ctrl      |  circle    convex hull  locate    ");
  116.   P.text_item("                                              ");
  117.  
  118.   int key = 0;
  119.  
  120.   int input = 0;          // 0:mouse, 1: random
  121.   int grid_width = 0;
  122.   int line_width = 1;
  123.   int node_width = 4;
  124.   int N = 100;
  125.  
  126.   P.choice_item("input",input,"mouse","random");
  127.  
  128.   P.int_item("grid width  ",grid_width,0,40,10);
  129.   P.int_item("#sites ",N);
  130.   P.int_item("line width", line_width,1,5);
  131.   P.int_item("node width", node_width,1,10);
  132.  
  133.  
  134. for(;;)
  135. {
  136.   P.open();
  137.  
  138.   W.set_line_width(line_width);
  139.   W.set_node_width(node_width);
  140.   W.set_grid_mode(grid_width);
  141.  
  142.   real x, y;
  143.  
  144.   it = nil;
  145.   vor = false;
  146.   triang = false;
  147.   CH.clear();
  148.  
  149.  
  150.   if (input == 1)
  151.   { init_random();
  152.     DT.clear();
  153.     W.clear();
  154.     while (N--)
  155.     { point p(random(10,500),random(10,ymax));
  156.       DT.insert(p,N);
  157.       W << p;
  158.      }
  159.  
  160.     DT.trace_voronoi_edges( draw_vor_seg,infi_pt);
  161.     W.flush();
  162.     vor = true;
  163.    }
  164.  
  165.  
  166.    while ( (key = W.read_mouse(x,y)) != 3 ) 
  167.     {
  168.       segment s;
  169.  
  170.       // undo previous drawings
  171.  
  172.         if (vor)         DT.trace_voronoi_edges(draw_vor_seg,infi_pt);
  173.         if (triang)      DT.trace_triang_edges(draw_triang_seg);
  174.         if (!CH.empty()) forall(s,CH) W.draw_arrow(s,green);
  175.         if (it != nil)   W.draw_filled_node(DT.key(it));
  176.  
  177.  
  178.         vor = false;
  179.         triang = false;
  180.         CH.clear();
  181.         it = nil;
  182.  
  183.         point p(x,y);
  184.  
  185.     switch (key) {
  186.  
  187.     case  1 : { W << p;
  188.                     DT.insert(p,0);
  189.                     break;
  190.                    }
  191.  
  192.     case -1 :  { list(point) pl;
  193.                      real x1,y1;
  194.                      W.read_mouse_seg(x,y,x1,y1);
  195.                      segment s(x,y,x1,y1);
  196.                      segment_to_points(s,pl,10/W.scale());
  197.                      point p;
  198.                      forall(p,pl)
  199.                      { W << p;
  200.                        DT.insert(p,0);
  201.                       }
  202.                      break;
  203.                     }
  204.  
  205.     case  4 :  { list(point) pl;
  206.                      real x1,y1;
  207.                      W.read_mouse_circle(x,y,x1,y1);
  208.                      point p(x,y);
  209.                      real r = p.distance(point(x1,y1));
  210.                      circle_to_points(circle(p,r),pl,10/W.scale());
  211.                      forall(p,pl)
  212.                      { W << p;
  213.                        DT.insert(p,0);
  214.                       }
  215.                      break;
  216.                     }
  217.  
  218.  
  219.  
  220.     case  2 : DT.trace_voronoi_edges( draw_vor_seg,infi_pt);
  221.                   vor = true;
  222.                   break;
  223.  
  224.     case -2 : DT.trace_triang_edges( draw_triang_seg);
  225.                   triang = true;
  226.                   break;
  227.  
  228.         case  5: { // convex hull
  229.                    list(DT_item) L;
  230.                    list_item it;
  231.                    DT.convex_hull(L);
  232.                    cout << "Convex Hull =\n";
  233.                    forall_items(it,L) 
  234.                    { point p = DT.key(L[it]);
  235.                      point q = DT.key(L[L.cyclic_succ(it)]);
  236.                      cout << p;
  237.                      newline;
  238.                      CH.append(segment(p,q));
  239.                      W.draw_arrow(p,q,green);
  240.                     }
  241.                    newline;
  242.                    break;
  243.                   }
  244.  
  245.         case  3 : // panel
  246.                   break;
  247.  
  248.  
  249.     case -3 : it = DT.neighbor(p); 
  250.                   if (it) 
  251.           { W << DT.key(it);
  252.                     DT.del_item(it); 
  253.                    }
  254.                   it = nil;
  255.                   break;
  256.  
  257.     case  6 : it = DT.neighbor(p); 
  258.                   if (it)
  259.           { W.draw_filled_node(DT.key(it));
  260.             cout << DT.inf(it) << "\n";
  261.                    }
  262.                   break;
  263.  
  264.  
  265.  
  266.     }  // switch
  267.  
  268.       W.flush();
  269.  
  270.      }  // while
  271.  
  272.  } // for(;;)
  273.  
  274. }
  275.  
  276.  
  277.  
  278. void demo(int N, int wait)
  279. { int i;
  280.  
  281.   for(;;)
  282.   {
  283.     DT.clear();
  284.     Wp->clear();
  285.     Wp->message(form("%d sites",N));
  286.     Wp->flush();
  287.  
  288.     for (i=0; i<N ; i++)
  289.     { point p(random(10,500),random(10,ymax));
  290.       DT.insert(p,i);
  291.       *Wp << p;
  292.      }
  293.  
  294.  
  295.     //DT.trace_voronoi_sites( draw_vor_site);
  296.  
  297.     DT.trace_voronoi_edges( draw_vor_seg,infi_pt);
  298.     Wp->flush();
  299.     sleep(wait);
  300.  
  301.     Wp->clear();
  302.  
  303.     DT.trace_triang_edges( draw_triang_seg);
  304.     Wp->flush();
  305.     sleep(wait);
  306.   }
  307.  
  308. }
  309.  
  310.  
  311. main(int argc, char** argv)
  312. {
  313.   int   position=0, N=0;
  314.   float f1=0, f2=0;
  315.  
  316.   float w,h,xpos,ypos;
  317.  
  318.   string_istream arguments(argc-1,argv+1);
  319.  
  320.   arguments >> f1;
  321.   arguments >> f2;
  322.  
  323.  
  324.   if (f1 == 0 && f2 == 0) 
  325.    { f1 = 0.75;
  326.      f2 = 0.95;
  327.     }
  328.   else 
  329.    if (f2 == 0) 
  330.      f2 = f1;
  331.    else
  332.      { arguments >> position;
  333.        arguments >> N;
  334.       }
  335.  
  336.   w = SCREEN_WIDTH*f1;
  337.   h = SCREEN_HEIGHT*f2;
  338.  
  339.   switch(position) {
  340.  
  341.   case 0: xpos = SCREEN_WIDTH - w;    // upper right corner
  342.           ypos = 0;
  343.           break; 
  344.  
  345.   case 1: xpos = 0;                   // upper left corner
  346.           ypos = 0;
  347.           break; 
  348.  
  349.   case 2: xpos = 0;
  350.           ypos = SCREEN_HEIGHT - h;   // lower left corner
  351.           break; 
  352.  
  353.   case 3: xpos = SCREEN_WIDTH - w;    // lower right corner
  354.           ypos = SCREEN_HEIGHT - h;
  355.           break; 
  356. }
  357.  
  358.  
  359.   window W(w,h,xpos,ypos);
  360.  
  361.   W.set_flush(false);
  362.   W.set_node_width(5);
  363.  
  364.   W.init(0,512,0);
  365.  
  366.   Wp = &W;
  367.  
  368.   ymax = int(W.ymax()-10);
  369.  
  370.   if (N==0) 
  371.      interactive(W);
  372.   else
  373.      demo(N,1);
  374.  
  375. }
  376.