gb_plane.w
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:39k
源码类别:

通讯编程

开发平台:

Visual C++

  1. % This file is part of the Stanford GraphBase (c) Stanford University 1993
  2. @i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES!
  3. @i gb_types.w
  4. deftitle{GB_,PLANE}
  5. prerequisite{GB_,MILES}
  6. @* Introduction. This GraphBase module contains the |plane| subroutine,
  7. which constructs undirected planar graphs from vertices located randomly
  8. in a rectangle,
  9. as well as the |plane_miles| routine, which constructs planar graphs
  10. based on the mileage and coordinate data in .{miles.dat}. Both
  11. routines use a general-purpose |delaunay| subroutine,
  12. which computes the Delaunay triangulation of a given set of points.
  13. @d plane_miles p_miles /* abbreviation for Procrustean external linkage */
  14. @(gb_plane.h@>=
  15. #define plane_miles p_miles
  16. extern Graph *plane();
  17. extern Graph *plane_miles();
  18. extern void delaunay();
  19. @ The subroutine call |plane(n,x_range,y_range,extend,prob,seed)| constructs
  20. a planar graph whose vertices have integer coordinates
  21. uniformly distributed in the rectangle
  22. $${,(x,y);mid;0le x<|x_range|, ;0le y<|y_range|,},.$$
  23. The values of |x_range| and |y_range| must be at most $2^{14}=16384$; the
  24. latter value is the default, which is substituted if |x_range| or |y_range|
  25. is given as zero. If |extend==0|, the graph will have |n| vertices; otherwise
  26. it will have |n+1| vertices, where the |(n+1)|st is assigned the coordinates
  27. $(-1,-1)$ and may be regarded as a point at~$infty$.
  28. Some of the |n|~finite vertices might have identical coordinates, particularly
  29. if the point density |n/(x_range*y_range)| is not very small.
  30. The subroutine works by first constructing the Delaunay triangulation
  31. of the points, then discarding
  32. each edge of the resulting graph with probability |prob/65536|. Thus,
  33. for example, if |prob| is zero the full Delaunay triangulation will be
  34. returned; if |prob==32768|, about half of the Delaunay edges will remain.
  35. Each finite edge is assigned a length equal to the Euclidean distance between
  36. points, multiplied by $2^{10}$ and
  37. rounded to the nearest integer. If |extend!=0|, the
  38. Delaunay triangulation will also contain edges between $infty$ and
  39. all points of the convex hull; such edges, if not discarded, are
  40. assigned length $2^{28}$, otherwise known as |INFTY|.
  41. If |extend!=0| and |prob==0|, the graph will have $n+1$ vertices and
  42. $3(n-1)$ edges; this is the maximum number of edges that a planar graph
  43. on $n+1$ vertices can have. In such a case the average degree of a vertex will
  44. be $6(n-1)/(n+1)$, slightly less than~6; hence, if |prob==32768|,
  45. the average degree of a vertex will usually be near~3.
  46. As with all other GraphBase routines that rely on random numbers,
  47. different values of |seed| will produce different graphs, in a
  48. machine-independent fashion that is reproducible on many different
  49. computers. Any |seed| value between 0 and $2^{31}-1$ is permissible.
  50. @d INFTY 0x10000000L /* ``infinite'' length */
  51. @(gb_plane.h@>=
  52. #define INFTY @tquad@> 0x10000000L
  53. @ If the |plane| routine encounters a problem, it returns |NULL|
  54. (.{NULL}), after putting a code number into the external variable
  55. |panic_code|. This code number identifies the type of failure.
  56. Otherwise |plane| returns a pointer to the newly created graph, which
  57. will be represented with the data structures explained in {sc GB_,GRAPH}.
  58. (The external variable |panic_code| is itself defined in {sc GB_,GRAPH}.)
  59. @d panic(c) @+{@+panic_code=c;@+gb_trouble_code=0;@+return NULL;@+}
  60. @ Here is the overall shape of the CEE/ file .{gb_plane.c}kern.2em:
  61. @p
  62. #include "gb_flip.h"
  63.  /* we will use the {sc GB_,FLIP} routines for random numbers */
  64. #include "gb_graph.h" /* we will use the {sc GB_,GRAPH} data structures */
  65. #include "gb_miles.h" /* and we might use {sc GB_,MILES} for mileage data */
  66. #include "gb_io.h"
  67.  /* and {sc GB_,MILES} uses {sc GB_,IO}, which has |str_buf| */
  68. @h@#
  69. @<Type declarations@>@;
  70. @<Global variables@>@;
  71. @<Subroutines for arithmetic@>@;
  72. @<Other subroutines@>@;
  73. @<The |delaunay| routine@>@;
  74. @<The |plane| routine@>@;
  75. @<The |plane_miles| routine@>@;
  76. @ @<The |plane| routine@>=
  77. Graph *plane(n,x_range,y_range,extend,prob,seed)
  78.   unsigned long n; /* number of vertices desired */
  79.   unsigned long x_range,y_range; /* upper bounds on rectangular coordinates */
  80.   unsigned long extend; /* should a point at infinity be included? */
  81.   unsigned long prob; /* probability of rejecting a Delaunay edge */
  82.   long seed; /* random number seed */
  83. {@+Graph *new_graph; /* the graph constructed by |plane| */
  84.   register Vertex *v; /* the current vertex of interest */
  85.   register long k; /* the canonical all-purpose index */
  86.   gb_init_rand(seed);
  87.   if (x_range>16384 || y_range>16384) panic(bad_specs); /* range too large */
  88.   if (n<2) panic(very_bad_specs); /* don't make |n| so small, you fool */
  89.   if (x_range==0) x_range=16384; /* default */
  90.   if (y_range==0) y_range=16384; /* default */
  91.   @<Set up a graph with |n| uniformly distributed vertices@>;
  92.   @<Compute the Delaunay triangulation and
  93.     run through the Delaunay edges; reject them with probability
  94.     |prob/65536|, otherwise append them with their Euclidean length@>;
  95.   if (gb_trouble_code) {
  96.     gb_recycle(new_graph);
  97.     panic(alloc_fault); /* oops, we ran out of memory somewhere back there */
  98.   }
  99.   if (extend) new_graph->n++; /* make the ``infinite'' vertex legitimate */
  100.   return new_graph;
  101. }
  102. @ The coordinates are placed into utility fields |x_coord| and |y_coord|.
  103. A random ID number is also stored in utility field~|z_coord|; this number is
  104. used by the |delaunay| subroutine to break ties when points are equal or
  105. collinear or cocircular. No two vertices have the same ID number.
  106. (The header file .{gb_miles.h} defines |x_coord|, |y_coord|, and
  107. |index_no| to be |x.I|, |y.I|, and |z.I| respectively.)
  108. @d z_coord z.I
  109. @<Set up a graph with |n| uniform...@>=
  110. if (extend) extra_n++; /* allocate one more vertex than usual */
  111. new_graph=gb_new_graph(n);
  112. if (new_graph==NULL)
  113.   panic(no_room); /* out of memory before we're even started */
  114. sprintf(new_graph->id,"plane(%lu,%lu,%lu,%lu,%lu,%ld)",
  115.   n,x_range,y_range,extend,prob,seed);
  116. strcpy(new_graph->util_types,"ZZZIIIZZZZZZZZ");
  117. for (k=0,v=new_graph->vertices; k<n; k++,v++) {
  118.   v->x_coord=gb_unif_rand(x_range);
  119.   v->y_coord=gb_unif_rand(y_range);
  120.   v->z_coord=((long)(gb_next_rand()/n))*n+k;
  121.   sprintf(str_buf,"%ld",k);@+v->name=gb_save_string(str_buf);
  122. }
  123. if (extend) {
  124.   v->name=gb_save_string("INF");
  125.   v->x_coord=v->y_coord=v->z_coord=-1;
  126.   extra_n--;
  127. }
  128. @ @(gb_plane.h@>=
  129. #define x_coord @tquad@> x.I
  130. #define y_coord @tquad@> y.I
  131. #define z_coord @tquad@> z.I
  132. @* Delaunay triangulation. The Delaunay triangulation of a set of
  133. vertices in the plane consists of all line segments $uv$ such that
  134. there exists a circle passing through $u$ and~$v$ containing no other
  135. vertices. Equivalently, $uv$ is a Delaunay edge if and only if the
  136. Voronoi regions for $u$ and $v$ are adjacent; the Voronoi region of a
  137. vertex~$u$ is the polygon with the property that all points inside it
  138. are closer to $u$ than to any other vertex. In this sense, we can say
  139. that Delaunay edges connect vertices with their ``neighbors.''
  140. @^Delaunay [Delone], Boris Nikolaevich@>
  141. The definitions in the previous paragraph assume that no two vertices are
  142. equal, that no three vertices lie on a straight line, and that no four vertices
  143. lie on a circle. If those nondegeneracy conditions aren't satisfied, we can
  144. perturb the points very slightly so that the assumptions do hold.
  145. Another way to characterize the Delaunay triangulation is to consider
  146. what happens when we map a given set of
  147. points onto the unit sphere via stereographic projection: Point $(x,y)$ is
  148. mapped to
  149. $$bigl(2x/(r^2+1),2y/(r^2+1),(r^2-1)/(r^2+1)bigr),,$$ where $r^2=x^2+y^2$.
  150. If we now extend the configuration by adding $(0,0,1)$,
  151. which is the limiting point on the sphere when $r$ approaches infinity,
  152. the Delaunay edges of the original points
  153. turn out to be edges of the polytope defined by the mapped
  154. points. This polytope, which is the 3-dimensional convex hull of $n+1$ points
  155. on the sphere, also has edges from $(0,0,1)$ to the mapped points
  156. that correspond to the 2-dimensional convex hull of the original points. Under
  157. our assumption of nondegeneracy, the faces of this polytope are all
  158. triangles; hence its edges are said to form a triangulation.
  159. A self-contained presentation of all the relevant theory, together with
  160. an exposition and proof of correctness of the algorithm below, can be found
  161. in the author's monograph {sl Axioms and Hulls}, Lecture Notes in
  162. Computer Science {bf606} (Springer-Verlag, 1992).
  163. @^Axioms and Hulls@>
  164. For further references, see Franz Aurenhammer, {sl ACM Computing Surveys/
  165. @^Aurenhammer, Franz@>
  166. bf23} (1991), 345--405.
  167. @ The |delaunay| procedure, which finds the Delaunay triangulation of
  168. a given set of vertices, is the key ingredient in \{gb_plane}'s
  169. algorithms for generating planar graphs. The given vertices should
  170. appear in a GraphBase graph~|g| whose edges, if any, are ignored by
  171. |delaunay|. The coordinates of each vertex appear in utility fields
  172. |x_coord| and~|y_coord|, which must be nonnegative and less than
  173. $2^{14}=16384$. The utility field~|z_coord| must contain a unique ID
  174. number, distinct for every vertex, so that the algorithm can break
  175. ties in cases of degeneracy. (Note: These assumptions about the input
  176. data are the responsibility of the calling procedure; |delaunay| does not
  177. double-check them. If they are violated, catastrophic failure is possible.)
  178. Instead of returning the Delaunay triangulation as a graph, |delaunay|
  179. communicates its answer implicitly by performing the procedure call
  180. |f(u,v)| on every pair of vertices |u| and~|v| joined by a Delaunay edge.
  181. Here |f|~is a procedure supplied as a parameter; |u| and~|v| are either
  182. pointers to vertices or |NULL| (i.e., .{NULL}), where |NULL| denotes the
  183. vertex ``$infty$.'' As remarked above, edges run between $infty$ and all
  184. vertices on the convex hull of the given points. The graph of all edges,
  185. including the infinite edges, is planar.
  186. For example, if the vertex at infinity is being ignored, the user can
  187. declare
  188. $$vcenter{halign{#hfilcr
  189. |void ins_finite(u,v)|cr
  190. qquad|Vertex *u,*v;|cr
  191. |{@+if (u&&v)@+gb_new_edge(u,v,1L);@+}|cr}}$$
  192. Then the procedure call |delaunay(g,ins_finite)| will add all the finite
  193. Delaunay edges to the current graph~|g|, giving them all length~1.
  194. If |delaunay| is unable to allocate enough storage to do its work, it
  195. will set |gb_trouble_code| nonzero and there will be no edges in
  196. the triangulation.
  197. @<The |delaunay| routine@>=
  198. void delaunay(g,f)
  199.   Graph *g; /* vertices in the plane */
  200.   void @[@] (*f)(); /* procedure that absorbs the triangulated edges */
  201. {@+@<Local variables for |delaunay|@>;@#
  202.   @<Find the Delaunay triangulation of |g|, or return with |gb_trouble_code|
  203.     nonzero if out of memory@>;
  204.   @<Call |f(u,v)| for each Delaunay edge \{uv}@>;
  205.   gb_free(working_storage);
  206. }
  207. @ The procedure passed to |delaunay| will communicate with |plane| via
  208. global variables called |gprob| and |inf_vertex|.
  209. @<Glob...@>=
  210. static unsigned long gprob; /* copy of the |prob| parameter */
  211. static Vertex *inf_vertex; /* pointer to the vertex $infty$, or |NULL| */
  212. @ @<Compute the Delaunay triangulation and
  213.     run through the Delaunay edges; reject them with probability
  214.     |prob/65536|, otherwise append them with their Euclidean length@>=
  215. gprob=prob;
  216. if (extend) inf_vertex=new_graph->vertices+n;
  217. else inf_vertex=NULL;
  218. delaunay(new_graph,new_euclid_edge);
  219. @ @<Other...@>=
  220. void new_euclid_edge(u,v)
  221.   Vertex *u,*v;
  222. {@+register long dx,dy;
  223.   if ((gb_next_rand()>>15)>=gprob) {
  224.     if (u) {
  225.       if (v) {
  226.         dx=u->x_coord-v->x_coord;
  227.         dy=u->y_coord-v->y_coord;
  228.         gb_new_edge(u,v,int_sqrt(dx*dx+dy*dy));
  229.       }@+else if (inf_vertex) gb_new_edge(u,inf_vertex,INFTY);
  230.     }@+else if (inf_vertex) gb_new_edge(inf_vertex,v,INFTY);
  231.   }
  232. }
  233. @* Arithmetic. Before we lunge into the world of geometric algorithms,
  234. let's build up some confidence by polishing off some subroutines that
  235. will be needed to ensure correct results. We assume that |long| integers
  236. are less than $2^{31}$.
  237. First is a routine to calculate $s=lfloor2^{10}sqrt x+{1over2}rfloor$,
  238. the nearest integer to $2^{10}$ times the square root of a given nonnegative
  239. integer~|x|. If |x>0|, this
  240. is the unique integer such that $2^{20}x-sle s^2<2^{20}x+s$.
  241. The following routine appears to work by magic, but the mystery goes
  242. away when one considers the invariant relations
  243. $$ m=lfloor 2^{2k-21}rfloor,qquad
  244.    0<y=lfloor 2^{20-2k}xrfloor-s^2+sle q=2s.$$
  245. (Exception: We might actually have $y=0$ for a short time when |q=2|.)
  246. @<Subroutines for arith...@>=
  247. long int_sqrt(x)
  248.   long x;
  249. {@+register long y, m, q=2; long k;
  250.   if (x<=0) return 0;
  251.   for (k=25,m=0x20000000;x<m;k--,m>>=2) ; /* find the range */
  252.   if (x>=m+m) y=1;
  253.   else y=0;
  254.   do @<Decrease |k| by 1, maintaining the invariant relations
  255.        between |x|, |y|, |m|, and |q|@>@;
  256.   while (k);
  257.   return q>>1;
  258. }
  259. @ @<Decrease |k| by 1, maintaining the invariant relations...@>=
  260. {
  261.   if (x&m) y+=y+1;
  262.   else y+=y;
  263.   m>>=1;
  264.   if (x&m) y+=y-q+1;
  265.   else y+=y-q;
  266.   q+=q;
  267.   if (y>q)
  268.     y-=q,q+=2;
  269.   else if (y<=0)
  270.     q-=2,y+=q;
  271.   m>>=1;
  272.   k--;
  273. }
  274. @ We are going to need multiple-precision arithmetic in order to
  275. calculate certain geometric predicates properly, but it turns out
  276. that we do not need to implement general-purpose subroutines for bignums.
  277. It suffices to have a single special-purpose routine called
  278. $|sign_test|(|x1|,|x2|,|x3|,allowbreak|y1|,|y2|,|y3|)$, which
  279. computes a single-precision integer having the same sign as the dot product
  280. $$hbox{|x1*y1+x2*y2+x3*y3|}$$
  281. when we have $-2^{29}<|x1|,|x2|,|x3|<2^{29}$ and $0le|y1|,|y2|,|y3|<2^{29}$.
  282. @<Subroutines for arith...@>=
  283. long sign_test(x1,x2,x3,y1,y2,y3)
  284.   long x1,x2,x3,y1,y2,y3;
  285. {@+long s1,s2,s3; /* signs of individual terms */
  286.   long a,b,c; /* components of a redundant representation of the dot product */
  287.   register long t; /* temporary register for swapping */
  288.   @<Determine the signs of the terms@>;
  289.   @<If the answer is obvious, return it without further ado; otherwise,
  290.     arrange things so that |x3*y3| has the opposite sign to |x1*y1+x2*y2|@>;
  291.   @<Compute a redundant representation of |x1*y1+x2*y2+x3*y3|@>;
  292.   @<Return the sign of the redundant representation@>;
  293. }
  294. @ @<Determine the signs of the terms@>=
  295. if (x1==0 || y1==0) s1=0;
  296. else {
  297.   if (x1>0) s1=1;
  298.   else x1=-x1,s1=-1;
  299. }
  300. if (x2==0 || y2==0) s2=0;
  301. else {
  302.   if (x2>0) s2=1;
  303.   else x2=-x2,s2=-1;
  304. }
  305. if (x3==0 || y3==0) s3=0;
  306. else {
  307.   if (x3>0) s3=1;
  308.   else x3=-x3,s3=-1;
  309. }
  310. @ The answer is obvious unless one of the terms is positive and one
  311. of the terms is negative.
  312. @<If the answer is obvious, return it without further ado; otherwise,
  313.     arrange things so that |x3*y3| has the opposite sign to |x1*y1+x2*y2|@>=
  314. if ((s1>=0 && s2>=0 && s3>=0) || (s1<=0 && s2<=0 && s3<=0))
  315.   return (s1+s2+s3);
  316. if (s3==0 || s3==s1) {
  317.   t=s3;@+s3=s2;@+s2=t;
  318.   t=x3;@+x3=x2;@+x2=t;
  319.   t=y3;@+y3=y2;@+y2=t;
  320. }@+else if (s3==s2) {
  321.   t=s3;@+s3=s1;@+s1=t;
  322.   t=x3;@+x3=x1;@+x1=t;
  323.   t=y3;@+y3=y1;@+y1=t;
  324. }
  325. @ We make use of a redundant representation $2^{28}a+2^{14}b+c$, which
  326. can be computed by brute force. (Everything is understood to be multiplied
  327. by |-s3|.)
  328. @<Compute a redundant...@>=
  329. {@+register long lx,rx,ly,ry;
  330.   lx=x1/0x4000;@+rx=x1%0x4000; /* split off the least significant 14 bits */
  331.   ly=y1/0x4000;@+ry=y1%0x4000;
  332.   a=lx*ly;@+b=lx*ry+ly*rx;@+c=rx*ry;
  333.   lx=x2/0x4000;@+rx=x2%0x4000;
  334.   ly=y2/0x4000;@+ry=y2%0x4000;
  335.   a+=lx*ly;@+b+=lx*ry+ly*rx;@+c+=rx*ry;
  336.   lx=x3/0x4000;@+rx=x3%0x4000;
  337.   ly=y3/0x4000;@+ry=y3%0x4000;
  338.   a-=lx*ly;@+b-=lx*ry+ly*rx;@+c-=rx*ry;
  339. }
  340. @ Here we use the fact that $vert cvert<2^{29}$.
  341. @<Return the sign...@>=
  342. if (a==0) goto ez;
  343. if (a<0)
  344.   a=-a,b=-b,c=-c,s3=-s3;
  345. while (c<0) {
  346.   a--;@+c+=0x10000000;
  347.   if (a==0) goto ez;
  348. }
  349. if (b>=0) return -s3; /* the answer is clear when |a>0 && b>=0 && c>=0| */
  350. b=-b;
  351. a-=b/0x4000;
  352. if (a>0) return -s3;
  353. if (a<=-2) return s3;
  354. return -s3*((a*0x4000-b%0x4000)*0x4000+c);
  355. ez:@+ if (b>=0x8000) return -s3;
  356. if (b<=-0x8000) return s3;
  357. return -s3*(b*0x4000+c);
  358. @*Determinants. The |delaunay| routine bases all of its decisions on
  359. two geometric predicates, which depend on whether certain determinants
  360. are positive or negative.
  361. The first predicate, |ccw(u,v,w)|, is true if and only if the three points
  362. $(u,v,w)$ have a counterclockwise orientation. This means that if we draw the
  363. unique circle through those points, and if we travel along that circle
  364. in the counterclockwise direction starting at~|u|, we will encounter
  365. |v| before~|w|.
  366. It turns out that |ccw(u,v,w)| holds if and only if the determinant
  367. $$leftvertmatrix{x_u&y_u&1cr x_v&y_v&1cr x_w&y_w&1cr}
  368.  rightvert=leftvertmatrix{x_u-x_w&y_u-y_wcr x_v-x_w&y_v-y_wcr}
  369.  rightvert$$
  370. is positive. The evaluation must be exact; if the answer is zero, a special
  371. tie-breaking rule must be used because the three points were collinear.
  372. The tie-breaking rule is tricky (and necessarily so, according to the
  373. theory in {sl Axioms and Hulls/}).
  374. Integer evaluation of that determinant will not cause |long| integer
  375. overflow, because we have assumed that all |x| and |y| coordinates lie
  376. between 0 and~$2^{14}-1$, inclusive. In fact, we could go up to
  377. $2^{15}-1$ without risking overflow; but the limitation to 14 bits will
  378. be helpful when we consider a more complicated determinant below.
  379. @<Other...@>=
  380. long ccw(u,v,w)
  381.   Vertex *u,*v,*w;
  382. {@+register long wx=w->x_coord, wy=w->y_coord; /* $x_w$, $y_w$ */
  383.   register long det=(u->x_coord-wx)*(v->y_coord-wy)
  384.                      -(u->y_coord-wy)*(v->x_coord-wx);
  385.   Vertex *t;
  386.   if (det==0) {
  387.     det=1;
  388.     if (u->z_coord>v->z_coord) {
  389.            t=u;@+u=v;@+v=t;@+det=-det;
  390.     }
  391.     if (v->z_coord>w->z_coord) {
  392.            t=v;@+v=w;@+w=t;@+det=-det;
  393.     }
  394.     if (u->z_coord>v->z_coord) {
  395.            t=u;@+u=v;@+v=t;@+det=-det;
  396.     }
  397.     if (u->x_coord>v->x_coord || (u->x_coord==v->x_coord &&@|
  398.         (u->y_coord>v->y_coord || (u->y_coord==v->y_coord &&@|
  399.          (w->x_coord>u->x_coord ||
  400.           (w->x_coord==u->x_coord && w->y_coord>=u->y_coord))))))
  401.            det=-det;
  402.   }
  403.   return (det>0);
  404. }
  405. @ The other geometric predicate, |incircle(t,u,v,w)|, is true if and only
  406. if point |t| lies outside the circle passing through |u|, |v|, and~|w|,
  407. assuming that |ccw(u,v,w)| holds. This predicate makes us work harder, because
  408. it is equivalent to the sign of a $4times4$ determinant that requires
  409. twice as much precision:
  410. $$leftvertmatrix{x_t&y_t&x_t^2+y_t^2&1cr
  411.                     x_u&y_u&x_u^2+y_u^2&1cr
  412.                     x_v&y_v&x_v^2+y_v^2&1cr
  413.                     x_w&y_w&x_w^2+y_w^2&1cr}rightvert=
  414. leftvertmatrix{x_t-x_w&y_t-y_w&(x_t-x_w)^2+(y_t-y_w)^2cr
  415.                   x_u-x_w&y_u-y_w&(x_u-x_w)^2+(y_u-y_w)^2cr
  416.                   x_v-x_w&y_v-y_w&(x_v-x_w)^2+(y_v-y_w)^2cr}
  417.  rightvert,.$$
  418. The sign can, however, be deduced by the |sign_test| subroutine we had
  419. the foresight to provide earlier.
  420. @<Other...@>=
  421. long incircle(t,u,v,w)
  422.   Vertex *t,*u,*v,*w;
  423. {@+register long wx=w->x_coord, wy=w->y_coord; /* $x_w$, $y_w$ */
  424.   long tx=t->x_coord-wx, ty=t->y_coord-wy; /* $x_t-x_w$, $y_t-y_w$ */
  425.   long ux=u->x_coord-wx, uy=u->y_coord-wy; /* $x_u-x_w$, $y_u-y_w$ */
  426.   long vx=v->x_coord-wx, vy=v->y_coord-wy; /* $x_v-x_w$, $y_v-y_w$ */
  427.   register long det=sign_test(tx*uy-ty*ux,ux*vy-uy*vx,vx*ty-vy*tx,@|
  428.                             vx*vx+vy*vy,tx*tx+ty*ty,ux*ux+uy*uy);
  429.   Vertex *s;
  430.   if (det==0) {
  431.     @<Sort |(t,u,v,w)| by ID number@>;
  432.     @<Remove incircle degeneracy@>;
  433.   }
  434.   return (det>0);
  435. }
  436. @ @<Sort...@>=
  437. det=1;
  438. if (t->z_coord>u->z_coord) {
  439.    s=t;@+t=u;@+u=s;@+det=-det;
  440. }
  441. if (v->z_coord>w->z_coord) {
  442.    s=v;@+v=w;@+w=s;@+det=-det;
  443. }
  444. if (t->z_coord>v->z_coord) {
  445.    s=t;@+t=v;@+v=s;@+det=-det;
  446. }
  447. if (u->z_coord>w->z_coord) {
  448.    s=u;@+u=w;@+w=s;@+det=-det;
  449. }
  450. if (u->z_coord>v->z_coord) {
  451.    s=u;@+u=v;@+v=s;@+det=-det;
  452. }
  453. @ By slightly perturbing the points, we can always make them nondegenerate,
  454. although the details are complicated. A sequence of 12 steps, involving
  455. up to four auxiliary functions
  456. $$openup3jot
  457. eqalign{|ff|(t,u,v,w)&=leftvert
  458.   matrix{x_t-x_v&(x_t-x_w)^2+(y_t-y_w)^2-(x_v-x_w)^2-(y_v-y_w)^2cr
  459.           x_u-x_v&(x_u-x_w)^2+(y_u-y_w)^2-(x_v-x_w)^2-(y_v-y_w)^2cr}
  460.      rightvert,,cr
  461. |gg|(t,u,v,w)&=leftvert
  462.   matrix{y_t-y_v&(x_t-x_w)^2+(y_t-y_w)^2-(x_v-x_w)^2-(y_v-y_w)^2cr
  463.           y_u-y_v&(x_u-x_w)^2+(y_u-y_w)^2-(x_v-x_w)^2-(y_v-y_w)^2cr}
  464.      rightvert,,cr
  465. |hh|(t,u,v,w)&=(x_u-x_t)(y_v-y_w),,cr
  466. |jj|(t,u,v,w)&=(x_u-x_v)^2+(y_u-y_w)^2-(x_t-x_v)^2-(y_t-y_w)^2,,cr}
  467. $$
  468. does the trick, as explained in {sl Axioms and Hulls}.
  469. @<Remove incircle degeneracy@>=
  470. {@+long dd;
  471.   if ((dd=ff(t,u,v,w))<0 || (dd==0 &&@|
  472.        ((dd=gg(t,u,v,w))<0 || (dd==0 &&@|
  473.          ((dd=ff(u,t,w,v))<0 || (dd==0 &&@|
  474.            ((dd=gg(u,t,w,v))<0 || (dd==0 &&@|
  475.              ((dd=ff(v,w,t,u))<0 || (dd==0 &&@|
  476.                ((dd=gg(v,w,t,u))<0 || (dd==0 &&@|
  477.                  ((dd=hh(t,u,v,w))<0 || (dd==0 &&@|
  478.                    ((dd=jj(t,u,v,w))<0 || (dd==0 &&@|
  479.                      ((dd=hh(v,t,u,w))<0 || (dd==0 &&@|
  480.                        ((dd=jj(v,t,u,w))<0 || (dd==0 &&
  481.                          jj(t,w,u,v)<0))))))))))))))))))))
  482.     det=-det;
  483. }
  484. @ @<Subroutines for arith...@>=
  485. long ff(t,u,v,w)
  486.   Vertex *t,*u,*v,*w;
  487. {@+register long wx=w->x_coord, wy=w->y_coord; /* $x_w$, $y_w$ */
  488.   long tx=t->x_coord-wx, ty=t->y_coord-wy; /* $x_t-x_w$, $y_t-y_w$ */
  489.   long ux=u->x_coord-wx, uy=u->y_coord-wy; /* $x_u-x_w$, $y_u-y_w$ */
  490.   long vx=v->x_coord-wx, vy=v->y_coord-wy; /* $x_v-x_w$, $y_v-y_w$ */
  491.   return sign_test(ux-tx,vx-ux,tx-vx,vx*vx+vy*vy,tx*tx+ty*ty,ux*ux+uy*uy);
  492. }
  493. long gg(t,u,v,w)
  494.   Vertex *t,*u,*v,*w;
  495. {@+register long wx=w->x_coord, wy=w->y_coord; /* $x_w$, $y_w$ */
  496.   long tx=t->x_coord-wx, ty=t->y_coord-wy; /* $x_t-x_w$, $y_t-y_w$ */
  497.   long ux=u->x_coord-wx, uy=u->y_coord-wy; /* $x_u-x_w$, $y_u-y_w$ */
  498.   long vx=v->x_coord-wx, vy=v->y_coord-wy; /* $x_v-x_w$, $y_v-y_w$ */
  499.   return sign_test(uy-ty,vy-uy,ty-vy,vx*vx+vy*vy,tx*tx+ty*ty,ux*ux+uy*uy);
  500. }
  501. long hh(t,u,v,w)
  502.   Vertex *t,*u,*v,*w;
  503. {
  504.   return (u->x_coord-t->x_coord)*(v->y_coord-w->y_coord);
  505. }
  506. long jj(t,u,v,w)
  507.   Vertex *t,*u,*v,*w;
  508. {@+register long vx=v->x_coord, wy=w->y_coord;
  509.   return (u->x_coord-vx)*(u->x_coord-vx)+(u->y_coord-wy)*(u->y_coord-wy)@|
  510.         -(t->x_coord-vx)*(t->x_coord-vx)-(t->y_coord-wy)*(t->y_coord-wy);
  511. }
  512. @* Delaunay data structures. Now we have the primitive predicates
  513. we need, and we can get on with the geometric aspects of |delaunay|.
  514. As mentioned above, each vertex is represented by two coordinates and an
  515. ID number, stored in the utility fields |x_coord|, |y_coord|, and~|z_coord|.
  516. Each edge of the current triangulation is represented by two arcs
  517. pointing in opposite directions; the two arcs are called {sl mates}. Each
  518. arc conceptually has a triangle on its left and a mate on its right.
  519. An &{arc} record differs from an |Arc|; it has three fields:
  520. smallskip
  521. |vert| is the vertex this arc leads to, or |NULL| if that vertex is $infty$;
  522. smallskip
  523. |next| is the next arc having the same triangle at the left;
  524. smallskip
  525. |inst| is the branch node that points to the triangle at the left, as
  526. explained below.
  527. smallskipnoindent
  528. If |p| points to an arc, then |p->next->next->next==p|, because a triangle
  529. is bounded by three arcs. We also have |p->next->inst==p->inst|, for
  530. all arcs~|p|.
  531. @<Type...@>=
  532. typedef struct a_struct {
  533.   Vertex *vert; /* |v|, if this arc goes from |u| to |v| */
  534.   struct a_struct *next; /* the arc from |v| that shares
  535.          a triangle with this one */
  536.   struct n_struct *inst; /* instruction to change
  537.           when the triangle is modified */
  538. } arc;
  539. @ Storage is allocated in such a way that, if |p| and |q| point respectively
  540. to an arc and its mate, then |p+q=&arc_block[0]+&arc_block[m-1]|, where |m| is
  541. the total number of arc records allocated in the |arc_block| array. This
  542. convention saves us one pointer field in each arc.
  543. When setting |q| to the mate of |p|, we need to do the calculation
  544. cautiously using an auxiliary register, because the constant
  545. |&arc_block[0]+&arc_block[m-1]| might be too large to evaluate without
  546. integer overflow on some systems.
  547. @^pointer hacks@>
  548. @d mate(a,b) { /* given |a|, set |b| to its mate */
  549.   reg=max_arc-(siz_t)a;
  550.   b=(arc*)(reg+min_arc);
  551. }
  552. @<Local variables for |delaunay|@>=
  553. register siz_t reg; /* used while computing mates */
  554. siz_t min_arc,max_arc; /* |&arc_block[0]|, |&arc_block[m-1]| */
  555. arc *next_arc; /* the first arc record that hasn't yet been used */
  556. @ @<Initialize the array of arcs@>=
  557. next_arc=gb_typed_alloc(6*g->n-6,arc,working_storage);
  558. if (next_arc==NULL) return; /* |gb_trouble_code| is nonzero */
  559. min_arc=(siz_t)next_arc;
  560. max_arc=(siz_t)(next_arc+(6*g->n-7));
  561. @ @<Call |f(u,v)| for each Delaunay edge...@>=
  562. a=(arc *)min_arc;
  563. b=(arc *)max_arc;
  564. for (; a<next_arc; a++,b--)
  565.   (*f)(a->vert,b->vert);
  566. @ The last and probably most crucial component of the data structure
  567. is the collection of {sl branch nodes}, which will be linked together
  568. into a binary tree.  Given a new vertex |w|, we will ascertain what
  569. triangle it belongs to by starting at the root of this tree and
  570. executing a sequence of instructions, each of which has the form `if
  571. |w| lies to the right of the straight line from |u| to~|v| then go to
  572. $alpha$ else go to~$beta$', where $alpha$ and~$beta$ are nodes
  573. that continue the search. This process continues until we reach a
  574. terminal node, which says `congratulations, you're done, |w|~is in
  575. triangle such-and-such'. The terminal node points to one of the three
  576. arcs bounding that triangle. If a vertex of the triangle is~$infty$,
  577. the terminal node points to the arc whose |vert| pointer is~|NULL|.
  578. @<Type...@>=
  579. typedef struct n_struct {
  580.   Vertex *u; /* first vertex, or |NULL| if this is a terminal node */
  581.   Vertex *v; /* second vertex, or pointer to the triangle
  582.                 corresponding to a terminal node */
  583.   struct n_struct *l; /* go here if |w| lies to the left of $uv$ */
  584.   struct n_struct *r; /* go here if |w| lies to the right of $uv$ */
  585. } node;
  586. @ The search tree just described is actually a dag (a directed acyclic
  587. graph), because it has overlapping subtrees. As the algorithm proceeds,
  588. the dag gets bigger and bigger, since the number of triangles keeps
  589. growing. Instructions are never deleted; we just extend the dag by
  590. substituting new branches for nodes that once were terminal.
  591. The expected number of nodes in this dag is $O(n)$ when there are $n$~vertices,
  592. if we input the vertices in random order. But it can be as high as order~$n^2$
  593. in the worst case. So our program will allocate blocks of nodes dynamically
  594. instead of assuming a maximum size.
  595. @d nodes_per_block 127 /* on most computers we want it $equiv 15$ (mod 16) */
  596. @d new_node(x)
  597.   if (next_node==max_node) {
  598.     x=gb_typed_alloc(nodes_per_block,node,working_storage);
  599.     if (x==NULL) {
  600.       gb_free(working_storage); /* release |delaunay|'s auxiliary memory */
  601.       return; /* |gb_trouble_code| is nonzero */
  602.     }
  603.     next_node=x+1; max_node=x+nodes_per_block;
  604.   }@+else x=next_node++;
  605. @#
  606. @d terminal_node(x,p) {@+new_node(x); /* allocate a new node */
  607.    x->v=(Vertex*)(p); /* make it point to a given arc from the triangle */
  608. }  /* note that |x->u==NULL|, representing a terminal node */
  609. @<Local variables for |delaunay|@>=
  610. node *next_node; /* the first yet-unused node slot
  611.    in the current block of nodes */
  612. node *max_node; /* address of nonexistent node following the current
  613.    block of nodes */
  614. node root_node; /* start here to locate a vertex in its triangle */
  615. Area working_storage; /* where |delaunay| builds its triangulation */
  616. @ The algorithm begins with a trivial triangulation that contains
  617. only the first two vertices, together with two ``triangles'' extending
  618. to infinity at their left and right.
  619. @<Initialize the data structures@>=
  620. next_node=max_node=NULL;
  621. init_area(working_storage);
  622. @<Initialize the array of arcs@>;
  623. u=g->vertices;
  624. v=u+1;
  625. @<Make two ``triangles'' for |u|, |v|, and $infty$@>;
  626. @ We'll need a bunch of local variables to do elementary operations on
  627. data structures.
  628. @<Local variables for |delaunay|@>=
  629. Vertex *p, *q, *r, *s, *t, *tp, *tpp, *u, *v;
  630. arc *a,*aa,*b,*c,*d, *e;
  631. node *x,*y,*yp,*ypp;
  632. @ @<Make two ``triangles'' for |u|, |v|, and $infty$@>=
  633. root_node.u=u; root_node.v=v;
  634. a=next_arc;
  635. terminal_node(x,a+1);
  636. root_node.l=x;
  637. a->vert=v;@+a->next=a+1;@+a->inst=x;
  638. (a+1)->next=a+2;@+(a+1)->inst=x;
  639.  /* |(a+1)->vert=NULL|, representing $infty$ */
  640. (a+2)->vert=u;@+(a+2)->next=a;@+(a+2)->inst=x;
  641. mate(a,b);
  642. terminal_node(x,b-2);
  643. root_node.r=x;
  644. b->vert=u;@+b->next=b-2;@+b->inst=x;
  645. (b-2)->next=b-1;@+(b-2)->inst=x;
  646.  /* |(b-2)->vert=NULL|, representing $infty$ */
  647. (b-1)->vert=v;@+(b-1)->next=b;@+(b-1)->inst=x;
  648. next_arc+=3;
  649. @*Delaunay updating.
  650. The main loop of the algorithm updates the data structure incrementally
  651. by adding one new vertex at a time. The new vertex will always be connected
  652. by an edge (i.e., by two arcs) to each of the vertices of the triangle that
  653. previously enclosed it. It might also deserve to be connected to other
  654. nearby vertices.
  655. @<Find the Delaunay triangulation...@>=
  656. if (g->n<2) return; /* no edges unless there are at least 2 vertices */
  657. @<Initialize the data structures@>;
  658. for (p=g->vertices+2;p<g->vertices+g->n;p++) {
  659.   @<Find an arc |a| on the boundary of the triangle containing |p|@>;
  660.   @<Divide the triangle left of |a| into three triangles surrounding |p|@>;
  661.   @<Explore the triangles surrounding |p|, ``flipping'' their neighbors
  662.     until all triangles that should touch |p| are found@>;
  663. }
  664. @ We have set up the branch nodes so that they solve the triangle location
  665. problem.
  666. @<Find an arc |a| on the boundary of the triangle containing |p|@>=
  667. x=&root_node;
  668. do@+{
  669.   if (ccw(x->u,x->v,p))
  670.     x = x->l;
  671.   else x = x->r;
  672. }@+while (x->u);
  673. a = (arc*) x->v; /* terminal node points to the arc we want */
  674. @ Subdividing a triangle is an easy exercise in data structure manipulation,
  675. except that we must do something special when one of the vertices is
  676. infinite. Let's look carefully at what needs to be done.
  677. Suppose the triangle containing |p| has the vertices |q|, |r|, and |s|
  678. in counterclockwise order. Let |x| be the terminal node that points to
  679. the triangle~$Delta qrs$. We want to change |x| so that we will be
  680. able to locate a future point of $Delta qrs$ within either $Delta pqr$,
  681. $Delta prs$, or $Delta psq$.
  682. If |q|, |r|, and |s| are finite, we will change |x| and add five new nodes
  683. as follows:
  684. $$vbox{halign{hfil#:enspace&#hfilcr
  685. $x$&if left of $rp$, go to $x''$, else go to $x'$;cr
  686. $x'$&if left of $sp$, go to $y$, else go to $y'$;cr
  687. $x''$&if left of $qp$, go to $y'$, else go to $y''$;cr
  688. $y$&you're in $Delta prs$;cr
  689. $y'$&you're in $Delta psq$;cr
  690. $y''$&you're in $Delta pqr$.cr}}$$
  691. But if, say, $q=infty$, such instructions make no sense,
  692. because there are lines in all directions that run from $infty$ to any point.
  693. In such a case we use ``wedges'' instead of triangles, as explained below.
  694. At the beginning of the following code, we have |x==a->inst|.
  695. @<Divide the triangle left of |a| into three triangles surrounding |p|@>=
  696. b=a->next;@+c=b->next;
  697. q=a->vert;@+r=b->vert;@+s=c->vert;
  698. @<Create new terminal nodes |y|, |yp|, |ypp|, and new arcs pointing to them@>;
  699. if (q==NULL) @<Compile instructions to update convex hull@>
  700. else {@+register node *xp;
  701.   x->u=r;@+x->v=p;
  702.   new_node(xp);
  703.   xp->u=q;@+xp->v=p;@+xp->l=yp;@+xp->r=ypp; /* instruction $x''$ above */
  704.   x->l=xp;
  705.   new_node(xp);
  706.   xp->u=s;@+xp->v=p;@+xp->l=y;@+xp->r=yp; /* instruction $x'$ above */
  707.   x->r=xp;
  708. }
  709. @ The only subtle point here is that |q=a->vert| might be |NULL|. A terminal
  710. node must point to the proper arc of an infinite triangle.
  711. @<Create new terminal nodes |y|, |yp|, |ypp|, and new arcs pointing to them@>=
  712. terminal_node(yp,a);@+terminal_node(ypp,next_arc);@+terminal_node(y,c);
  713. c->inst=y;@+a->inst=yp;@+b->inst=ypp;
  714. mate(next_arc,e);
  715. a->next=e;@+b->next=e-1;@+c->next=e-2;
  716. next_arc->vert=q;@+next_arc->next=b;@+next_arc->inst=ypp;
  717. (next_arc+1)->vert=r;@+(next_arc+1)->next=c;@+(next_arc+1)->inst=y;
  718. (next_arc+2)->vert=s;@+(next_arc+2)->next=a;@+(next_arc+2)->inst=yp;
  719. e->vert=(e-1)->vert=(e-2)->vert=p;
  720. e->next=next_arc+2;@+(e-1)->next=next_arc;@+(e-2)->next=next_arc+1;
  721. e->inst=yp;@+(e-1)->inst=ypp;@+(e-2)->inst=y;
  722. next_arc += 3;
  723. @ Outside of the current convex hull, we have ``wedges'' instead of
  724. triangles. Wedges are exterior angles whose points lie outside an
  725. edge $rs$ of the convex hull, but not outside the next edge on the other
  726. side of point |r|. When a new point lies in such a wedge, we have to
  727. see if it also lies outside the edges $st$, $tu$, etc., in the
  728. clockwise direction, in which case the convex hull loses points
  729. $s$, $t$, etc., and we must update the new wedges accordingly.
  730. This was the hardest part of the program to prove correct; a complete
  731. proof can be found in {sl Axioms and Hulls}.
  732. @<Compile...@>=
  733. {@+register node *xp;
  734.   x->u=r;@+x->v=p;@+x->l=ypp;
  735.   new_node(xp);
  736.   xp->u=s;@+xp->v=p;@+xp->l=y;@+xp->r=yp;
  737.   x->r=xp;
  738.   mate(a,aa);@+d=aa->next;@+t=d->vert;
  739.   while (t!=r && (ccw(p,s,t))) {@+register node *xpp;
  740.     terminal_node(xpp,d);
  741.     xp->r=d->inst;
  742.     xp=d->inst;
  743.     xp->u=t;@+xp->v=p;@+xp->l=xpp;@+xp->r=yp;
  744.     flip(a,aa,d,s,NULL,t,p,xpp,yp);
  745.     a=aa->next;@+mate(a,aa);@+d=aa->next;
  746.     s=t;@+t=d->vert;
  747.     yp->v=(Vertex*)a;
  748.   }
  749.   terminal_node(xp,d->next);
  750.   x=d->inst;@+x->u=s;@+x->v=p;@+x->l=xp;@+x->r=yp;
  751.   d->inst=xp;@+d->next->inst=xp;@+d->next->next->inst=xp;
  752.   r=s; /* this value of |r| shortens the exploration step that follows */
  753. }
  754. @ The updating process finishes by walking around the triangles
  755. that surround |p|, making sure that none of them are adjacent to
  756. triangles containing |p| in their circumcircle. (Such triangles are
  757. no longer in the Delaunay triangulation, by definition.)
  758. @<Explore...@>=
  759. while(1) {
  760.   mate(c,d);@+e=d->next;
  761.   t=d->vert;@+tp=c->vert;@+tpp=e->vert;
  762.   if (tpp && incircle(tpp,tp,t,p)) { /* triangle $tt''t'$ no longer Delaunay */
  763.     register node *xp, *xpp;
  764.     terminal_node(xp,e);
  765.     terminal_node(xpp,d);
  766.     x=c->inst;@+x->u=tpp;@+x->v=p;@+x->l=xp;@+x->r=xpp;
  767.     x=d->inst;@+x->u=tpp;@+x->v=p;@+x->l=xp;@+x->r=xpp;
  768.     flip(c,d,e,t,tp,tpp,p,xp,xpp);
  769.     c=e;
  770.   }
  771.   else if (tp==r) break;
  772.   else {
  773.     mate(c->next,aa);
  774.     c=aa->next;
  775.   }
  776. }
  777. @ Here |d| is the mate of |c|, |e=d->next|, |t=d->vert|, |tp=c->vert|,
  778. and |tpp=e->vert|. The triangles $Delta tt'p$ and $Delta t'tt''$ to the
  779. left and right of arc~|c| are being replaced in the current triangulation
  780. by $Delta ptt''$ and $Delta t''t'p$, corresponding to terminal nodes
  781. |xp| and |xpp|. (The values of |t| and |tp| are not actually used, so
  782. some optimization is possible.)
  783. @<Other...@>=
  784. void flip(c,d,e,t,tp,tpp,p,xp,xpp)
  785.   arc *c,*d,*e;
  786.   Vertex *t,*tp,*tpp,*p;
  787.   node *xp,*xpp;
  788. {@+register arc *ep=e->next, *cp=c->next, *cpp=cp->next;
  789.   e->next=c;@+c->next=cpp;@+cpp->next=e;
  790.   e->inst=c->inst=cpp->inst=xp;
  791.   c->vert=p;
  792.   d->next=ep;@+ep->next=cp;@+cp->next=d;
  793.   d->inst=ep->inst=cp->inst=xpp;
  794.   d->vert=tpp;
  795. }
  796. @*Use of mileage data. The |delaunay| routine is now complete, and the
  797. only missing piece of code is the promised routine that generates
  798. planar graphs based on data from the real world.
  799. The subroutine call {advancethinmuskip 0mu plus 2mu
  800. |plane_miles(n,north_weight,west_weight,pop_weight, extend,prob,seed)|}
  801. will construct a planar graph with min$(128,n)$ vertices, where the
  802. vertices are exactly the same as the cities produced by the subroutine call
  803. |miles(n,north_weight,west_weight, pop_weight,0,0,seed)|. (As
  804. explained in module {sc GB_,MILES}, the weight parameters |north_weight|,
  805. |west_weight|, and |pop_weight| are used to rank the cities by
  806. location and/or population.)  The edges of the new graph are obtained
  807. by first constructing the Delaunay triangulation of those cities,
  808. based on a simple projection onto the plane using their latitude and
  809. longitude, then discarding each Delaunay edge with probability
  810. |prob/65536|. The length of each surviving edge is the same as the
  811. mileage between cities that would appear in the complete graph
  812. produced by |miles|.
  813. If |extend!=0|, an additional vertex representing $infty$ is also
  814. included. The Delaunay triangulation includes edges of length |INFTY|
  815. connecting this vertex with all cities on the convex hull; these edges,
  816. like the others, are subject to being discarded with probability |prob/65536|.
  817. (See the description of |plane| for further comments about using
  818. |prob| to control the sparseness of the graph.)
  819. The weight parameters must satisfy
  820. $$ vert|north_weight|vertle100{,}000,quad
  821.    vert|west_weight|vertle100{,}000,quad
  822.    vert|pop_weight|vertle100.$$
  823. Vertices of the graph will appear in order of decreasing weight.
  824. The |seed| parameter defines the pseudo-random numbers used wherever
  825. a ``random'' choice between equal-weight vertices needs to be made,
  826. or when deciding whether to discard a Delaunay edge.
  827. @<The |plane_miles| routine@>=
  828. Graph *plane_miles(n,north_weight,west_weight,pop_weight,extend,prob,seed)
  829.   unsigned long n; /* number of vertices desired */
  830.   long north_weight; /* coefficient of latitude in the weight function */
  831.   long west_weight; /* coefficient of longitude in the weight function */
  832.   long pop_weight; /* coefficient of population in the weight function */
  833.   unsigned long extend; /* should a point at infinity be included? */
  834.   unsigned long prob; /* probability of rejecting a Delaunay edge */
  835.   long seed; /* random number seed */
  836. {@+Graph *new_graph; /* the graph constructed by |plane_miles| */
  837.   @<Use |miles| to set up the vertices of a graph@>;
  838.   @<Compute the Delaunay triangulation and
  839.     run through the Delaunay edges; reject them with probability
  840.     |prob/65536|, otherwise append them with the road length in miles@>;
  841.   if (gb_trouble_code) {
  842.     gb_recycle(new_graph);
  843.     panic(alloc_fault); /* oops, we ran out of memory somewhere back there */
  844.   }
  845.   gb_free(new_graph->aux_data); /* recycle special memory used by |miles| */
  846.   if (extend) new_graph->n++; /* make the ``infinite'' vertex legitimate */
  847.   return new_graph;
  848. }
  849. @ By setting the |max_distance| parameter to~1, we cause |miles|
  850. to produce a graph having the desired vertices but no edges.
  851. The vertices of this graph will have appropriate coordinate fields
  852. |x_coord|, |y_coord|, and~|z_coord|.
  853. @<Use |miles|...@>=
  854. if (extend) extra_n++; /* allocate one more vertex than usual */
  855. if (n==0 || n>MAX_N) n=MAX_N; /* compute true number of vertices */
  856. new_graph=miles(n,north_weight,west_weight,pop_weight,1L,0L,seed);
  857. if (new_graph==NULL) return NULL; /* |panic_code| has been set by |miles| */
  858. sprintf(new_graph->id,"plane_miles(%lu,%ld,%ld,%ld,%lu,%lu,%ld)",
  859.   n,north_weight,west_weight,pop_weight,extend,prob,seed);
  860. if (extend) extra_n--; /* restore |extra_n| to its previous value */
  861. @ @<Compute the Delaunay triangulation and
  862.     run through the Delaunay edges; reject them with probability
  863.     |prob/65536|, otherwise append them with the road length in miles@>=
  864. gprob=prob;
  865. if (extend) {
  866.   inf_vertex=new_graph->vertices+new_graph->n;
  867.   inf_vertex->name=gb_save_string("INF");
  868.   inf_vertex->x_coord=inf_vertex->y_coord=inf_vertex->z_coord= -1;
  869. }@+else inf_vertex=NULL;
  870. delaunay(new_graph,new_mile_edge);
  871. @ The mileages will all have been negated by |miles|, so we make them
  872. positive again.
  873. @<Other...@>=
  874. void new_mile_edge(u,v)
  875.   Vertex *u,*v;
  876. {
  877.   if ((gb_next_rand()>>15)>=gprob) {
  878.     if (u) {
  879.       if (v) gb_new_edge(u,v,-miles_distance(u,v));
  880.       else if (inf_vertex) gb_new_edge(u,inf_vertex,INFTY);
  881.     }@+else if (inf_vertex) gb_new_edge(inf_vertex,v,INFTY);
  882.   }
  883. }
  884. @* Index. As usual, we close with an index that
  885. shows where the identifiers of \{gb_plane} are defined and used.