make_map.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #define STANDALONE
  11. #include <assert.h>
  12. #include <sparse/SparseMatrix.h>
  13. #include <sparse/general.h>
  14. #include <math.h>
  15. #include <sparse/QuadTree.h>
  16. #include <stdbool.h>
  17. #include <stddef.h>
  18. #include <string.h>
  19. #include <cgraph/list.h>
  20. #include <cgraph/cgraph.h>
  21. #include "make_map.h"
  22. #include <sfdpgen/stress_model.h>
  23. #include "country_graph_coloring.h"
  24. #include <sparse/colorutil.h>
  25. #include <neatogen/delaunay.h>
  26. #include <util/agxbuf.h>
  27. #include <util/alloc.h>
  28. #include <util/prisize_t.h>
  29. #include <edgepaint/lab.h>
  30. #include <edgepaint/node_distinct_coloring.h>
  31. void map_palette_optimal_coloring(char *color_scheme, SparseMatrix A0,
  32. float **rgb_r, float **rgb_g, float **rgb_b){
  33. /*
  34. for a graph A, get a distinctive color of its nodes so that the color distanmce among all nodes are maximized. Here
  35. color distance on a node is defined as the minimum of color differences between a node and its neighbors.
  36. 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"
  37. A: the graph of n nodes
  38. cdim: dimension of the color space
  39. rgb_r, rgb_g, rgb_b: float array of length A->m + 1, which contains color for each country. 1-based
  40. */
  41. /*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)
  42. */
  43. double *colors = NULL;
  44. int n = A0->m, i, cdim;
  45. SparseMatrix A;
  46. bool weightedQ = true;
  47. {double *dist = NULL;
  48. A = SparseMatrix_symmetrize(A0, false);
  49. SparseMatrix_distance_matrix(A, &dist);
  50. SparseMatrix_delete(A);
  51. A = SparseMatrix_from_dense(n, n, dist);
  52. free(dist);
  53. A = SparseMatrix_remove_diagonal(A);
  54. SparseMatrix_export(stdout, A);
  55. }
  56. // lightness: of the form 0,70, specifying the range of lightness of LAB
  57. // color. Ignored if scheme is not COLOR_LAB.
  58. int lightness[] = {0, 100};
  59. // accuracy is the threshold given so that when finding the coloring for each
  60. // node, the optimal is with in "accuracy" of the true global optimal.
  61. const double accuracy = 0.01;
  62. // seed: random_seed. If negative, consider -seed as the number of random
  63. // start iterations
  64. const int seed = -10;
  65. node_distinct_coloring(color_scheme, lightness, weightedQ, A, accuracy, seed,
  66. &cdim, &colors);
  67. if (A != A0){
  68. SparseMatrix_delete(A);
  69. }
  70. *rgb_r = gv_calloc(n + 1, sizeof(float));
  71. *rgb_g = gv_calloc(n + 1, sizeof(float));
  72. *rgb_b = gv_calloc(n + 1, sizeof(float));
  73. for (i = 0; i < n; i++){
  74. (*rgb_r)[i+1] = (float) colors[cdim*i];
  75. (*rgb_g)[i+1] = (float) colors[cdim*i + 1];
  76. (*rgb_b)[i+1] = (float) colors[cdim*i + 2];
  77. }
  78. free(colors);
  79. }
  80. void map_optimal_coloring(int seed, SparseMatrix A, float *rgb_r, float *rgb_g, float *rgb_b){
  81. int *p = NULL;
  82. float *u = NULL;
  83. int n = A->m;
  84. int i;
  85. country_graph_coloring(seed, A, &p);
  86. rgb_r++; rgb_b++; rgb_g++;/* seems necessary, but need to better think about cases when clusters are not contiguous */
  87. vector_float_take(n, rgb_r, n, p, &u);
  88. for (i = 0; i < n; i++) rgb_r[i] = u[i];
  89. vector_float_take(n, rgb_g, n, p, &u);
  90. for (i = 0; i < n; i++) rgb_g[i] = u[i];
  91. vector_float_take(n, rgb_b, n, p, &u);
  92. for (i = 0; i < n; i++) rgb_b[i] = u[i];
  93. free(u);
  94. }
  95. static int get_poly_id(int ip, SparseMatrix point_poly_map){
  96. return point_poly_map->ja[point_poly_map->ia[ip]];
  97. }
  98. void improve_contiguity(int n, int dim, int *grouping, SparseMatrix poly_point_map, double *x, SparseMatrix graph){
  99. /*
  100. grouping: which group each of the vertex belongs to
  101. poly_point_map: a matrix of dimension npolys x (n + nrandom), poly_point_map[i,j] != 0 if polygon i contains the point j.
  102. . If j < n, it is the original point, otherwise it is artificial point (forming the rectangle around a label) or random points.
  103. */
  104. int i, j, *ia, *ja, u, v;
  105. SparseMatrix point_poly_map, D;
  106. double dist;
  107. int nbad = 0, flag;
  108. int maxit = 10;
  109. D = SparseMatrix_get_real_adjacency_matrix_symmetrized(graph);
  110. assert(graph->m == n);
  111. ia = D->ia; ja = D->ja;
  112. double *a = D->a;
  113. /* point_poly_map: each row i has only 1 entry at column j, which says that point i is in polygon j */
  114. point_poly_map = SparseMatrix_transpose(poly_point_map);
  115. for (i = 0; i < n; i++){
  116. u = i;
  117. for (j = ia[i]; j < ia[i+1]; j++){
  118. v = ja[j];
  119. dist = distance_cropped(x, dim, u, v);
  120. if (grouping[u] != grouping[v]){
  121. a[j] = 1.1*dist;
  122. } else if (get_poly_id(u, point_poly_map) == get_poly_id(v, point_poly_map)){
  123. a[j] = dist;
  124. } else {
  125. nbad++;
  126. a[j] = 0.9*dist;
  127. }
  128. }
  129. }
  130. if (Verbose) fprintf(stderr,"ratio (edges among discontiguous regions vs total edges)=%f\n",((double) nbad)/ia[n]);
  131. stress_model(dim, D, &x, maxit, &flag);
  132. assert(!flag);
  133. SparseMatrix_delete(D);
  134. SparseMatrix_delete(point_poly_map);
  135. }
  136. struct Triangle {
  137. int vertices[3];/* 3 points */
  138. double center[2]; /* center of the triangle */
  139. };
  140. static void normal(double v[], double normal[]){
  141. if (v[0] == 0){
  142. normal[0] = 1; normal[1] = 0;
  143. } else {
  144. normal[0] = -v[1];
  145. normal[1] = v[0];
  146. }
  147. }
  148. static void triangle_center(double x[], double y[], double z[], double c[]){
  149. /* find the "center" c, which is the intersection of the 3 vectors that are normal to each
  150. of the edges respectively, and which passes through the center of the edges respectively
  151. center[{x_, y_, z_}] := Module[
  152. {xy = 0.5*(x + y), yz = 0.5*(y + z), zx = 0.5*(z + x), nxy, nyz,
  153. beta, cen},
  154. nxy = normal[y - x];
  155. nyz = normal[y - z];
  156. beta = (y-x).(xy - yz)/(nyz.(y-x));
  157. cen = yz + beta*nyz;
  158. Graphics[{Line[{x, y, z, x}], Red, Point[cen], Line[{cen, xy}],
  159. Line[{cen, yz}], Green, Line[{cen, zx}]}]
  160. ]
  161. */
  162. double xy[2], yz[2], nxy[2], nyz[2], ymx[2], ymz[2], beta, bot;
  163. int i;
  164. for (i = 0; i < 2; i++) ymx[i] = y[i] - x[i];
  165. for (i = 0; i < 2; i++) ymz[i] = y[i] - z[i];
  166. for (i = 0; i < 2; i++) xy[i] = 0.5*(x[i] + y[i]);
  167. for (i = 0; i < 2; i++) yz[i] = 0.5*(y[i] + z[i]);
  168. normal(ymx, nxy);
  169. normal(ymz, nyz);
  170. bot = nyz[0]*(x[0]-y[0])+nyz[1]*(x[1]-y[1]);
  171. if (bot == 0){/* xy and yz are parallel */
  172. c[0] = xy[0]; c[1] = xy[1];
  173. return;
  174. }
  175. beta = ((x[0] - y[0])*(xy[0] - yz[0])+(x[1] - y[1])*(xy[1] - yz[1]))/bot;
  176. c[0] = yz[0] + beta*nyz[0];
  177. c[1] = yz[1] + beta*nyz[1];
  178. }
  179. static SparseMatrix matrix_add_entry(SparseMatrix A, int i, int j, int val){
  180. int i1 = i, j1 = j;
  181. if (i < j) {
  182. i1 = j; j1 = i;
  183. }
  184. A = SparseMatrix_coordinate_form_add_entry(A, j1, i1, &val);
  185. return SparseMatrix_coordinate_form_add_entry(A, i1, j1, &val);
  186. }
  187. static void plot_dot_edges(FILE *f, SparseMatrix A){
  188. int i, *ia, *ja, j;
  189. int n = A->m;
  190. ia = A->ia;
  191. ja = A->ja;
  192. for (i = 0; i < n; i++){
  193. for (j = ia[i]; j < ia[i+1]; j++){
  194. if (ja[j] == i) continue;
  195. fprintf(f,"%d -- %d;\n",i,ja[j]);
  196. }
  197. }
  198. }
  199. static void plot_dot_labels(FILE *f, int n, int dim, double *x, char **labels, float *fsz){
  200. int i;
  201. for (i = 0; i < n; i++){
  202. if (fsz){
  203. fprintf(f, "%d [label=\"%s\", pos=\"%lf,%lf\", fontsize=%f];\n",i, labels[i], x[i*dim], x[i*dim+1], fsz[i]);
  204. } else {
  205. fprintf(f, "%d [label=\"%s\", pos=\"%lf,%lf\"];\n",i, labels[i], x[i*dim], x[i*dim+1]);
  206. }
  207. }
  208. }
  209. DEFINE_LIST(doubles, double)
  210. static void dot_polygon(agxbuf *sbuff, doubles_t xp, doubles_t yp,
  211. double line_width, bool fill, const char *cstring) {
  212. assert(doubles_size(&xp) == doubles_size(&yp));
  213. if (!doubles_is_empty(&xp)){
  214. if (fill) {
  215. agxbprint(sbuff,
  216. " c %" PRISIZE_T " -%s C %" PRISIZE_T " -%s P %" PRISIZE_T " ",
  217. strlen(cstring), cstring, strlen(cstring), cstring,
  218. doubles_size(&xp));
  219. } else {
  220. if (line_width > 0){
  221. size_t len_swidth = (size_t)snprintf(NULL, 0, "%f", line_width);
  222. agxbprint(sbuff, " c %" PRISIZE_T " -%s S %" PRISIZE_T
  223. " -setlinewidth(%f) L %" PRISIZE_T " ", strlen(cstring), cstring,
  224. len_swidth + 14, line_width, doubles_size(&xp));
  225. } else {
  226. agxbprint(sbuff, " c %" PRISIZE_T " -%s L %" PRISIZE_T " ", strlen(cstring),
  227. cstring, doubles_size(&xp));
  228. }
  229. }
  230. for (size_t i = 0; i < doubles_size(&xp); i++) {
  231. agxbprint(sbuff, " %f %f", doubles_get(&xp, i), doubles_get(&yp, i));
  232. }
  233. }
  234. }
  235. static void plot_dot_polygons(agxbuf *sbuff, double line_width,
  236. const char *line_color, SparseMatrix polys,
  237. double *x_poly, int *polys_groups, float *r,
  238. float *g, float *b, const char *opacity) {
  239. int i, j, *ia = polys->ia, *ja = polys->ja, *a = polys->a, npolys = polys->m, nverts = polys->n, ipoly,first;
  240. const bool fill = false;
  241. const bool use_line = line_width >= 0;
  242. agxbuf cstring_buffer = {0};
  243. agxbput(&cstring_buffer, "#aaaaaaff");
  244. char *cstring = agxbuse(&cstring_buffer);
  245. doubles_t xp = {0};
  246. doubles_t yp = {0};
  247. if (Verbose) fprintf(stderr,"npolys = %d\n",npolys);
  248. first = abs(a[0]); ipoly = first + 1;
  249. for (i = 0; i < npolys; i++){
  250. for (j = ia[i]; j < ia[i+1]; j++){
  251. assert(ja[j] < nverts && ja[j] >= 0);
  252. (void)nverts;
  253. if (abs(a[j]) != ipoly){/* the first poly, or a hole */
  254. ipoly = abs(a[j]);
  255. if (r && g && b) {
  256. rgb2hex(r[polys_groups[i]], g[polys_groups[i]], b[polys_groups[i]],
  257. &cstring_buffer, opacity);
  258. cstring = agxbuse(&cstring_buffer);
  259. }
  260. dot_polygon(sbuff, xp, yp, line_width, fill, cstring);
  261. // start a new polygon
  262. doubles_clear(&xp);
  263. doubles_clear(&yp);
  264. }
  265. doubles_append(&xp, x_poly[2 * ja[j]]);
  266. doubles_append(&yp, x_poly[2 * ja[j] + 1]);
  267. }
  268. if (use_line) {
  269. dot_polygon(sbuff, xp, yp, line_width, fill, line_color);
  270. } else {
  271. /* why set fill to polys_groups[i]?*/
  272. dot_polygon(sbuff, xp, yp, -1, true, cstring);
  273. }
  274. }
  275. agxbfree(&cstring_buffer);
  276. doubles_free(&xp);
  277. doubles_free(&yp);
  278. }
  279. void plot_dot_map(Agraph_t* gr, int n, int dim, double *x, SparseMatrix polys,
  280. SparseMatrix poly_lines, double line_width,
  281. const char *line_color, double *x_poly, int *polys_groups,
  282. char **labels, float *fsz, float *r, float *g, float *b,
  283. const char* opacity, SparseMatrix A, FILE* f) {
  284. /* if graph object exist, we just modify some attributes, otherwise we dump the whole graph */
  285. bool plot_polyQ = true;
  286. agxbuf sbuff = {0};
  287. if (!r || !g || !b) plot_polyQ = false;
  288. if (!gr) {
  289. 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");
  290. } else {
  291. agattr(gr, AGNODE, "margin", "0");
  292. agattr(gr, AGNODE, "width", "0.0001");
  293. agattr(gr, AGNODE, "height", "0.0001");
  294. agattr(gr, AGNODE, "shape", "plaintext");
  295. agattr(gr, AGNODE, "margin", "0");
  296. agattr(gr, AGNODE, "fontname", "Helvetica-Bold");
  297. agattr(gr, AGRAPH, "outputorder", "edgesfirst");
  298. agattr(gr, AGRAPH, "bgcolor", "#dae2ff");
  299. if (!A) agattr(gr, AGEDGE, "style","invis");/* do not plot edges */
  300. }
  301. /*polygons */
  302. if (plot_polyQ) {
  303. if (!gr) fprintf(f,"_background = \"");
  304. plot_dot_polygons(&sbuff, -1., NULL, polys, x_poly, polys_groups, r, g, b, opacity);
  305. }
  306. /* polylines: line width is set here */
  307. if (line_width >= 0){
  308. plot_dot_polygons(&sbuff, line_width, line_color, poly_lines, x_poly, polys_groups, NULL, NULL, NULL, NULL);
  309. }
  310. if (!gr) {
  311. fprintf(f,"%s",agxbuse(&sbuff));
  312. fprintf(f,"\"\n");/* close polygons/lines */
  313. } else {
  314. agattr(gr, AGRAPH, "_background", agxbuse(&sbuff));
  315. agwrite(gr, f);
  316. }
  317. /* nodes */
  318. if (!gr && labels) plot_dot_labels(f, n, dim, x, labels, fsz);
  319. /* edges */
  320. if (!gr && A) plot_dot_edges(f, A);
  321. /* background color + plot label?*/
  322. if (!gr) fprintf(f, "}\n");
  323. agxbfree(&sbuff);
  324. }
  325. /** construct triangles
  326. *
  327. * Always contains a self edge and is symmetric.
  328. *
  329. * @param n Number of points
  330. * @param dim Dimension, only first2D is used
  331. * @param x Point j is stored x[j × dim] -- x[j × dim + dim - 1]
  332. * @param nt [out] Number of triangles
  333. * @param T [out] triangles
  334. * @param E [out] A matrix of size n×n, if two points i > j are connected by an
  335. * triangulation edge, and is neighboring two triangles t1 and t2, then
  336. * A[i, j] is both t1 and t2
  337. * @return 0 on success
  338. */
  339. static int get_tri(int n, int dim, double *x, int *nt, struct Triangle **T,
  340. SparseMatrix *E) {
  341. int i, j, i0, i1, i2, ntri;
  342. SparseMatrix A, B;
  343. int* trilist = get_triangles(x, n, &ntri);
  344. if (trilist == NULL) {
  345. return -1;
  346. }
  347. *T = gv_calloc(ntri, sizeof(struct Triangle));
  348. A = SparseMatrix_new(n, n, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
  349. for (i = 0; i < ntri; i++) {
  350. for (j = 0; j < 3; j++) {
  351. (*T)[i].vertices[j] = trilist[i * 3 + j];
  352. }
  353. i0 = (*T)[i].vertices[0]; i1 = (*T)[i].vertices[1]; i2 = (*T)[i].vertices[2];
  354. triangle_center(&x[i0*dim], &x[i1*dim], &x[i2*dim], (*T)[i].center);
  355. A = matrix_add_entry(A, i0, i1, i);
  356. A = matrix_add_entry(A, i1, i2, i);
  357. A = matrix_add_entry(A, i2, i0, i);
  358. }
  359. B = SparseMatrix_from_coordinate_format_not_compacted(A);
  360. SparseMatrix_delete(A);
  361. B = SparseMatrix_sort(B);
  362. *E = B;
  363. *nt = ntri;
  364. free(trilist);
  365. return 0;
  366. }
  367. static SparseMatrix get_country_graph(int n, SparseMatrix A, int *groups, int GRP_RANDOM, int GRP_BBOX){
  368. /* form a graph each vertex is a group (a country), and a vertex is connected to another if the two countries shares borders.
  369. since the group ID may not be contiguous (e.g., only groups 2,3,5, -1), we will return NULL if one of the group has non-positive ID! */
  370. int *ia, *ja;
  371. int one = 1, jj, i, j, ig1, ig2;
  372. SparseMatrix B, BB;
  373. int min_grp, max_grp;
  374. min_grp = max_grp = groups[0];
  375. for (i = 0; i < n; i++) {
  376. max_grp = MAX(groups[i], max_grp);
  377. min_grp = MIN(groups[i], min_grp);
  378. }
  379. if (min_grp <= 0) return NULL;
  380. B = SparseMatrix_new(max_grp, max_grp, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
  381. ia = A->ia;
  382. ja = A->ja;
  383. for (i = 0; i < n; i++){
  384. ig1 = groups[i]-1;/* add a diagonal entry */
  385. SparseMatrix_coordinate_form_add_entry(B, ig1, ig1, &one);
  386. for (j = ia[i]; j < ia[i+1]; j++){
  387. jj = ja[j];
  388. if (i != jj && groups[i] != groups[jj] && groups[jj] != GRP_RANDOM && groups[jj] != GRP_BBOX){
  389. ig1 = groups[i]-1; ig2 = groups[jj]-1;
  390. SparseMatrix_coordinate_form_add_entry(B, ig1, ig2, &one);
  391. }
  392. }
  393. }
  394. BB = SparseMatrix_from_coordinate_format(B);
  395. SparseMatrix_delete(B);
  396. return BB;
  397. }
  398. static void conn_comp(int n, SparseMatrix A, int *groups, SparseMatrix *poly_point_map){
  399. /* form a graph where only vertices that are connected as well as in the same group are connected */
  400. int *ia, *ja;
  401. int one = 1, jj, i, j;
  402. SparseMatrix B, BB;
  403. int ncomps, *comps = NULL;
  404. B = SparseMatrix_new(n, n, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
  405. ia = A->ia;
  406. ja = A->ja;
  407. for (i = 0; i < n; i++){
  408. for (j = ia[i]; j < ia[i+1]; j++){
  409. jj = ja[j];
  410. if (i != jj && groups[i] == groups[jj]){
  411. SparseMatrix_coordinate_form_add_entry(B, i, jj, &one);
  412. }
  413. }
  414. }
  415. BB = SparseMatrix_from_coordinate_format(B);
  416. int *comps_ptr = SparseMatrix_weakly_connected_components(BB, &ncomps, &comps);
  417. SparseMatrix_delete(B);
  418. SparseMatrix_delete(BB);
  419. *poly_point_map = SparseMatrix_new(ncomps, n, n, MATRIX_TYPE_PATTERN, FORMAT_CSR);
  420. free((*poly_point_map)->ia);
  421. free((*poly_point_map)->ja);
  422. (*poly_point_map)->ia = comps_ptr;
  423. (*poly_point_map)->ja = comps;
  424. (*poly_point_map)->nz = n;
  425. }
  426. static void get_poly_lines(int nt, SparseMatrix E, int ncomps, int *comps_ptr,
  427. int *comps, int *groups, SparseMatrix *poly_lines,
  428. int **polys_groups, int GRP_RANDOM, int GRP_BBOX) {
  429. /*============================================================
  430. polygon outlines
  431. ============================================================*/
  432. int i, *tlist, nz, ipoly, nnt, ii, jj, t1, t2, t, cur, next, nn, j, nlink, sta;
  433. int *elist, edim = 3;/* a list tell which vertex a particular vertex is linked with during poly construction.
  434. since the surface is a cycle, each can only link with 2 others, the 3rd position is used to record how many links
  435. */
  436. int *ie = E->ia, *je = E->ja, *e = E->a;
  437. SparseMatrix A;
  438. int *mask = gv_calloc(nt, sizeof(int));
  439. for (i = 0; i < nt; i++) mask[i] = -1;
  440. /* loop over every point in each connected component */
  441. elist = gv_calloc(nt * edim, sizeof(int));
  442. tlist = gv_calloc(nt * 2, sizeof(int));
  443. *poly_lines = SparseMatrix_new(ncomps, nt, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
  444. *polys_groups = gv_calloc(ncomps, sizeof(int));
  445. for (i = 0; i < nt; i++) elist[i*edim + 2] = 0;
  446. nz = ie[E->m] - ie[0];
  447. ipoly = 1;
  448. for (i = 0; i < ncomps; i++){
  449. nnt = 0;
  450. for (j = comps_ptr[i]; j < comps_ptr[i+1]; j++){
  451. ii = comps[j];
  452. (*polys_groups)[i] = groups[ii];/* assign the grouping of each poly */
  453. /* skip the country formed by random points */
  454. if (groups[ii] == GRP_RANDOM || groups[ii] == GRP_BBOX) continue;
  455. for (jj = ie[ii]; jj < ie[ii+1]; jj++){
  456. 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 */
  457. t1 = e[jj];
  458. t2 = e[jj+1];
  459. nlink = elist[t1*edim + 2]%2;
  460. elist[t1*edim + nlink] = t2;/* t1->t2*/
  461. elist[t1*edim + 2]++;
  462. nlink = elist[t2*edim + 2]%2;
  463. elist[t2*edim + nlink] = t1;/* t1->t2*/
  464. elist[t2*edim + 2]++;
  465. tlist[nnt++] = t1; tlist[nnt++] = t2;
  466. jj++;
  467. }
  468. }
  469. }/* done poly edges for this component i */
  470. /* form one or more (if there is a hole) polygon outlines for this component */
  471. for (j = 0; j < nnt; j++){
  472. t = tlist[j];
  473. if (mask[t] != i){
  474. cur = sta = t; mask[cur] = i;
  475. next = neighbor(t, 1, edim, elist);
  476. SparseMatrix_coordinate_form_add_entry(*poly_lines, i, cur, &ipoly);
  477. while (next != sta){
  478. mask[next] = i;
  479. SparseMatrix_coordinate_form_add_entry(*poly_lines, i, next, &ipoly);
  480. nn = neighbor(next, 0, edim, elist);
  481. if (nn == cur) {
  482. nn = neighbor(next, 1, edim, elist);
  483. }
  484. assert(nn != cur);
  485. cur = next;
  486. next = nn;
  487. }
  488. SparseMatrix_coordinate_form_add_entry(*poly_lines, i, sta, &ipoly);/* complete a cycle by adding starting point */
  489. ipoly++;
  490. }
  491. }/* found poly_lines for this comp */
  492. }
  493. A = SparseMatrix_from_coordinate_format_not_compacted(*poly_lines);
  494. SparseMatrix_delete(*poly_lines);
  495. *poly_lines = A;
  496. free(tlist);
  497. free(elist);
  498. free(mask);
  499. }
  500. static void cycle_print(int head, int *cycle, int *edge_table){
  501. int cur, next;
  502. cur = head;
  503. fprintf(stderr, "cycle (edges): {");
  504. while ((next = cycle_next(cur)) != head){
  505. fprintf(stderr, "%d,",cur);
  506. cur = next;
  507. }
  508. fprintf(stderr, "%d}\n",cur);
  509. cur = head;
  510. fprintf(stderr, "cycle (vertices): ");
  511. while ((next = cycle_next(cur)) != head){
  512. fprintf(stderr, "%d--",edge_head(cur));
  513. cur = next;
  514. }
  515. fprintf(stderr, "%d--%d\n",edge_head(cur),edge_tail(cur));
  516. }
  517. static int same_edge(int ecur, int elast, int *edge_table){
  518. return (edge_head(ecur) == edge_head(elast) && edge_tail(ecur) == edge_tail(elast))
  519. || (edge_head(ecur) == edge_tail(elast) && edge_tail(ecur) == edge_head(elast));
  520. }
  521. static void get_polygon_solids(int nt, SparseMatrix E, int ncomps,
  522. int *comps_ptr, int *comps, SparseMatrix *polys)
  523. {
  524. /*============================================================
  525. polygon solids that will be colored
  526. ============================================================*/
  527. int *edge_table;/* a table of edges of the triangle graph. If two vertex u and v are connected and are adjacent to two triangles
  528. t1 and t2, then from u there are two edges to v, one denoted as t1->t2, and the other t2->t1. They are
  529. numbered as e1 and e2. edge_table[e1]={t1,t2} and edge_table[e2]={t2,t1}
  530. */
  531. SparseMatrix half_edges;/* a graph of triangle edges. If two vertex u and v are connected and are adjacent to two triangles
  532. t1 and t2, then from u there are two edges to v, one denoted as t1->t2, and the other t2->t1. They are
  533. numbered as e1 and e2. Likewise from v to u there are also two edges e1 and e2.
  534. */
  535. int n = E->m, *ie = E->ia, *je = E->ja, *e = E->a, ne, i, j, t1, t2, jj, ii;
  536. 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,
  537. cycle[e][1] gives the next edge
  538. */
  539. 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) */
  540. int *emask;/* whether an edge is seen this iter */
  541. enum {NO_DUPLICATE = -1};
  542. int *elist, edim = 3;/* a list tell which edge a particular vertex is linked with when a voro cell has been visited,
  543. since the surface is a cycle, each vertex can only link with 2 edges, the 3rd position is used to record how many links
  544. */
  545. int k, duplicate, ee = 0, ecur, enext, eprev, cur, next, nn, nlink, head, elast = 0, etail, tail, ehead, efirst;
  546. int DEBUG_CYCLE = 0;
  547. SparseMatrix B;
  548. ne = E->nz;
  549. edge_table = gv_calloc(ne * 2, sizeof(int));
  550. half_edges = SparseMatrix_new(n, n, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
  551. ne = 0;
  552. for (i = 0; i < n; i++){
  553. for (j = ie[i]; j < ie[i+1]; j++){
  554. 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*/
  555. t1 = e[j];
  556. t2 = e[j+1];
  557. jj = je[j];
  558. assert(jj < n);
  559. edge_table[ne*2] = t1;/*t1->t2*/
  560. edge_table[ne*2+1] = t2;
  561. half_edges = SparseMatrix_coordinate_form_add_entry(half_edges, i, jj, &ne);
  562. half_edges = SparseMatrix_coordinate_form_add_entry(half_edges, jj, i, &ne);
  563. ne++;
  564. edge_table[ne*2] = t2;/*t2->t1*/
  565. edge_table[ne*2+1] = t1;
  566. half_edges = SparseMatrix_coordinate_form_add_entry(half_edges, i, jj, &ne);
  567. half_edges = SparseMatrix_coordinate_form_add_entry(half_edges, jj, i, &ne);
  568. ne++;
  569. j++;
  570. }
  571. }
  572. }
  573. assert(E->nz >= ne);
  574. cycle = gv_calloc(ne * 2, sizeof(int));
  575. B = SparseMatrix_from_coordinate_format_not_compacted(half_edges);
  576. SparseMatrix_delete(half_edges);half_edges = B;
  577. edge_cycle_map = gv_calloc(ne, sizeof(int));
  578. emask = gv_calloc(ne, sizeof(int));
  579. for (i = 0; i < ne; i++) edge_cycle_map[i] = NOT_ON_CYCLE;
  580. for (i = 0; i < ne; i++) emask[i] = -1;
  581. ie = half_edges->ia;
  582. je = half_edges->ja;
  583. e = half_edges->a;
  584. elist = gv_calloc(nt * 3, sizeof(int));
  585. for (i = 0; i < nt; i++) elist[i*edim + 2] = 0;
  586. *polys = SparseMatrix_new(ncomps, nt, 1, MATRIX_TYPE_INTEGER, FORMAT_COORD);
  587. for (i = 0; i < ncomps; i++){
  588. if (DEBUG_CYCLE) fprintf(stderr, "\n ============ comp %d has %d members\n",i, comps_ptr[i+1]-comps_ptr[i]);
  589. for (k = comps_ptr[i]; k < comps_ptr[i+1]; k++){
  590. ii = comps[k];
  591. duplicate = NO_DUPLICATE;
  592. if (DEBUG_CYCLE) fprintf(stderr,"member = %d has %d neighbors\n",ii, ie[ii+1]-ie[ii]);
  593. for (j = ie[ii]; j < ie[ii+1]; j++){
  594. jj = je[j];
  595. ee = e[j];
  596. t1 = edge_head(ee);
  597. 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));
  598. nlink = elist[t1*edim + 2]%2;
  599. elist[t1*edim + nlink] = ee;/* t1->t2*/
  600. elist[t1*edim + 2]++;
  601. if (edge_cycle_map[ee] != NOT_ON_CYCLE) duplicate = ee;
  602. emask[ee] = ii;
  603. }
  604. if (duplicate == NO_DUPLICATE){
  605. /* this must be the first time the cycle is being established, a new voro cell*/
  606. ecur = ee;
  607. cycle_head = ecur;
  608. cycle_next(ecur) = ecur;
  609. cycle_prev(ecur) = ecur;
  610. edge_cycle_map[ecur] = 1;
  611. head = cur = edge_head(ecur);
  612. next = edge_tail(ecur);
  613. if (DEBUG_CYCLE) fprintf(stderr, "NEW CYCLE\n starting with edge %d, {head,tail}={%d,%d}\n", ee, head, next);
  614. while (next != head){
  615. enext = neighbor(next, 0, edim, elist);/* two voro edges linked with triangle "next" */
  616. if ((edge_head(enext) == cur && edge_tail(enext) == next)
  617. || (edge_head(enext) == next && edge_tail(enext) == cur)){/* same edge */
  618. enext = neighbor(next, 1, edim, elist);
  619. };
  620. if (DEBUG_CYCLE) fprintf(stderr, "cur edge = %d, next edge %d, {head,tail}={%d,%d},\n",ecur, enext, edge_head(enext), edge_tail(enext));
  621. nn = edge_head(enext);
  622. if (nn == next) nn = edge_tail(enext);
  623. cycle_next(enext) = cycle_next(ecur);
  624. cycle_prev(enext) = ecur;
  625. cycle_next(ecur) = enext;
  626. cycle_prev(ee) = enext;
  627. edge_cycle_map[enext] = 1;
  628. ecur = enext;
  629. cur = next;
  630. next = nn;
  631. }
  632. if (DEBUG_CYCLE) cycle_print(ee, cycle,edge_table);
  633. } else {
  634. /* we found a duplicate edge, remove that, and all contiguous neighbors that overlap with the current voro
  635. */
  636. ecur = ee = duplicate;
  637. while (emask[ecur] == ii){
  638. /* contiguous overlapping edges, Cycling is not possible
  639. since the cycle can not complete surround the new voro cell and yet
  640. do not contain any other edges
  641. */
  642. ecur = cycle_next(ecur);
  643. }
  644. if (DEBUG_CYCLE) fprintf(stderr," duplicating edge = %d, starting from the a non-duplicating edge %d, search backwards\n",ee, ecur);
  645. ecur = cycle_prev(ecur);
  646. efirst = ecur;
  647. while (emask[ecur] == ii){
  648. if (DEBUG_CYCLE) fprintf(stderr," remove edge %d (%d--%d)\n",ecur, edge_head(ecur), edge_tail(ecur));
  649. /* short this duplicating edge */
  650. edge_cycle_map[ecur] = NOT_ON_CYCLE;
  651. enext = cycle_next(ecur);
  652. eprev = cycle_prev(ecur);
  653. cycle_next(ecur) = ecur;/* isolate this edge */
  654. cycle_prev(ecur) = ecur;
  655. cycle_next(eprev) = enext;/* short */
  656. cycle_prev(enext) = eprev;
  657. elast = ecur;/* record the last removed edge */
  658. ecur = eprev;
  659. }
  660. if (DEBUG_CYCLE) {
  661. fprintf(stderr, "remaining (broken) cycle = ");
  662. cycle_print(cycle_next(ecur), cycle,edge_table);
  663. }
  664. /* we now have a broken cycle of head = edge_tail(ecur) and tail = edge_head(cycle_next(ecur)) */
  665. ehead = ecur; etail = cycle_next(ecur);
  666. cycle_head = ehead;
  667. head = edge_tail(ehead);
  668. tail = edge_head(etail);
  669. /* pick an edge ev from head in the voro that is a removed edge: since the removed edges form a path starting from
  670. efirst, and at elast (head of elast is head), usually we just need to check that ev is not the same as elast,
  671. but in the case of a voro filling in a hole, we also need to check that ev is not efirst,
  672. since in this case every edge of the voro cell is removed
  673. */
  674. ecur = neighbor(head, 0, edim, elist);
  675. if (same_edge(ecur, elast, edge_table)){
  676. ecur = neighbor(head, 1, edim, elist);
  677. };
  678. if (DEBUG_CYCLE) fprintf(stderr, "forwarding now from edge %d = {%d, %d}, try to reach vtx %d, first edge from voro = %d\n",
  679. ehead, edge_head(ehead), edge_tail(ehead), tail, ecur);
  680. /* now go along voro edges till we reach the tail of the broken cycle*/
  681. cycle_next(ehead) = ecur;
  682. cycle_prev(ecur) = ehead;
  683. cycle_prev(etail) = ecur;
  684. cycle_next(ecur) = etail;
  685. if (same_edge(ecur, efirst, edge_table)){
  686. if (DEBUG_CYCLE) fprintf(stderr, "this voro cell fill in a hole completely!!!!\n");
  687. } else {
  688. edge_cycle_map[ecur] = 1;
  689. head = cur = edge_head(ecur);
  690. next = edge_tail(ecur);
  691. if (DEBUG_CYCLE) fprintf(stderr, "starting with edge %d, {head,tail}={%d,%d}\n", ecur, head, next);
  692. while (next != tail){
  693. enext = neighbor(next, 0, edim, elist);/* two voro edges linked with triangle "next" */
  694. if ((edge_head(enext) == cur && edge_tail(enext) == next)
  695. || (edge_head(enext) == next && edge_tail(enext) == cur)){/* same edge */
  696. enext = neighbor(next, 1, edim, elist);
  697. };
  698. if (DEBUG_CYCLE) fprintf(stderr, "cur edge = %d, next edge %d, {head,tail}={%d,%d},\n",ecur, enext, edge_head(enext), edge_tail(enext));
  699. nn = edge_head(enext);
  700. if (nn == next) nn = edge_tail(enext);
  701. cycle_next(enext) = cycle_next(ecur);
  702. cycle_prev(enext) = ecur;
  703. cycle_next(ecur) = enext;
  704. cycle_prev(etail) = enext;
  705. edge_cycle_map[enext] = 1;
  706. ecur = enext;
  707. cur = next;
  708. next = nn;
  709. }
  710. }
  711. }
  712. }
  713. /* done this component, load to sparse matrix, unset edge_map*/
  714. ecur = cycle_head;
  715. while ((enext = cycle_next(ecur)) != cycle_head){
  716. edge_cycle_map[ecur] = NOT_ON_CYCLE;
  717. head = edge_head(ecur);
  718. SparseMatrix_coordinate_form_add_entry(*polys, i, head, &i);
  719. ecur = enext;
  720. }
  721. edge_cycle_map[ecur] = NOT_ON_CYCLE;
  722. head = edge_head(ecur); tail = edge_tail(ecur);
  723. SparseMatrix_coordinate_form_add_entry(*polys, i, head, &i);
  724. SparseMatrix_coordinate_form_add_entry(*polys, i, tail, &i);
  725. /* unset edge_map */
  726. }
  727. B = SparseMatrix_from_coordinate_format_not_compacted(*polys);
  728. SparseMatrix_delete(*polys);
  729. *polys = B;
  730. SparseMatrix_delete(half_edges);
  731. free(cycle);
  732. free(edge_cycle_map);
  733. free(elist);
  734. free(emask);
  735. free(edge_table);
  736. }
  737. static void get_polygons(int n, int nrandom, int dim, int *grouping, int nt,
  738. struct Triangle *Tp, SparseMatrix E, int *nverts,
  739. double **x_poly, SparseMatrix *poly_lines,
  740. SparseMatrix *polys, int **polys_groups,
  741. SparseMatrix *poly_point_map,
  742. SparseMatrix *country_graph) {
  743. int i, j;
  744. int *groups;
  745. int maxgrp;
  746. int *comps = NULL, *comps_ptr = NULL, ncomps;
  747. int GRP_RANDOM, GRP_BBOX;
  748. assert(dim == 2);
  749. *nverts = nt;
  750. groups = gv_calloc(n + nrandom, sizeof(int));
  751. maxgrp = grouping[0];
  752. for (i = 0; i < n; i++) {
  753. maxgrp = MAX(maxgrp, grouping[i]);
  754. groups[i] = grouping[i];
  755. }
  756. GRP_RANDOM = maxgrp + 1; GRP_BBOX = maxgrp + 2;
  757. for (i = n; i < n + nrandom - 4; i++) {/* all random points in the same group */
  758. groups[i] = GRP_RANDOM;
  759. }
  760. for (i = n + nrandom - 4; i < n + nrandom; i++) {/* last 4 pts of the expanded bonding box in the same group */
  761. groups[i] = GRP_BBOX;
  762. }
  763. /* finding connected components: vertices that are connected in the triangle graph, as well as in the same group */
  764. conn_comp(n + nrandom, E, groups, poly_point_map);
  765. ncomps = (*poly_point_map)->m;
  766. comps = (*poly_point_map)->ja;
  767. comps_ptr = (*poly_point_map)->ia;
  768. /* connected components are such that the random points and the bounding box 4 points forms the last
  769. remaining components */
  770. for (i = ncomps - 1; i >= 0; i--) {
  771. if (groups[comps[comps_ptr[i]]] != GRP_RANDOM &&
  772. groups[comps[comps_ptr[i]]] != GRP_BBOX) break;
  773. }
  774. ncomps = i + 1;
  775. if (Verbose) fprintf(stderr,"ncomps = %d\n",ncomps);
  776. *x_poly = gv_calloc(dim * nt, sizeof(double));
  777. for (i = 0; i < nt; i++){
  778. for (j = 0; j < dim; j++){
  779. (*x_poly)[i*dim+j] = Tp[i].center[j];
  780. }
  781. }
  782. /*============================================================
  783. polygon outlines
  784. ============================================================*/
  785. get_poly_lines(nt, E, ncomps, comps_ptr, comps, groups, poly_lines,
  786. polys_groups, GRP_RANDOM, GRP_BBOX);
  787. /*============================================================
  788. polygon solids
  789. ============================================================*/
  790. get_polygon_solids(nt, E, ncomps, comps_ptr, comps, polys);
  791. *country_graph = get_country_graph(n, E, groups, GRP_RANDOM, GRP_BBOX);
  792. free(groups);
  793. }
  794. static int make_map_internal(bool include_OK_points, int n, int dim, double *x0,
  795. int *grouping0, SparseMatrix graph,
  796. double bounding_box_margin, int nrandom,
  797. int nedgep, double shore_depth_tol, int *nverts,
  798. double **x_poly, SparseMatrix *poly_lines,
  799. SparseMatrix *polys, int **polys_groups,
  800. SparseMatrix *poly_point_map,
  801. SparseMatrix *country_graph, int highlight_cluster) {
  802. double xmax[2], xmin[2], area, *x = x0;
  803. int i, j;
  804. QuadTree qt;
  805. int dim2 = 2, nn = 0;
  806. int max_qtree_level = 10;
  807. double ymin[2], min;
  808. int imin, nzok = 0, nzok0 = 0, nt;
  809. double *xran, point[2];
  810. struct Triangle *Tp;
  811. SparseMatrix E;
  812. double boxsize[2];
  813. bool INCLUDE_OK_POINTS = include_OK_points;/* OK points are random points inserted and found to be within shore_depth_tol of real/artificial points,
  814. including them instead of throwing away increase realism of boundary */
  815. int *grouping = grouping0;
  816. int HIGHLIGHT_SET = highlight_cluster;
  817. for (j = 0; j < dim2; j++) {
  818. xmax[j] = x[j];
  819. xmin[j] = x[j];
  820. }
  821. for (i = 0; i < n; i++){
  822. for (j = 0; j < dim2; j++) {
  823. xmax[j] = fmax(xmax[j], x[i*dim+j]);
  824. xmin[j] = fmin(xmin[j], x[i*dim+j]);
  825. }
  826. }
  827. boxsize[0] = xmax[0] - xmin[0];
  828. boxsize[1] = xmax[1] - xmin[1];
  829. area = boxsize[0]*boxsize[1];
  830. if (nrandom == 0) {
  831. nrandom = n;
  832. } else if (nrandom < 0){
  833. nrandom = -nrandom * n;
  834. } else if (nrandom < 4) {/* by default we add 4 point on 4 corners anyway */
  835. nrandom = 0;
  836. } else {
  837. nrandom -= 4;
  838. }
  839. if (shore_depth_tol < 0) shore_depth_tol = sqrt(area/(double) n); /* set to average distance for random distribution */
  840. if (Verbose) fprintf(stderr, "nrandom=%d shore_depth_tol=%.08f\n", nrandom, shore_depth_tol);
  841. /* add artificial points along each edge to avoid as much as possible
  842. two connected components be separated due to small shore depth */
  843. {
  844. int nz;
  845. double *y;
  846. int k, t, np=nedgep;
  847. if (graph && np){
  848. fprintf(stderr,"add art np = %d\n",np);
  849. nz = graph->nz;
  850. y = gv_calloc(dim * n + dim * nz * np, sizeof(double));
  851. for (i = 0; i < n*dim; i++) y[i] = x[i];
  852. grouping = gv_calloc(n + nz * np, sizeof(int));
  853. for (i = 0; i < n; i++) grouping[i] = grouping0[i];
  854. nz = n;
  855. for (i = 0; i < graph->m; i++){
  856. for (j = graph->ia[i]; j < graph->ia[i+1]; j++){
  857. if (!HIGHLIGHT_SET || (grouping[i] == grouping[graph->ja[j]] && grouping[i] == HIGHLIGHT_SET)){
  858. for (t = 0; t < np; t++){
  859. for (k = 0; k < dim; k++){
  860. y[nz*dim+k] = t/((double) np)*x[i*dim+k] + (1-t/((double) np))*x[(graph->ja[j])*dim + k];
  861. }
  862. assert(n + (nz-n)*np + t < n + nz*np && n + (nz-n)*np + t >= 0);
  863. if (t/((double) np) > 0.5){
  864. grouping[nz] = grouping[i];
  865. } else {
  866. grouping[nz] = grouping[graph->ja[j]];
  867. }
  868. nz++;
  869. }
  870. }
  871. }
  872. }
  873. fprintf(stderr, "after adding edge points, n:%d->%d\n",n, nz);
  874. n = nz;
  875. x = y;
  876. qt = QuadTree_new_from_point_list(dim, nz, max_qtree_level, y);
  877. } else {
  878. qt = QuadTree_new_from_point_list(dim, n, max_qtree_level, x);
  879. }
  880. }
  881. /* generate random points for lake/sea effect */
  882. if (nrandom != 0){
  883. for (i = 0; i < dim2; i++) {
  884. if (bounding_box_margin > 0){
  885. xmin[i] -= bounding_box_margin;
  886. xmax[i] += bounding_box_margin;
  887. } else if (bounding_box_margin < 0) {
  888. xmin[i] -= boxsize[i]*(-bounding_box_margin);
  889. xmax[i] += boxsize[i]*(-bounding_box_margin);
  890. } else { // auto bounding box
  891. xmin[i] -= fmax(boxsize[i] * 0.2, 2.* shore_depth_tol);
  892. xmax[i] += fmax(boxsize[i] * 0.2, 2 * shore_depth_tol);
  893. }
  894. }
  895. if (Verbose) {
  896. double bbm = bounding_box_margin;
  897. if (bbm > 0)
  898. fprintf (stderr, "bounding box margin: %.06f", bbm);
  899. else if (bbm < 0)
  900. fprintf (stderr, "bounding box margin: (%.06f * %.06f)", boxsize[0], -bbm);
  901. else
  902. fprintf(stderr, "bounding box margin: %.06f",
  903. fmax(boxsize[0] * 0.2, 2 * shore_depth_tol));
  904. }
  905. if (nrandom < 0) {
  906. const double area2 = (xmax[1] - xmin[1]) * (xmax[0] - xmin[0]);
  907. const double n1 = floor(area2 / (shore_depth_tol * shore_depth_tol));
  908. const double n2 = n * floor(area2 / area);
  909. nrandom = fmax(n1, n2);
  910. }
  911. srand(123);
  912. xran = gv_calloc((nrandom + 4) * dim2, sizeof(double));
  913. int nz = 0;
  914. if (INCLUDE_OK_POINTS){
  915. nzok0 = nzok = nrandom - 1;/* points that are within tolerance of real or artificial points */
  916. if (grouping == grouping0) {
  917. int *grouping2 = gv_calloc(n + nrandom, sizeof(int));
  918. memcpy(grouping2, grouping, sizeof(int)*n);
  919. grouping = grouping2;
  920. } else {
  921. grouping = gv_recalloc(grouping, n, n + nrandom, sizeof(int));
  922. }
  923. }
  924. nn = n;
  925. for (i = 0; i < nrandom; i++){
  926. for (j = 0; j < dim2; j++){
  927. point[j] = xmin[j] + (xmax[j] - xmin[j])*drand();
  928. }
  929. QuadTree_get_nearest(qt, point, ymin, &imin, &min);
  930. if (min > shore_depth_tol){/* point not too close, accepted */
  931. for (j = 0; j < dim2; j++){
  932. xran[nz*dim2+j] = point[j];
  933. }
  934. nz++;
  935. } else if (INCLUDE_OK_POINTS && min > shore_depth_tol/10){/* avoid duplicate points */
  936. for (j = 0; j < dim2; j++){
  937. xran[nzok*dim2+j] = point[j];
  938. }
  939. grouping[nn++] = grouping[imin];
  940. nzok--;
  941. }
  942. }
  943. nrandom = nz;
  944. if (Verbose) fprintf(stderr, "nn nrandom=%d\n", nrandom);
  945. } else {
  946. xran = gv_calloc(4 * dim2, sizeof(double));
  947. }
  948. /* add 4 corners even if nrandom = 0. The corners should be further away from the other points to avoid skinny triangles */
  949. for (i = 0; i < dim2; i++) xmin[i] -= 0.2*(xmax[i]-xmin[i]);
  950. for (i = 0; i < dim2; i++) xmax[i] += 0.2*(xmax[i]-xmin[i]);
  951. i = nrandom;
  952. for (j = 0; j < dim2; j++) xran[i*dim2+j] = xmin[j];
  953. i++;
  954. for (j = 0; j < dim2; j++) xran[i*dim2+j] = xmax[j];
  955. i++;
  956. xran[i*dim2] = xmin[0]; xran[i*dim2+1] = xmax[1];
  957. i++;
  958. xran[i*dim2] = xmax[0]; xran[i*dim2+1] = xmin[1];
  959. nrandom += 4;
  960. double *xcombined;
  961. if (INCLUDE_OK_POINTS){
  962. xcombined = gv_calloc((nn + nrandom) * dim2, sizeof(double));
  963. } else {
  964. xcombined = gv_calloc((n + nrandom) * dim2, sizeof(double));
  965. }
  966. for (i = 0; i < n; i++) {
  967. for (j = 0; j < dim2; j++) xcombined[i*dim2+j] = x[i*dim+j];
  968. }
  969. for (i = 0; i < nrandom; i++) {
  970. for (j = 0; j < dim2; j++) xcombined[(i + nn)*dim2+j] = xran[i*dim+j];
  971. }
  972. if (INCLUDE_OK_POINTS){
  973. for (i = 0; i < nn - n; i++) {
  974. for (j = 0; j < dim2; j++) xcombined[(i + n)*dim2+j] = xran[(nzok0 - i)*dim+j];
  975. }
  976. n = nn;
  977. }
  978. {
  979. int nz, nh = 0;/* the set to highlight */
  980. if (HIGHLIGHT_SET){
  981. if (Verbose) fprintf(stderr," highlight cluster %d, n = %d\n",HIGHLIGHT_SET, n);
  982. /* shift set to the beginning */
  983. nz = 0;
  984. for (i = 0; i < n; i++){
  985. if (grouping[i] == HIGHLIGHT_SET){
  986. nh++;
  987. for (j = 0; j < dim; j++){
  988. xcombined[nz++] = x[i*dim+j];
  989. }
  990. }
  991. }
  992. for (i = 0; i < n; i++){
  993. if (grouping[i] != HIGHLIGHT_SET){
  994. for (j = 0; j < dim; j++){
  995. xcombined[nz++] = x[i*dim+j];
  996. }
  997. }
  998. }
  999. assert(nz == n*dim);
  1000. for (i = 0; i < nh; i++){
  1001. grouping[i] = 1;
  1002. }
  1003. for (i = nh; i < n; i++){
  1004. grouping[i] = 2;
  1005. }
  1006. nrandom += n - nh;/* count everything except cluster HIGHLIGHT_SET as random */
  1007. n = nh;
  1008. if (Verbose) fprintf(stderr,"nh = %d\n",nh);
  1009. }
  1010. }
  1011. int rc = 0;
  1012. if (get_tri(n + nrandom, dim2, xcombined, &nt, &Tp, &E) != 0) {
  1013. rc = -1;
  1014. goto done;
  1015. }
  1016. get_polygons(n, nrandom, dim2, grouping, nt, Tp, E, nverts, x_poly,
  1017. poly_lines, polys, polys_groups, poly_point_map, country_graph);
  1018. SparseMatrix_delete(E);
  1019. free(Tp);
  1020. done:
  1021. free(xcombined);
  1022. free(xran);
  1023. if (grouping != grouping0) free(grouping);
  1024. if (x != x0) free(x);
  1025. return rc;
  1026. }
  1027. static void add_point(int *n, int igrp, double **x, int *nmax, double point[], int **groups){
  1028. if (*n >= *nmax){
  1029. int old_nmax = *nmax;
  1030. *nmax = 20 + *n;
  1031. *x = gv_recalloc(*x, 2 * old_nmax, 2 * *nmax, sizeof(double));
  1032. *groups = gv_recalloc(*groups, old_nmax, *nmax, sizeof(int));
  1033. }
  1034. (*x)[(*n)*2] = point[0];
  1035. (*x)[(*n)*2+1] = point[1];
  1036. (*groups)[*n] = igrp;
  1037. (*n)++;
  1038. }
  1039. static void get_boundingbox(int n, int dim, double *x, double *width, double *bbox){
  1040. int i;
  1041. bbox[0] = bbox[1] = x[0];
  1042. bbox[2] = bbox[3] = x[1];
  1043. for (i = 0; i < n; i++){
  1044. bbox[0] = fmin(bbox[0], x[i * dim] - width[i * dim]);
  1045. bbox[1] = fmax(bbox[1], x[i * dim] + width[i * dim]);
  1046. bbox[2] = fmin(bbox[2], x[i * dim + 1] - width[i * dim + 1]);
  1047. bbox[3] = fmax(bbox[3], x[i * dim + 1] + width[i * dim + 1]);
  1048. }
  1049. }
  1050. int make_map_from_rectangle_groups(bool include_OK_points,
  1051. int n, int dim, double *x, double *sizes,
  1052. int *grouping, SparseMatrix graph, double bounding_box_margin, int nrandom, int *nart, int nedgep,
  1053. double shore_depth_tol,
  1054. int *nverts, double **x_poly,
  1055. SparseMatrix *poly_lines, SparseMatrix *polys, int **polys_groups, SparseMatrix *poly_point_map,
  1056. SparseMatrix *country_graph, int highlight_cluster){
  1057. /* 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
  1058. geometrically will be in the same polygon describing the outline of the group. The main difference for this function and
  1059. make_map_from_point_groups is that in this function, the input are points with width/heights, and we try not to place
  1060. "lakes" inside these rectangles. This is achieved approximately by adding artificial points along the perimeter of the rectangles,
  1061. as well as near the center.
  1062. input:
  1063. include_OK_points: OK points are random points inserted and found to be within shore_depth_tol of real/artificial points,
  1064. . including them instead of throwing away increase realism of boundary
  1065. n: number of points
  1066. dim: dimension of the points. If dim > 2, only the first 2D is used.
  1067. x: coordinates
  1068. sizes: width and height
  1069. grouping: which group each of the vertex belongs to
  1070. graph: the link structure between points. If graph == NULL, this is not used. otherwise
  1071. . it is assumed that matrix is symmetric and the graph is undirected
  1072. bounding_box_margin: margin used to form the bounding box.
  1073. . if negative, it is taken as relative. i.e., -0.5 means a margin of 0.5*box_size
  1074. nrandom (input): number of random points to insert in the bounding box to figure out lakes and seas.
  1075. . If nrandom = 0, no points are inserted, if nrandom < 0, the number is decided automatically.
  1076. .
  1077. nart: on entry, number of artificial points to be added along each side of a rectangle enclosing the labels. if < 0, auto-selected.
  1078. . On exit, actual number of artificial points added.
  1079. nedgep: number of artificial points are adding along edges to establish as much as possible a bright between nodes
  1080. . connected by the edge, and avoid islands that are connected. k = 0 mean no points.
  1081. shore_depth_tol: nrandom random points are inserted in the bounding box of the points,
  1082. . such random points are then weeded out if it is within distance of shore_depth_tol from
  1083. . real points. If 0, auto assigned
  1084. output:
  1085. nverts: number of vertices in the Voronoi diagram
  1086. x_poly: the 2D coordinates of these polygons, dimension nverts*2
  1087. poly_lines: the sparse matrix representation of the polygon indices, as well as their identity. The matrix is of size
  1088. . npolygons x nverts. The i-th polygon is formed by linking vertices with index in the i-th row of the sparse matrix.
  1089. . 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,
  1090. . and l1 -- l2 -- ... form another. Each row can have more than 1 loop only when the connected region the polylines represent
  1091. . has at least 1 holes.
  1092. polys: the sparse matrix representation of the polygon indices, as well as their identity. The matrix is of size
  1093. . npolygons x nverts. The i-th polygon is formed by linking vertices with index in the i-th row of the sparse matrix.
  1094. . Unlike poly_lines, here each row represent an one stroke drawing of the SOLID polygon, vertices
  1095. . along this path may repeat
  1096. polys_groups: the group (color) each polygon belongs to, this include all groups of the real points,
  1097. . plus the random point group and the bounding box group
  1098. poly_point_map: a matrix of dimension npolys x (n + nrandom), poly_point_map[i,j] != 0 if polygon i contains the point j.
  1099. . If j < n, it is the original point, otherwise it is artificial point (forming the rectangle around a label) or random points.
  1100. country_graph: shows which country is a neighbor of which country.
  1101. . if country i and country j are neighbor, then the {i,j} entry is the total number of vertices that
  1102. . belongs to i and j, and share an edge of the triangulation. In addition, {i,i} and {j,j} have values equal
  1103. . to the number of vertices in each of the countries. If the input "grouping" has negative or zero value, then
  1104. . country_graph = NULL.
  1105. */
  1106. double *X;
  1107. int N, nmax, i, j, k, igrp;
  1108. int *groups, K = *nart;/* average number of points added per side of rectangle */
  1109. double avgsize[2], avgsz, h[2], p1, p0;
  1110. double point[2];
  1111. int nadded[2];
  1112. double delta[2];
  1113. double bbox[4];
  1114. if (K < 0){
  1115. K = (int) 10/(1+n/400.);/* 0 if n > 3600*/
  1116. }
  1117. *nart = 0;
  1118. if (Verbose){
  1119. int maxgp = grouping[0];
  1120. int mingp = grouping[0];
  1121. for (i = 0; i < n; i++) {
  1122. maxgp = MAX(maxgp, grouping[i]);
  1123. mingp = MIN(mingp, grouping[i]);
  1124. }
  1125. fprintf(stderr, "max grouping - min grouping + 1 = %d\n",maxgp - mingp + 1);
  1126. }
  1127. int rc = 0;
  1128. if (!sizes){
  1129. return make_map_internal(include_OK_points, n, dim, x, grouping, graph,
  1130. bounding_box_margin, nrandom, nedgep,
  1131. shore_depth_tol, nverts, x_poly, poly_lines, polys,
  1132. polys_groups, poly_point_map, country_graph,
  1133. highlight_cluster);
  1134. } else {
  1135. /* add artificial node due to node sizes */
  1136. avgsize[0] = 0;
  1137. avgsize[1] = 0;
  1138. for (i = 0; i < n; i++){
  1139. for (j = 0; j < 2; j++) {
  1140. avgsize[j] += sizes[i*dim+j];
  1141. }
  1142. }
  1143. for (i = 0; i < 2; i++) avgsize[i] /= n;
  1144. avgsz = 0.5*(avgsize[0] + avgsize[1]);
  1145. if (Verbose) fprintf(stderr, "avgsize = {%f, %f}\n",avgsize[0], avgsize[1]);
  1146. nmax = 2*n;
  1147. X = gv_calloc(dim * (n + nmax), sizeof(double));
  1148. groups = gv_calloc(n + nmax, sizeof(int));
  1149. for (i = 0; i < n; i++) {
  1150. groups[i] = grouping[i];
  1151. for (j = 0; j < 2; j++){
  1152. X[i*2+j] = x[i*dim+j];
  1153. }
  1154. }
  1155. N = n;
  1156. if (shore_depth_tol < 0) {
  1157. shore_depth_tol = -(shore_depth_tol)*avgsz;
  1158. } else if (shore_depth_tol == 0){
  1159. get_boundingbox(n, dim, x, sizes, bbox);
  1160. const double area = (bbox[1] - bbox[0]) * (bbox[3] - bbox[2]);
  1161. shore_depth_tol = sqrt(area / n);
  1162. if (Verbose) fprintf(stderr,"setting shore length ======%f\n",shore_depth_tol);
  1163. } else {
  1164. }
  1165. /* add artificial points in an anti-clockwise fashion */
  1166. if (K > 0){
  1167. delta[0] = .5*avgsize[0]/K; delta[1] = .5*avgsize[1]/K;/* small perturbation to make boundary between labels looks more fractal */
  1168. } else {
  1169. delta[0] = delta[1] = 0.;
  1170. }
  1171. for (i = 0; i < n; i++){
  1172. igrp = grouping[i];
  1173. for (j = 0; j < 2; j++) {
  1174. if (avgsz == 0){
  1175. nadded[j] = 0;
  1176. } else {
  1177. nadded[j] = (int) K*sizes[i*dim+j]/avgsz;
  1178. }
  1179. }
  1180. /*top: left to right */
  1181. if (nadded[0] > 0){
  1182. h[0] = sizes[i*dim]/nadded[0];
  1183. point[0] = x[i*dim] - sizes[i*dim]/2;
  1184. p1 = point[1] = x[i*dim+1] + sizes[i*dim + 1]/2;
  1185. add_point(&N, igrp, &X, &nmax, point, &groups);
  1186. for (k = 0; k < nadded[0] - 1; k++){
  1187. point[0] += h[0];
  1188. point[1] = p1 + (0.5-drand())*delta[1];
  1189. add_point(&N, igrp, &X, &nmax, point, &groups);
  1190. }
  1191. /* bot: right to left */
  1192. point[0] = x[i*dim] + sizes[i*dim]/2;
  1193. p1 = point[1] = x[i*dim+1] - sizes[i*dim + 1]/2;
  1194. add_point(&N, igrp, &X, &nmax, point, &groups);
  1195. for (k = 0; k < nadded[0] - 1; k++){
  1196. point[0] -= h[0];
  1197. point[1] = p1 + (0.5-drand())*delta[1];
  1198. add_point(&N, igrp, &X, &nmax, point, &groups);
  1199. }
  1200. }
  1201. if (nadded[1] > 0){
  1202. /* left: bot to top */
  1203. h[1] = sizes[i*dim + 1]/nadded[1];
  1204. p0 = point[0] = x[i*dim] - sizes[i*dim]/2;
  1205. point[1] = x[i*dim+1] - sizes[i*dim + 1]/2;
  1206. add_point(&N, igrp, &X, &nmax, point, &groups);
  1207. for (k = 0; k < nadded[1] - 1; k++){
  1208. point[0] = p0 + (0.5-drand())*delta[0];
  1209. point[1] += h[1];
  1210. add_point(&N, igrp, &X, &nmax, point, &groups);
  1211. }
  1212. /* right: top to bot */
  1213. p0 = point[0] = x[i*dim] + sizes[i*dim]/2;
  1214. point[1] = x[i*dim+1] + sizes[i*dim + 1]/2;
  1215. add_point(&N, igrp, &X, &nmax, point, &groups);
  1216. for (k = 0; k < nadded[1] - 1; k++){
  1217. point[0] = p0 + (0.5-drand())*delta[0];
  1218. point[1] -= h[1];
  1219. add_point(&N, igrp, &X, &nmax, point, &groups);
  1220. }
  1221. }
  1222. *nart = N - n;
  1223. }/* done adding artificial points due to node size*/
  1224. rc = make_map_internal(include_OK_points, N, dim, X, groups, graph,
  1225. bounding_box_margin, nrandom, nedgep,
  1226. shore_depth_tol, nverts, x_poly, poly_lines, polys,
  1227. polys_groups, poly_point_map, country_graph,
  1228. highlight_cluster);
  1229. free(groups);
  1230. free(X);
  1231. }
  1232. return rc;
  1233. }