par_bubbles.h 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975
  1. // BUBBLES :: https://github.com/prideout/par
  2. // Simple C library for packing circles into hierarchical (or flat) diagrams.
  3. //
  4. // Based on "Visualization of Large Hierarchical Data by Circle Packing" by
  5. // Wang et al (2006).
  6. //
  7. // Also implements Emo Welzl's "Smallest enclosing disks" algorithm (1991).
  8. //
  9. // The API is divided into three sections:
  10. //
  11. // - Enclosing. Compute the smallest bounding circle for points or circles.
  12. // - Packing. Pack circles together, or into other circles.
  13. // - Queries. Given a touch point, pick a circle from a hierarchy, etc.
  14. //
  15. // In addition to the comment block above each function declaration, the API
  16. // has informal documentation here:
  17. //
  18. // http://github.prideout.net/bubbles/
  19. //
  20. // The MIT License
  21. // Copyright (c) 2015 Philip Rideout
  22. #ifndef PAR_BUBBLES_H
  23. #define PAR_BUBBLES_H
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. #include <stdbool.h>
  28. #include <stdint.h>
  29. // This can be any signed integer type.
  30. #ifndef PAR_BUBBLES_INT
  31. #define PAR_BUBBLES_INT int32_t
  32. #endif
  33. // This must be "float" or "double" or "long double". Note that you should not
  34. // need high precision if you use the relative coordinate systems API.
  35. #ifndef PAR_BUBBLES_FLT
  36. #define PAR_BUBBLES_FLT double
  37. #endif
  38. // Enclosing / Touching --------------------------------------------------------
  39. // Read an array of (x,y) coordinates, write a single 3-tuple (x,y,radius).
  40. void par_bubbles_enclose_points(PAR_BUBBLES_FLT const* xy, PAR_BUBBLES_INT npts,
  41. PAR_BUBBLES_FLT* result);
  42. // Read an array of 3-tuples (x,y,radius), write a 3-tuple (x,y,radius).
  43. // Internally, this approximates each disk with an enclosing octagon.
  44. void par_bubbles_enclose_disks(PAR_BUBBLES_FLT const* xyr,
  45. PAR_BUBBLES_INT ndisks, PAR_BUBBLES_FLT* result);
  46. // Find the circle (x,y,radius) that is tangent to 3 points (x,y).
  47. void par_bubbles_touch_three_points(PAR_BUBBLES_FLT const* xy,
  48. PAR_BUBBLES_FLT* result);
  49. // Find a position for disk "c" that makes it tangent to "a" and "b".
  50. // Note that the ordering of a and b can affect where c will land.
  51. // All three arguments are pointers to three-tuples (x,y,radius).
  52. void par_bubbles_touch_two_disks(PAR_BUBBLES_FLT* c, PAR_BUBBLES_FLT const* a,
  53. PAR_BUBBLES_FLT const* b);
  54. // Packing ---------------------------------------------------------------------
  55. // Tiny POD structure returned by all packing functions. Private data is
  56. // attached after the public fields, so clients should call the provided
  57. // free function rather than freeing the memory manually.
  58. typedef struct {
  59. PAR_BUBBLES_FLT* xyr; // array of 3-tuples (x y radius) in input order
  60. PAR_BUBBLES_INT count; // number of 3-tuples in "xyr"
  61. PAR_BUBBLES_INT* ids; // populated by par_bubbles_cull
  62. } par_bubbles_t;
  63. void par_bubbles_free_result(par_bubbles_t*);
  64. // Entry point for unbounded non-hierarchical packing. Takes a list of radii.
  65. par_bubbles_t* par_bubbles_pack(PAR_BUBBLES_FLT const* radiuses,
  66. PAR_BUBBLES_INT nradiuses);
  67. // Consume a hierarchy defined by a list of integers. Each integer is an index
  68. // to its parent. The root node is its own parent, and it must be the first node
  69. // in the list. Clients do not have control over individual radiuses, only the
  70. // radius of the outermost enclosing disk.
  71. par_bubbles_t* par_bubbles_hpack_circle(PAR_BUBBLES_INT* nodes,
  72. PAR_BUBBLES_INT nnodes, PAR_BUBBLES_FLT radius);
  73. // Queries ---------------------------------------------------------------------
  74. // Find the node at the given position. Children are on top of their parents.
  75. // If the result is -1, there is no node at the given pick coordinate.
  76. PAR_BUBBLES_INT par_bubbles_pick(par_bubbles_t const*, PAR_BUBBLES_FLT x,
  77. PAR_BUBBLES_FLT y);
  78. // Get bounding box; take a pointer to 4 floats and set them to min xy, max xy.
  79. void par_bubbles_compute_aabb(par_bubbles_t const*, PAR_BUBBLES_FLT* aabb);
  80. // Check if the given circle (3-tuple) intersects the given aabb (4-tuple).
  81. bool par_bubbles_check_aabb(PAR_BUBBLES_FLT const* disk,
  82. PAR_BUBBLES_FLT const* aabb);
  83. // Clip the bubble diagram to the given AABB (4-tuple of left,bottom,right,top)
  84. // and return the result. Circles smaller than the given world-space
  85. // "minradius" are removed. Optionally, an existing diagram (dst) can be passed
  86. // in to receive the culled dataset, which reduces the number of memory allocs
  87. // when calling this function frequently. Pass null to "dst" to create a new
  88. // culled diagram.
  89. par_bubbles_t* par_bubbles_cull(par_bubbles_t const* src,
  90. PAR_BUBBLES_FLT const* aabb, PAR_BUBBLES_FLT minradius, par_bubbles_t* dst);
  91. // Dump out a SVG file for diagnostic purposes.
  92. void par_bubbles_export(par_bubbles_t const* bubbles, char const* filename);
  93. // Returns a pointer to a list of children nodes.
  94. void par_bubbles_get_children(par_bubbles_t const* bubbles, PAR_BUBBLES_INT idx,
  95. PAR_BUBBLES_INT** pchildren, PAR_BUBBLES_INT* nchildren);
  96. // Finds the height of the tree and returns one of its deepest leaves.
  97. void par_bubbles_get_maxdepth(par_bubbles_t const* bubbles,
  98. PAR_BUBBLES_INT* maxdepth, PAR_BUBBLES_INT* leaf);
  99. // Finds the height of the tree at a certain node.
  100. PAR_BUBBLES_INT par_bubbles_get_depth(par_bubbles_t const* bubbles,
  101. PAR_BUBBLES_INT node);
  102. // Returns a 4-tuple (min xy, max xy) for the given node.
  103. void par_bubbles_compute_aabb_for_node(par_bubbles_t const* bubbles,
  104. PAR_BUBBLES_INT node, PAR_BUBBLES_FLT* aabb);
  105. // Relative Coordinate Systems -------------------------------------------------
  106. // Similar to hpack, but maintains precision by storing disk positions within
  107. // the local coordinate system of their parent. After calling this function,
  108. // clients can use cull_local to flatten the coordinate systems.
  109. par_bubbles_t* par_bubbles_hpack_local(PAR_BUBBLES_INT* nodes,
  110. PAR_BUBBLES_INT nnodes);
  111. // Similar to par_bubbles_cull, but takes a root node rather than an AABB,
  112. // and returns a result within the local coordinate system of the new root.
  113. // In other words, the new root will have radius 1, centered at (0,0). The
  114. // minradius is also expressed in this coordinate system.
  115. par_bubbles_t* par_bubbles_cull_local(par_bubbles_t const* src,
  116. PAR_BUBBLES_INT root, PAR_BUBBLES_FLT minradius, par_bubbles_t* dst);
  117. // Finds the smallest node in the given bubble diagram that completely encloses
  118. // the given axis-aligned bounding box (min xy, max xy). The AABB coordinates
  119. // are expressed in the local coordinate system of the given root node.
  120. PAR_BUBBLES_INT par_bubbles_find_local(par_bubbles_t const* src,
  121. PAR_BUBBLES_FLT const* aabb, PAR_BUBBLES_INT root);
  122. // Similar to pick, but expects (x,y) to be in the coordinate system of the
  123. // given root node.
  124. PAR_BUBBLES_INT par_bubbles_pick_local(par_bubbles_t const*, PAR_BUBBLES_FLT x,
  125. PAR_BUBBLES_FLT y, PAR_BUBBLES_INT root, PAR_BUBBLES_FLT minradius);
  126. // Dump out a SVG file for diagnostic purposes.
  127. void par_bubbles_export_local(par_bubbles_t const* bubbles,
  128. PAR_BUBBLES_INT idx, char const* filename);
  129. #ifndef PAR_PI
  130. #define PAR_PI (3.14159265359)
  131. #define PAR_MIN(a, b) (a > b ? b : a)
  132. #define PAR_MAX(a, b) (a > b ? a : b)
  133. #define PAR_CLAMP(v, lo, hi) PAR_MAX(lo, PAR_MIN(hi, v))
  134. #define PAR_SWAP(T, A, B) { T tmp = B; B = A; A = tmp; }
  135. #define PAR_SQR(a) ((a) * (a))
  136. #endif
  137. #ifndef PAR_MALLOC
  138. #define PAR_MALLOC(T, N) ((T*) malloc(N * sizeof(T)))
  139. #define PAR_CALLOC(T, N) ((T*) calloc(N * sizeof(T), 1))
  140. #define PAR_REALLOC(T, BUF, N) ((T*) realloc(BUF, sizeof(T) * N))
  141. #define PAR_FREE(BUF) free(BUF)
  142. #endif
  143. #ifdef __cplusplus
  144. }
  145. #endif
  146. #endif // PAR_BUBBLES_H
  147. // -----------------------------------------------------------------------------
  148. // END PUBLIC API
  149. // -----------------------------------------------------------------------------
  150. #ifdef PAR_BUBBLES_IMPLEMENTATION
  151. #define PARINT PAR_BUBBLES_INT
  152. #define PARFLT PAR_BUBBLES_FLT
  153. #include <math.h>
  154. #include <stdio.h>
  155. #include <stdlib.h>
  156. #include <float.h>
  157. #include <assert.h>
  158. typedef struct {
  159. PARINT prev;
  160. PARINT next;
  161. } par_bubbles__node;
  162. typedef struct {
  163. PARFLT* xyr; // results array
  164. PARINT count; // client-provided count
  165. PARINT* ids; // populated by par_bubbles_cull
  166. PARFLT const* radiuses; // client-provided radius list
  167. par_bubbles__node* chain; // counterclockwise enveloping chain
  168. PARINT const* graph_parents; // client-provided parent indices
  169. PARINT* graph_children; // flat list of children indices
  170. PARINT* graph_heads; // list of "pointers" to first child
  171. PARINT* graph_tails; // list of "pointers" to one-past-last child
  172. PARINT npacked;
  173. PARINT maxwidth;
  174. PARINT capacity;
  175. } par_bubbles__t;
  176. static PARFLT par_bubbles__len2(PARFLT const* a)
  177. {
  178. return a[0] * a[0] + a[1] * a[1];
  179. }
  180. static void par_bubbles__initgraph(par_bubbles__t* bubbles)
  181. {
  182. PARINT const* parents = bubbles->graph_parents;
  183. PARINT* nchildren = PAR_CALLOC(PARINT, bubbles->count);
  184. for (PARINT i = 0; i < bubbles->count; i++) {
  185. nchildren[parents[i]]++;
  186. }
  187. PARINT c = 0;
  188. bubbles->graph_heads = PAR_CALLOC(PARINT, bubbles->count * 2);
  189. bubbles->graph_tails = bubbles->graph_heads + bubbles->count;
  190. for (PARINT i = 0; i < bubbles->count; i++) {
  191. bubbles->maxwidth = PAR_MAX(bubbles->maxwidth, nchildren[i]);
  192. bubbles->graph_heads[i] = bubbles->graph_tails[i] = c;
  193. c += nchildren[i];
  194. }
  195. bubbles->graph_heads[0] = bubbles->graph_tails[0] = 1;
  196. bubbles->graph_children = PAR_MALLOC(PARINT, c);
  197. for (PARINT i = 1; i < bubbles->count; i++) {
  198. PARINT parent = parents[i];
  199. bubbles->graph_children[bubbles->graph_tails[parent]++] = i;
  200. }
  201. PAR_FREE(nchildren);
  202. }
  203. static void par_bubbles__initflat(par_bubbles__t* bubbles)
  204. {
  205. PARFLT* xyr = bubbles->xyr;
  206. PARFLT const* radii = bubbles->radiuses;
  207. par_bubbles__node* chain = bubbles->chain;
  208. *xyr++ = -*radii;
  209. *xyr++ = 0;
  210. *xyr++ = *radii++;
  211. if (bubbles->count == ++bubbles->npacked) {
  212. return;
  213. }
  214. *xyr++ = *radii;
  215. *xyr++ = 0;
  216. *xyr++ = *radii++;
  217. if (bubbles->count == ++bubbles->npacked) {
  218. return;
  219. }
  220. xyr[2] = *radii;
  221. par_bubbles_touch_two_disks(xyr, xyr - 6, xyr - 3);
  222. if (bubbles->count == ++bubbles->npacked) {
  223. return;
  224. }
  225. chain[0].prev = 2;
  226. chain[0].next = 1;
  227. chain[1].prev = 0;
  228. chain[1].next = 2;
  229. chain[2].prev = 1;
  230. chain[2].next = 0;
  231. }
  232. // March forward or backward along the enveloping chain, starting with the
  233. // node at "cn" and testing for collision against the node at "ci".
  234. static PARINT par_bubbles__collide(par_bubbles__t* bubbles, PARINT ci,
  235. PARINT cn, PARINT* cj, PARINT direction)
  236. {
  237. PARFLT const* ci_xyr = bubbles->xyr + ci * 3;
  238. par_bubbles__node* chain = bubbles->chain;
  239. PARINT nsteps = 1;
  240. if (direction > 0) {
  241. for (PARINT i = chain[cn].next; i != cn; i = chain[i].next, ++nsteps) {
  242. PARFLT const* i_xyr = bubbles->xyr + i * 3;
  243. PARFLT dx = i_xyr[0] - ci_xyr[0];
  244. PARFLT dy = i_xyr[1] - ci_xyr[1];
  245. PARFLT dr = i_xyr[2] + ci_xyr[2];
  246. if (0.999 * dr * dr > dx * dx + dy * dy) {
  247. *cj = i;
  248. return nsteps;
  249. }
  250. }
  251. return 0;
  252. }
  253. for (PARINT i = chain[cn].prev; i != cn; i = chain[i].prev, ++nsteps) {
  254. PARFLT const* i_xyr = bubbles->xyr + i * 3;
  255. PARFLT dx = i_xyr[0] - ci_xyr[0];
  256. PARFLT dy = i_xyr[1] - ci_xyr[1];
  257. PARFLT dr = i_xyr[2] + ci_xyr[2];
  258. if (0.999 * dr * dr > dx * dx + dy * dy) {
  259. *cj = i;
  260. return nsteps;
  261. }
  262. }
  263. return 0;
  264. }
  265. static void par_bubbles__packflat(par_bubbles__t* bubbles)
  266. {
  267. PARFLT const* radii = bubbles->radiuses;
  268. PARFLT* xyr = bubbles->xyr;
  269. par_bubbles__node* chain = bubbles->chain;
  270. // Find the circle closest to the origin, known as "Cm" in the paper.
  271. PARINT cm = 0;
  272. PARFLT mindist = par_bubbles__len2(xyr + 0);
  273. PARFLT dist = par_bubbles__len2(xyr + 3);
  274. if (dist > mindist) {
  275. cm = 1;
  276. }
  277. dist = par_bubbles__len2(xyr + 6);
  278. if (dist > mindist) {
  279. cm = 2;
  280. }
  281. // In the paper, "Cn" is always the node that follows "Cm".
  282. PARINT ci, cn = chain[cm].next;
  283. for (ci = bubbles->npacked; ci < bubbles->count; ) {
  284. PARFLT* ci_xyr = xyr + ci * 3;
  285. ci_xyr[2] = radii[ci];
  286. PARFLT* cm_xyr = xyr + cm * 3;
  287. PARFLT* cn_xyr = xyr + cn * 3;
  288. par_bubbles_touch_two_disks(ci_xyr, cn_xyr, cm_xyr);
  289. // Check for a collision. In the paper, "Cj" is the intersecting node.
  290. PARINT cj_f;
  291. PARINT nfsteps = par_bubbles__collide(bubbles, ci, cn, &cj_f, +1);
  292. if (!nfsteps) {
  293. chain[cm].next = ci;
  294. chain[ci].prev = cm;
  295. chain[ci].next = cn;
  296. chain[cn].prev = ci;
  297. cm = ci++;
  298. continue;
  299. }
  300. // Search backwards for a collision, in case it is closer.
  301. PARINT cj_b;
  302. PARINT nbsteps = par_bubbles__collide(bubbles, ci, cm, &cj_b, -1);
  303. // Intersection occurred after Cn.
  304. if (nfsteps <= nbsteps) {
  305. cn = cj_f;
  306. chain[cm].next = cn;
  307. chain[cn].prev = cm;
  308. continue;
  309. }
  310. // Intersection occurred before Cm.
  311. cm = cj_b;
  312. chain[cm].next = cn;
  313. chain[cn].prev = cm;
  314. }
  315. bubbles->npacked = bubbles->count;
  316. }
  317. static void par__disk_from_two(PARFLT const* xy1, PARFLT const* xy2,
  318. PARFLT* result)
  319. {
  320. PARFLT dx = xy1[0] - xy2[0];
  321. PARFLT dy = xy1[1] - xy2[1];
  322. result[0] = 0.5 * (xy1[0] + xy2[0]);
  323. result[1] = 0.5 * (xy1[1] + xy2[1]);
  324. result[2] = sqrt(dx * dx + dy * dy) / 2.0;
  325. }
  326. static PARINT par__disk_contains(PARFLT const* xyr, PARFLT const* xy)
  327. {
  328. PARFLT dx = xyr[0] - xy[0];
  329. PARFLT dy = xyr[1] - xy[1];
  330. return dx * dx + dy * dy <= PAR_SQR(xyr[2]);
  331. }
  332. static void par__easydisk(PARFLT* disk, PARFLT const* edgepts, PARINT nedgepts)
  333. {
  334. if (nedgepts == 0) {
  335. disk[0] = 0;
  336. disk[1] = 0;
  337. disk[2] = 0;
  338. return;
  339. }
  340. if (nedgepts == 1) {
  341. disk[0] = edgepts[0];
  342. disk[1] = edgepts[1];
  343. disk[2] = 0;
  344. return;
  345. }
  346. par__disk_from_two(edgepts, edgepts + 2, disk);
  347. if (nedgepts == 2 || par__disk_contains(disk, edgepts + 4)) {
  348. return;
  349. }
  350. par__disk_from_two(edgepts, edgepts + 4, disk);
  351. if (par__disk_contains(disk, edgepts + 2)) {
  352. return;
  353. }
  354. par__disk_from_two(edgepts + 2, edgepts + 4, disk);
  355. if (par__disk_contains(disk, edgepts)) {
  356. return;
  357. }
  358. par_bubbles_touch_three_points(edgepts, disk);
  359. }
  360. static void par__minidisk(PARFLT* disk, PARFLT const* pts, PARINT npts,
  361. PARFLT const* edgepts, PARINT nedgepts)
  362. {
  363. if (npts == 0 || nedgepts == 3) {
  364. par__easydisk(disk, edgepts, nedgepts);
  365. return;
  366. }
  367. PARFLT const* pt = pts + (--npts) * 2;
  368. par__minidisk(disk, pts, npts, edgepts, nedgepts);
  369. if (!par__disk_contains(disk, pt)) {
  370. PARFLT edgepts1[6];
  371. for (PARINT i = 0; i < nedgepts * 2; i += 2) {
  372. edgepts1[i] = edgepts[i];
  373. edgepts1[i + 1] = edgepts[i + 1];
  374. }
  375. edgepts1[2 * nedgepts] = pt[0];
  376. edgepts1[2 * nedgepts + 1] = pt[1];
  377. par__minidisk(disk, pts, npts, edgepts1, ++nedgepts);
  378. }
  379. }
  380. static void par_bubbles__copy_disk(par_bubbles__t const* src,
  381. par_bubbles__t* dst, PARINT parent)
  382. {
  383. PARINT i = dst->count++;
  384. if (dst->capacity < dst->count) {
  385. dst->capacity = PAR_MAX(16, dst->capacity) * 2;
  386. dst->xyr = PAR_REALLOC(PARFLT, dst->xyr, 3 * dst->capacity);
  387. dst->ids = PAR_REALLOC(PARINT, dst->ids, dst->capacity);
  388. }
  389. PARFLT const* xyr = src->xyr + parent * 3;
  390. dst->xyr[i * 3] = xyr[0];
  391. dst->xyr[i * 3 + 1] = xyr[1];
  392. dst->xyr[i * 3 + 2] = xyr[2];
  393. dst->ids[i] = parent;
  394. }
  395. void par_bubbles_enclose_points(PARFLT const* xy, PARINT npts, PARFLT* result)
  396. {
  397. if (npts == 0) {
  398. return;
  399. }
  400. par__minidisk(result, xy, npts, 0, 0);
  401. }
  402. void par_bubbles_enclose_disks(PARFLT const* xyr, PARINT ndisks, PARFLT* result)
  403. {
  404. PARINT ngon = 8;
  405. PARINT npts = ndisks * ngon;
  406. PARFLT* pts = PAR_MALLOC(PARFLT, npts * 2);
  407. PARFLT* ppts = pts;
  408. float dtheta = PAR_PI * 2.0 / ngon;
  409. for (PARINT i = 0; i < ndisks; i++) {
  410. PARFLT cx = xyr[i * 3];
  411. PARFLT cy = xyr[i * 3 + 1];
  412. PARFLT cr = xyr[i * 3 + 2];
  413. PARFLT a = 2.0 * cr / (1.0 + sqrt(2));
  414. PARFLT r = 0.5 * sqrt(2) * a * sqrt(2 + sqrt(2));
  415. float theta = 0;
  416. for (PARINT j = 0; j < ngon; j++, theta += dtheta) {
  417. *ppts++ = cx + r * cos(theta);
  418. *ppts++ = cy + r * sin(theta);
  419. }
  420. }
  421. par_bubbles_enclose_points(pts, npts, result);
  422. PAR_FREE(pts);
  423. }
  424. void par_bubbles_touch_three_points(PARFLT const* xy, PARFLT* xyr)
  425. {
  426. // Many thanks to Stephen Schmitts:
  427. // http://www.abecedarical.com/zenosamples/zs_circle3pts.html
  428. PARFLT p1x = xy[0], p1y = xy[1];
  429. PARFLT p2x = xy[2], p2y = xy[3];
  430. PARFLT p3x = xy[4], p3y = xy[5];
  431. PARFLT a = p2x - p1x, b = p2y - p1y;
  432. PARFLT c = p3x - p1x, d = p3y - p1y;
  433. PARFLT e = a * (p2x + p1x) * 0.5 + b * (p2y + p1y) * 0.5;
  434. PARFLT f = c * (p3x + p1x) * 0.5 + d * (p3y + p1y) * 0.5;
  435. PARFLT det = a*d - b*c;
  436. PARFLT cx = xyr[0] = (d*e - b*f) / det;
  437. PARFLT cy = xyr[1] = (-c*e + a*f) / det;
  438. xyr[2] = sqrt((p1x - cx)*(p1x - cx) + (p1y - cy)*(p1y - cy));
  439. }
  440. void par_bubbles_touch_two_disks(PARFLT* c, PARFLT const* a, PARFLT const* b)
  441. {
  442. PARFLT db = a[2] + c[2], dx = b[0] - a[0], dy = b[1] - a[1];
  443. if (db && (dx || dy)) {
  444. PARFLT da = b[2] + c[2], dc = dx * dx + dy * dy;
  445. da *= da;
  446. db *= db;
  447. PARFLT x = 0.5 + (db - da) / (2 * dc);
  448. PARFLT db1 = db - dc;
  449. PARFLT y0 = PAR_MAX(0, 2 * da * (db + dc) - db1 * db1 - da * da);
  450. PARFLT y = sqrt(y0) / (2 * dc);
  451. c[0] = a[0] + x * dx + y * dy;
  452. c[1] = a[1] + x * dy - y * dx;
  453. } else {
  454. c[0] = a[0] + db;
  455. c[1] = a[1];
  456. }
  457. }
  458. void par_bubbles_free_result(par_bubbles_t* pubbub)
  459. {
  460. par_bubbles__t* bubbles = (par_bubbles__t*) pubbub;
  461. PAR_FREE(bubbles->graph_children);
  462. PAR_FREE(bubbles->graph_heads);
  463. PAR_FREE(bubbles->chain);
  464. PAR_FREE(bubbles->xyr);
  465. PAR_FREE(bubbles->ids);
  466. PAR_FREE(bubbles);
  467. }
  468. par_bubbles_t* par_bubbles_pack(PARFLT const* radiuses, PARINT nradiuses)
  469. {
  470. par_bubbles__t* bubbles = PAR_CALLOC(par_bubbles__t, 1);
  471. if (nradiuses > 0) {
  472. bubbles->radiuses = radiuses;
  473. bubbles->count = nradiuses;
  474. bubbles->chain = PAR_MALLOC(par_bubbles__node, nradiuses);
  475. bubbles->xyr = PAR_MALLOC(PARFLT, 3 * nradiuses);
  476. par_bubbles__initflat(bubbles);
  477. par_bubbles__packflat(bubbles);
  478. }
  479. return (par_bubbles_t*) bubbles;
  480. }
  481. // Assigns a radius to every node according to its number of descendants.
  482. void par_bubbles__generate_radii(par_bubbles__t* bubbles,
  483. par_bubbles__t* worker, PARINT parent)
  484. {
  485. PARINT head = bubbles->graph_heads[parent];
  486. PARINT tail = bubbles->graph_tails[parent];
  487. PARINT nchildren = tail - head;
  488. PARINT pr = parent * 3 + 2;
  489. bubbles->xyr[pr] = 1;
  490. if (nchildren == 0) {
  491. return;
  492. }
  493. for (PARINT cindex = head; cindex != tail; cindex++) {
  494. PARINT child = bubbles->graph_children[cindex];
  495. par_bubbles__generate_radii(bubbles, worker, child);
  496. bubbles->xyr[pr] += bubbles->xyr[child * 3 + 2];
  497. }
  498. // The following square root seems to produce a nicer, more space-filling,
  499. // distribution of radiuses in randomly-generated trees.
  500. bubbles->xyr[pr] = sqrtf(bubbles->xyr[pr]);
  501. }
  502. void par_bubbles__hpack(par_bubbles__t* bubbles, par_bubbles__t* worker,
  503. PARINT parent, bool local)
  504. {
  505. PARINT head = bubbles->graph_heads[parent];
  506. PARINT tail = bubbles->graph_tails[parent];
  507. PARINT nchildren = tail - head;
  508. if (nchildren == 0) {
  509. return;
  510. }
  511. // Cast away const because we're using the worker as a cache to avoid
  512. // a kazillion malloc / free calls.
  513. PARFLT* radiuses = (PARFLT*) worker->radiuses;
  514. // We perform flat layout twice: once without padding (to determine scale)
  515. // and then again with scaled padding.
  516. PARFLT enclosure[3];
  517. PARFLT px = bubbles->xyr[parent * 3 + 0];
  518. PARFLT py = bubbles->xyr[parent * 3 + 1];
  519. PARFLT pr = bubbles->xyr[parent * 3 + 2];
  520. const PARFLT PAR_HPACK_PADDING1 = 0.15;
  521. const PARFLT PAR_HPACK_PADDING2 = 0.025;
  522. PARFLT scaled_padding = 0.0;
  523. while (1) {
  524. worker->npacked = 0;
  525. worker->count = nchildren;
  526. PARINT c = 0;
  527. for (PARINT cindex = head; cindex != tail; cindex++) {
  528. PARINT child = bubbles->graph_children[cindex];
  529. radiuses[c++] = bubbles->xyr[child * 3 + 2] + scaled_padding;
  530. }
  531. par_bubbles__initflat(worker);
  532. par_bubbles__packflat(worker);
  533. // Using Welzl's algorithm instead of a simple AABB enclosure is
  534. // slightly slower and doesn't yield much aesthetic improvement.
  535. #if PAR_BUBBLES_HPACK_WELZL
  536. par_bubbles_enclose_disks(worker->xyr, nchildren, enclosure);
  537. #else
  538. PARFLT aabb[6];
  539. par_bubbles_compute_aabb((par_bubbles_t const*) worker, aabb);
  540. enclosure[0] = 0.5 * (aabb[0] + aabb[2]);
  541. enclosure[1] = 0.5 * (aabb[1] + aabb[3]);
  542. enclosure[2] = 0;
  543. for (PARINT c = 0; c < nchildren; c++) {
  544. PARFLT x = worker->xyr[c * 3 + 0] - enclosure[0];
  545. PARFLT y = worker->xyr[c * 3 + 1] - enclosure[1];
  546. PARFLT r = worker->xyr[c * 3 + 2];
  547. enclosure[2] = PAR_MAX(enclosure[2], r + sqrtf(x * x + y * y));
  548. }
  549. #endif
  550. if (scaled_padding || !PAR_HPACK_PADDING1) {
  551. break;
  552. } else {
  553. scaled_padding = PAR_HPACK_PADDING1 / enclosure[2];
  554. }
  555. }
  556. PARFLT cx = enclosure[0], cy = enclosure[1], cr = enclosure[2];
  557. scaled_padding *= cr;
  558. cr += PAR_HPACK_PADDING2 * cr;
  559. // Transform the children to fit nicely into either (a) the unit circle,
  560. // or (b) their parent. The former is used if "local" is true.
  561. PARFLT scale, tx, ty;
  562. if (local) {
  563. scale = 1.0 / cr;
  564. tx = 0;
  565. ty = 0;
  566. } else {
  567. scale = pr / cr;
  568. tx = px;
  569. ty = py;
  570. }
  571. PARFLT const* src = worker->xyr;
  572. for (PARINT cindex = head; cindex != tail; cindex++, src += 3) {
  573. PARFLT* dst = bubbles->xyr + 3 * bubbles->graph_children[cindex];
  574. dst[0] = tx + scale * (src[0] - cx);
  575. dst[1] = ty + scale * (src[1] - cy);
  576. dst[2] = scale * (src[2] - scaled_padding);
  577. }
  578. // Recursion. TODO: It might be better to use our own stack here.
  579. for (PARINT cindex = head; cindex != tail; cindex++) {
  580. par_bubbles__hpack(bubbles, worker, bubbles->graph_children[cindex],
  581. local);
  582. }
  583. }
  584. par_bubbles_t* par_bubbles_hpack_circle(PARINT* nodes, PARINT nnodes,
  585. PARFLT radius)
  586. {
  587. par_bubbles__t* bubbles = PAR_CALLOC(par_bubbles__t, 1);
  588. if (nnodes > 0) {
  589. bubbles->graph_parents = nodes;
  590. bubbles->count = nnodes;
  591. bubbles->chain = PAR_MALLOC(par_bubbles__node, nnodes);
  592. bubbles->xyr = PAR_MALLOC(PARFLT, 3 * nnodes);
  593. par_bubbles__initgraph(bubbles);
  594. par_bubbles__t* worker = PAR_CALLOC(par_bubbles__t, 1);
  595. worker->radiuses = PAR_MALLOC(PARFLT, bubbles->maxwidth);
  596. worker->chain = PAR_MALLOC(par_bubbles__node, bubbles->maxwidth);
  597. worker->xyr = PAR_MALLOC(PARFLT, 3 * bubbles->maxwidth);
  598. par_bubbles__generate_radii(bubbles, worker, 0);
  599. bubbles->xyr[0] = 0;
  600. bubbles->xyr[1] = 0;
  601. bubbles->xyr[2] = radius;
  602. par_bubbles__hpack(bubbles, worker, 0, false);
  603. par_bubbles_free_result((par_bubbles_t*) worker);
  604. }
  605. return (par_bubbles_t*) bubbles;
  606. }
  607. // TODO: use a stack instead of recursion
  608. static PARINT par_bubbles__pick(par_bubbles__t const* bubbles, PARINT parent,
  609. PARFLT x, PARFLT y)
  610. {
  611. PARFLT const* xyr = bubbles->xyr + parent * 3;
  612. PARFLT d2 = PAR_SQR(x - xyr[0]) + PAR_SQR(y - xyr[1]);
  613. if (d2 > PAR_SQR(xyr[2])) {
  614. return -1;
  615. }
  616. PARINT head = bubbles->graph_heads[parent];
  617. PARINT tail = bubbles->graph_tails[parent];
  618. for (PARINT cindex = head; cindex != tail; cindex++) {
  619. PARINT child = bubbles->graph_children[cindex];
  620. PARINT result = par_bubbles__pick(bubbles, child, x, y);
  621. if (result > -1) {
  622. return result;
  623. }
  624. }
  625. return parent;
  626. }
  627. PARINT par_bubbles_pick(par_bubbles_t const* cbubbles, PARFLT x, PARFLT y)
  628. {
  629. par_bubbles__t const* bubbles = (par_bubbles__t const*) cbubbles;
  630. if (bubbles->count == 0) {
  631. return -1;
  632. }
  633. return par_bubbles__pick(bubbles, 0, x, y);
  634. }
  635. void par_bubbles_compute_aabb(par_bubbles_t const* bubbles, PARFLT* aabb)
  636. {
  637. if (bubbles->count == 0) {
  638. return;
  639. }
  640. PARFLT const* xyr = bubbles->xyr;
  641. aabb[0] = aabb[2] = xyr[0];
  642. aabb[1] = aabb[3] = xyr[1];
  643. for (PARINT i = 0; i < bubbles->count; i++, xyr += 3) {
  644. aabb[0] = PAR_MIN(xyr[0] - xyr[2], aabb[0]);
  645. aabb[1] = PAR_MIN(xyr[1] - xyr[2], aabb[1]);
  646. aabb[2] = PAR_MAX(xyr[0] + xyr[2], aabb[2]);
  647. aabb[3] = PAR_MAX(xyr[1] + xyr[2], aabb[3]);
  648. }
  649. }
  650. bool par_bubbles_check_aabb(PARFLT const* disk, PARFLT const* aabb)
  651. {
  652. PARFLT cx = PAR_CLAMP(disk[0], aabb[0], aabb[2]);
  653. PARFLT cy = PAR_CLAMP(disk[1], aabb[1], aabb[3]);
  654. PARFLT dx = disk[0] - cx;
  655. PARFLT dy = disk[1] - cy;
  656. PARFLT d2 = dx * dx + dy * dy;
  657. return d2 < (disk[2] * disk[2]);
  658. }
  659. static void par_bubbles__cull(par_bubbles__t const* src, PARFLT const* aabb,
  660. PARFLT minradius, par_bubbles__t* dst, PARINT parent)
  661. {
  662. PARFLT const* xyr = src->xyr + parent * 3;
  663. if (xyr[2] < minradius || !par_bubbles_check_aabb(xyr, aabb)) {
  664. return;
  665. }
  666. par_bubbles__copy_disk(src, dst, parent);
  667. PARINT head = src->graph_heads[parent];
  668. PARINT tail = src->graph_tails[parent];
  669. for (PARINT cindex = head; cindex != tail; cindex++) {
  670. PARINT child = src->graph_children[cindex];
  671. par_bubbles__cull(src, aabb, minradius, dst, child);
  672. }
  673. }
  674. par_bubbles_t* par_bubbles_cull(par_bubbles_t const* psrc,
  675. PARFLT const* aabb, PARFLT minradius, par_bubbles_t* pdst)
  676. {
  677. par_bubbles__t const* src = (par_bubbles__t const*) psrc;
  678. par_bubbles__t* dst = (par_bubbles__t*) pdst;
  679. if (!dst) {
  680. dst = PAR_CALLOC(par_bubbles__t, 1);
  681. pdst = (par_bubbles_t*) dst;
  682. } else {
  683. dst->count = 0;
  684. }
  685. if (src->count == 0) {
  686. return pdst;
  687. }
  688. par_bubbles__cull(src, aabb, minradius, dst, 0);
  689. return pdst;
  690. }
  691. void par_bubbles_export(par_bubbles_t const* bubbles, char const* filename)
  692. {
  693. PARFLT aabb[4];
  694. par_bubbles_compute_aabb(bubbles, aabb);
  695. PARFLT maxextent = PAR_MAX(aabb[2] - aabb[0], aabb[3] - aabb[1]);
  696. PARFLT padding = 0.05 * maxextent;
  697. FILE* svgfile = fopen(filename, "wt");
  698. fprintf(svgfile,
  699. "<svg viewBox='%f %f %f %f' width='640px' height='640px' "
  700. "version='1.1' "
  701. "xmlns='http://www.w3.org/2000/svg'>\n"
  702. "<g stroke-width='0.5' stroke-opacity='0.5' stroke='black' "
  703. "fill-opacity='0.2' fill='#2A8BB6'>\n"
  704. "<rect fill-opacity='0.1' stroke='none' fill='#2A8BB6' x='%f' y='%f' "
  705. "width='100%%' height='100%%'/>\n",
  706. aabb[0] - padding, aabb[1] - padding,
  707. aabb[2] - aabb[0] + 2 * padding, aabb[3] - aabb[1] + 2 * padding,
  708. aabb[0] - padding, aabb[1] - padding);
  709. PARFLT const* xyr = bubbles->xyr;
  710. for (PARINT i = 0; i < bubbles->count; i++, xyr += 3) {
  711. fprintf(svgfile, "<circle stroke-width='%f' cx='%f' cy='%f' r='%f'/>\n",
  712. xyr[2] * 0.01, xyr[0], xyr[1], xyr[2]);
  713. fprintf(svgfile, "<text text-anchor='middle' stroke='none' "
  714. "x='%f' y='%f' font-size='%f'>%d</text>\n",
  715. xyr[0], xyr[1] + xyr[2] * 0.125, xyr[2] * 0.5, (int) i);
  716. }
  717. fputs("</g>\n</svg>", svgfile);
  718. fclose(svgfile);
  719. }
  720. void par_bubbles_get_children(par_bubbles_t const* pbubbles, PARINT node,
  721. PARINT** pchildren, PARINT* nchildren)
  722. {
  723. par_bubbles__t const* bubbles = (par_bubbles__t const*) pbubbles;
  724. *pchildren = bubbles->graph_children + bubbles->graph_heads[node];
  725. *nchildren = bubbles->graph_tails[node] - bubbles->graph_heads[node];
  726. }
  727. void par_bubbles__get_maxdepth(par_bubbles__t const* bubbles, PARINT* maxdepth,
  728. PARINT* leaf, PARINT parent, PARINT depth)
  729. {
  730. if (depth > *maxdepth) {
  731. *leaf = parent;
  732. *maxdepth = depth;
  733. }
  734. PARINT* children;
  735. PARINT nchildren;
  736. par_bubbles_t const* pbubbles = (par_bubbles_t const*) bubbles;
  737. par_bubbles_get_children(pbubbles, parent, &children, &nchildren);
  738. for (PARINT c = 0; c < nchildren; c++) {
  739. par_bubbles__get_maxdepth(bubbles, maxdepth, leaf, children[c],
  740. depth + 1);
  741. }
  742. }
  743. void par_bubbles_get_maxdepth(par_bubbles_t const* pbubbles, PARINT* maxdepth,
  744. PARINT* leaf)
  745. {
  746. par_bubbles__t const* bubbles = (par_bubbles__t const*) pbubbles;
  747. *maxdepth = -1;
  748. *leaf = -1;
  749. return par_bubbles__get_maxdepth(bubbles, maxdepth, leaf, 0, 0);
  750. }
  751. PARINT par_bubbles_get_depth(par_bubbles_t const* pbubbles, PARINT node)
  752. {
  753. par_bubbles__t const* bubbles = (par_bubbles__t const*) pbubbles;
  754. PARINT const* parents = bubbles->graph_parents;
  755. PARINT depth = 0;
  756. while (node) {
  757. node = parents[node];
  758. depth++;
  759. }
  760. return depth;
  761. }
  762. void par_bubbles_compute_aabb_for_node(par_bubbles_t const* bubbles,
  763. PAR_BUBBLES_INT node, PAR_BUBBLES_FLT* aabb)
  764. {
  765. PARFLT const* xyr = bubbles->xyr + 3 * node;
  766. aabb[0] = aabb[2] = xyr[0];
  767. aabb[1] = aabb[3] = xyr[1];
  768. aabb[0] = PAR_MIN(xyr[0] - xyr[2], aabb[0]);
  769. aabb[1] = PAR_MIN(xyr[1] - xyr[2], aabb[1]);
  770. aabb[2] = PAR_MAX(xyr[0] + xyr[2], aabb[2]);
  771. aabb[3] = PAR_MAX(xyr[1] + xyr[2], aabb[3]);
  772. }
  773. void par_bubbles_export_local(par_bubbles_t const* bubbles,
  774. PAR_BUBBLES_INT idx, char const* filename)
  775. {
  776. par_bubbles_t* clone = par_bubbles_cull_local(bubbles, idx, 0, 0);
  777. FILE* svgfile = fopen(filename, "wt");
  778. fprintf(svgfile,
  779. "<svg viewBox='%f %f %f %f' width='640px' height='640px' "
  780. "version='1.1' "
  781. "xmlns='http://www.w3.org/2000/svg'>\n"
  782. "<g stroke-width='0.5' stroke-opacity='0.5' stroke='black' "
  783. "fill-opacity='0.2' fill='#2A8BB6'>\n"
  784. "<rect fill-opacity='0.1' stroke='none' fill='#2AB68B' x='%f' y='%f' "
  785. "width='100%%' height='100%%'/>\n",
  786. -1.0, -1.0, 2.0, 2.0, -1.0, -1.0);
  787. PARFLT const* xyr = clone->xyr;
  788. for (PARINT i = 0; i < clone->count; i++, xyr += 3) {
  789. fprintf(svgfile, "<circle stroke-width='%f' cx='%f' cy='%f' r='%f'/>\n",
  790. xyr[2] * 0.01, xyr[0], xyr[1], xyr[2]);
  791. }
  792. fputs("</g>\n</svg>", svgfile);
  793. fclose(svgfile);
  794. par_bubbles_free_result(clone);
  795. }
  796. static void par_bubbles__copy_disk_local(par_bubbles__t const* src,
  797. par_bubbles__t* dst, PARINT parent, PARFLT const* xform)
  798. {
  799. PARINT i = dst->count++;
  800. if (dst->capacity < dst->count) {
  801. dst->capacity = PAR_MAX(16, dst->capacity) * 2;
  802. dst->xyr = PAR_REALLOC(PARFLT, dst->xyr, 3 * dst->capacity);
  803. dst->ids = PAR_REALLOC(PARINT, dst->ids, dst->capacity);
  804. }
  805. PARFLT const* xyr = src->xyr + parent * 3;
  806. dst->xyr[i * 3] = xyr[0] * xform[2] + xform[0];
  807. dst->xyr[i * 3 + 1] = xyr[1] * xform[2] + xform[1];
  808. dst->xyr[i * 3 + 2] = xyr[2] * xform[2];
  809. dst->ids[i] = parent;
  810. }
  811. static void par_bubbles__cull_local(par_bubbles__t const* src,
  812. PARFLT const* xform, PARFLT minradius, par_bubbles__t* dst, PARINT parent)
  813. {
  814. PARFLT const* xyr = src->xyr + parent * 3;
  815. if (xyr[2] < minradius) {
  816. return;
  817. }
  818. PARFLT child_xform[3] = {
  819. xform[0] + xform[2] * xyr[0],
  820. xform[1] + xform[2] * xyr[1],
  821. xform[2] * xyr[2]
  822. };
  823. minradius *= xyr[2];
  824. par_bubbles__copy_disk_local(src, dst, parent, xform);
  825. xform = child_xform;
  826. PARINT head = src->graph_heads[parent];
  827. PARINT tail = src->graph_tails[parent];
  828. for (PARINT cindex = head; cindex != tail; cindex++) {
  829. PARINT child = src->graph_children[cindex];
  830. par_bubbles__cull_local(src, xform, minradius, dst, child);
  831. }
  832. }
  833. par_bubbles_t* par_bubbles_cull_local(par_bubbles_t const* psrc,
  834. PAR_BUBBLES_INT root, PAR_BUBBLES_FLT minradius, par_bubbles_t* pdst)
  835. {
  836. par_bubbles__t const* src = (par_bubbles__t const*) psrc;
  837. par_bubbles__t* dst = (par_bubbles__t*) pdst;
  838. if (!dst) {
  839. dst = PAR_CALLOC(par_bubbles__t, 1);
  840. pdst = (par_bubbles_t*) dst;
  841. } else {
  842. dst->count = 0;
  843. }
  844. if (src->count == 0) {
  845. return pdst;
  846. }
  847. PARFLT xform[3] = {0, 0, 1};
  848. par_bubbles__copy_disk_local(src, dst, root, xform);
  849. dst->xyr[0] = dst->xyr[1] = 0;
  850. dst->xyr[2] = 1;
  851. PARINT head = src->graph_heads[root];
  852. PARINT tail = src->graph_tails[root];
  853. for (PARINT cindex = head; cindex != tail; cindex++) {
  854. PARINT child = src->graph_children[cindex];
  855. par_bubbles__cull_local(src, xform, minradius, dst, child);
  856. }
  857. return pdst;
  858. }
  859. par_bubbles_t* par_bubbles_hpack_local(PARINT* nodes, PARINT nnodes)
  860. {
  861. par_bubbles__t* bubbles = PAR_CALLOC(par_bubbles__t, 1);
  862. if (nnodes > 0) {
  863. bubbles->graph_parents = nodes;
  864. bubbles->count = nnodes;
  865. bubbles->chain = PAR_MALLOC(par_bubbles__node, nnodes);
  866. bubbles->xyr = PAR_MALLOC(PARFLT, 3 * nnodes);
  867. par_bubbles__initgraph(bubbles);
  868. par_bubbles__t* worker = PAR_CALLOC(par_bubbles__t, 1);
  869. worker->radiuses = PAR_MALLOC(PARFLT, bubbles->maxwidth);
  870. worker->chain = PAR_MALLOC(par_bubbles__node, bubbles->maxwidth);
  871. worker->xyr = PAR_MALLOC(PARFLT, 3 * bubbles->maxwidth);
  872. par_bubbles__generate_radii(bubbles, worker, 0);
  873. bubbles->xyr[0] = 0;
  874. bubbles->xyr[1] = 0;
  875. bubbles->xyr[2] = 1;
  876. par_bubbles__hpack(bubbles, worker, 0, true);
  877. par_bubbles_free_result((par_bubbles_t*) worker);
  878. }
  879. return (par_bubbles_t*) bubbles;
  880. }
  881. #undef PARINT
  882. #undef PARFLT
  883. #endif // PAR_BUBBLES_IMPLEMENTATION