1 /* $Id$Revision: */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 #define STANDALONE
15 #include "SparseMatrix.h"
16 #include "general.h"
17 #include "QuadTree.h"
18 #include "string.h"
19 /* #include "types.h" */
20 #include <cgraph.h>
21 #include "make_map.h"
22 /* #include "ps.h" */
23 #include "stress_model.h"
24 #include "country_graph_coloring.h"
25 #include "colorutil.h"
26 #include "delaunay.h"
27 
28 #ifdef SINGLE
29 #define REAL float
30 #else /* not SINGLE */
31 #define REAL double
32 #endif /* not SINGLE */
33 /* #include "triangle.h" */
34 
35 #include "lab.h"
36 #include "node_distinct_coloring.h"
37 
map_palette_optimal_coloring(char * color_scheme,char * lightness,SparseMatrix A0,real accuracy,int seed,float ** rgb_r,float ** rgb_g,float ** rgb_b)38 void map_palette_optimal_coloring(char *color_scheme, char *lightness, SparseMatrix A0, real accuracy, int seed,
39 				  float **rgb_r, float **rgb_g, float **rgb_b){
40   /*
41     for a graph A, get a distinctive color of its nodes so that the color distanmce among all nodes are maximized. Here
42     color distance on a node is defined as the minimum of color differences between a node and its neighbors.
43     accuracy is the threshold given so that when finding the coloring for each node, the optimal is
44     with in "accuracy" of the true global optimal.
45     color_scheme: rgb, gray, lab, or one of the color palettes in color_palettes.h, or a list of hex rgb colors separaterd by comma like "#ff0000,#00ff00"
46     lightness: of the form 0,70, specifying the range of lightness of LAB color. Ignored if scheme is not COLOR_LAB.
47     .          if NULL, 0,70 is assumed
48     A: the graph of n nodes
49     accuracy: how accurate to find the optimal
50     cdim: dimension of the color space
51     seed: random_seed. If negative, consider -seed as the number of random start iterations
52     rgb_r, rgb_g, rgb_b: float array of length A->m + 1, which contains color for each country. 1-based
53   */
54 
55   /*color: On input an array of size n*cdim, if NULL, will be allocated. On exit the final color assignment for node i is [cdim*i,cdim*(i+1)), in RGB (between 0 to 1)
56     color_diff: the minuimum color difference across all edges
57     color_diff_sum: the sum of min color dfference across all nodes
58   */
59   real *colors = NULL, color_diff, color_diff_sum;
60   int flag;
61   int n = A0->m, i, cdim;
62 
63   SparseMatrix A;
64   int weightedQ = TRUE;
65   int iter_max = 100;
66 
67   {real *dist = NULL;
68     A = SparseMatrix_symmetrize(A0, FALSE);
69     SparseMatrix_distance_matrix(A, 0, &dist);
70     SparseMatrix_delete(A);
71     A = SparseMatrix_from_dense(n, n, dist);
72     FREE(dist);
73     A = SparseMatrix_remove_diagonal(A);
74     SparseMatrix_export(stdout, A);
75   }
76 
77   //  A = SparseMatrix_multiply(A0, A0);
78   node_distinct_coloring(color_scheme, lightness, weightedQ, A, accuracy, iter_max, seed, &cdim, &colors, &color_diff, &color_diff_sum, &flag);
79 
80   if (A != A0){
81     SparseMatrix_delete(A);
82   }
83   *rgb_r = MALLOC(sizeof(float)*(n+1));
84   *rgb_g = MALLOC(sizeof(float)*(n+1));
85   *rgb_b = MALLOC(sizeof(float)*(n+1));
86 
87   for (i = 0; i < n; i++){
88     (*rgb_r)[i+1] = (float) colors[cdim*i];
89     (*rgb_g)[i+1] = (float) colors[cdim*i + 1];
90     (*rgb_b)[i+1] = (float) colors[cdim*i + 2];
91   }
92   FREE(colors);
93 
94 }
95 
map_optimal_coloring(int seed,SparseMatrix A,float * rgb_r,float * rgb_g,float * rgb_b)96 void map_optimal_coloring(int seed, SparseMatrix A, float *rgb_r,  float *rgb_g, float *rgb_b){
97   int *p = NULL;
98   float *u = NULL;
99   int n = A->m;
100   int i;
101   real norm1;
102 
103   country_graph_coloring(seed, A, &p, &norm1);
104 
105   rgb_r++; rgb_b++; rgb_g++;/* seems necessary, but need to better think about cases when clusters are not contigous */
106   vector_float_take(n, rgb_r, n, p, &u);
107   for (i = 0; i < n; i++) rgb_r[i] = u[i];
108   vector_float_take(n, rgb_g, n, p, &u);
109   for (i = 0; i < n; i++) rgb_g[i] = u[i];
110   vector_float_take(n, rgb_b, n, p, &u);
111   for (i = 0; i < n; i++) rgb_b[i] = u[i];
112   FREE(u);
113 
114 }
115 
get_poly_id(int ip,SparseMatrix point_poly_map)116 static int get_poly_id(int ip, SparseMatrix point_poly_map){
117   return point_poly_map->ja[point_poly_map->ia[ip]];
118 }
119 
improve_contiguity(int n,int dim,int * grouping,SparseMatrix poly_point_map,real * x,SparseMatrix graph,real * label_sizes)120 void improve_contiguity(int n, int dim, int *grouping, SparseMatrix poly_point_map, real *x, SparseMatrix graph, real *label_sizes){
121  /*
122      grouping: which group each of the vertex belongs to
123      poly_point_map: a matrix of dimension npolys x (n + nrandom), poly_point_map[i,j] != 0 if polygon i contains the point j.
124      .  If j < n, it is the original point, otherwise it is artificial point (forming the rectangle around a label) or random points.
125   */
126   int i, j, *ia, *ja, u, v;
127   //int *ib, *jb;
128   real *a;
129   SparseMatrix point_poly_map, D;
130   real dist;
131   int nbad = 0, flag;
132   int maxit = 10;
133   real tol = 0.001;
134 
135   D = SparseMatrix_get_real_adjacency_matrix_symmetrized(graph);
136 
137   assert(graph->m == n);
138   ia = D->ia; ja = D->ja;
139   a = (real*) D->a;
140 
141   /* point_poly_map: each row i has only 1 entry at column j, which says that point i is in polygon j */
142   point_poly_map = SparseMatrix_transpose(poly_point_map);
143 
144   //  ib = point_poly_map->ia;
145   //  jb = point_poly_map->ja;
146 
147 
148   for (i = 0; i < n; i++){
149     u = i;
150     for (j = ia[i]; j < ia[i+1]; j++){
151       v = ja[j];
152       dist = distance_cropped(x, dim, u, v);
153       /*
154 	if ((grouping[u] != grouping[v]) || (get_poly_id(u, point_poly_map) == get_poly_id(v, point_poly_map))){
155 	a[j] = 1.1*dist;
156 	} else {
157 	nbad++;
158 	a[j] = 0.9*dist;
159 	}
160       */
161       if (grouping[u] != grouping[v]){
162 	a[j] = 1.1*dist;
163       }	else if (get_poly_id(u, point_poly_map) == get_poly_id(v, point_poly_map)){
164 	a[j] = dist;
165       } else {
166 	nbad++;
167 	a[j] = 0.9*dist;
168       }
169 
170     }
171   }
172 
173   if (Verbose) fprintf(stderr,"ratio (edges among discontiguous regions vs total edges)=%f\n",((real) nbad)/ia[n]);
174   stress_model(dim, D, D, &x, FALSE, maxit, tol, &flag);
175 
176   assert(!flag);
177 
178   SparseMatrix_delete(D);
179   SparseMatrix_delete(point_poly_map);
180 }
181 
182 /*
183 struct color_card{
184   int ncolor;
185   real *rgb;
186 };
187 
188 color_card color_card_new(int ncolor, real *rgb){
189   color_card c;
190 
191   c->ncolor = ncolor;
192   c->rgb = MALLOC(sizeof(real)*ncolor);
193   for (i = 0; i < ncolor*3; i++){
194     c->rgb[i] = rgb[i];
195   }
196   return c;
197 }
198 
199 void color_card_delete(color_card c){
200   FREE(c->rgb);
201 }
202 
203 color_card_blend(color_card c, real x){
204   real c1[3], c2[3];
205   int ista, isto;
206   if (x > 1) x = 1;
207   if (x < 0) x = 0;
208   ista = x*(ncolor-1);
209 
210 }
211 
212 */
213 
214 struct Triangle {
215   int vertices[3];/* 3 points */
216   real center[2]; /* center of the triangle */
217 };
218 
normal(real v[],real normal[])219 static void normal(real v[], real normal[]){
220   if (v[0] == 0){
221     normal[0] = 1; normal[1] = 0;
222   } else {
223     normal[0] = -v[1];
224     normal[1] = v[0];
225   }
226   return;
227 }
228 
229 
230 
triangle_center(real x[],real y[],real z[],real c[])231 static void triangle_center(real x[], real y[], real z[], real c[]){
232   /* find the "center" c, which is the intersection of the 3 vectors that are normal to each
233      of the edges respectively, and which passes through the center of the edges respectively
234      center[{x_, y_, z_}] := Module[
235      {xy = 0.5*(x + y), yz = 0.5*(y + z), zx = 0.5*(z + x), nxy, nyz,
236      beta, cen},
237      nxy = normal[y - x];
238      nyz = normal[y - z];
239      beta = (y-x).(xy - yz)/(nyz.(y-x));
240      cen = yz + beta*nyz;
241      Graphics[{Line[{x, y, z, x}], Red, Point[cen], Line[{cen, xy}],
242      Line[{cen, yz}], Green, Line[{cen, zx}]}]
243 
244      ]
245  */
246   real xy[2], yz[2], nxy[2], nyz[2], ymx[2], ymz[2], beta, bot;
247   int i;
248 
249   for (i = 0; i < 2; i++) ymx[i] = y[i] - x[i];
250   for (i = 0; i < 2; i++) ymz[i] = y[i] - z[i];
251   for (i = 0; i < 2; i++) xy[i] = 0.5*(x[i] + y[i]);
252   for (i = 0; i < 2; i++) yz[i] = 0.5*(y[i] + z[i]);
253 
254 
255   normal(ymx, nxy);
256   normal(ymz, nyz);
257   bot = nyz[0]*(x[0]-y[0])+nyz[1]*(x[1]-y[1]);
258   if (bot == 0){/* xy and yz are parallel */
259     c[0] = xy[0]; c[1] = xy[1];
260     return;
261   }
262   beta = ((x[0] - y[0])*(xy[0] - yz[0])+(x[1] - y[1])*(xy[1] - yz[1]))/bot;
263   c[0] = yz[0] + beta*nyz[0];
264   c[1] = yz[1] + beta*nyz[1];
265   return;
266 
267 }
268 
matrix_add_entry(SparseMatrix A,int i,int j,int val)269 static SparseMatrix matrix_add_entry(SparseMatrix A, int i, int j, int val){
270   int i1 = i, j1 = j;
271   if (i < j) {
272     i1 = j; j1 = i;
273   }
274   A = SparseMatrix_coordinate_form_add_entries(A, 1, &j1, &i1, &val);
275   return SparseMatrix_coordinate_form_add_entries(A, 1, &i1, &j1, &val);
276 }
277 
278 
279 
plot_polys(int use_line,SparseMatrix polys,real * x_poly,int * polys_groups,float * r,float * g,float * b)280 void plot_polys(int use_line, SparseMatrix polys, real *x_poly, int *polys_groups, float *r, float *g, float *b){
281   int i, j, *ia = polys->ia, *ja = polys->ja, *a = (int*) polys->a, npolys = polys->m, nverts = polys->n, ipoly = -1, max_grp,
282     min_grp;
283 
284 
285   min_grp = max_grp = polys_groups[0];
286   for (i = 0; i < npolys; i++) {
287     max_grp = MAX(polys_groups[i], max_grp);
288     min_grp = MIN(polys_groups[i], min_grp);
289   }
290   if (max_grp == min_grp) max_grp++;
291   if (Verbose) fprintf(stderr,"npolys = %d\n",npolys);
292   printf("Graphics[{");
293   for (i = 0; i < npolys; i++){
294     for (j = ia[i]; j < ia[i+1]; j++){
295       assert(ja[j] < nverts && ja[j] >= 0);
296       if (a[j] != ipoly){/* the first poly, or a hole */
297 	ipoly = a[j];
298 	if (ipoly != a[0]) printf("}],");
299 	if (use_line){
300 	  printf("Black,");
301 	  printf("Line[{");
302 	} else {
303 	  /*printf("Hue[%f],",0.6*(polys_groups[i]/(real) (max_grp-min_grp)));*/
304 	  if (r && g && b){
305 	    printf("RGBColor[%f,%f,%f],",r[polys_groups[i]], g[polys_groups[i]], b[polys_groups[i]]);
306 	  } else {
307 	    printf("Hue[%f],",((polys_groups[i]-min_grp)/(real) (max_grp-min_grp)));
308 	  }
309 	  printf("Polygon[{");
310 	}
311 
312       } else {
313 	if (j > ia[i]) printf(",");
314       }
315       printf("{%f,%f}",x_poly[2*ja[j]],x_poly[2*ja[j]+1]);
316     }
317   }
318   printf("}]}]");
319 }
320 
321 #if 0
322 void ps_one_poly(psfile_t *f, int use_line, int border, int fill, int close, int is_river, int np, float *xp, float *yp){
323   if (use_line){
324     if (is_river){
325       /*river*/
326     } else {
327     }
328     ps_polygon(f, np, xp, yp, border, fill, close);
329   } else {
330     ps_polygon(f, np, xp, yp, border, fill, close);
331   }
332 }
333 
334 void plot_ps_polygons(psfile_t *f, int use_line, SparseMatrix polys, real *x_poly, int *polys_groups){
335   int i, j, *ia = polys->ia, *ja = polys->ja, *a = (int*) polys->a, npolys = polys->m, nverts = polys->n, ipoly,first;
336   int np = 0, maxlen = 0;
337   float *xp, *yp;
338   int border = 0, fill = -1, close = 1;
339   int is_river;
340 
341   for (i = 0; i < npolys; i++) maxlen = MAX(maxlen, ia[i+1]-ia[i]);
342 
343   xp = MALLOC(sizeof(float)*maxlen);
344   yp = MALLOC(sizeof(float)*maxlen);
345 
346   if (Verbose) fprintf(stderr,"npolys = %d\n",npolys);
347   first = ABS(a[0]); ipoly = first + 1;
348   for (i = 0; i < npolys; i++){
349     np = 0;
350     for (j = ia[i]; j < ia[i+1]; j++){
351       assert(ja[j] < nverts && ja[j] >= 0);
352       if (ABS(a[j]) != ipoly){/* the first poly, or a hole */
353 	ipoly = ABS(a[j]);
354 	is_river = (a[j] < 0);
355 	ps_one_poly(f, use_line, border, fill, close, is_river, np, xp, yp);
356 	np = 0;/* start a new polygon */
357 
358       }
359       xp[np] = x_poly[2*ja[j]]; yp[np++] = x_poly[2*ja[j]+1];
360     }
361     if (use_line) {
362       ps_one_poly(f, use_line, border, fill, close, is_river, np, xp, yp);
363     } else {
364       ps_one_poly(f, use_line, polys_groups[i], polys_groups[i], close, is_river, np, xp, yp);
365     }
366   }
367   FREE(xp);
368   FREE(yp);
369 
370 }
371 
372 static void plot_line(real *x, real *y){
373   printf("Line[{{%f,%f},{%f,%f}}]", x[0], x[1], y[0], y[1]);
374 }
375 static void plot_voronoi(int n, SparseMatrix A, struct Triangle *T){
376   int *val, i, j, nline = 0;
377   val = (int*) A->a;
378 
379   printf("Graphics[{");
380   for (i = 0; i < n; i++){
381     for (j = A->ia[i]; j < A->ia[i+1]; j++){
382       if (j < A->ia[n] - A->ia[0] - 1 && A->ja[j] == A->ja[j+1]){
383 	if (nline > 0) printf(",");
384 	nline++;
385 	plot_line((T)[val[j]].center, (T)[val[j+1]].center);
386 	j++;
387       }
388     }
389   }
390   printf("}]");
391 }
392 
393 
394 void plot_ps_labels(psfile_t *f, int n, int dim, real *x, char **labels, real *width, float *fsz){
395 
396   int i;
397 
398   for (i = 0; i < n; i++){
399     if (fsz){
400       ps_font(f, NULL, 3*fsz[i]); /* name can be NULL if the current font name is to be used */
401     } else {
402       ps_font(f, NULL, -7); /* name can be NULL if the current font name is to be used */
403     }
404     ps_textc(f, x[i*dim], x[i*dim+1], labels[i], 0);
405   }
406 
407 }
408 
409 static void plot_ps_edges(psfile_t *f, SparseMatrix A, int dim, real *x){
410   int i, *ia, *ja, n, j;
411   float xx[2], yy[2];
412   n = A->m;
413   ia = A->ia;
414   ja = A->ja;
415   for (i = 0; i < n; i++){
416     for (j = ia[i]; j < ia[i+1]; j++){
417       if (ja[j] == i) continue;
418       xx[0] = x[i*dim];
419       xx[1] = x[ja[j]*dim];
420       yy[0] = x[i*dim+1];
421       yy[1] = x[ja[j]*dim+1];
422       ps_polygon(f, 2, xx, yy, TRUE, -1, FALSE);
423     }
424   }
425 }
426 static void plot_triangles(int n, SparseMatrix A, int dim, real *x){
427   int i, j, ii, jj;
428   printf("Graphics[{Green");
429   for (i = 0; i < n; i++) {
430     for (j = A->ia[i]; j < A->ia[i+1]; j++){
431       ii = i;
432       jj = A->ja[j];
433       if (j < A->ia[n] - A->ia[0] - 1 && A->ja[j] == A->ja[j+1]) j++;
434       printf(",Line[{{%f,%f},{%f,%f}}]", x[ii*dim], x[ii*dim+1], x[jj*dim], x[jj*dim+1]);
435     }
436   }
437   printf("}]");
438 }
439 
440 static void poly_bbox(SparseMatrix polys, real *x_poly, real *bbox){
441   /* get the bounding box of a polygon.
442      bbox[0]: xmin
443      bbox[1]: xmax
444      bbox[2]: ymin
445      bbox[3]: ymax
446   */
447   int i, j, *ia = polys->ia, *ja = polys->ja;
448   int npolys = polys->m;
449 
450   bbox[0] = bbox[1] = x_poly[2*ja[ia[0]]];
451   bbox[2] = bbox[3] = x_poly[2*ja[ia[0]] + 1];
452 
453   for (i = 0; i < npolys; i++){
454     for (j = ia[i]; j < ia[i+1]; j++){
455       bbox[0] = MIN(bbox[0], x_poly[2*ja[j]]);
456       bbox[1] = MAX(bbox[1], x_poly[2*ja[j]]);
457       bbox[2] = MIN(bbox[2], x_poly[2*ja[j]+1]);
458       bbox[3] = MAX(bbox[3], x_poly[2*ja[j]+1]);
459     }
460   }
461 }
462 
463 void plot_ps_map(int n, int dim, real *x, SparseMatrix polys, SparseMatrix poly_lines, real line_width, real *x_poly, int *polys_groups, char **labels, real *width,
464 		 float *fsz, float *r, float *g, float *b, char *plot_label, real *bg_color, SparseMatrix A){
465 
466   psfile_t *f;
467   int i;
468   real xmin[2], xmax[2], w = 7, h = 10;
469   real asp;
470   real bbox[4];
471   float pad = 20, label_fsz = 10;
472   int MAX_GRP;
473   int IBG;/*back ground color number */
474   int plot_polyQ = TRUE;
475 
476   if (!r || !g || !b) plot_polyQ = FALSE;
477 
478   xmin[0] = xmax[0] = x[0];
479   xmin[1] = xmax[1] = x[1];
480 
481   for (i = 0; i < n; i++){
482     xmin[0] = MIN(xmin[0], x[i*dim] - width[i*dim]);
483     xmax[0] = MAX(xmax[0], x[i*dim] + width[i*dim]);
484     xmin[1] = MIN(xmin[1], x[i*dim + 1] - width[i*dim+1]);
485     xmax[1] = MAX(xmax[1], x[i*dim + 1] + width[i*dim+1]);
486   }
487 
488   if (polys){
489     poly_bbox(polys, x_poly, bbox);
490     xmin[0] = MIN(xmin[0], bbox[0]);
491     xmax[0] = MAX(xmax[0], bbox[1]);
492     xmin[1] = MIN(xmin[1], bbox[2]);
493     xmax[1] = MAX(xmax[1], bbox[3]);
494   }
495 
496   if (poly_lines){
497     poly_bbox(poly_lines, x_poly, bbox);
498     xmin[0] = MIN(xmin[0], bbox[0]);
499     xmax[0] = MAX(xmax[0], bbox[1]);
500     xmin[1] = MIN(xmin[1], bbox[2]);
501     xmax[1] = MAX(xmax[1], bbox[3]);
502   }
503 
504   pad = .08*MIN(xmax[0] - xmin[0], xmax[1] - xmin[1]);
505   label_fsz = pad/3;
506 
507   xmin[0] -= pad;
508   xmax[0] += pad;
509   xmin[1] -= pad;
510   xmax[1] += pad;
511 
512 
513  if ((xmax[1] - xmin[1]) < 0.001*(xmax[0] - xmin[0])){
514     asp = 0.001;
515   } else {
516     asp = (xmax[1] - xmin[1])/(xmax[0] - xmin[0]);
517   }
518   if (w*asp > h){
519     w = h/asp;
520   } else {
521     h = w*asp;
522   }
523   fprintf(stderr, "asp = %f, w = %f, h = %f\n",asp,w,h);
524 
525   /*  f = ps_create_autoscale("test.ps", "title", 7, 7, 0);*/
526   f = ps_create_autoscale(NULL, "title", w, h, 0);
527   /*f = ps_create_epsf(NULL, "title", xmin[0], xmin[1], xmax[0] - xmin[0], xmax[1] - xmin[1]);*/
528 
529   ps_line_width(f, 0.00001); // line width 1 point
530 
531   ps_font(f, NULL, 10); /* name can be NULL if the current font name is to be used */
532 
533   MAX_GRP = polys_groups[0];
534 
535   for (i = 0; i < polys->m; i++){
536     if (r && g && b) ps_define_color_rgb(f, polys_groups[i], r[polys_groups[i]], g[polys_groups[i]], b[polys_groups[i]]);
537     MAX_GRP = MAX(MAX_GRP, polys_groups[i]);
538     assert(polys_groups[i] < PS_MAX_COLORS && polys_groups[i] >= 0);
539   }
540 
541   /* set bg color */
542   IBG = MAX_GRP + 1;
543   assert(MAX_GRP + 1 < PS_MAX_COLORS);
544   if (bg_color) ps_define_color_rgb(f, IBG, bg_color[0], bg_color[1], bg_color[2]);
545 
546   ps_color_model(f, PS_COLOR_MODEL_PALETTE);
547   if (bg_color) ps_rect(f, (float) xmin[0], (float) xmin[1], xmax[0] - xmin[0], xmax[1] - xmin[1], -1, IBG);
548 
549 
550   /* labels */
551   ps_color_model(f, PS_COLOR_MODEL_RGB);
552   ps_font(f, NULL, label_fsz); /* name can be NULL if the current font name is to be used */
553   ps_textc(f, (float)(.5*(xmin[0] + xmax[0])), (float) xmin[1] + pad, plot_label, 0);
554 
555   ps_color_model(f, PS_COLOR_MODEL_PALETTE);
556 
557   /*polygons */
558   if (plot_polyQ) plot_ps_polygons(f, FALSE, polys, x_poly, polys_groups);
559 
560   ps_color_model(f, PS_COLOR_MODEL_RGB);
561   /* polylines*/
562   if (line_width >= 0){
563     ps_line_width(f, (float) line_width);
564     plot_ps_polygons(f, TRUE, poly_lines, x_poly, polys_groups);
565   }
566 
567   /* edges*/
568   if (A) plot_ps_edges(f, A, dim, x);
569 
570   if (labels) plot_ps_labels(f, n, dim, x, labels, width, fsz);
571 
572   ps_done(f);
573 
574 
575 }
576 
577 #endif
578 
579 
plot_dot_edges(FILE * f,SparseMatrix A,int dim,real * x)580 static void plot_dot_edges(FILE *f, SparseMatrix A, int dim, real *x){
581   int i, *ia, *ja, j;
582 
583 
584   int n = A->m;
585   ia = A->ia;
586   ja = A->ja;
587   for (i = 0; i < n; i++){
588     for (j = ia[i]; j < ia[i+1]; j++){
589       if (ja[j] == i) continue;
590       fprintf(f,"%d -- %d;\n",i,ja[j]);
591     }
592   }
593 }
594 #if 0
595 static void plot_processing_edges(FILE *f, SparseMatrix A, int dim, real *x){
596   int i, *ia, *ja, j;
597 
598   //fprintf(f,"stroke(.5);\n");
599   fprintf(f, "beginLines\n");
600   fprintf(f, "color(125,125,125)\n");
601   int n = A->m;
602   ia = A->ia;
603   ja = A->ja;
604   for (i = 0; i < n; i++){
605     for (j = ia[i]; j < ia[i+1]; j++){
606       if (ja[j] == i) continue;
607       //fprintf(f,"line(%f, %f, %f, %f);\n", x[i*dim], x[i*dim+1], x[ja[j]*dim], x[ja[j]*dim+1]);
608       fprintf(f,"%f %f %f %f\n", x[i*dim], x[i*dim+1], x[ja[j]*dim], x[ja[j]*dim+1]);
609     }
610   }
611   fprintf(f,"endLines\n");
612 }
613 #endif
614 
plot_dot_labels(FILE * f,int n,int dim,real * x,char ** labels,real * width,float * fsz)615 void plot_dot_labels(FILE *f, int n, int dim, real *x, char **labels, real *width, float *fsz){
616   int i;
617 
618   for (i = 0; i < n; i++){
619     if (fsz){
620       fprintf(f, "%d [label=\"%s\", pos=\"%lf,%lf\", fontsize=%f];\n",i, labels[i], x[i*dim], x[i*dim+1], fsz[i]);
621     } else {
622       fprintf(f, "%d [label=\"%s\", pos=\"%lf,%lf\"];\n",i, labels[i], x[i*dim], x[i*dim+1]);
623     }
624   }
625 
626 }
627 
628 #if 0
629 void plot_processing_labels(FILE *f, int n, int dim, real *x, char **labels, real *width, float *fsz){
630   int i;
631   //  fprintf(f, "PFont myFont; myFont = createFont(\"FFScala\",8); fill(0,0,0);\n");
632   for (i = 0; i < n; i++){
633     if (fsz){
634       //   fprintf(f, "textFont(myFont, %f); text(\"%s\", %f, %f);\n", fsz[i], labels[i], x[i*dim], x[i*dim+1]);
635       fprintf(f, "beginText\nfontSize(%f)\ntext(\"%s\")\nposition(%f, %f)\nendText\n", fsz[i], labels[i], x[i*dim], x[i*dim+1]);
636     } else {
637       fprintf(f, "beginText\ntext(\"%s\")\nposition(%f, %f)\nendText\n", labels[i], x[i*dim], x[i*dim+1]);
638     }
639   }
640 
641 }
642 #endif
643 
dot_polygon(char ** sbuff,int * len,int * len_max,int np,float * xp,float * yp,real line_width,int fill,int close,char * cstring)644 static void dot_polygon(char **sbuff, int *len, int *len_max, int np, float *xp, float *yp, real line_width,
645 			int fill, int close, char *cstring){
646   int i;
647   int ret = 0;
648   char buf[10000];
649   char swidth[10000];
650   int len_swidth;
651 
652   if (np > 0){
653     /* figure out the size needed */
654     if (fill >= 0){/* poly*/
655       ret += snprintf(buf, sizeof(buf), " c %d -%s C %d -%s P %d ",(int) strlen(cstring), cstring, (int) strlen(cstring), cstring, np);
656     } else {/* line*/
657       assert(line_width >= 0);
658       if (line_width > 0){
659 	sprintf(swidth,"%f",line_width);
660 	len_swidth = strlen(swidth);
661 	sprintf(swidth,"S %d -setlinewidth(%f)",len_swidth+14, line_width);
662 	ret += snprintf(buf, sizeof(buf), " c %d -%s %s L %d ",(int) strlen(cstring), cstring, swidth, np);
663       } else {
664 	ret += snprintf(buf, sizeof(buf), " c %d -%s L %d ",(int) strlen(cstring), cstring, np);
665       }
666     }
667     for (i = 0; i < np; i++){
668       ret += sprintf(buf, " %f %f",xp[i], yp[i]);
669     }
670 
671     if (*len + ret > *len_max - 1){
672       *len_max = *len_max + MAX(100, 0.2*(*len_max)) + ret;
673       *sbuff = REALLOC(*sbuff, *len_max);
674     }
675 
676     /* do the actual string */
677     if (fill >= 0){
678       ret = sprintf(&((*sbuff)[*len]), " c %d -%s C %d -%s P %d ",(int) strlen(cstring), cstring, (int) strlen(cstring), cstring, np);
679     } else {
680       if (line_width > 0){
681         sprintf(swidth,"%f",line_width);
682         len_swidth = strlen(swidth);
683         sprintf(swidth,"S %d -setlinewidth(%f)",len_swidth+14, line_width);
684 	ret = sprintf(&((*sbuff)[*len]), " c %d -%s %s L %d ",(int) strlen(cstring), cstring, swidth, np);
685       } else {
686 	ret = sprintf(&((*sbuff)[*len]), " c %d -%s L %d ",(int) strlen(cstring), cstring, np);
687       }
688     }
689     (*len) += ret;
690     for (i = 0; i < np; i++){
691       assert(*len < *len_max);
692       ret = sprintf(&((*sbuff)[*len]), " %f %f",xp[i], yp[i]);
693       (*len) += ret;
694     }
695 
696 
697   }
698 }
processing_polygon(FILE * f,int np,float * xp,float * yp,real line_width,int fill,int close,float rr,float gg,float bb)699 static void processing_polygon(FILE *f, int np, float *xp, float *yp, real line_width, int fill, int close,
700 			       float rr, float gg, float bb){
701   int i;
702 
703   if (np > 0){
704     if (fill >= 0){
705       // fprintf(f, "beginShape();\n noStroke(); fill(%f, %f, %f);\n", 255*rr, 255*gg, 255*bb);
706       fprintf(f, "beginPolygons\ncolor(%f, %f, %f)\n", 255*rr, 255*gg, 255*bb);
707     } else {
708       //fprintf(f, "beginShape();\n");
709       fprintf(f, "beginPolylines\n");
710       if (line_width > 0){
711 	fprintf(f, "strokeWeight(%f);\n", line_width);
712       }
713     }
714     for (i = 0; i < np; i++){
715       //fprintf(f, "vertex(%f, %f);\n",xp[i], yp[i]);
716       fprintf(f, "%f %f\n",xp[i], yp[i]);
717     }
718     //fprintf(f, "endShape(CLOSE);\n");
719     if (fill >= 0){
720       fprintf(f, "endPolygons\n");
721     } else {
722       fprintf(f, "endPolylines\n");
723     }
724 
725   }
726 }
727 
dot_one_poly(char ** sbuff,int * len,int * len_max,int use_line,real line_width,int fill,int close,int is_river,int np,float * xp,float * yp,char * cstring)728 void dot_one_poly(char **sbuff, int *len, int *len_max, int use_line, real line_width, int fill, int close, int is_river, int np, float *xp, float *yp, char *cstring){
729   if (use_line){
730     if (is_river){
731       /*river*/
732     } else {
733     }
734     dot_polygon(sbuff, len, len_max, np, xp, yp, line_width, fill, close, cstring);
735   } else {
736     dot_polygon(sbuff, len, len_max, np, xp, yp, line_width, fill, close, cstring);
737   }
738 }
739 
processing_one_poly(FILE * f,int use_line,real line_width,int fill,int close,int is_river,int np,float * xp,float * yp,float rr,float gg,float bb)740 void processing_one_poly(FILE *f, int use_line, real line_width, int fill, int close, int is_river, int np, float *xp, float *yp,
741 		      float rr, float gg, float bb){
742   if (use_line){
743     if (is_river){
744       /*river*/
745     } else {
746     }
747     processing_polygon(f, np, xp, yp, line_width, fill, close, rr, gg, bb);
748   } else {
749     processing_polygon(f, np, xp, yp, line_width, fill, close, rr, gg, bb);
750   }
751 }
752 
753 
plot_dot_polygons(char ** sbuff,int * len,int * len_max,real line_width,char * line_color,SparseMatrix polys,real * x_poly,int * polys_groups,float * r,float * g,float * b,char * opacity)754 void plot_dot_polygons(char **sbuff, int *len, int *len_max, real line_width, char *line_color, SparseMatrix polys, real *x_poly, int *polys_groups, float *r, float *g, float *b, char *opacity){
755   int i, j, *ia = polys->ia, *ja = polys->ja, *a = (int*) polys->a, npolys = polys->m, nverts = polys->n, ipoly,first;
756   int np = 0, maxlen = 0;
757   float *xp, *yp;
758   int fill = -1, close = 1;
759   int is_river = FALSE;
760   char cstring[] = "#aaaaaaff";
761   int use_line = (line_width >= 0);
762 
763   for (i = 0; i < npolys; i++) maxlen = MAX(maxlen, ia[i+1]-ia[i]);
764 
765   xp = MALLOC(sizeof(float)*maxlen);
766   yp = MALLOC(sizeof(float)*maxlen);
767 
768   if (Verbose) fprintf(stderr,"npolys = %d\n",npolys);
769   first = ABS(a[0]); ipoly = first + 1;
770   for (i = 0; i < npolys; i++){
771     np = 0;
772     for (j = ia[i]; j < ia[i+1]; j++){
773       assert(ja[j] < nverts && ja[j] >= 0);
774       if (ABS(a[j]) != ipoly){/* the first poly, or a hole */
775 	ipoly = ABS(a[j]);
776 	is_river = (a[j] < 0);
777 	if (r && g && b) {
778 	  rgb2hex(r[polys_groups[i]], g[polys_groups[i]], b[polys_groups[i]], cstring, opacity);
779 	}
780 	dot_one_poly(sbuff, len, len_max, use_line, line_width, fill, close, is_river, np, xp, yp, cstring);
781 	np = 0;/* start a new polygon */
782       }
783       xp[np] = x_poly[2*ja[j]]; yp[np++] = x_poly[2*ja[j]+1];
784     }
785     if (use_line) {
786       dot_one_poly(sbuff, len, len_max, use_line, line_width, fill, close, is_river, np, xp, yp, line_color);
787     } else {
788       /* why set fill to polys_groups[i]?*/
789       //dot_one_poly(sbuff, len, len_max, use_line, polys_groups[i], polys_groups[i], close, is_river, np, xp, yp, cstring);
790       dot_one_poly(sbuff, len, len_max, use_line, -1, 1, close, is_river, np, xp, yp, cstring);
791     }
792   }
793   FREE(xp);
794   FREE(yp);
795 
796 }
797 
plot_processing_polygons(FILE * f,real line_width,SparseMatrix polys,real * x_poly,int * polys_groups,float * r,float * g,float * b)798 void plot_processing_polygons(FILE *f, real line_width, SparseMatrix polys, real *x_poly, int *polys_groups, float *r, float *g, float *b){
799   int i, j, *ia = polys->ia, *ja = polys->ja, *a = (int*) polys->a, npolys = polys->m, nverts = polys->n, ipoly,first;
800   int np = 0, maxlen = 0;
801   float *xp, *yp;
802   int fill = -1, close = 1;
803   int is_river = FALSE;
804   int use_line = (line_width >= 0);
805   float rr = 0, gg = 0, bb = 0;
806 
807   for (i = 0; i < npolys; i++) maxlen = MAX(maxlen, ia[i+1]-ia[i]);
808 
809   xp = MALLOC(sizeof(float)*maxlen);
810   yp = MALLOC(sizeof(float)*maxlen);
811 
812   if (Verbose) fprintf(stderr,"npolys = %d\n",npolys);
813   first = ABS(a[0]); ipoly = first + 1;
814   for (i = 0; i < npolys; i++){
815     np = 0;
816     for (j = ia[i]; j < ia[i+1]; j++){
817       assert(ja[j] < nverts && ja[j] >= 0);
818       if (ABS(a[j]) != ipoly){/* the first poly, or a hole */
819 	ipoly = ABS(a[j]);
820 	is_river = (a[j] < 0);
821 	if (r && g && b) {
822 	  rr = r[polys_groups[i]]; gg = g[polys_groups[i]]; bb = b[polys_groups[i]];
823 	}
824 	  processing_one_poly(f, use_line, line_width, fill, close, is_river, np, xp, yp, rr, gg, bb);
825 	np = 0;/* start a new polygon */
826       }
827       xp[np] = x_poly[2*ja[j]]; yp[np++] = x_poly[2*ja[j]+1];
828     }
829     if (use_line) {
830       processing_one_poly(f, use_line, line_width, fill, close, is_river, np, xp, yp, rr, gg, bb);
831     } else {
832       /* why set fill to polys_groups[i]?*/
833       processing_one_poly(f,  use_line, -1, 1, close, is_river, np, xp, yp, rr, gg, bb);
834     }
835   }
836   FREE(xp);
837   FREE(yp);
838 
839 }
840 
841 
plot_dot_map(Agraph_t * gr,int n,int dim,real * x,SparseMatrix polys,SparseMatrix poly_lines,real line_width,char * line_color,real * x_poly,int * polys_groups,char ** labels,real * width,float * fsz,float * r,float * g,float * b,char * opacity,char * plot_label,real * bg_color,SparseMatrix A,FILE * f)842 void plot_dot_map(Agraph_t* gr, int n, int dim, real *x, SparseMatrix polys, SparseMatrix poly_lines, real line_width, char *line_color, real *x_poly, int *polys_groups, char **labels, real *width,
843 		  float *fsz, float *r, float *g, float *b, char* opacity, char *plot_label, real *bg_color, SparseMatrix A, FILE* f){
844   /* if graph object exist, we just modify some attributes, otherwise we dump the whole graph */
845   int plot_polyQ = TRUE;
846   char *sbuff;
847   int len = 0, len_max = 1000;
848 
849   sbuff = N_NEW(len_max,char);
850 
851   if (!r || !g || !b) plot_polyQ = FALSE;
852 
853   if (!gr) {
854     fprintf(f, "graph map {\n node [margin = 0 width=0.0001 height=0.00001 shape=plaintext];\n graph [outputorder=edgesfirst, bgcolor=\"#dae2ff\"]\n edge [color=\"#55555515\",fontname=\"Helvetica-Bold\"]\n");
855   } else {
856     agattr(gr, AGNODE, "margin", "0");
857     agattr(gr, AGNODE, "width", "0.0001");
858     agattr(gr, AGNODE, "height", "0.0001");
859     agattr(gr, AGNODE, "shape", "plaintext");
860     agattr(gr, AGNODE, "margin", "0");
861     agattr(gr, AGNODE, "fontname", "Helvetica-Bold");
862     agattr(gr, AGRAPH, "outputorder", "edgesfirst");
863     agattr(gr, AGRAPH, "bgcolor", "#dae2ff");
864     if (!A) agattr(gr, AGEDGE, "style","invis");/* do not plot edges */
865     //    agedgeattr(gr, "color", "#55555515");
866   }
867 
868   /*polygons */
869   if (plot_polyQ) {
870     if (!gr) fprintf(f,"_background = \"");
871     plot_dot_polygons(&sbuff, &len, &len_max, -1., NULL, polys, x_poly, polys_groups, r, g, b, opacity);
872   }
873 
874   /* polylines: line width is set here */
875   if (line_width >= 0){
876     plot_dot_polygons(&sbuff, &len, &len_max, line_width, line_color, poly_lines, x_poly, polys_groups, NULL, NULL, NULL, NULL);
877   }
878   if (!gr) {
879     fprintf(f,"%s",sbuff);
880     fprintf(f,"\"\n");/* close polygons/lines */
881   } else {
882     agattr(gr, AGRAPH, "_background", sbuff);
883     agwrite(gr, f);
884   }
885 
886   /* nodes */
887   if (!gr && labels) plot_dot_labels(f, n, dim, x, labels, width, fsz);
888   /* edges */
889   if (!gr && A) plot_dot_edges(f, A, dim, x);
890 
891   /* background color + plot label?*/
892 
893   if (!gr) fprintf(f, "}\n");
894 
895   FREE(sbuff);
896 }
897 
898 #if 0
899 static void get_polygon_bbox(SparseMatrix polys, real *x_poly, real *bbox_x, real *bbox_y){
900   /* find bounding box. bbox_x is the xmin and xmax, bbox_y is ymin and ymax */
901   int i, j, *ia = polys->ia, *ja = polys->ja, *a = (int*) polys->a, npolys = polys->m, nverts = polys->n, ipoly,first;
902   int NEW = TRUE;
903 
904   first = ABS(a[0]); ipoly = first + 1;
905   for (i = 0; i < npolys; i++){
906     for (j = ia[i]; j < ia[i+1]; j++){
907       assert(ja[j] < nverts && ja[j] >= 0);
908       if (NEW){
909 	bbox_x[0] = bbox_x[1] =  x_poly[2*ja[j]];
910 	bbox_y[0] = bbox_y[1] =  x_poly[2*ja[j]+1];
911 	NEW = FALSE;
912       } else {
913 	bbox_x[0] = MIN(bbox_x[0], x_poly[2*ja[j]]);
914 	bbox_x[1] = MAX(bbox_x[1], x_poly[2*ja[j]]);
915 	bbox_y[0] = MIN(bbox_y[0], x_poly[2*ja[j]+1]);
916 	bbox_y[1] = MAX(bbox_y[1], x_poly[2*ja[j]+1]);
917       }
918     }
919   }
920 }
921 #endif
922 
923 #if 0
924 void plot_processing_map(Agraph_t* gr, int n, int dim, real *x, SparseMatrix polys, SparseMatrix poly_lines, real line_width, int nverts, real *x_poly, int *polys_groups, char **labels, real *width,
925 		 float *fsz, float *r, float *g, float *b, char *plot_label, real *bg_color, SparseMatrix A){
926   /* if graph object exist, we just modify some attributes, otherwise we dump the whole graph */
927   int plot_polyQ = TRUE;
928   FILE *f = stdout;
929   real xmin[2], xwidth[2], scaling=1, bbox_x[2], bbox_y[2];
930   int i;
931 
932   /* shift to make all coordinates position */
933   get_polygon_bbox(polys, x_poly, bbox_x, bbox_y);
934   xmin[0] = bbox_x[0]; xmin[1] = bbox_y[0];
935   xwidth[0] = (bbox_x[1] - bbox_x[0])*scaling;
936   xwidth[1] = (bbox_y[1] - bbox_y[0])*scaling;
937   for (i = 0; i < n; i++) {
938     xmin[0] = MIN(xmin[0], x[i*dim]);
939     xmin[1] = MIN(xmin[1], x[i*dim+1]);
940   }
941 
942   fprintf(stderr,"xmin={%f, %f}\n", xmin[0], xmin[1]);
943 
944   for (i = 0; i < n; i++) {
945     x[i*dim] = (x[i*dim] - xmin[0])*scaling;
946     x[i*dim+1] = (x[i*dim+1] - xmin[1])*scaling;
947     xwidth[0] = MAX(xwidth[0], x[i*dim]);
948     xwidth[1] = MAX(xwidth[1], x[i*dim+1]);
949   }
950   for (i = 0; i < nverts; i++) {
951     x_poly[i*dim] = (x_poly[i*dim] - xmin[0])*scaling;
952     x_poly[i*dim+1] = (x_poly[i*dim+1] - xmin[1])*scaling;
953   }
954   /*
955   fprintf(f,"//This file is for processing language. Syntax:\n//\n");
956   fprintf(f,"//beginPolygons\n//[color(r,g,b)]\n//x y\n...\n//endPolygons\n//\n");
957   fprintf(f,"//beginPolylines\n//[color(r,g,b)]\n//...\n//endPolylines\n\n");
958   fprintf(f,"//beginLines\n//[color(r,g,b)]\n//x1 y1 x2 y2\n//...\n endLines\n//\n");
959   fprintf(f,"//beginText\n//[fontSize(x)]\n//text(\"foo\")\n//position(x,y)\n\\endText\n//\n");
960   fprintf(f,"//\n");
961 
962   fprintf(f, "size(%d, %d);\n", (int)(xwidth[0]+1), (int) (xwidth[1]+1));
963   */
964 
965   if (!r || !g || !b) plot_polyQ = FALSE;
966 
967   if (!gr) {
968     fprintf(f, "background(234, 242, 255)");
969   }
970 
971   /*polygons */
972   if (plot_polyQ) {
973     plot_processing_polygons(f, -1., polys, x_poly, polys_groups, r, g, b);
974   }
975 
976   /* polylines: line width is set here */
977   if (line_width >= 0){
978     plot_processing_polygons(f, line_width, poly_lines, x_poly, polys_groups, NULL, NULL, NULL);
979   }
980 
981   /* edges */
982   if (A) plot_processing_edges(f, A, dim, x);
983 
984   /* nodes */
985   if (labels) plot_processing_labels(f, n, dim, x, labels, width, fsz);
986 
987 
988 }
989 #endif
990 
get_tri(int n,int dim,real * x,int * nt,struct Triangle ** T,SparseMatrix * E,int * flag)991 static void get_tri(int n, int dim, real *x, int *nt, struct Triangle **T, SparseMatrix *E, int *flag) {
992    /* always contains a self edge and is symmetric.
993      input:
994      n: number of points
995      dim: dimension, only first2D used
996      x: point j is stored x[j*dim]--x[j*dim+dim-1]
997      output:
998      nt: number of triangles
999      T: triangles
1000      E: a matrix of size nxn, if two points i > j are connected by an taiangulation edge, and is neighboring two triangles
1001      .  t1 and t2, then A[i,j] is both t1 and t2
1002    */
1003   int i, j, i0, i1, i2, ntri;
1004   SparseMatrix A, B;
1005 
1006   int* trilist = get_triangles(x, n, &ntri);
1007   *flag = 0;
1008 
1009 
1010   *T = N_NEW(ntri,struct Triangle);
1011 
1012   A = SparseMatrix_new(n, n, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
1013   for (i = 0; i < ntri; i++) {
1014     for (j = 0; j < 3; j++) {
1015       ((*T)[i]).vertices[j] = trilist[i * 3 + j];
1016     }
1017     i0 = (*T)[i].vertices[0]; i1 = (*T)[i].vertices[1]; i2 = (*T)[i].vertices[2];
1018 
1019     triangle_center(&x[i0*dim], &x[i1*dim], &x[i2*dim], (*T)[i].center);
1020     A = matrix_add_entry(A, i0, i1, i);
1021     A = matrix_add_entry(A, i1, i2, i);
1022     A = matrix_add_entry(A, i2, i0, i);
1023   }
1024 
1025   B = SparseMatrix_from_coordinate_format_not_compacted(A, SUM_REPEATED_NONE);
1026   SparseMatrix_delete(A);
1027   B = SparseMatrix_sort(B);
1028   *E = B;
1029 
1030   *nt = ntri;
1031 
1032   FREE(trilist);
1033 
1034   return;
1035 }
1036 
1037 
1038 
plot_labels(int n,int dim,real * x,char ** labels)1039 void plot_labels(int n, int dim, real *x, char **labels){
1040   int i, j;
1041 
1042   printf("Graphics[{");
1043 
1044   for (i = 0; i < n; i++){
1045     printf("Text[\"%s\",{",labels[i]);
1046     for (j = 0; j < 2; j++) {
1047       printf("%f",x[i*dim+j]);
1048       if (j == 0) printf(",");
1049     }
1050     printf("}]");
1051     if (i < n - 1) printf(",\n");
1052   }
1053   printf("}]");
1054 
1055 
1056 }
plot_points(int n,int dim,real * x)1057 void plot_points(int n, int dim, real *x){
1058   int i, j;
1059 
1060   printf("Graphics[{Point[{");
1061   for (i = 0; i < n; i++){
1062     printf("{");
1063     for (j = 0; j < 2; j++) {
1064       printf("%f",x[i*dim+j]);
1065       if (j == 0) printf(",");
1066     }
1067     printf("}");
1068     if (i < n - 1) printf(",");
1069   }
1070   printf("}]");
1071 
1072   /*
1073   printf(",");
1074   for (i = 0; i < n; i++){
1075     printf("Text[%d,{",i);
1076     for (j = 0; j < 2; j++) {
1077       printf("%f",x[i*dim+j]);
1078       if (j == 0) printf(",");
1079     }
1080     printf("}]");
1081     if (i < n - 1) printf(",");
1082   }
1083   */
1084   printf("}]");
1085 
1086 }
1087 
plot_edges(int n,int dim,real * x,SparseMatrix A)1088 void plot_edges(int n, int dim, real *x, SparseMatrix A){
1089   int i, j, k;
1090   int *ia, *ja;
1091 
1092   if (!A) {
1093     printf("Graphics[{}]");
1094     return;
1095   }
1096   ia = A->ia; ja = A->ja;
1097 
1098   printf("Graphics[(* edges of the graph*){");
1099   for (i = 0; i < n; i++){
1100     for (j = ia[i]; j < ia[i+1]; j++){
1101       if (i > 0 && j == ia[i]) printf(",");;
1102       printf("Line[{{");
1103       for (k = 0; k < 2; k++) {
1104 	printf("%f",x[i*dim+k]);
1105 	if (k == 0) printf(",");
1106       }
1107       printf("},{");
1108       for (k = 0; k < 2; k++) {
1109 	printf("%f",x[ja[j]*dim+k]);
1110 	if (k == 0) printf(",");
1111       }
1112       printf("}}]");
1113       if (j < ia[i+1] - 1) printf(",");
1114     }
1115   }
1116   printf("}(* end of edges of the graph*)]");
1117 
1118 }
get_country_graph(int n,SparseMatrix A,int * groups,SparseMatrix * poly_point_map,int GRP_RANDOM,int GRP_BBOX)1119 static SparseMatrix get_country_graph(int n, SparseMatrix A, int *groups, SparseMatrix *poly_point_map, int GRP_RANDOM, int GRP_BBOX){
1120   /* form a graph each vertex is a group (a country), and a vertex is connected to another if the two countryes shares borders.
1121    since the group ID may not be contigous (e.g., only groups 2,3,5, -1), we will return NULL if one of the group has non-positive ID! */
1122   int *ia, *ja;
1123   int one = 1, jj, i, j, ig1, ig2;
1124   SparseMatrix B, BB;
1125   int min_grp, max_grp;
1126 
1127   min_grp = max_grp = groups[0];
1128   for (i = 0; i < n; i++) {
1129     max_grp = MAX(groups[i], max_grp);
1130     min_grp = MIN(groups[i], min_grp);
1131   }
1132   if (min_grp <= 0) return NULL;
1133   B = SparseMatrix_new(max_grp, max_grp, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
1134   ia = A->ia;
1135   ja = A->ja;
1136   for (i = 0; i < n; i++){
1137     ig1 = groups[i]-1;/* add a diagonal entry */
1138     SparseMatrix_coordinate_form_add_entries(B, 1, &ig1, &ig1, &one);
1139     for (j = ia[i]; j < ia[i+1]; j++){
1140       jj = ja[j];
1141       if (i != jj && groups[i] != groups[jj] && groups[jj] != GRP_RANDOM && groups[jj] != GRP_BBOX){
1142 	ig1 = groups[i]-1; ig2 = groups[jj]-1;
1143 	SparseMatrix_coordinate_form_add_entries(B, 1, &ig1, &ig2, &one);
1144       }
1145     }
1146   }
1147   BB = SparseMatrix_from_coordinate_format(B);
1148   SparseMatrix_delete(B);
1149   return BB;
1150 }
1151 
conn_comp(int n,SparseMatrix A,int * groups,SparseMatrix * poly_point_map)1152 static void conn_comp(int n, SparseMatrix A, int *groups, SparseMatrix *poly_point_map){
1153   /* form a graph where only vertices that are connected as well as in the same group are connected */
1154   int *ia, *ja;
1155   int one = 1, jj, i, j;
1156   SparseMatrix B, BB;
1157   int ncomps, *comps = NULL, *comps_ptr = NULL;
1158 
1159   B = SparseMatrix_new(n, n, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
1160   ia = A->ia;
1161   ja = A->ja;
1162   for (i = 0; i < n; i++){
1163     for (j = ia[i]; j < ia[i+1]; j++){
1164       jj = ja[j];
1165       if (i != jj && groups[i] == groups[jj]){
1166 	SparseMatrix_coordinate_form_add_entries(B, 1, &i, &jj, &one);
1167       }
1168     }
1169   }
1170   BB = SparseMatrix_from_coordinate_format(B);
1171 
1172   SparseMatrix_weakly_connected_components(BB, &ncomps, &comps, &comps_ptr);
1173   SparseMatrix_delete(B);
1174   SparseMatrix_delete(BB);
1175   *poly_point_map = SparseMatrix_new(ncomps, n, n, MATRIX_TYPE_PATTERN, FORMAT_CSR);
1176   FREE((*poly_point_map)->ia);
1177   FREE((*poly_point_map)->ja);
1178   (*poly_point_map)->ia = comps_ptr;
1179   (*poly_point_map)->ja = comps;
1180   (*poly_point_map)->nz = n;
1181 
1182 }
1183 
1184 
get_poly_lines(int exclude_random,int nt,SparseMatrix graph,SparseMatrix E,int ncomps,int * comps_ptr,int * comps,int * groups,int * mask,SparseMatrix * poly_lines,int ** polys_groups,int GRP_RANDOM,int GRP_BBOX)1185 static void get_poly_lines(int exclude_random, int nt, SparseMatrix graph, SparseMatrix E, int ncomps, int *comps_ptr, int *comps,
1186 			   int *groups, int *mask, SparseMatrix *poly_lines, int **polys_groups,
1187 			   int GRP_RANDOM, int GRP_BBOX){
1188   /*============================================================
1189 
1190     polygon outlines
1191 
1192     ============================================================*/
1193   int i, *tlist, nz, ipoly, ipoly2, nnt, ii, jj, t1, t2, t, cur, next, nn, j, nlink, sta;
1194   int *elist, edim = 3;/* a list tell which vertex a particular vertex is linked with during poly construction.
1195 		since the surface is a cycle, each can only link with 2 others, the 3rd position is used to record how many links
1196 	      */
1197   int *ie = E->ia, *je = E->ja, *e = (int*) E->a, n = E->m;
1198   int *ia = NULL, *ja = NULL;
1199   SparseMatrix A;
1200   int *gmask = NULL;
1201 
1202 
1203   graph = NULL;/* we disable checking whether a polyline cross an edge for now due to issues with labels */
1204   if (graph) {
1205     assert(graph->m == n);
1206     gmask = malloc(sizeof(int)*n);
1207     for (i = 0; i < n; i++) gmask[i] = -1;
1208     ia = graph->ia; ja = graph->ja;
1209     edim = 5;/* we also store info about whether an edge of a polygon correspondes to a real edge or not. */
1210   }
1211 
1212   for (i = 0; i < nt; i++) mask[i] = -1;
1213   /* loop over every point in each connected component */
1214   elist = MALLOC(sizeof(int)*(nt)*edim);
1215   tlist = MALLOC(sizeof(int)*nt*2);
1216   *poly_lines = SparseMatrix_new(ncomps, nt, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
1217   *polys_groups = MALLOC(sizeof(int)*(ncomps));
1218 
1219   for (i = 0; i < nt; i++) elist[i*edim + 2] = 0;
1220   nz = ie[E->m] - ie[0];
1221 
1222   ipoly = 1;
1223 
1224   for (i = 0; i < ncomps; i++){
1225     /*fprintf(stderr, "comp %d has %d members\n",i, comps_ptr[i+1]-comps_ptr[i]);*/
1226     nnt = 0;
1227     for (j = comps_ptr[i]; j < comps_ptr[i+1]; j++){
1228       ii = comps[j];
1229 
1230       if (graph){
1231 	for (jj = ia[ii]; jj < ia[ii+1]; jj++) gmask[ja[jj]] = ii;
1232       }
1233 
1234       (*polys_groups)[i] = groups[ii];/* assign the grouping of each poly */
1235 
1236       /* skip the country formed by random points */
1237       if (exclude_random && (groups[ii] == GRP_RANDOM || groups[ii] == GRP_BBOX)) continue;
1238 
1239       /* always skip bounding box */
1240       if (groups[ii] == GRP_BBOX) continue;
1241 
1242       /*fprintf(stderr, "member %d is in group %d, it is\n",ii, groups[ii]);*/
1243       for (jj = ie[ii]; jj < ie[ii+1]; jj++){
1244 	/*
1245 	fprintf(stderr, "connected with %d in group %d\n",je[jj], groups[je[jj]]);
1246 	fprintf(stderr, "jj=%d nz = %d je[jj]=%d je[jj+1]=%d\n",jj,nz, je[jj],je[jj+1]);
1247 	*/
1248 	if (groups[je[jj]] != groups[ii] && jj < nz - 1  && je[jj] == je[jj+1]){/* an triangle edge neighboring 2 triangles and two ends not in the same groups */
1249 	  t1 = e[jj];
1250 	  t2 = e[jj+1];
1251 
1252 	  nlink = elist[t1*edim + 2]%2;
1253 	  elist[t1*edim + nlink] = t2;/* t1->t2*/
1254 	  if (graph){
1255 	    if (gmask[je[jj]] == ii){/* a real edge */
1256 	      elist[t1*edim+nlink+3] = POLY_LINE_REAL_EDGE;
1257 	    } else {
1258 	      fprintf(stderr,"not real!!!\n");
1259 	      elist[t1*edim+nlink+3] = POLY_LINE_NOT_REAL_EDGE;
1260 	    }
1261 	  }
1262 	  elist[t1*edim + 2]++;
1263 
1264 	  nlink = elist[t2*edim + 2]%2;
1265 	  elist[t2*edim + nlink] = t1;/* t1->t2*/
1266 	  elist[t2*edim + 2]++;
1267 	  if (graph){
1268 	    if (gmask[je[jj]] == ii){/* a real edge */
1269 	      elist[t2*edim+nlink+3] = POLY_LINE_REAL_EDGE;
1270 	    } else {
1271 	      fprintf(stderr,"not real!!!\n");
1272 	      elist[t2*edim+nlink+3] = POLY_LINE_NOT_REAL_EDGE;
1273 	    }
1274 	  }
1275 
1276 	  tlist[nnt++] = t1; tlist[nnt++] = t2;
1277 	  jj++;
1278 	}
1279       }
1280     }/* done poly edges for this component i */
1281 
1282 
1283     /* debugging*/
1284 #ifdef DEBUG
1285     /*
1286     for (j = 0; j < nnt; j++) {
1287       if (elist[tlist[j]*edim + 2]%2 != 0){
1288 	printf("wrong: elist[%d*edim+2] = %d\n",j,elist[tlist[j]*edim + 2]%);
1289 	assert(0);
1290       }
1291     }
1292     */
1293 #endif
1294 
1295     /* form one or more (if there is a hole) polygon outlines for this component  */
1296     for (j = 0; j < nnt; j++){
1297       t = tlist[j];
1298       if (mask[t] != i){
1299 	cur = sta = t; mask[cur] = i;
1300 	next = neighbor(t, 1, edim, elist);
1301 	nlink = 1;
1302 	if (graph && neighbor(cur, 3, edim, elist) == POLY_LINE_NOT_REAL_EDGE){
1303 	  ipoly2 = - ipoly;
1304 	} else {
1305 	  ipoly2 = ipoly;
1306 	}
1307 	SparseMatrix_coordinate_form_add_entries(*poly_lines, 1, &i, &cur, &ipoly2);
1308 	while (next != sta){
1309 	  mask[next] = i;
1310 
1311 	  if (graph && neighbor(cur, nlink + 3, edim, elist) == POLY_LINE_NOT_REAL_EDGE){
1312 	    ipoly2 = -ipoly;
1313 	  } else {
1314 	    ipoly2 = ipoly;
1315 	  }
1316 	  SparseMatrix_coordinate_form_add_entries(*poly_lines, 1, &i, &next, &ipoly2);
1317 
1318 	  nn = neighbor(next, 0, edim, elist);
1319 	  nlink = 0;
1320 	  if (nn == cur) {
1321 	    nlink = 1;
1322 	    nn = neighbor(next, 1, edim, elist);
1323 	  }
1324 	  assert(nn != cur);
1325 
1326 	  cur = next;
1327 	  next = nn;
1328 	}
1329 
1330 	if (graph && neighbor(cur, nlink + 3, edim, elist) == POLY_LINE_NOT_REAL_EDGE){
1331 	  ipoly2 = -ipoly;
1332 	} else {
1333 	  ipoly2 = ipoly;
1334 	}
1335 	SparseMatrix_coordinate_form_add_entries(*poly_lines, 1, &i, &sta, &ipoly2);/* complete a cycle by adding starting point */
1336 
1337 	ipoly++;
1338       }
1339 
1340     }/* found poly_lines for this comp */
1341   }
1342 
1343   A = SparseMatrix_from_coordinate_format_not_compacted(*poly_lines, SUM_REPEATED_NONE);
1344   SparseMatrix_delete(*poly_lines);
1345   *poly_lines = A;
1346 
1347   FREE(tlist);
1348   FREE(elist);
1349 }
1350 
plot_cycle(int head,int * cycle,int * edge_table,real * x)1351 static void plot_cycle(int head, int *cycle, int *edge_table, real *x){
1352   int cur, next;
1353   real x1, x2, y1, y2;
1354 
1355   printf("Graphics[{");
1356   cur = head;
1357   while ((next = cycle_next(cur)) != head){
1358     x1 = x[2*edge_head(cur)];
1359     y1 = x[2*edge_head(cur)+1];
1360     x2 = x[2*edge_tail(cur)];
1361     y2 = x[2*edge_tail(cur)+1];
1362     printf("{Black,Arrow[{{%f,%f},{%f,%f}}],Green,Text[%d, {%f,%f}],Text[%d, {%f,%f}]},",x1,y1,x2,y2,edge_head(cur),x1,y1,edge_tail(cur),x2,y2);
1363     cur = next;
1364   }
1365   x1 = x[2*edge_head(cur)];
1366   y1 = x[2*edge_head(cur)+1];
1367   x2 = x[2*edge_tail(cur)];
1368   y2 = x[2*edge_tail(cur)+1];
1369   printf("{Black,Arrow[{{%f,%f},{%f,%f}}],Green,Text[%d, {%f,%f}],Text[%d, {%f,%f}]}}]",x1,y1,x2,y2,edge_head(cur),x1,y1,edge_tail(cur),x2,y2);
1370 
1371 
1372 }
1373 
cycle_print(int head,int * cycle,int * edge_table)1374 static void cycle_print(int head, int *cycle, int *edge_table){
1375   int cur, next;
1376 
1377   cur = head;
1378   fprintf(stderr, "cycle (edges): {");
1379   while ((next = cycle_next(cur)) != head){
1380     fprintf(stderr, "%d,",cur);
1381     cur = next;
1382   }
1383   fprintf(stderr, "%d}\n",cur);
1384 
1385   cur = head;
1386   fprintf(stderr, "cycle (vertices): ");
1387   while ((next = cycle_next(cur)) != head){
1388     fprintf(stderr, "%d--",edge_head(cur));
1389     cur = next;
1390   }
1391   fprintf(stderr, "%d--%d\n",edge_head(cur),edge_tail(cur));
1392 
1393 
1394 
1395 
1396 
1397 
1398 }
1399 
same_edge(int ecur,int elast,int * edge_table)1400 static int same_edge(int ecur, int elast, int *edge_table){
1401   return ((edge_head(ecur) == edge_head(elast) && edge_tail(ecur) == edge_tail(elast))
1402 	  || (edge_head(ecur) == edge_tail(elast) && edge_tail(ecur) == edge_head(elast)));
1403 }
1404 
get_polygon_solids(int exclude_random,int nt,SparseMatrix E,int ncomps,int * comps_ptr,int * comps,int * groups,int * mask,real * x_poly,SparseMatrix * polys,int ** polys_groups,int GRP_RANDOM,int GRP_BBOX)1405 static void get_polygon_solids(int exclude_random, int nt, SparseMatrix E, int ncomps, int *comps_ptr, int *comps,
1406 			       int *groups, int *mask, real *x_poly, SparseMatrix *polys, int **polys_groups,
1407 			       int GRP_RANDOM, int GRP_BBOX){
1408   /*============================================================
1409 
1410     polygon slids that will be colored
1411 
1412     ============================================================*/
1413   int *edge_table;/* a table of edges of the triangle graph. If two vertex u and v are connected and are adjencent to two triangles
1414 		     t1 and t2, then from u there are two edges to v, one denoted as t1->t2, and the other t2->t1. They are
1415 		     numbered as e1 and e2. edge_table[e1]={t1,t2} and edge_table[e2]={t2,t1}
1416 		  */
1417   SparseMatrix half_edges;/* a graph of triangle edges. If two vertex u and v are connected and are adjencent to two triangles
1418 		     t1 and t2, then from u there are two edges to v, one denoted as t1->t2, and the other t2->t1. They are
1419 		     numbered as e1 and e2. Likewise from v to u there are also two edges e1 and e2.
1420 		  */
1421 
1422   int n = E->m, *ie = E->ia, *je = E->ja, *e = (int*) E->a, ne, i, j, t1, t2, jj, ii;
1423   int *cycle, cycle_head = 0;/* a list of edges that form a cycle that describe the polygon. cycle[e][0] gives the prev edge in the cycle from e,
1424 	       cycle[e][1] gives the next edge
1425 	     */
1426   int *edge_cycle_map, NOT_ON_CYCLE = -1;/* map an edge e to its position on cycle, unless it does not exist (NOT_ON_CYCLE) */
1427   int *emask;/* whether an edge is seens this iter */
1428   enum {NO_DUPLICATE = -1};
1429   int *elist, edim = 3;/* a list tell which edge a particular vertex is linked with when a voro cell has been visited,
1430 		since the surface is a cycle, each vertex can only link with 2 edges, the 3rd position is used to record how many links
1431 	      */
1432 
1433   int k, duplicate, ee = 0, ecur, enext, eprev, cur, next, nn, nlink, head, elast = 0, etail, tail, ehead, efirst;
1434 
1435   int DEBUG_CYCLE = 0;
1436   SparseMatrix B;
1437 
1438   ne = E->nz;
1439   edge_table = MALLOC(sizeof(int)*ne*2);
1440 
1441   for (i = 0; i < n; i++) mask[i] = -1;
1442 
1443   half_edges = SparseMatrix_new(n, n, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
1444 
1445   ne = 0;
1446   for (i = 0; i < n; i++){
1447     for (j = ie[i]; j < ie[i+1]; j++){
1448       if (j < ie[n] - ie[0] - 1 && i > je[j] && je[j] == je[j+1]){/* an triangle edge neighboring 2 triangles. Since E is symmetric, we only do one edge of E*/
1449 	t1 = e[j];
1450 	t2 = e[j+1];
1451 	jj = je[j];
1452 	assert(jj < n);
1453 	edge_table[ne*2] = t1;/*t1->t2*/
1454 	edge_table[ne*2+1] = t2;
1455 	half_edges = SparseMatrix_coordinate_form_add_entries(half_edges, 1, &i, &jj, &ne);
1456 	half_edges = SparseMatrix_coordinate_form_add_entries(half_edges, 1, &jj, &i, &ne);
1457 	ne++;
1458 
1459 	edge_table[ne*2] = t2;/*t2->t1*/
1460 	edge_table[ne*2+1] = t1;
1461 	half_edges = SparseMatrix_coordinate_form_add_entries(half_edges, 1, &i, &jj, &ne);
1462 	half_edges = SparseMatrix_coordinate_form_add_entries(half_edges, 1, &jj, &i, &ne);
1463 
1464 
1465 	ne++;
1466 	j++;
1467       }
1468     }
1469   }
1470   assert(E->nz >= ne);
1471 
1472   cycle = MALLOC(sizeof(int)*ne*2);
1473   B = SparseMatrix_from_coordinate_format_not_compacted(half_edges, SUM_REPEATED_NONE);
1474   SparseMatrix_delete(half_edges);half_edges = B;
1475 
1476   edge_cycle_map = MALLOC(sizeof(int)*ne);
1477   emask = MALLOC(sizeof(int)*ne);
1478   for (i = 0; i < ne; i++) edge_cycle_map[i] = NOT_ON_CYCLE;
1479   for (i = 0; i < ne; i++) emask[i] = -1;
1480 
1481   ie = half_edges->ia;
1482   je = half_edges->ja;
1483   e = (int*) half_edges->a;
1484   elist = MALLOC(sizeof(int)*(nt)*3);
1485   for (i = 0; i < nt; i++) elist[i*edim + 2] = 0;
1486 
1487   *polys = SparseMatrix_new(ncomps, nt, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
1488 
1489   for (i = 0; i < ncomps; i++){
1490     if (DEBUG_CYCLE) fprintf(stderr, "\n ============  comp %d has %d members\n",i, comps_ptr[i+1]-comps_ptr[i]);
1491     for (k = comps_ptr[i]; k < comps_ptr[i+1]; k++){
1492       ii = comps[k];
1493       mask[ii] = i;
1494       duplicate = NO_DUPLICATE;
1495       if (DEBUG_CYCLE) fprintf(stderr,"member = %d has %d neighbors\n",ii, ie[ii+1]-ie[ii]);
1496       for (j = ie[ii]; j < ie[ii+1]; j++){
1497 	jj = je[j];
1498 	ee = e[j];
1499 	t1 = edge_head(ee);
1500 	if (DEBUG_CYCLE) fprintf(stderr," linked with %d using half-edge %d, {head,tail} of the edge = {%d, %d}\n",jj, ee, t1, edge_tail(ee));
1501 	nlink = elist[t1*edim + 2]%2;
1502 	elist[t1*edim + nlink] = ee;/* t1->t2*/
1503 	elist[t1*edim + 2]++;
1504 
1505 	if (edge_cycle_map[ee] != NOT_ON_CYCLE) duplicate = ee;
1506 	emask[ee] = ii;
1507       }
1508 
1509       if (duplicate == NO_DUPLICATE){
1510 	/* this must be the first time the cycle is being established, a new voro cell*/
1511 	ecur = ee;
1512 	cycle_head = ecur;
1513 	cycle_next(ecur) = ecur;
1514 	cycle_prev(ecur) = ecur;
1515 	edge_cycle_map[ecur] = 1;
1516 	head = cur = edge_head(ecur);
1517 	next = edge_tail(ecur);
1518 	if (DEBUG_CYCLE) fprintf(stderr, "NEW CYCLE\n starting with edge %d, {head,tail}={%d,%d}\n", ee, head, next);
1519 	while (next != head){
1520 	  enext = neighbor(next, 0, edim, elist);/* two voro edges linked with triangle "next" */
1521 	  if ((edge_head(enext) == cur && edge_tail(enext) == next)
1522 	      || (edge_head(enext) == next && edge_tail(enext) == cur)){/* same edge */
1523 	    enext = neighbor(next, 1, edim, elist);
1524 	  };
1525 	  if (DEBUG_CYCLE) fprintf(stderr, "cur edge = %d, next edge %d, {head,tail}={%d,%d},\n",ecur, enext, edge_head(enext), edge_tail(enext));
1526 	  nn = edge_head(enext);
1527 	  if (nn == next) nn = edge_tail(enext);
1528 	  cycle_next(enext) = cycle_next(ecur);
1529 	  cycle_prev(enext) = ecur;
1530 	  cycle_next(ecur) = enext;
1531 	  cycle_prev(ee) = enext;
1532 	  edge_cycle_map[enext] = 1;
1533 
1534 	  ecur = enext;
1535 	  cur = next;
1536 	  next = nn;
1537 	}
1538 	if (DEBUG_CYCLE) cycle_print(ee, cycle,edge_table);
1539       } else {
1540 	/* we found a duplicate edge, remove that, and all contiguous neighbors that overlap with the current voro
1541 	 */
1542 	ecur = ee = duplicate;
1543 	while (emask[ecur] == ii){
1544 	  /* contigous overlapping edges, Cycling is not possible
1545 	     since the cycle can not complete surround the new voro cell and yet
1546 	     do not contain any other edges
1547 	  */
1548 	  ecur = cycle_next(ecur);
1549 	}
1550 	if (DEBUG_CYCLE) fprintf(stderr," duplicating edge = %d, starting from the a non-duplicating edge %d, search backwards\n",ee, ecur);
1551 
1552 	ecur = cycle_prev(ecur);
1553 	efirst = ecur;
1554 	while (emask[ecur] == ii){
1555 	  if (DEBUG_CYCLE) fprintf(stderr," remove edge %d (%d--%d)\n",ecur, edge_head(ecur), edge_tail(ecur));
1556 	  /* short this duplicating edge */
1557 	  edge_cycle_map[ecur] = NOT_ON_CYCLE;
1558 	  enext = cycle_next(ecur);
1559 	  eprev = cycle_prev(ecur);
1560 	  cycle_next(ecur) = ecur;/* isolate this edge */
1561 	  cycle_prev(ecur) = ecur;
1562 	  cycle_next(eprev) = enext;/* short */
1563 	  cycle_prev(enext) = eprev;
1564 	  elast = ecur;/* record the last removed edge */
1565 	  ecur = eprev;
1566 	}
1567 
1568 	if (DEBUG_CYCLE) {
1569 	  fprintf(stderr, "remaining (broken) cycle = ");
1570 	  cycle_print(cycle_next(ecur), cycle,edge_table);
1571 	}
1572 
1573 	/* we now have a broken cycle of head = edge_tail(ecur) and tail = edge_head(cycle_next(ecur)) */
1574 	ehead = ecur; etail = cycle_next(ecur);
1575 	cycle_head = ehead;
1576 	head = edge_tail(ehead);
1577 	tail = edge_head(etail);
1578 
1579 	/* pick an edge ev from head in the voro that is a removed edge: since the removed edges form a path starting from
1580 	   efirst, and at elast (head of elast is head), usually we just need to check that ev is not the same as elast,
1581 	   but in the case of a voro filling in a hole, we also need to check that ev is not efirst,
1582 	   since in this case every edge of the voro cell is removed
1583 	 */
1584 	ecur = neighbor(head, 0, edim, elist);
1585 	if (same_edge(ecur, elast, edge_table)){
1586 	  ecur = neighbor(head, 1, edim, elist);
1587 	};
1588 
1589 	if (DEBUG_CYCLE) fprintf(stderr, "forwarding now from edge %d = {%d, %d}, try to reach vtx %d, first edge from voro = %d\n",
1590 				 ehead, edge_head(ehead), edge_tail(ehead), tail, ecur);
1591 
1592 	/* now go along voro edges till we reach the tail of the broken cycle*/
1593 	cycle_next(ehead) = ecur;
1594 	cycle_prev(ecur) = ehead;
1595 	cycle_prev(etail) = ecur;
1596 	cycle_next(ecur) = etail;
1597 	if (same_edge(ecur, efirst, edge_table)){
1598 	  if (DEBUG_CYCLE) fprintf(stderr, "this voro cell fill in a hole completely!!!!\n");
1599 	} else {
1600 
1601 	  edge_cycle_map[ecur] = 1;
1602 	  head = cur = edge_head(ecur);
1603 	  next = edge_tail(ecur);
1604 	  if (DEBUG_CYCLE) fprintf(stderr, "starting with edge %d, {head,tail}={%d,%d}\n", ecur, head, next);
1605 	  while (next != tail){
1606 	    enext = neighbor(next, 0, edim, elist);/* two voro edges linked with triangle "next" */
1607 	    if ((edge_head(enext) == cur && edge_tail(enext) == next)
1608 		|| (edge_head(enext) == next && edge_tail(enext) == cur)){/* same edge */
1609 	      enext = neighbor(next, 1, edim, elist);
1610 	    };
1611 	    if (DEBUG_CYCLE) fprintf(stderr, "cur edge = %d, next edge %d, {head,tail}={%d,%d},\n",ecur, enext, edge_head(enext), edge_tail(enext));
1612 
1613 
1614 	    nn = edge_head(enext);
1615 	    if (nn == next) nn = edge_tail(enext);
1616 	    cycle_next(enext) = cycle_next(ecur);
1617 	    cycle_prev(enext) = ecur;
1618 	    cycle_next(ecur) = enext;
1619 	    cycle_prev(etail) = enext;
1620 	    edge_cycle_map[enext] = 1;
1621 
1622 	    ecur = enext;
1623 	    cur = next;
1624 	    next = nn;
1625 	  }
1626 	}
1627 	if (DEBUG_CYCLE && 0) {
1628 	  cycle_print(etail, cycle,edge_table);
1629 	  plot_cycle(etail, cycle,edge_table, x_poly);
1630 	  printf(",");
1631 	}
1632 
1633       }
1634 
1635     }
1636     /* done this component, load to sparse matrix, unset edge_map*/
1637     ecur = cycle_head;
1638     while ((enext = cycle_next(ecur)) != cycle_head){
1639       edge_cycle_map[ecur] = NOT_ON_CYCLE;
1640       head = edge_head(ecur);
1641       SparseMatrix_coordinate_form_add_entries(*polys, 1, &i, &head, &i);
1642       ecur = enext;
1643     }
1644     edge_cycle_map[ecur] = NOT_ON_CYCLE;
1645     head = edge_head(ecur); tail = edge_tail(ecur);
1646     SparseMatrix_coordinate_form_add_entries(*polys, 1, &i, &head, &i);
1647     SparseMatrix_coordinate_form_add_entries(*polys, 1, &i, &tail, &i);
1648 
1649 
1650     /* unset edge_map */
1651   }
1652 
1653 
1654 
1655   B = SparseMatrix_from_coordinate_format_not_compacted(*polys, SUM_REPEATED_NONE);
1656   SparseMatrix_delete(*polys);
1657   *polys = B;
1658 
1659   SparseMatrix_delete(half_edges);
1660   FREE(cycle);
1661   FREE(edge_cycle_map);
1662   FREE(elist);
1663   FREE(emask);
1664   FREE(edge_table);
1665 
1666 }
get_polygons(int exclude_random,int n,int nrandom,int dim,SparseMatrix graph,real * xcombined,int * grouping,int nt,struct Triangle * Tp,SparseMatrix E,int * nverts,real ** x_poly,int * npolys,SparseMatrix * poly_lines,SparseMatrix * polys,int ** polys_groups,SparseMatrix * poly_point_map,SparseMatrix * country_graph,int * flag)1667 static void get_polygons(int exclude_random, int n, int nrandom, int dim, SparseMatrix graph, real *xcombined, int *grouping,
1668 			 int nt, struct Triangle *Tp, SparseMatrix E, int *nverts, real **x_poly,
1669 			 int *npolys, SparseMatrix *poly_lines, SparseMatrix *polys, int **polys_groups, SparseMatrix *poly_point_map, SparseMatrix *country_graph,
1670 			 int *flag){
1671   int i, j;
1672   int *mask;
1673   int *groups;
1674   int maxgrp;
1675   int *comps = NULL, *comps_ptr = NULL, ncomps;
1676   int GRP_RANDOM, GRP_BBOX;
1677   SparseMatrix B;
1678 
1679   *flag = 0;
1680 
1681   assert(dim == 2);
1682   *nverts = nt;
1683 
1684   groups = MALLOC(sizeof(int)*(n + nrandom));
1685   maxgrp = grouping[0];
1686   for (i = 0; i < n; i++) {
1687     maxgrp = MAX(maxgrp, grouping[i]);
1688     groups[i] = grouping[i];
1689   }
1690 
1691   GRP_RANDOM = maxgrp + 1; GRP_BBOX = maxgrp + 2;
1692   for (i = n; i < n + nrandom - 4; i++) {/* all random points in the same group */
1693     groups[i] = GRP_RANDOM;
1694   }
1695   for (i = n + nrandom - 4; i < n + nrandom; i++) {/* last 4 pts of the expanded bonding box in the same group */
1696     groups[i] = GRP_BBOX;
1697   }
1698 
1699   /* finding connected componts: vertices that are connected in the triangle graph, as well as in the same group */
1700   mask = MALLOC(sizeof(int)*MAX(n + nrandom, 2*nt));
1701   conn_comp(n + nrandom, E, groups, poly_point_map);
1702 
1703   ncomps = (*poly_point_map)->m;
1704   comps = (*poly_point_map)->ja;
1705   comps_ptr = (*poly_point_map)->ia;
1706 
1707   if (exclude_random){
1708     /* connected components are such that  the random points and the bounding box 4 points forms the last
1709      remaining components */
1710     for (i = ncomps - 1; i >= 0; i--) {
1711       if ((groups[comps[comps_ptr[i]]] != GRP_RANDOM) &&
1712 	  (groups[comps[comps_ptr[i]]] != GRP_BBOX)) break;
1713     }
1714     ncomps = i + 1;
1715     if (Verbose) fprintf(stderr,"ncomps = %d\n",ncomps);
1716   } else {/* always exclude bounding box */
1717     for (i = ncomps - 1; i >= 0; i--) {
1718       if (groups[comps[comps_ptr[i]]] != GRP_BBOX) break;
1719     }
1720     ncomps = i + 1;
1721     if (Verbose) fprintf(stderr," ncomops = %d\n",ncomps);
1722   }
1723   *npolys = ncomps;
1724 
1725   *x_poly = MALLOC(sizeof(real)*dim*nt);
1726   for (i = 0; i < nt; i++){
1727     for (j = 0; j < dim; j++){
1728       (*x_poly)[i*dim+j] = (Tp[i]).center[j];
1729     }
1730   }
1731 
1732 
1733   /*============================================================
1734 
1735     polygon outlines
1736 
1737     ============================================================*/
1738   get_poly_lines(exclude_random, nt, graph, E, ncomps, comps_ptr, comps, groups, mask, poly_lines, polys_groups, GRP_RANDOM, GRP_BBOX);
1739 
1740   /*============================================================
1741 
1742     polygon solids
1743 
1744     ============================================================*/
1745   get_polygon_solids(exclude_random, nt, E, ncomps, comps_ptr, comps, groups, mask, *x_poly, polys, polys_groups, GRP_RANDOM, GRP_BBOX);
1746 
1747   B = get_country_graph(n, E, groups, poly_point_map, GRP_RANDOM, GRP_BBOX);
1748   *country_graph = B;
1749 
1750   FREE(groups);
1751   FREE(mask);
1752 
1753 }
1754 
1755 
make_map_internal(int exclude_random,int include_OK_points,int n,int dim,real * x0,int * grouping0,SparseMatrix graph,real bounding_box_margin[],int * nrandom,int nedgep,real shore_depth_tol,real edge_bridge_tol,real ** xcombined,int * nverts,real ** x_poly,int * npolys,SparseMatrix * poly_lines,SparseMatrix * polys,int ** polys_groups,SparseMatrix * poly_point_map,SparseMatrix * country_graph,int highlight_cluster,int * flag)1756 int make_map_internal(int exclude_random, int include_OK_points,
1757 		      int n, int dim, real *x0, int *grouping0, SparseMatrix graph, real bounding_box_margin[], int *nrandom, int nedgep,
1758 		      real shore_depth_tol, real edge_bridge_tol, real **xcombined, int *nverts, real **x_poly,
1759 		      int *npolys, SparseMatrix *poly_lines, SparseMatrix *polys, int **polys_groups, SparseMatrix *poly_point_map,
1760 		      SparseMatrix *country_graph, int highlight_cluster, int *flag){
1761 
1762 
1763   real xmax[2], xmin[2], area, *x = x0;
1764   int i, j;
1765   QuadTree qt;
1766   int dim2 = 2, nn = 0;
1767   int max_qtree_level = 10;
1768   real ymin[2], min;
1769   int imin, nz, nzok = 0, nzok0 = 0, nt;
1770   real *xran, point[2];
1771   struct Triangle *Tp;
1772   SparseMatrix E;
1773   real boxsize[2];
1774   int INCLUDE_OK_POINTS = include_OK_points;/* OK points are random points inserted and found to be within shore_depth_tol of real/artificial points,
1775 			      including them instead of throwing away increase realism of boundary */
1776   int *grouping = grouping0;
1777 
1778   int HIGHLIGHT_SET = highlight_cluster;
1779 
1780   *flag = 0;
1781   for (j = 0; j < dim2; j++) {
1782     xmax[j] = x[j];
1783     xmin[j] = x[j];
1784   }
1785 
1786   for (i = 0; i < n; i++){
1787     for (j = 0; j < dim2; j++) {
1788       xmax[j] = MAX(xmax[j], x[i*dim+j]);
1789       xmin[j] = MIN(xmin[j], x[i*dim+j]);
1790     }
1791   }
1792   boxsize[0] = (xmax[0] - xmin[0]);
1793   boxsize[1] = (xmax[1] - xmin[1]);
1794   area = boxsize[0]*boxsize[1];
1795 
1796   if (*nrandom == 0) {
1797     *nrandom = n;
1798   } else if (*nrandom < 0){
1799     *nrandom = -(*nrandom)*n;
1800   } else if (*nrandom < 4) {/* by default we add 4 point on 4 corners anyway */
1801     *nrandom = 0;
1802   } else {
1803     *nrandom -= 4;
1804   }
1805 
1806   if (shore_depth_tol < 0) shore_depth_tol = sqrt(area/(real) n); /* set to average distance for random distribution */
1807   if (Verbose) fprintf(stderr,"nrandom=%d shore_depth_tol=%.08f\n",*nrandom, shore_depth_tol);
1808 
1809 
1810   /* add artificial points along each edge to avoid as much as possible
1811      two connected components be separated due to small shore depth */
1812   {
1813     int nz;
1814     real *y;
1815     int k, t, np=nedgep;
1816     if (graph && np){
1817       fprintf(stderr,"add art np = %d\n",np);
1818       nz = graph->nz;
1819       y = MALLOC(sizeof(real)*(dim*n + dim*nz*np));
1820       for (i = 0; i < n*dim; i++) y[i] = x[i];
1821       grouping = MALLOC(sizeof(int)*(n + nz*np));
1822       for (i = 0; i < n; i++) grouping[i] = grouping0[i];
1823       nz = n;
1824       for (i = 0; i < graph->m; i++){
1825 
1826 	for (j = graph->ia[i]; j < graph->ia[i+1]; j++){
1827 	  if (!HIGHLIGHT_SET || (grouping[i] == grouping[graph->ja[j]] && grouping[i] == HIGHLIGHT_SET)){
1828 	    for (t = 0; t < np; t++){
1829 	      for (k = 0; k < dim; k++){
1830 		y[nz*dim+k] = t/((real) np)*x[i*dim+k] + (1-t/((real) np))*x[(graph->ja[j])*dim + k];
1831 	      }
1832 	      assert(n + (nz-n)*np + t < n + nz*np && n + (nz-n)*np + t >= 0);
1833 	      if (t/((real) np) > 0.5){
1834 		grouping[nz] = grouping[i];
1835 	      } else {
1836 		grouping[nz] = grouping[graph->ja[j]];
1837 	      }
1838 	      nz++;
1839 	    }
1840 	  }
1841 	}
1842       }
1843       fprintf(stderr, "after adding edge points, n:%d->%d\n",n, nz);
1844       n = nz;
1845       x = y;
1846       qt = QuadTree_new_from_point_list(dim, nz, max_qtree_level, y, NULL);
1847     } else {
1848       qt = QuadTree_new_from_point_list(dim, n, max_qtree_level, x, NULL);
1849     }
1850   }
1851   graph = NULL;
1852 
1853 
1854   /* generate random points for lake/sea effect */
1855   if (*nrandom != 0){
1856     for (i = 0; i < dim2; i++) {
1857       if (bounding_box_margin[i] > 0){
1858 	xmin[i] -= bounding_box_margin[i];
1859 	xmax[i] += bounding_box_margin[i];
1860       } else if (bounding_box_margin[i] == 0) {/* auto bounding box */
1861 	xmin[i] -= MAX(boxsize[i]*0.2, 2.*shore_depth_tol);
1862 	xmax[i] += MAX(boxsize[i]*0.2, 2*shore_depth_tol);
1863       } else {
1864 	xmin[i] -= boxsize[i]*(-bounding_box_margin[i]);
1865 	xmax[i] += boxsize[i]*(-bounding_box_margin[i]);
1866       }
1867     }
1868     if (Verbose) {
1869       real bbm0 = bounding_box_margin[0];
1870       real bbm1 = bounding_box_margin[1];
1871       if (bbm0 > 0)
1872 	fprintf (stderr, "bounding box margin: %.06f", bbm0);
1873       else if (bbm0 == 0)
1874 	fprintf (stderr, "bounding box margin: %.06f", MAX(boxsize[0]*0.2, 2*shore_depth_tol));
1875       else
1876 	fprintf (stderr, "bounding box margin: (%.06f * %.06f)", boxsize[0], -bbm0);
1877       if (bbm1 > 0)
1878 	fprintf (stderr, " %.06f\n", bbm1);
1879       else if (bbm1 == 0)
1880 	fprintf (stderr, " %.06f\n", MAX(boxsize[1]*0.2, 2*shore_depth_tol));
1881       else
1882 	fprintf (stderr, " (%.06f * %.06f)\n", boxsize[1], -bbm1);
1883     }
1884     if (*nrandom < 0) {
1885       real n1, n2, area2;
1886       area2 = (xmax[1] - xmin[1])*(xmax[0] - xmin[0]);
1887       n1 = (int) area2/(shore_depth_tol*shore_depth_tol);
1888       n2 = n*((int) area2/area);
1889       *nrandom = MAX(n1, n2);
1890     }
1891     srand(123);
1892     xran = MALLOC(sizeof(real)*(*nrandom + 4)*dim2);
1893     nz = 0;
1894     if (INCLUDE_OK_POINTS){
1895       int *grouping2;
1896       nzok0 = nzok = *nrandom - 1;/* points that are within tolerance of real or artificial points */
1897       grouping2 = MALLOC(sizeof(int)*(n + *nrandom));
1898       memcpy(grouping2, grouping, sizeof(int)*n);
1899       grouping = grouping2;
1900     }
1901     nn = n;
1902 
1903     for (i = 0; i < *nrandom; i++){
1904 
1905       for (j = 0; j < dim2; j++){
1906 	point[j] = xmin[j] + (xmax[j] - xmin[j])*drand();
1907       }
1908 
1909       QuadTree_get_nearest(qt, point, ymin, &imin, &min, flag);
1910       assert(!(*flag));
1911 
1912       if (min > shore_depth_tol){/* point not too close, accepted */
1913 	for (j = 0; j < dim2; j++){
1914 	  xran[nz*dim2+j] = point[j];
1915 	}
1916 	nz++;
1917       } else if (INCLUDE_OK_POINTS && min > shore_depth_tol/10){/* avoid duplicate points */
1918 	for (j = 0; j < dim2; j++){
1919 	  xran[nzok*dim2+j] = point[j];
1920 	}
1921 	grouping[nn++] = grouping[imin];
1922 	nzok--;
1923 
1924       }
1925 
1926     }
1927     *nrandom = nz;
1928     if (Verbose) fprintf( stderr, "nn nrandom=%d\n",*nrandom);
1929   } else {
1930     xran = MALLOC(sizeof(real)*4*dim2);
1931   }
1932 
1933 
1934 
1935   /* add 4 corners even if nrandom = 0. The corners should be further away from the other points to avoid skinny triangles */
1936   for (i = 0; i < dim2; i++) xmin[i] -= 0.2*(xmax[i]-xmin[i]);
1937   for (i = 0; i < dim2; i++) xmax[i] += 0.2*(xmax[i]-xmin[i]);
1938   i = *nrandom;
1939   for (j = 0; j < dim2; j++) xran[i*dim2+j] = xmin[j];
1940   i++;
1941   for (j = 0; j < dim2; j++) xran[i*dim2+j] = xmax[j];
1942   i++;
1943   xran[i*dim2] = xmin[0]; xran[i*dim2+1] = xmax[1];
1944   i++;
1945   xran[i*dim2] = xmax[0]; xran[i*dim2+1] = xmin[1];
1946   *nrandom += 4;
1947 
1948 
1949   if (INCLUDE_OK_POINTS){
1950     *xcombined = MALLOC(sizeof(real)*(nn+*nrandom)*dim2);
1951   } else {
1952     *xcombined = MALLOC(sizeof(real)*(n+*nrandom)*dim2);
1953   }
1954   for (i = 0; i < n; i++) {
1955     for (j = 0; j < dim2; j++) (*xcombined)[i*dim2+j] = x[i*dim+j];
1956   }
1957   for (i = 0; i < *nrandom; i++) {
1958     for (j = 0; j < dim2; j++) (*xcombined)[(i + nn)*dim2+j] = xran[i*dim+j];
1959   }
1960 
1961   if (INCLUDE_OK_POINTS){
1962     for (i = 0; i < nn - n; i++) {
1963       for (j = 0; j < dim2; j++) (*xcombined)[(i + n)*dim2+j] = xran[(nzok0 - i)*dim+j];
1964     }
1965     n = nn;
1966   }
1967 
1968 
1969   {
1970     int nz, nh = 0;/* the set to highlight */
1971     real *xtemp;
1972     if (HIGHLIGHT_SET){
1973       if (Verbose) fprintf(stderr," highlight cluster %d, n = %d\n",HIGHLIGHT_SET, n);
1974       xtemp = MALLOC(sizeof(real)*n*dim);
1975       /* shift set to the beginning */
1976       nz = 0;
1977       for (i = 0; i < n; i++){
1978 	if (grouping[i] == HIGHLIGHT_SET){
1979 	  nh++;
1980 	  for (j = 0; j < dim; j++){
1981 	    xtemp[nz++] = x[i*dim+j];
1982 	  }
1983 	}
1984       }
1985       for (i = 0; i < n; i++){
1986 	if (grouping[i] != HIGHLIGHT_SET){
1987 	  for (j = 0; j < dim; j++){
1988 	    xtemp[nz++] = x[i*dim+j];
1989 	  }
1990 	}
1991       }
1992       assert(nz == n*dim);
1993       for (i = 0; i < nh; i++){
1994 	grouping[i] = 1;
1995       }
1996       for (i = nh; i < n; i++){
1997 	grouping[i] = 2;
1998       }
1999       memcpy(*xcombined, xtemp, n*dim*sizeof(real));
2000       *nrandom = *nrandom + n - nh;/* count everything except cluster HIGHLIGHT_SET as random */
2001       n = nh;
2002       if (Verbose) fprintf(stderr,"nh = %d\n",nh);
2003       FREE(xtemp);
2004     }
2005   }
2006 
2007   get_tri(n + *nrandom, dim2, *xcombined, &nt, &Tp, &E, flag);
2008   get_polygons(exclude_random, n, *nrandom, dim2, graph, *xcombined, grouping, nt, Tp, E, nverts, x_poly, npolys, poly_lines, polys, polys_groups,
2009 	       poly_point_map, country_graph, flag);
2010   /*
2011   {
2012     plot_voronoi(n + *nrandom, E, Tp);
2013     printf("(*voronoi*),");
2014 
2015   }
2016 */
2017 
2018 
2019 
2020 
2021   SparseMatrix_delete(E);
2022   FREE(Tp);
2023   FREE(xran);
2024   if (grouping != grouping0) FREE(grouping);
2025   if (x != x0) FREE(x);
2026   return 0;
2027 }
2028 
2029 
make_map_from_point_groups(int exclude_random,int include_OK_points,int n,int dim,real * x,int * grouping,SparseMatrix graph,real bounding_box_margin[],int * nrandom,real shore_depth_tol,real edge_bridge_tol,real ** xcombined,int * nverts,real ** x_poly,int * npolys,SparseMatrix * poly_lines,SparseMatrix * polys,int ** polys_groups,SparseMatrix * poly_point_map,SparseMatrix * country_graph,int * flag)2030 int make_map_from_point_groups(int exclude_random, int include_OK_points,
2031 			       int n, int dim, real *x, int *grouping, SparseMatrix graph, real bounding_box_margin[], int *nrandom,
2032 			       real shore_depth_tol, real edge_bridge_tol, real **xcombined, int *nverts, real **x_poly,
2033 			       int *npolys, SparseMatrix *poly_lines, SparseMatrix *polys, int **polys_groups, SparseMatrix *poly_point_map,
2034 			       SparseMatrix *country_graph, int *flag){
2035 
2036   /* create a list of polygons from a list of points in 2D. Points belong to groups. Points in the same group that are also close
2037      gemetrically will be in the same polygon describing the outline of the group.
2038 
2039      input:
2040      exclude_random:
2041      include_OK_points: OK points are random points inserted and found to be within shore_depth_tol of real/artificial points,
2042      .                  including them instead of throwing away increase realism of boundary
2043      n: number of points
2044      dim: dimension of the points. If dim > 2, only the first 2D is used.
2045      x: coordinates
2046      grouping: which group each of the vertex belongs to
2047      graph: the link structure between points. If graph == NULL, this is not used. otherwise
2048      .      it is assumed that matrix is symmetric and the graph is undirected
2049      bounding_box_margin: margins used to form the bounding box. Dimension 2.
2050      .      if negative, it is taken as relative. i.e., -0.5 means a margin of 0.5*box_size
2051      nrandom (inout): number of random points to insert in the bounding box to figure out lakes and seas.
2052      .        If nrandom = 0, no points are inserted, if nrandom < 0, the number is decided automatically.
2053      .        On exit, it is the actual number of random points used. The last 4 "random" points is always the
2054      .
2055      shore_depth_tol: nrandom random points are inserted in the bounding box of the points,
2056      .      such random points are then weeded out if it is within distance of shore_depth_tol from
2057      .      real points. If < 0, auto assigned
2058      edge_bridge_tol: insert points on edges to give an bridge effect.These points will be evenly spaced
2059      .       along each edge, and be less than a distance of edge_bridge_tol from each other and from the two ends of the edge.
2060      .       If < 0, -edge_bridge_tol is the average number of points inserted per half edge
2061      output:
2062      xcombined: combined points which contains n + ncombined number of points, dimension 2x(n+nrandom)
2063      npolys: number of polygons generated to reprsent the real points, the edge insertion points, and the sea/lake points.
2064      nverts: number of vertices in the Voronoi diagram
2065      x_poly: the 2D coordinates of these polygons
2066      poly_lines: the sparse matrix representation of the polygon indices, as well as their identity. The matrix is of size
2067      .       npolygons x nverts. The i-th polygon is formed by linking vertices with index in the i-th row of the sparse matrix.
2068      .       Each row is of the form {{i,j1,m},...{i,jk,m},{i,j1,m},{i,l1,m+1},...}, where j1--j2--jk--j1 form one loop,
2069      .       and l1 -- l2 -- ... form another. Each row can have more than 1 loop only when the connected region the polylines represent
2070      .       has at least 1 holes.
2071      polys: the sparse matrix representation of the polygon indices, as well as their identity. The matrix is of size
2072      .       npolygons x nverts. The i-th polygon is formed by linking vertices with index in the i-th row of the sparse matrix.
2073      .       Unlike poly_lines, here each row represent an one stroke drawing of the SOLID polygon, vertices
2074      .       along this path may repeat
2075      polys_groups: the group (color) each polygon belongs to, this include all groups of the real points,
2076      .       plus the random point group and the bounding box group
2077      poly_point_map: a matrix of dimension npolys x (n + nrandom), poly_point_map[i,j] != 0 if polygon i contains the point j.
2078      .  If j < n, it is the original point, otherwise it is
2079      country_graph: shows which country is a neighbor of which country.
2080      .     if country i and country j are neighbor, then the {i,j} entry is the total number of vertices that
2081      .     belongs to i and j, and share an edge of the triangulation. In addition, {i,i} and {j,j} have values equal
2082      .     to the number of vertices in each of the countries. If the input "grouping" has negative or zero value, then
2083      .     country_graph = NULL.
2084 
2085   */
2086   int res;
2087   int nedgep = 0;
2088   int highlight_cluster = FALSE;
2089   /* get poly outlines */
2090   res = make_map_internal(exclude_random, include_OK_points, n, dim, x, grouping, graph, bounding_box_margin, nrandom, nedgep,
2091 		  shore_depth_tol, edge_bridge_tol, xcombined, nverts, x_poly,
2092 			  npolys, poly_lines, polys, polys_groups, poly_point_map, country_graph, highlight_cluster, flag);
2093 
2094   printf("Show[{");
2095 
2096   plot_points(n + *nrandom, dim, *xcombined);
2097 
2098 
2099   printf(",");
2100   plot_polys(TRUE, *poly_lines, *x_poly, *polys_groups, NULL, NULL, NULL);
2101 
2102   printf("}]\n");
2103 
2104   return res;
2105 }
2106 
add_point(int * n,int igrp,real ** x,int * nmax,real point[],int ** groups)2107 static void add_point(int *n, int igrp, real **x, int *nmax, real point[], int **groups){
2108 
2109   if (*n >= *nmax){
2110     *nmax = MAX((int) 0.2*(*n), 20) + *n;
2111     *x = REALLOC(*x, sizeof(real)*2*(*nmax));
2112     *groups = REALLOC(*groups, sizeof(int)*(*nmax));
2113   }
2114 
2115   (*x)[(*n)*2] = point[0];
2116   (*x)[(*n)*2+1] = point[1];
2117   (*groups)[*n] = igrp;
2118   (*n)++;
2119 
2120 }
2121 
get_boundingbox(int n,int dim,real * x,real * width,real * bbox)2122 static void get_boundingbox(int n, int dim, real *x, real *width, real *bbox){
2123   int i;
2124   bbox[0] = bbox[1] = x[0];
2125   bbox[2] = bbox[3] = x[1];
2126 
2127   for (i = 0; i < n; i++){
2128     bbox[0] = MIN(bbox[0], x[i*dim] - width[i*dim]);
2129     bbox[1] = MAX(bbox[1], x[i*dim] + width[i*dim]);
2130     bbox[2] = MIN(bbox[2], x[i*dim + 1] - width[i*dim+1]);
2131     bbox[3] = MAX(bbox[3], x[i*dim + 1] + width[i*dim+1]);
2132   }
2133 }
2134 
2135 
make_map_from_rectangle_groups(int exclude_random,int include_OK_points,int n,int dim,real * x,real * sizes,int * grouping,SparseMatrix graph0,real bounding_box_margin[],int * nrandom,int * nart,int nedgep,real shore_depth_tol,real edge_bridge_tol,real ** xcombined,int * nverts,real ** x_poly,int * npolys,SparseMatrix * poly_lines,SparseMatrix * polys,int ** polys_groups,SparseMatrix * poly_point_map,SparseMatrix * country_graph,int highlight_cluster,int * flag)2136 int make_map_from_rectangle_groups(int exclude_random, int include_OK_points,
2137 				   int n, int dim, real *x, real *sizes,
2138 				   int *grouping, SparseMatrix graph0, real bounding_box_margin[], int *nrandom, int *nart, int nedgep,
2139 				   real shore_depth_tol, real edge_bridge_tol,
2140 				   real **xcombined, int *nverts, real **x_poly,
2141 				   int *npolys, SparseMatrix *poly_lines, SparseMatrix *polys, int **polys_groups, SparseMatrix *poly_point_map,
2142 				   SparseMatrix *country_graph, int highlight_cluster, int *flag){
2143 
2144   /* create a list of polygons from a list of rectangles in 2D. rectangles belong to groups. rectangles in the same group that are also close
2145      geometrically will be in the same polygon describing the outline of the group. The main difference for this function and
2146      make_map_from_point_groups is that in this function, the input are points with width/heights, and we try not to place
2147      "lakes" inside these rectangles. This is achieved approximately by adding artificial points along the perimeter of the rectangles,
2148      as well as near the center.
2149 
2150      input:
2151      include_OK_points: OK points are random points inserted and found to be within shore_depth_tol of real/artificial points,
2152      .                  including them instead of throwing away increase realism of boundary
2153      n: number of points
2154      dim: dimension of the points. If dim > 2, only the first 2D is used.
2155      x: coordinates
2156      sizes: width and height
2157      grouping: which group each of the vertex belongs to
2158      graph: the link structure between points. If graph == NULL, this is not used. otherwise
2159      .      it is assumed that matrix is symmetric and the graph is undirected
2160      bounding_box_margin: margins used to form the bounding box. Dimension 2.
2161      .      if negative, it is taken as relative. i.e., -0.5 means a margin of 0.5*box_size
2162      nrandom (inout): number of random points to insert in the bounding box to figure out lakes and seas.
2163      .        If nrandom = 0, no points are inserted, if nrandom < 0, the number is decided automatically.
2164      .        On exit, it is the actual number of random points used. The last 4 "random" points is always the
2165      .
2166      nart: on entry, number of artificial points to be added along each side of a rectangle enclosing the labels. if < 0, auto-selected.
2167      . On exit, actual number of artificial points added.
2168      nedgep: number of artificial points are adding along edges to establish as much as possible a bright between nodes
2169      .       connected by the edge, and avoid islands that are connected. k = 0 mean no points.
2170      shore_depth_tol: nrandom random points are inserted in the bounding box of the points,
2171      .      such random points are then weeded out if it is within distance of shore_depth_tol from
2172      .      real points. If 0, auto assigned
2173      edge_bridge_tol: insert points on edges to give an bridge effect.These points will be evenly spaced
2174      .       along each edge, and be less than a distance of edge_bridge_tol from each other and from the two ends of the edge.
2175      .       If < 0, -edge_bridge_tol is the average number of points inserted per half edge
2176 
2177      output:
2178      xcombined: combined points which contains n + ncombined number of points, dimension 2x(n+nrandom)
2179      npolys: number of polygons generated to reprsent the real points, the edge insertion points, and the sea/lake points.
2180      nverts: number of vertices in the Voronoi diagram
2181      x_poly: the 2D coordinates of these polygons, dimension nverts*2
2182      poly_lines: the sparse matrix representation of the polygon indices, as well as their identity. The matrix is of size
2183      .       npolygons x nverts. The i-th polygon is formed by linking vertices with index in the i-th row of the sparse matrix.
2184      .       Each row is of the form {{i,j1,m},...{i,jk,m},{i,j1,m},{i,l1,m+1},...}, where j1--j2--jk--j1 form one loop,
2185      .       and l1 -- l2 -- ... form another. Each row can have more than 1 loop only when the connected region the polylines represent
2186      .       has at least 1 holes.
2187      polys: the sparse matrix representation of the polygon indices, as well as their identity. The matrix is of size
2188      .       npolygons x nverts. The i-th polygon is formed by linking vertices with index in the i-th row of the sparse matrix.
2189      .       Unlike poly_lines, here each row represent an one stroke drawing of the SOLID polygon, vertices
2190      .       along this path may repeat
2191      polys_groups: the group (color) each polygon belongs to, this include all groups of the real points,
2192      .       plus the random point group and the bounding box group
2193      poly_point_map: a matrix of dimension npolys x (n + nrandom), poly_point_map[i,j] != 0 if polygon i contains the point j.
2194      .  If j < n, it is the original point, otherwise it is artificial point (forming the rectangle around a label) or random points.
2195     country_graph: shows which country is a neighbor of which country.
2196      .     if country i and country j are neighbor, then the {i,j} entry is the total number of vertices that
2197      .     belongs to i and j, and share an edge of the triangulation. In addition, {i,i} and {j,j} have values equal
2198      .     to the number of vertices in each of the countries. If the input "grouping" has negative or zero value, then
2199      .     country_graph = NULL.
2200 
2201 
2202   */
2203     real dist, avgdist;
2204   real *X;
2205   int N, nmax, i, j, k, igrp;
2206   int *groups, K = *nart;/* average number of points added per side of rectangle */
2207 
2208   real avgsize[2],  avgsz, h[2], p1, p0;
2209   real point[2];
2210   int nadded[2];
2211   int res;
2212   real delta[2];
2213   SparseMatrix graph = graph0;
2214   real bbox[4];
2215 
2216   if (K < 0){
2217     K = (int) 10/(1+n/400.);/* 0 if n > 3600*/
2218   }
2219   *nart = 0;
2220   if (Verbose){
2221     int maxgp = grouping[0];
2222     int mingp = grouping[0];
2223     for (i = 0; i < n; i++) {
2224       maxgp = MAX(maxgp, grouping[i]);
2225       mingp = MIN(mingp, grouping[i]);
2226     }
2227     fprintf(stderr, "max grouping - min grouping + 1 = %d\n",maxgp - mingp + 1);
2228   }
2229 
2230   if (!sizes){
2231     return make_map_internal(exclude_random, include_OK_points, n, dim, x, grouping, graph, bounding_box_margin, nrandom, nedgep,
2232 			    shore_depth_tol, edge_bridge_tol, xcombined, nverts, x_poly,
2233 			     npolys, poly_lines, polys, polys_groups, poly_point_map, country_graph, highlight_cluster, flag);
2234   } else {
2235 
2236     /* add artificial node due to node sizes */
2237     avgsize[0] = 0;
2238     avgsize[1] = 0;
2239     for (i = 0; i < n; i++){
2240       for (j = 0; j < 2; j++) {
2241 	avgsize[j] += sizes[i*dim+j];
2242       }
2243     }
2244     for (i = 0; i < 2; i++) avgsize[i] /= n;
2245     avgsz = 0.5*(avgsize[0] + avgsize[1]);
2246     if (Verbose) fprintf(stderr, "avgsize = {%f, %f}\n",avgsize[0], avgsize[1]);
2247 
2248     nmax = 2*n;
2249     X = MALLOC(sizeof(real)*dim*(n+nmax));
2250     groups = MALLOC(sizeof(int)*(n+nmax));
2251     for (i = 0; i < n; i++) {
2252       groups[i] = grouping[i];
2253       for (j = 0; j < 2; j++){
2254 	X[i*2+j] = x[i*dim+j];
2255       }
2256     }
2257     N = n;
2258 
2259     if (shore_depth_tol < 0) {
2260       shore_depth_tol = -(shore_depth_tol)*avgsz;
2261     } else if (shore_depth_tol == 0){
2262       real area;
2263       get_boundingbox(n, dim, x, sizes, bbox);
2264       //shore_depth_tol = MIN(bbox[1] - bbox[0], bbox[3] - bbox[2])*0.05;
2265       area = (bbox[1] - bbox[0])*(bbox[3] - bbox[2]);
2266       shore_depth_tol = sqrt(area/(real) n);
2267       if (Verbose) fprintf(stderr,"setting shore length ======%f\n",shore_depth_tol);
2268     } else {
2269       /*
2270       get_boundingbox(n, dim, x, sizes, bbox);
2271       shore_depth_tol = MIN(bbox[1] - bbox[0], bbox[3] - bbox[2])*shore_depth_tol;
2272       */
2273 
2274     }
2275 
2276     /* add artificial points in an anti-clockwise fashion */
2277 
2278     if (K > 0){
2279       delta[0] = .5*avgsize[0]/K; delta[1] = .5*avgsize[1]/K;/* small perturbation to make boundary between labels looks more fractal */
2280     } else {
2281       delta[0] = delta[1] = 0.;
2282     }
2283     for (i = 0; i < n; i++){
2284       igrp = grouping[i];
2285       for (j = 0; j < 2; j++) {
2286 	if (avgsz == 0){
2287 	  nadded[j] = 0;
2288 	} else {
2289 	  nadded[j] = (int) K*sizes[i*dim+j]/avgsz;
2290 	}
2291       }
2292 
2293       /*top: left to right */
2294       if (nadded[0] > 0){
2295 	h[0] = sizes[i*dim]/nadded[0];
2296 	point[0] = x[i*dim] - sizes[i*dim]/2;
2297 	p1 = point[1] = x[i*dim+1] + sizes[i*dim + 1]/2;
2298 	add_point(&N, igrp, &X, &nmax, point, &groups);
2299 	for (k = 0; k < nadded[0] - 1; k++){
2300 	  point[0] += h[0];
2301 	  point[1] = p1 + (0.5-drand())*delta[1];
2302 	  add_point(&N, igrp, &X, &nmax, point, &groups);
2303 	}
2304 
2305 	/* bot: right to left */
2306 	point[0] = x[i*dim] + sizes[i*dim]/2;
2307 	p1 = point[1] = x[i*dim+1] - sizes[i*dim + 1]/2;
2308 	add_point(&N, igrp, &X, &nmax, point, &groups);
2309 	for (k = 0; k < nadded[0] - 1; k++){
2310 	  point[0] -= h[0];
2311 	  point[1] = p1 + (0.5-drand())*delta[1];
2312 	  add_point(&N, igrp, &X, &nmax, point, &groups);
2313 	}
2314       }
2315 
2316       if (nadded[1] > 0){
2317 	/* left: bot to top */
2318 	h[1] = sizes[i*dim + 1]/nadded[1];
2319 	p0 = point[0] = x[i*dim] - sizes[i*dim]/2;
2320 	point[1] = x[i*dim+1] - sizes[i*dim + 1]/2;
2321 	add_point(&N, igrp, &X, &nmax, point, &groups);
2322 	for (k = 0; k < nadded[1] - 1; k++){
2323 	  point[0] = p0 + (0.5-drand())*delta[0];
2324 	  point[1] += h[1];
2325 	  add_point(&N, igrp, &X, &nmax, point, &groups);
2326 	}
2327 
2328 	/* right: top to bot */
2329 	p0 = point[0] = x[i*dim] + sizes[i*dim]/2;
2330 	point[1] = x[i*dim+1] + sizes[i*dim + 1]/2;
2331 	add_point(&N, igrp, &X, &nmax, point, &groups);
2332 	for (k = 0; k < nadded[1] - 1; k++){
2333 	  point[0] = p0 + (0.5-drand())*delta[0];
2334 	  point[1] -= h[1];
2335 	  add_point(&N, igrp, &X, &nmax, point, &groups);
2336 	}
2337       }
2338       *nart = N - n;
2339 
2340     }/* done adding artificial points due to node size*/
2341 
2342 
2343     /* add artificial node due to edges */
2344     if (graph && edge_bridge_tol != 0){
2345       int *ia = graph->ia, *ja = graph->ja, nz = 0, jj;
2346       int KB;
2347 
2348       graph = SparseMatrix_symmetrize(graph, TRUE);
2349       ia = graph->ia; ja = graph->ja;
2350       dist=avgdist = 0.;
2351       for (i = 0; i < n; i++){
2352 	for (j = ia[i]; j < ia[i+1]; j++){
2353 	  jj = ja[j];
2354 	  if (jj <= i) continue;
2355 	  dist = distance(x, dim, i, jj);
2356 	  avgdist += dist;
2357 	  nz++;
2358 	}
2359       }
2360       avgdist /= nz;
2361       if (edge_bridge_tol < 0){
2362 	KB = (int) (-edge_bridge_tol);
2363       } else {
2364 	KB = (int) (avgdist/edge_bridge_tol);
2365       }
2366 
2367       assert(avgdist > 0);
2368       for (i = 0; i < n; i++){
2369 	for (j = ia[i]; j < ia[i+1]; j++){
2370 	  jj = ja[j];
2371 	  if (jj <= i) continue;
2372 	  dist = distance(x, dim, i, jj);
2373 	  nadded[0] = (int) 2*KB*dist/avgdist;
2374 
2375 	  /* half the line segment near i */
2376 	  h[0] = 0.5*(x[jj*dim] - x[i*dim])/nadded[0];
2377 	  h[1] = 0.5*(x[jj*dim+1] - x[i*dim+1])/nadded[0];
2378 	  point[0] = x[i*dim];
2379 	  point[1] = x[i*dim+1];
2380 	  for (k = 0; k < nadded[0] - 1; k++){
2381 	    point[0] += h[0];
2382 	    point[1] += h[1];
2383 	    add_point(&N, grouping[i], &X, &nmax, point, &groups);
2384 	  }
2385 
2386 	  /* half the line segment near jj */
2387 	  h[0] = 0.5*(x[i*dim] - x[jj*dim])/nadded[0];
2388 	  h[1] = 0.5*(x[i*dim+1] - x[jj*dim+1])/nadded[0];
2389 	  point[0] = x[jj*dim];
2390 	  point[1] = x[jj*dim+1];
2391 	  for (k = 0; k < nadded[0] - 1; k++){
2392 	    point[0] += h[0];
2393 	    point[1] += h[1];
2394 	    add_point(&N, grouping[jj], &X, &nmax, point, &groups);
2395 	  }
2396 	}
2397 
2398       }/* done adding artifial points for edges */
2399     }
2400 
2401     res = make_map_internal(exclude_random, include_OK_points, N, dim, X, groups, graph, bounding_box_margin, nrandom, nedgep,
2402 			    shore_depth_tol, edge_bridge_tol, xcombined, nverts, x_poly,
2403 			    npolys, poly_lines, polys, polys_groups, poly_point_map, country_graph, highlight_cluster, flag);
2404     if (graph != graph0) SparseMatrix_delete(graph);
2405     FREE(groups);
2406     FREE(X);
2407   }
2408 
2409   return res;
2410 
2411 }
2412