polyhedron.c
上传用户:gzelex
上传日期:2007-01-07
资源大小:707k
文件大小:6k
开发平台:

MultiPlatform

  1. #include <LEDA/graph.h>
  2. #include <LEDA/graph_alg.h>
  3. #include <LEDA/array.h>
  4. #include <LEDA/stream.h>
  5. #include <LEDA/array.h>
  6. #include <LEDA/window.h>
  7. #include <math.h>
  8. typedef GRAPH<vector,int> polyhedron;
  9. void rotate(float alpha1,float alpha2, vector& p)
  10.   // rotate 3d-point p about the origin
  11.   // by alpha2 in yz-plane and alpha1 in xy-plane
  12.     double R  = hypot(p[1],p[2]);
  13.     double phi = asin(p[1]/R);
  14.   
  15.     if (p[2] < 0) phi = LEDA_PI - phi;
  16.   
  17.     p[1]  = ((R != 0) ? R*sin(phi+alpha2) : 0);
  18.     p[2]  = ((R != 0) ? R*cos(phi+alpha2) : 0);
  19.     R   = hypot(p[0],p[2]);
  20.     phi = asin(p[0]/R);
  21.     if (p[2] < 0) phi = LEDA_PI - phi;
  22.   
  23.     p[0]  = ((R != 0) ? R*sin(phi+alpha1) : 0);
  24.     p[2]  = ((R != 0) ? R*cos(phi+alpha1) : 0);
  25. }
  26. point project(vector p)   // project p into xy-plane
  27. {
  28.   return point(p[0],p[1]); 
  29.  }
  30. void draw_poly(window& W, polyhedron& poly, vector& trans)
  31. { node v,w;
  32.   node_array<bool> marked(poly,false);
  33.   forall_nodes(v,poly) 
  34.   { forall_adj_nodes(w,v)
  35.       if (!marked[w])
  36.       { point a = project(poly[v]+trans);
  37.         point b = project(poly[w]+trans);
  38.         W.draw_segment(a,b,blue);
  39.        }
  40.     marked[v] = true;
  41.    }
  42.  }
  43. /*
  44. void draw_poly(window& W, polyhedron& poly, vector& trans)
  45. { edge e;
  46.   forall_edges(e,poly) 
  47.   { point a = project(poly[source(e)]+trans);
  48.     point b = project(poly[target(e)]+trans);
  49.     W.draw_segment(a,b,blue);
  50.    }
  51.  }
  52. */
  53. void make_poly(polyhedron& poly, int N)
  54.   
  55.     node* L = new node[N];
  56.     node* R = new node[N];
  57.   
  58.     float d = 2*LEDA_PI/N;
  59.     node v;
  60.     poly.clear();
  61.   
  62.     int i;
  63.     for(i=0; i<N; i++)
  64.     { point origin(0,0);
  65.       point p = origin.translate(i*d,100);
  66.       L[i] = poly.new_node(vector(p.xcoord(),p.ycoord(), 120));
  67.       R[i] = poly.new_node(vector(p.xcoord(),p.ycoord(),-120));
  68.      }
  69.     node v0 = poly.new_node(vector(0,0,-30));
  70.   
  71.     for(i=1; i<N; i++)
  72.     { poly.new_edge(L[i],L[i-1]);
  73.       poly.new_edge(L[i-1],L[i]);
  74.       poly.new_edge(R[i],R[i-1]);
  75.       poly.new_edge(R[i-1],R[i]);
  76.       poly.new_edge(L[i],R[i]);
  77.       poly.new_edge(R[i],L[i]);
  78.       poly.new_edge(v0,R[i]);
  79.       poly.new_edge(R[i],v0);
  80.      }
  81.   
  82.     poly.new_edge(L[0],L[N-1]);
  83.     poly.new_edge(L[N-1],L[0]);
  84.     poly.new_edge(R[0],R[N-1]);
  85.     poly.new_edge(R[N-1],R[0]);
  86.     poly.new_edge(L[0],R[0]);
  87.     poly.new_edge(R[0],L[0]);
  88.     poly.new_edge(v0,R[0]);
  89.     poly.new_edge(R[0],v0);
  90.     if (!PLANAR(poly,true)) error_handler(1,"graph not planar !");
  91.     // compute an interior point M and move the origin to this point
  92.   
  93.     vector M(3);
  94.   
  95.     forall_nodes(v,poly)
  96.     {  M[0] += poly[v][0];
  97.        M[1] += poly[v][1];
  98.        M[2] += poly[v][2];
  99.      }
  100.   
  101.   
  102.     M[0] /= poly.number_of_nodes();
  103.     M[1] /= poly.number_of_nodes();
  104.     M[2] /= poly.number_of_nodes();
  105.   
  106.   
  107.     forall_nodes(v,poly)
  108.     { poly[v][0] -= M[0];
  109.       poly[v][1] -= M[1];
  110.       poly[v][2] -= M[2];
  111.      }
  112.   
  113. }
  114. void make_sphere(GRAPH<vector,int>& G, int n)
  115. {
  116.   int m = 2*n;
  117.   array<node>  V(m);
  118.   node north = G.new_node(vector(0,0, 1));
  119.   int i;
  120.   int j;
  121.   double phi1 = 0;
  122.   double phi2 = 0;
  123.   double d1 = LEDA_PI/n;
  124.   double d2 = LEDA_PI/n;
  125.   for(i=0; i<m; i++) V[i] = north;
  126.   for(phi1=d1, j=1; j<n; phi1+=d1, j++)
  127.   { double z = cos(phi1);
  128.     double r = sin(phi1);
  129.     for(phi2=0, i=0; i<m; phi2+=d2, i++)
  130.     {
  131.       double x = r*cos(phi2);
  132.       double y = r*sin(phi2);
  133.       node v = G.new_node(vector(x,y,z));
  134.       if(i==0) 
  135.       { G.new_edge(v,V[i]);
  136.         G.new_edge(V[i],v);
  137.         if (j > 1)  
  138.         { G.new_edge(V[0],V[m-1]);
  139.           G.new_edge(V[m-1],V[0]);
  140.          }
  141.        }
  142.       else
  143.        { G.new_edge(v,V[i-1]);
  144.          G.new_edge(V[i-1],v);
  145.          G.new_edge(v,V[i]);
  146.          G.new_edge(V[i],v);
  147.         }
  148.       V[i] = v;
  149.      }
  150.    }
  151.   node south = G.new_node(vector(0,0,-1));
  152.   G.new_edge(V[m-1],V[0]);
  153.   G.new_edge(V[0],V[m-1]);
  154.   for (i=0;i<m;i++) 
  155.   { G.new_edge(south,V[i]);
  156.     G.new_edge(V[i],south);
  157.    }
  158.   node v;
  159.   forall_nodes(v,G) G[v] = G[v]*100;
  160.   if (!PLANAR(G,true)) error_handler(1," G not planar !");
  161. }
  162. void read_poly(polyhedron& poly, string fname)
  163. {
  164.   poly.clear();
  165.   file_istream IN(fname);
  166.   int N;
  167.   int i;
  168.   IN >> N;
  169.   array<node> V(N);
  170.   vector v(3);
  171.   for(i = 0; i<N; i++) 
  172.   { IN >> v;
  173.     V[i] = poly.new_node(v);
  174.    }
  175. /*
  176.   for(i = 0; i<N; i++) 
  177.   { int d;
  178.     IN >> d;
  179.     while(d--)
  180.     { IN >> j;
  181.       poly.new_edge(V[i], V[j])
  182.      }
  183.    }
  184. */
  185.   for(i = 0; i<N; i++) 
  186.   { int u,v,w;
  187.     IN >> u >> v >> w;
  188.     poly.new_edge(V[u], V[v]);
  189.     poly.new_edge(V[v], V[w]);
  190.     poly.new_edge(V[w], V[u]);
  191.   }
  192. }
  193. main()
  194.   window W(700,700);
  195.   W.init(-250,250,-250);
  196.   W.set_node_width(4);
  197.   W.set_mode(xor_mode);
  198.   node v;
  199.   int     N = 5;
  200.   int speed = 40;
  201.   bool  ran = false;
  202.  panel P("Rotate Polyhedron");
  203.  P.text_item("");
  204.  P.text_item("This program creates and rotates a 3-dimensional polyhedron.");
  205.  P.text_item("Direction and duration of the rotation is controled by the");
  206.  P.text_item("left mouse button.");
  207.  P.text_item("");
  208.  P.bool_item("random",ran);
  209.  P.int_item("speed",speed,1,80);
  210.  P.int_item("# vertices",N,3,32);
  211.  for(;;)
  212.  {
  213.     P.open(W);
  214.     W.clear();
  215.     // define a polyhedron in 3d space
  216.   
  217.     polyhedron poly;
  218.     //make_poly(poly,N);
  219.     make_sphere(poly,N);
  220.   
  221.   
  222.   
  223.     forall_nodes(v,poly) rotate(1.5,0.7,poly[v]);
  224.     W.draw_point(0,0);
  225.   
  226.   
  227.     polyhedron poly0 = poly;
  228.     vector dir(2);   // direction and duration of rotation
  229.     //vector trans(50,50,50);  // translation
  230.     vector trans(0,0,0);  // translation
  231.     int steps;
  232.     draw_poly(W,poly,trans);
  233.   
  234.     for(;;)
  235.     {
  236.       if (ran)
  237.       { dir[0] += rand_int(-10000,10000)/(5000000.0);
  238.         dir[1] += rand_int(-10000,10000)/(5000000.0);
  239.         dir = dir.norm()*(speed/500.0);
  240.         steps = 1;
  241.         if (W.get_button() != 0) break;
  242.        }
  243.       else
  244.       { int but = W.read_mouse(dir[0],dir[1]);
  245.         steps = int(dir.length()*W.scale())/8;
  246.         if (but == 3) break;
  247.         dir = dir.norm()*(speed/500.0);
  248.        }
  249.   
  250.       while (steps--)
  251.       {  
  252.         forall_nodes(v,poly) rotate(dir[0],dir[1],poly[v]);
  253.    
  254.         draw_poly(W,poly,trans);   // draw new position
  255.         draw_poly(W,poly0,trans);  // erase old position  (xor_mode !!)
  256.   
  257.         // poly0 = poly;
  258.   
  259.         node w = poly.first_node();
  260.         forall_nodes(v,poly0) 
  261.         { poly0[v] = poly[w];
  262.           w = poly.succ_node(w);
  263.          }
  264.       }
  265.     }
  266.   }
  267.  return 0;
  268. }