g_subpaths.c 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314
  1. /* This file is part of the GNU plotutils package. Copyright (C) 1995,
  2. 1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
  3. The GNU plotutils package is free software. You may redistribute it
  4. and/or modify it under the terms of the GNU General Public License as
  5. published by the Free Software foundation; either version 2, or (at your
  6. option) any later version.
  7. The GNU plotutils package is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. General Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with the GNU plotutils package; see the file COPYING. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
  14. Boston, MA 02110-1301, USA. */
  15. /* This file contains all of libplot's low-level code for constructing and
  16. manipulating paths, both simple and compound. It includes functions
  17. that construct polygonal and Bezier approximations to a given path.
  18. They are used by Plotters whose output format does not support all of
  19. libplot's graphics primitives. */
  20. /* E.g., _fakearc() draws polygonal approximations to circular and elliptic
  21. quarter-arcs. Each polygonal approximation will contain
  22. 2**NUM_ARC_SUBDIVISIONS line segments.
  23. Similarly, polygonal approximations to quadratic and cubic Beziers will
  24. contain no more than 2**MAX_NUM_BEZIER2_SUBDIVISIONS and
  25. 2**MAX_NUM_BEZIER3_SUBDIVISIONS line segments. However, each bisection
  26. algorithm used for drawing a Bezier normally usually its recursion based
  27. on a relative flatness criterion (see below). */
  28. #include "sys-defines.h"
  29. #include "extern.h"
  30. #include "g_arc.h" /* for chord table */
  31. /* Number of times a circular arc or quarter-ellipse will be recursively
  32. subdivided. Two raised to this power is the number of line segments
  33. that the polygonalization will contain. */
  34. /* NOTE: the maximum allowed value for NUM_ARC_SUBDIVISIONS is
  35. TABULATED_ARC_SUBDIVISIONS (i.e., the size of the chordal deviation
  36. table for a quarter-circle or quarter-ellipse, defined in g_arc.h). */
  37. #define NUM_ARC_SUBDIVISIONS 5
  38. /* Maximum number of times quadratic and cubic Beziers will be recursively
  39. subdivided. For Beziers we use an adaptive algorithm, in which
  40. bisection stops when a specified relative flatness has been reached.
  41. But these parameters provide a hard cutoff, which overrides the relative
  42. flatness end condition. */
  43. #define MAX_NUM_BEZIER2_SUBDIVISIONS 6
  44. #define MAX_NUM_BEZIER3_SUBDIVISIONS 7
  45. /* The relative flatness parameters. */
  46. #define REL_QUAD_FLATNESS 5e-4
  47. #define REL_CUBIC_FLATNESS 5e-4
  48. #define DATAPOINTS_BUFSIZ PL_MAX_UNFILLED_PATH_LENGTH
  49. #define DIST(p0,p1) (sqrt( ((p0).x - (p1).x)*((p0).x - (p1).x) \
  50. + ((p0).y - (p1).y)*((p0).y - (p1).y)))
  51. #define MIDWAY(x0, x1) (0.5 * ((x0) + (x1)))
  52. /* forward references */
  53. static void _prepare_chord_table (double sagitta, double custom_chord_table[TABULATED_ARC_SUBDIVISIONS]);
  54. static void _fakearc (plPath *path, plPoint p0, plPoint p1, int arc_type, const double *custom_chord_table, const double m[4]);
  55. /* ctor for plPath class; constructs an empty plPath, with type set to
  56. PATH_SEGMENT_LIST (default type) */
  57. plPath *
  58. _new_plPath (void)
  59. {
  60. plPath *path;
  61. path = (plPath *)_pl_xmalloc (sizeof (plPath));
  62. path->type = PATH_SEGMENT_LIST;
  63. path->segments = (plPathSegment *)NULL;
  64. path->segments_len = 0; /* number of slots allocated */
  65. path->num_segments = 0; /* number of slots occupied */
  66. path->primitive = false;
  67. path->llx = DBL_MAX;
  68. path->lly = DBL_MAX;
  69. path->urx = -(DBL_MAX);
  70. path->ury = -(DBL_MAX);
  71. return path;
  72. }
  73. /* dtor for plPath class */
  74. void
  75. _delete_plPath (plPath *path)
  76. {
  77. if (path == (plPath *)NULL)
  78. return;
  79. if (path->type == PATH_SEGMENT_LIST
  80. && path->segments_len > 0) /* number of slots allocated */
  81. free (path->segments);
  82. free (path);
  83. }
  84. /* reset function for plPath class */
  85. void
  86. _reset_plPath (plPath *path)
  87. {
  88. if (path == (plPath *)NULL)
  89. return;
  90. if (path->type == PATH_SEGMENT_LIST
  91. && path->segments_len > 0) /* number of slots allocated */
  92. free (path->segments);
  93. path->segments = (plPathSegment *)NULL;
  94. path->segments_len = 0;
  95. path->type = PATH_SEGMENT_LIST; /* restore to default */
  96. path->num_segments = 0;
  97. path->primitive = false;
  98. path->llx = DBL_MAX;
  99. path->lly = DBL_MAX;
  100. path->urx = -(DBL_MAX);
  101. path->ury = -(DBL_MAX);
  102. }
  103. void
  104. _add_moveto (plPath *path, plPoint p)
  105. {
  106. if (path == (plPath *)NULL)
  107. return;
  108. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  109. return;
  110. /* empty, so allocate a segment buffer */
  111. path->segments = (plPathSegment *)
  112. _pl_xmalloc (DATAPOINTS_BUFSIZ * sizeof(plPathSegment));
  113. path->segments_len = DATAPOINTS_BUFSIZ;
  114. path->segments[0].type = S_MOVETO;
  115. path->segments[0].p = p;
  116. path->num_segments = 1;
  117. path->llx = p.x;
  118. path->lly = p.y;
  119. path->urx = p.x;
  120. path->ury = p.y;
  121. }
  122. void
  123. _add_line (plPath *path, plPoint p)
  124. {
  125. if (path == (plPath *)NULL)
  126. return;
  127. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  128. return;
  129. if (path->num_segments == 0)
  130. /* empty, so allocate a segment buffer */
  131. {
  132. path->segments = (plPathSegment *)
  133. _pl_xmalloc (DATAPOINTS_BUFSIZ * sizeof(plPathSegment));
  134. path->segments_len = DATAPOINTS_BUFSIZ;
  135. }
  136. if (path->num_segments == path->segments_len)
  137. /* full, so reallocate */
  138. {
  139. path->segments = (plPathSegment *)
  140. _pl_xrealloc (path->segments,
  141. 2 * path->segments_len * sizeof(plPathSegment));
  142. path->segments_len *= 2;
  143. }
  144. path->segments[path->num_segments].type = S_LINE;
  145. path->segments[path->num_segments].p = p;
  146. path->num_segments++;
  147. path->llx = DMIN(path->llx, p.x);
  148. path->lly = DMIN(path->lly, p.y);
  149. path->urx = DMAX(path->urx, p.x);
  150. path->ury = DMAX(path->ury, p.y);
  151. }
  152. void
  153. _add_closepath (plPath *path)
  154. {
  155. if (path == (plPath *)NULL)
  156. return;
  157. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  158. return;
  159. if (path->num_segments == 0) /* meaningless */
  160. return;
  161. if (path->num_segments == path->segments_len)
  162. /* full, so reallocate */
  163. {
  164. path->segments = (plPathSegment *)
  165. _pl_xrealloc (path->segments,
  166. 2 * path->segments_len * sizeof(plPathSegment));
  167. path->segments_len *= 2;
  168. }
  169. path->segments[path->num_segments].type = S_CLOSEPATH;
  170. path->segments[path->num_segments].p = path->segments[0].p;
  171. path->num_segments++;
  172. }
  173. void
  174. _add_bezier2 (plPath *path, plPoint pc, plPoint p)
  175. {
  176. if (path == (plPath *)NULL)
  177. return;
  178. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  179. return;
  180. if (path->num_segments == 0)
  181. /* empty, so allocate a segment buffer */
  182. {
  183. path->segments = (plPathSegment *)
  184. _pl_xmalloc (DATAPOINTS_BUFSIZ * sizeof(plPathSegment));
  185. path->segments_len = DATAPOINTS_BUFSIZ;
  186. }
  187. if (path->num_segments == path->segments_len)
  188. /* full, so reallocate */
  189. {
  190. path->segments = (plPathSegment *)
  191. _pl_xrealloc (path->segments,
  192. 2 * path->segments_len * sizeof(plPathSegment));
  193. path->segments_len *= 2;
  194. }
  195. path->segments[path->num_segments].type = S_QUAD;
  196. path->segments[path->num_segments].p = p;
  197. path->segments[path->num_segments].pc = pc;
  198. path->num_segments++;
  199. }
  200. void
  201. _add_bezier3 (plPath *path, plPoint pc, plPoint pd, plPoint p)
  202. {
  203. if (path == (plPath *)NULL)
  204. return;
  205. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  206. return;
  207. if (path->num_segments == 0)
  208. /* empty, so allocate a segment buffer */
  209. {
  210. path->segments = (plPathSegment *)
  211. _pl_xmalloc (DATAPOINTS_BUFSIZ * sizeof(plPathSegment));
  212. path->segments_len = DATAPOINTS_BUFSIZ;
  213. }
  214. if (path->num_segments == path->segments_len)
  215. /* full, so reallocate */
  216. {
  217. path->segments = (plPathSegment *)
  218. _pl_xrealloc (path->segments,
  219. 2 * path->segments_len * sizeof(plPathSegment));
  220. path->segments_len *= 2;
  221. }
  222. path->segments[path->num_segments].type = S_CUBIC;
  223. path->segments[path->num_segments].p = p;
  224. path->segments[path->num_segments].pc = pc;
  225. path->segments[path->num_segments].pd = pd;
  226. path->num_segments++;
  227. }
  228. void
  229. _add_arc (plPath *path, plPoint pc, plPoint p1)
  230. {
  231. if (path == (plPath *)NULL)
  232. return;
  233. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  234. return;
  235. if (path->num_segments == 0)
  236. /* empty, so allocate a segment buffer */
  237. {
  238. path->segments = (plPathSegment *)
  239. _pl_xmalloc (DATAPOINTS_BUFSIZ * sizeof(plPathSegment));
  240. path->segments_len = DATAPOINTS_BUFSIZ;
  241. }
  242. if (path->num_segments == path->segments_len)
  243. /* full, so reallocate */
  244. {
  245. path->segments = (plPathSegment *)
  246. _pl_xrealloc (path->segments,
  247. 2 * path->segments_len * sizeof(plPathSegment));
  248. path->segments_len *= 2;
  249. }
  250. path->segments[path->num_segments].type = S_ARC;
  251. path->segments[path->num_segments].p = p1;
  252. path->segments[path->num_segments].pc = pc;
  253. path->num_segments++;
  254. }
  255. void
  256. _add_ellarc (plPath *path, plPoint pc, plPoint p1)
  257. {
  258. if (path == (plPath *)NULL)
  259. return;
  260. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  261. return;
  262. if (path->num_segments == 0)
  263. /* empty, so allocate a segment buffer */
  264. {
  265. path->segments = (plPathSegment *)
  266. _pl_xmalloc (DATAPOINTS_BUFSIZ * sizeof(plPathSegment));
  267. path->segments_len = DATAPOINTS_BUFSIZ;
  268. }
  269. if (path->num_segments == path->segments_len)
  270. /* full, so reallocate */
  271. {
  272. path->segments = (plPathSegment *)
  273. _pl_xrealloc (path->segments,
  274. 2 * path->segments_len * sizeof(plPathSegment));
  275. path->segments_len *= 2;
  276. }
  277. path->segments[path->num_segments].type = S_ELLARC;
  278. path->segments[path->num_segments].p = p1;
  279. path->segments[path->num_segments].pc = pc;
  280. path->num_segments++;
  281. }
  282. void
  283. _add_box (plPath *path, plPoint p0, plPoint p1, bool clockwise)
  284. {
  285. if (path == (plPath *)NULL)
  286. return;
  287. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  288. return;
  289. path->type = PATH_BOX;
  290. path->p0 = p0;
  291. path->p1 = p1;
  292. path->clockwise = clockwise;
  293. path->llx = DMIN(path->llx, p0.x);
  294. path->lly = DMIN(path->lly, p0.y);
  295. path->urx = DMAX(path->urx, p0.x);
  296. path->ury = DMAX(path->ury, p0.y);
  297. path->llx = DMIN(path->llx, p1.x);
  298. path->lly = DMIN(path->lly, p1.y);
  299. path->urx = DMAX(path->urx, p1.x);
  300. path->ury = DMAX(path->ury, p1.y);
  301. }
  302. void
  303. _add_circle (plPath *path, plPoint pc, double radius, bool clockwise)
  304. {
  305. if (path == (plPath *)NULL)
  306. return;
  307. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  308. return;
  309. path->type = PATH_CIRCLE;
  310. path->pc = pc;
  311. path->radius = radius;
  312. path->clockwise = clockwise;
  313. }
  314. void
  315. _add_ellipse (plPath *path, plPoint pc, double rx, double ry, double angle, bool clockwise)
  316. {
  317. if (path == (plPath *)NULL)
  318. return;
  319. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  320. return;
  321. path->type = PATH_ELLIPSE;
  322. path->pc = pc;
  323. path->rx = rx;
  324. path->ry = ry;
  325. path->angle = angle;
  326. path->clockwise = clockwise;
  327. }
  328. /* Draw a polygonal approximation to the circular arc from p0 to p1, with
  329. center pc, by calling _fakearc(), which in turn repeatedly calls
  330. _add_line(). It is assumed that p0 and p1 are distinct. It is assumed
  331. that pc is on the perpendicular bisector of the line segment joining
  332. them, and that the graphics cursor is initially located at p0. */
  333. void
  334. _add_arc_as_lines (plPath *path, plPoint pc, plPoint p1)
  335. {
  336. /* starting point */
  337. plPoint p0;
  338. /* bisection point of arc, and midpoint of chord */
  339. plPoint pb, pm;
  340. /* rotation matrix */
  341. double m[4];
  342. /* other variables */
  343. plVector v, v0, v1;
  344. double radius, sagitta;
  345. double cross, orientation;
  346. /* handcrafted relative chordal deviation table, for this arc */
  347. double custom_chord_table[TABULATED_ARC_SUBDIVISIONS];
  348. if (path == (plPath *)NULL)
  349. return;
  350. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  351. return;
  352. /* determine starting point */
  353. p0 = path->segments[path->num_segments - 1].p;
  354. if (p0.x == p1.x && p0.y == p1.y)
  355. /* zero-length arc, draw as zero-length line segment */
  356. _add_line (path, p0);
  357. else
  358. /* genuine polygonal approximation */
  359. {
  360. /* vectors from pc to p0, and pc to p1 */
  361. v0.x = p0.x - pc.x;
  362. v0.y = p0.y - pc.y;
  363. v1.x = p1.x - pc.x;
  364. v1.y = p1.y - pc.y;
  365. /* cross product, zero if points are collinear */
  366. cross = v0.x * v1.y - v1.x * v0.y;
  367. /* Compute orientation. Note libplot convention: if p0, p1, pc are
  368. collinear then arc goes counterclockwise from p0 to p1. */
  369. orientation = (cross >= 0.0 ? 1.0 : -1.0);
  370. radius = DIST(pc, p0); /* radius is distance to p0 or p1 */
  371. pm.x = 0.5 * (p0.x + p1.x); /* midpoint of chord from p0 to p1 */
  372. pm.y = 0.5 * (p0.y + p1.y);
  373. v.x = p1.x - p0.x; /* chord vector from p0 to p1 */
  374. v.y = p1.y - p0.y;
  375. _vscale(&v, radius);
  376. pb.x = pc.x + orientation * v.y; /* bisection point of arc */
  377. pb.y = pc.y - orientation * v.x;
  378. sagitta = DIST(pb, pm) / radius;
  379. /* fill in entries of chordal deviation table for this user-defined
  380. sagitta */
  381. _prepare_chord_table (sagitta, custom_chord_table);
  382. /* call _fakearc(), using for `rotation' matrix m[] a clockwise or
  383. counterclockwise rotation by 90 degrees, depending on orientation */
  384. m[0] = 0.0, m[1] = orientation, m[2] = -orientation, m[3] = 0.0;
  385. _fakearc (path, p0, p1, USER_DEFINED_ARC, custom_chord_table, m);
  386. }
  387. }
  388. /* Draw a polygonal approximation to a quarter-ellipse from p0 to p1, by
  389. calling _fakearc(), which in turn repeatedly calls _add_line(). pc is
  390. the center of the arc, and p0, p1, pc are assumed not to be collinear.
  391. It is assumed that the graphics cursor is located at p0 when this
  392. function is called.
  393. The control triangle for the elliptic arc will have vertices p0, p1, and
  394. K = p0 + (p1 - pc) = p1 + (p0 - pc). The arc will pass through p0 and
  395. p1, and will be tangent at p0 to the edge from p0 to K, and at p1 to the
  396. edge from p1 to K. */
  397. void
  398. _add_ellarc_as_lines (plPath *path, plPoint pc, plPoint p1)
  399. {
  400. plPoint p0;
  401. plVector v0, v1;
  402. double cross;
  403. double m[4];
  404. if (path == (plPath *)NULL)
  405. return;
  406. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  407. return;
  408. /* determine starting point */
  409. p0 = path->segments[path->num_segments - 1].p;
  410. /* vectors from pc to p0, and pc to p1 */
  411. v0.x = p0.x - pc.x;
  412. v0.y = p0.y - pc.y;
  413. v1.x = p1.x - pc.x;
  414. v1.y = p1.y - pc.y;
  415. /* cross product */
  416. cross = v0.x * v1.y - v1.x * v0.y;
  417. if (FROUND(cross) == 0.0)
  418. /* collinear points, draw line segment from p0 to p1
  419. (not quite right, could be bettered) */
  420. _add_line (path, p1);
  421. else
  422. {
  423. /* `rotation' matrix (it maps v0 -> -v1 and v1 -> v0) */
  424. m[0] = - (v0.x * v0.y + v1.x * v1.y) / cross;
  425. m[1] = (v0.x * v0.x + v1.x * v1.x) / cross;
  426. m[2] = - (v0.y * v0.y + v1.y * v1.y) / cross;
  427. m[3] = (v0.x * v0.y + v1.x * v1.y) / cross;
  428. /* draw polyline inscribed in the quarter-ellipse */
  429. _fakearc (path, p0, p1, QUARTER_ARC, (double *)NULL, m);
  430. }
  431. }
  432. /* A function that approximates a circular arc by a cubic Bezier. The
  433. approximation used is a standard one. E.g., a quarter circle extending
  434. from (1,0) to (0,1), with center (0,0), would be approximated by a cubic
  435. Bezier with control points (1,KAPPA) and (KAPPA,1). Here KAPPA =
  436. (4/3)[sqrt(2)-1] = 0.552284749825, approximately. The cubic Bezier will
  437. touch the quarter-circle along the line x=y.
  438. For a quarter-circle, the maximum relative error in r as a function of
  439. theta is about 2.7e-4. The error in r has the same sign, for all theta. */
  440. /* According to Berthold K. P. Horn <bkph@ai.mit.edu>, the general formula
  441. for KAPPA, for a radius-1 circular arc (not necessary a quarter-circle),
  442. KAPPA = (4/3)sqrt[(1-cos H)/(1+cos H)]
  443. = (4/3)[1-cos H]/[sin H] = (4/3)[sin H]/[1+cosH]
  444. where H is half the angle subtended by the arc. H=45 degrees for a
  445. quarter circle. This is the formula we use. */
  446. /* Louis Vosloo <support@yandy.com> points out that for a quarter-circle,
  447. the value 0.55228... for KAPPA is, for some purposes, sub-optimal. By
  448. dropping the requirement that the quarter-circle and the Bezier touch
  449. each other along the symmetry line x=y, one can slightly decrease the
  450. maximum relative error. He says 0.5541... is the best possible choice.
  451. He doesn't have an improved value of KAPPA for a general arc, though. */
  452. void
  453. _add_arc_as_bezier3 (plPath *path, plPoint pc, plPoint p1)
  454. {
  455. plPoint p0;
  456. plVector v0, v1;
  457. if (path == (plPath *)NULL)
  458. return;
  459. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  460. return;
  461. /* determine starting point */
  462. p0 = path->segments[path->num_segments - 1].p;
  463. /* vectors to starting, ending points */
  464. v0.x = p0.x - pc.x;
  465. v0.y = p0.y - pc.y;
  466. v1.x = p1.x - pc.x;
  467. v1.y = p1.y - pc.y;
  468. if ((v0.x == 0.0 && v0.y == 0.0) || (v1.x == 0.0 && v1.y == 0.0)
  469. || (v0.x == v1.x && v0.y == v1.y))
  470. /* degenerate case */
  471. _add_line (path, p1);
  472. else
  473. /* normal case */
  474. {
  475. double oldangle, newangle, anglerange;
  476. double cross;
  477. int orientation;
  478. /* cross product, zero if points are collinear */
  479. cross = v0.x * v1.y - v1.x * v0.y;
  480. /* Compute orientation. Note libplot convention: if p0, p1, pc
  481. are collinear then arc goes counterclockwise from p0 to p1. */
  482. orientation = (cross >= 0.0 ? 1 : -1);
  483. /* compute signed subtended angle */
  484. oldangle = _xatan2 (v0.y, v0.x);
  485. newangle = _xatan2 (v1.y, v1.x);
  486. anglerange = newangle - oldangle;
  487. if (anglerange > M_PI)
  488. anglerange -= (2 * M_PI);
  489. if (anglerange <= -(M_PI))
  490. anglerange += (2 * M_PI);
  491. if (FABS(anglerange) > 0.51 * M_PI)
  492. /* subtended angle > 0.51 * pi, so split arc in two and recurse,
  493. since Bezier approximation isn't very good for angles much
  494. greater than 90 degrees */
  495. {
  496. double radius;
  497. plPoint pb;
  498. plVector v;
  499. radius = DIST(pc, p0); /* radius is distance to p0 or p1 */
  500. v.x = p1.x - p0.x; /* chord vector from p0 to p1 */
  501. v.y = p1.y - p0.y;
  502. _vscale(&v, radius);
  503. pb.x = pc.x + orientation * v.y; /* bisection point of arc */
  504. pb.y = pc.y - orientation * v.x;
  505. _add_arc_as_bezier3 (path, pc, pb);
  506. _add_arc_as_bezier3 (path, pc, p1);
  507. }
  508. else
  509. /* subtended angle <= 0.51 * pi, so a single Bezier suffices */
  510. {
  511. double halfangle, sinhalf, coshalf, kappa;
  512. plPoint pc_bezier3, pd_bezier3;
  513. halfangle = 0.5 * FABS(anglerange);
  514. sinhalf = sin (halfangle);
  515. coshalf = cos (halfangle);
  516. /* compute kappa using either of two formulae, depending on
  517. numerical stability */
  518. if (FABS(sinhalf) < 0.5)
  519. kappa = (4.0/3.0) * sinhalf / (1.0 + coshalf);
  520. else
  521. kappa = (4.0/3.0) * (1.0 - coshalf) / sinhalf;
  522. pc_bezier3.x = p0.x - kappa * orientation * v0.y;
  523. pc_bezier3.y = p0.y + kappa * orientation * v0.x;
  524. pd_bezier3.x = p1.x + kappa * orientation * v1.y;
  525. pd_bezier3.y = p1.y - kappa * orientation * v1.x;
  526. _add_bezier3 (path, pc_bezier3, pd_bezier3, p1);
  527. }
  528. }
  529. }
  530. #define KAPPA_FOR_QUARTER_CIRCLE 0.552284749825
  531. void
  532. _add_ellarc_as_bezier3 (plPath *path, plPoint pc, plPoint p1)
  533. {
  534. plPoint p0, pc_bezier3, pd_bezier3;
  535. plVector v0, v1;
  536. if (path == (plPath *)NULL)
  537. return;
  538. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  539. return;
  540. /* determine starting point */
  541. p0 = path->segments[path->num_segments - 1].p;
  542. /* vectors to starting, ending points */
  543. v0.x = p0.x - pc.x;
  544. v0.y = p0.y - pc.y;
  545. v1.x = p1.x - pc.x;
  546. v1.y = p1.y - pc.y;
  547. /* replace by cubic Bezier, with computed control points */
  548. pc_bezier3.x = p0.x + KAPPA_FOR_QUARTER_CIRCLE * v1.x;
  549. pc_bezier3.y = p0.y + KAPPA_FOR_QUARTER_CIRCLE * v1.y;
  550. pd_bezier3.x = p1.x + KAPPA_FOR_QUARTER_CIRCLE * v0.x;
  551. pd_bezier3.y = p1.y + KAPPA_FOR_QUARTER_CIRCLE * v0.y;
  552. _add_bezier3 (path, pc_bezier3, pd_bezier3, p1);
  553. }
  554. /* Approximate a quadratic Bezier by a polyline: standard deCasteljau
  555. bisection algorithm. However, we stop subdividing when an appropriate
  556. metric of the quadratic Bezier to be drawn is sufficiently small. If
  557. (p0,p1,p2) defines the quadratic Bezier, we require that the length of
  558. p0-2*p1+p2 be less than REL_QUAD_FLATNESS times the distance between the
  559. endpoints of the original Bezier. */
  560. void
  561. _add_bezier2_as_lines (plPath *path, plPoint pc, plPoint p)
  562. {
  563. plPoint r0[MAX_NUM_BEZIER2_SUBDIVISIONS + 1], r1[MAX_NUM_BEZIER2_SUBDIVISIONS + 1], r2[MAX_NUM_BEZIER2_SUBDIVISIONS + 1];
  564. int level[MAX_NUM_BEZIER2_SUBDIVISIONS + 1];
  565. int n = 0; /* index of top of stack, < MAX_NUM_BEZIER2_SUBDIVISIONS */
  566. int segments_drawn = 0;
  567. plPoint p0;
  568. double sqdist, max_squared_length;
  569. if (path == (plPath *)NULL)
  570. return;
  571. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  572. return;
  573. /* determine starting point */
  574. p0 = path->segments[path->num_segments - 1].p;
  575. /* squared distance between p0 and p */
  576. sqdist = (p.x - p0.x) * (p.x - p0.x) + (p.y - p0.y) * (p.y - p0.y);
  577. max_squared_length = REL_QUAD_FLATNESS * REL_QUAD_FLATNESS * sqdist;
  578. r0[0] = p0;
  579. r1[0] = pc;
  580. r2[0] = p;
  581. level[0] = 0;
  582. while (n >= 0) /* i.e. while stack is nonempty */
  583. {
  584. int current_level;
  585. plPoint q0, q1, q2;
  586. current_level = level[n];
  587. q0 = r0[n];
  588. q1 = r1[n];
  589. q2 = r2[n];
  590. if (current_level >= MAX_NUM_BEZIER2_SUBDIVISIONS)
  591. /* to avoid stack overflow, draw as line segment */
  592. {
  593. _add_line (path, q2);
  594. segments_drawn++;
  595. n--;
  596. }
  597. else
  598. /* maybe bisect the Bezier */
  599. {
  600. plPoint qq0, qq1;
  601. plPoint qqq0;
  602. plVector vec1;
  603. vec1.x = q0.x - 2 * q1.x + q2.x;
  604. vec1.y = q0.y - 2 * q1.y + q2.y;
  605. if (vec1.x * vec1.x + vec1.y * vec1.y < max_squared_length)
  606. /* very flat Bezier, so draw as line segment */
  607. {
  608. _add_line (path, q2);
  609. segments_drawn++;
  610. n--;
  611. }
  612. else
  613. /* split Bezier into pair and recurse */
  614. /* level[n] >= n is an invariant */
  615. {
  616. qq0.x = MIDWAY(q0.x, q1.x);
  617. qq0.y = MIDWAY(q0.y, q1.y);
  618. qq1.x = MIDWAY(q1.x, q2.x);
  619. qq1.y = MIDWAY(q1.y, q2.y);
  620. qqq0.x = MIDWAY(qq0.x, qq1.x);
  621. qqq0.y = MIDWAY(qq0.y, qq1.y);
  622. /* first half, deal with next */
  623. r0[n+1] = q0;
  624. r1[n+1] = qq0;
  625. r2[n+1] = qqq0;
  626. level[n+1] = current_level + 1;
  627. /* second half, deal with later */
  628. r0[n] = qqq0;
  629. r1[n] = qq1;
  630. r2[n] = q2;
  631. level[n] = current_level + 1;
  632. n++;
  633. }
  634. }
  635. }
  636. }
  637. /* Approximate a cubic Bezier by a polyline: standard deCasteljau bisection
  638. algorithm. However, we stop subdividing when an appropriate metric of
  639. the cubic Bezier to be drawn is sufficiently small. If (p0,p1,p2,p3)
  640. defines the cubic Bezier, we require that the lengths of p0-2*p1+p2 and
  641. p1-2*p2+p3 be less than REL_CUBIC_FLATNESS times the distance between
  642. the endpoints of the original Bezier. */
  643. void
  644. _add_bezier3_as_lines (plPath *path, plPoint pc, plPoint pd, plPoint p)
  645. {
  646. plPoint r0[MAX_NUM_BEZIER3_SUBDIVISIONS + 1], r1[MAX_NUM_BEZIER3_SUBDIVISIONS + 1], r2[MAX_NUM_BEZIER3_SUBDIVISIONS + 1], r3[MAX_NUM_BEZIER3_SUBDIVISIONS + 1];
  647. int level[MAX_NUM_BEZIER3_SUBDIVISIONS + 1];
  648. int n = 0; /* index of top of stack, < MAX_NUM_BEZIER3_SUBDIVISIONS */
  649. int segments_drawn = 0;
  650. plPoint p0;
  651. double sqdist, max_squared_length;
  652. if (path == (plPath *)NULL)
  653. return;
  654. if (path->type != PATH_SEGMENT_LIST || path->num_segments == 0)
  655. return;
  656. /* determine starting point */
  657. p0 = path->segments[path->num_segments - 1].p;
  658. /* squared distance between p0 and p */
  659. sqdist = (p.x - p0.x) * (p.x - p0.x) + (p.y - p0.y) * (p.y - p0.y);
  660. max_squared_length = REL_CUBIC_FLATNESS * REL_CUBIC_FLATNESS * sqdist;
  661. r0[0] = p0;
  662. r1[0] = pc;
  663. r2[0] = pd;
  664. r3[0] = p;
  665. level[0] = 0;
  666. while (n >= 0) /* i.e. while stack is nonempty */
  667. {
  668. int current_level;
  669. plPoint q0, q1, q2, q3;
  670. current_level = level[n];
  671. q0 = r0[n];
  672. q1 = r1[n];
  673. q2 = r2[n];
  674. q3 = r3[n];
  675. if (current_level >= MAX_NUM_BEZIER3_SUBDIVISIONS)
  676. /* draw line segment, to avoid stack overflow */
  677. {
  678. _add_line (path, q3);
  679. segments_drawn++;
  680. n--;
  681. }
  682. else
  683. /* maybe bisect the Bezier */
  684. {
  685. plPoint qq0, qq1, qq2;
  686. plPoint qqq0, qqq1;
  687. plPoint qqqq0;
  688. plVector vec1, vec2;
  689. vec1.x = q0.x - 2 * q1.x + q2.x;
  690. vec1.y = q0.y - 2 * q1.y + q2.y;
  691. vec2.x = q1.x - 2 * q2.x + q3.x;
  692. vec2.y = q1.y - 2 * q2.y + q3.y;
  693. if (vec1.x * vec1.x + vec1.y * vec1.y < max_squared_length
  694. && vec2.x * vec2.x + vec2.y * vec2.y < max_squared_length)
  695. /* very flat Bezier, so draw as line segment */
  696. {
  697. _add_line (path, q3);
  698. segments_drawn++;
  699. n--;
  700. }
  701. else
  702. /* split Bezier into pair and recurse */
  703. /* level[n] >= n is an invariant */
  704. {
  705. qq0.x = MIDWAY(q0.x, q1.x);
  706. qq0.y = MIDWAY(q0.y, q1.y);
  707. qq1.x = MIDWAY(q1.x, q2.x);
  708. qq1.y = MIDWAY(q1.y, q2.y);
  709. qq2.x = MIDWAY(q2.x, q3.x);
  710. qq2.y = MIDWAY(q2.y, q3.y);
  711. qqq0.x = MIDWAY(qq0.x, qq1.x);
  712. qqq0.y = MIDWAY(qq0.y, qq1.y);
  713. qqq1.x = MIDWAY(qq1.x, qq2.x);
  714. qqq1.y = MIDWAY(qq1.y, qq2.y);
  715. qqqq0.x = MIDWAY(qqq0.x, qqq1.x);
  716. qqqq0.y = MIDWAY(qqq0.y, qqq1.y);
  717. /* first half, deal with next */
  718. level[n+1] = current_level + 1;
  719. r0[n+1] = q0;
  720. r1[n+1] = qq0;
  721. r2[n+1] = qqq0;
  722. r3[n+1] = qqqq0;
  723. /* second half, deal with later */
  724. level[n] = current_level + 1;
  725. r0[n] = qqqq0;
  726. r1[n] = qqq1;
  727. r2[n] = qq2;
  728. r3[n] = q3;
  729. n++;
  730. }
  731. }
  732. }
  733. }
  734. void
  735. _add_box_as_lines (plPath *path, plPoint p0, plPoint p1, bool clockwise)
  736. {
  737. bool x_move_is_first;
  738. plPoint newpoint;
  739. if (path == (plPath *)NULL)
  740. return;
  741. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  742. return;
  743. _add_moveto (path, p0);
  744. /* if counterclockwise, would first pen motion be in x direction? */
  745. x_move_is_first = ((p1.x >= p0.x && p1.y >= p0.y)
  746. || (p1.x < p0.x && p1.y < p0.y) ? true : false);
  747. if (clockwise)
  748. /* take complement */
  749. x_move_is_first = (x_move_is_first == true ? false : true);
  750. if (x_move_is_first)
  751. {
  752. newpoint.x = p1.x;
  753. newpoint.y = p0.y;
  754. }
  755. else
  756. {
  757. newpoint.x = p0.x;
  758. newpoint.y = p1.y;
  759. }
  760. _add_line (path, newpoint);
  761. _add_line (path, p1);
  762. if (x_move_is_first)
  763. {
  764. newpoint.x = p0.x;
  765. newpoint.y = p1.y;
  766. }
  767. else
  768. {
  769. newpoint.x = p1.x;
  770. newpoint.y = p0.y;
  771. }
  772. _add_line (path, newpoint);
  773. _add_line (path, p0);
  774. path->primitive = true; /* flag as flattened primitive */
  775. }
  776. void
  777. _add_ellipse_as_bezier3s (plPath *path, plPoint pc, double rx, double ry, double angle, bool clockwise)
  778. {
  779. plPoint startpoint, newpoint;
  780. double theta, costheta, sintheta;
  781. double xc, yc;
  782. if (path == (plPath *)NULL)
  783. return;
  784. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  785. return;
  786. /* draw ellipse by drawing four elliptic arcs */
  787. theta = (M_PI / 180.0) * angle; /* convert to radians */
  788. costheta = cos (theta);
  789. sintheta = sin (theta);
  790. xc = pc.x;
  791. yc = pc.y;
  792. startpoint.x = xc + rx * costheta;
  793. startpoint.y = yc + rx * sintheta;
  794. _add_moveto (path, startpoint);
  795. if (clockwise)
  796. {
  797. newpoint.x = xc + ry * sintheta;
  798. newpoint.y = yc - ry * costheta;
  799. }
  800. else
  801. {
  802. newpoint.x = xc - ry * sintheta;
  803. newpoint.y = yc + ry * costheta;
  804. }
  805. _add_ellarc_as_bezier3 (path, pc, newpoint);
  806. newpoint.x = xc - rx * costheta;
  807. newpoint.y = yc - rx * sintheta;
  808. _add_ellarc_as_bezier3 (path, pc, newpoint);
  809. if (clockwise)
  810. {
  811. newpoint.x = xc - ry * sintheta;
  812. newpoint.y = yc + ry * costheta;
  813. }
  814. else
  815. {
  816. newpoint.x = xc + ry * sintheta;
  817. newpoint.y = yc - ry * costheta;
  818. }
  819. _add_ellarc_as_bezier3 (path, pc, newpoint);
  820. _add_ellarc_as_bezier3 (path, pc, startpoint);
  821. path->primitive = true; /* flag as flattened primitive */
  822. }
  823. void
  824. _add_ellipse_as_ellarcs (plPath *path, plPoint pc, double rx, double ry, double angle, bool clockwise)
  825. {
  826. plPoint startpoint, newpoint;
  827. double theta, costheta, sintheta;
  828. double xc, yc;
  829. if (path == (plPath *)NULL)
  830. return;
  831. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  832. return;
  833. /* draw ellipse by drawing four elliptic arcs */
  834. theta = (M_PI / 180.0) * angle; /* convert to radians */
  835. costheta = cos (theta);
  836. sintheta = sin (theta);
  837. xc = pc.x;
  838. yc = pc.y;
  839. startpoint.x = xc + rx * costheta;
  840. startpoint.y = yc + rx * sintheta;
  841. _add_moveto (path, startpoint);
  842. if (clockwise)
  843. {
  844. newpoint.x = xc + ry * sintheta;
  845. newpoint.y = yc - ry * costheta;
  846. }
  847. else
  848. {
  849. newpoint.x = xc - ry * sintheta;
  850. newpoint.y = yc + ry * costheta;
  851. }
  852. _add_ellarc (path, pc, newpoint);
  853. newpoint.x = xc - rx * costheta;
  854. newpoint.y = yc - rx * sintheta;
  855. _add_ellarc (path, pc, newpoint);
  856. if (clockwise)
  857. {
  858. newpoint.x = xc - ry * sintheta;
  859. newpoint.y = yc + ry * costheta;
  860. }
  861. else
  862. {
  863. newpoint.x = xc + ry * sintheta;
  864. newpoint.y = yc - ry * costheta;
  865. }
  866. _add_ellarc (path, pc, newpoint);
  867. _add_ellarc (path, pc, startpoint);
  868. path->primitive = true; /* flag as flattened primitive */
  869. }
  870. void
  871. _add_ellipse_as_lines (plPath *path, plPoint pc, double rx, double ry, double angle, bool clockwise)
  872. {
  873. plPoint startpoint, newpoint;
  874. double theta, costheta, sintheta;
  875. double xc, yc;
  876. if (path == (plPath *)NULL)
  877. return;
  878. if (path->type != PATH_SEGMENT_LIST || path->num_segments > 0)
  879. return;
  880. /* draw ellipse by drawing four fake elliptic arcs */
  881. theta = (M_PI / 180.0) * angle; /* convert to radians */
  882. costheta = cos (theta);
  883. sintheta = sin (theta);
  884. xc = pc.x;
  885. yc = pc.y;
  886. startpoint.x = xc + rx * costheta;
  887. startpoint.y = yc + rx * sintheta;
  888. _add_moveto (path, startpoint);
  889. if (clockwise)
  890. {
  891. newpoint.x = xc + ry * sintheta;
  892. newpoint.y = yc - ry * costheta;
  893. }
  894. else
  895. {
  896. newpoint.x = xc - ry * sintheta;
  897. newpoint.y = yc + ry * costheta;
  898. }
  899. _add_ellarc_as_lines (path, pc, newpoint);
  900. newpoint.x = xc - rx * costheta;
  901. newpoint.y = yc - rx * sintheta;
  902. _add_ellarc_as_lines (path, pc, newpoint);
  903. if (clockwise)
  904. {
  905. newpoint.x = xc - ry * sintheta;
  906. newpoint.y = yc + ry * costheta;
  907. }
  908. else
  909. {
  910. newpoint.x = xc + ry * sintheta;
  911. newpoint.y = yc - ry * costheta;
  912. }
  913. _add_ellarc_as_lines (path, pc, newpoint);
  914. _add_ellarc_as_lines (path, pc, startpoint);
  915. path->primitive = true; /* flag as flattened primitive */
  916. }
  917. void
  918. _add_circle_as_bezier3s (plPath *path, plPoint pc, double radius, bool clockwise)
  919. {
  920. if (path == (plPath *)NULL)
  921. return;
  922. _add_ellipse_as_bezier3s (path, pc, radius, radius, 0.0, clockwise);
  923. path->primitive = true; /* flag as flattened primitive */
  924. }
  925. void
  926. _add_circle_as_ellarcs (plPath *path, plPoint pc, double radius, bool clockwise)
  927. {
  928. if (path == (plPath *)NULL)
  929. return;
  930. _add_ellipse_as_ellarcs (path, pc, radius, radius, 0.0, clockwise);
  931. path->primitive = true; /* flag as flattened primitive */
  932. }
  933. void
  934. _add_circle_as_lines (plPath *path, plPoint pc, double radius, bool clockwise)
  935. {
  936. if (path == (plPath *)NULL)
  937. return;
  938. _add_ellipse_as_lines (path, pc, radius, radius, 0.0, clockwise);
  939. path->primitive = true; /* flag as flattened primitive */
  940. }
  941. /* The _fakearc() subroutine below, which is called by _add_arc_as_lines()
  942. and _add_ellarc_as_lines(), contains a remote descendent of the
  943. arc-drawing algorithm of Ken Turkowski <turk@apple.com> described in
  944. Graphics Gems V. His algorithm is a recursive circle subdivision
  945. algorithm, which relies on the fact that if s and s' are the (chordal
  946. deviation)/radius associated to (respectively) an arc and a half-arc,
  947. then s' is approximately equal to s/4. The exact formula is s' = 1 -
  948. sqrt (1 - s/2), which applies for all s in the meaningful range, i.e. 0
  949. <= s <= 2.
  950. Ken's algorithm rotates the chord of an arc by 90 degrees and scales it
  951. to have length s'. The resulting vector will be the chordal deviation
  952. vector of the arc, which gives the midpoint of the arc, and hence the
  953. endpoints of each half of the arc. So this drawing technique is
  954. recursive.
  955. The problem with this approach is that scaling a vector to a specified
  956. length requires a square root, so there are two square roots in each
  957. subdivision step. One can attempt to remove one of them by noticing
  958. that the chord half-length h always satisfies h = sqrt(s * (2-s))). So
  959. one can rotate the chord vector by 90 degrees, and multiply its length
  960. by s/2h, i.e., s/2sqrt(s * (2-s)), to get the chordal deviation vector.
  961. This factor still includes a square root though. Also one still needs
  962. to compute a square root in order to proceed from one subdivision step
  963. to the next, i.e. to compute s' from s.
  964. We can get around the square root problem by drawing only circular arcs
  965. with subtended angle of 90 degrees (quarter-circles), or elliptic arcs
  966. that are obtained from such quarter-circles by affine transformations
  967. (so-called quarter-ellipses). To draw the latter, we need only replace
  968. the 90 degree rotation matrix mentioned above by an affine
  969. transformation that maps v0->-v1 and v1->v0, where v0 = p0 - pc and v1 =
  970. p1 - pc are the displacement vectors from the center of the ellipse to
  971. the endpoints of the arc. If we do this, we get an elliptic arc with p0
  972. and p1 as endpoints. The vectors v0 and v1 are said lie along conjugate
  973. diameters of the quarter-ellipse.
  974. So for drawing quarter-ellipses, the only initial value of s we need to
  975. consider is the one for a quarter-circle, which is 1-sqrt(1/2). The
  976. successive values of s/2h that will be encountered, after each
  977. bisection, are pre-computed and stored in a lookup table, found in
  978. g_arc.h.
  979. This approach lets us avoid, completely, any computation of square roots
  980. during the drawing of quarter-circles and quarter-ellipses. The only
  981. square roots we need are precomputed. We don't need any floating point
  982. divisions in the main loop either.
  983. Of course for other angles than 90 degrees, we precompute a chord table
  984. and pass it to _fakearc().
  985. The implementation below does not use recursion (we use a local array,
  986. rather than the call stack, to store the sequence of generated
  987. points). */
  988. static void
  989. _fakearc (plPath *path, plPoint p0, plPoint p1, int arc_type, const double *custom_chord_table, const double m[4])
  990. {
  991. plPoint p[NUM_ARC_SUBDIVISIONS + 1], q[NUM_ARC_SUBDIVISIONS + 1];
  992. int level[NUM_ARC_SUBDIVISIONS + 1];
  993. int n = 0; /* index of top of stack, < NUM_ARC_SUBDIVISIONS */
  994. int segments_drawn = 0;
  995. const double *our_chord_table;
  996. if (arc_type == USER_DEFINED_ARC)
  997. our_chord_table = custom_chord_table;
  998. else /* custom_chord_table arg ignored */
  999. our_chord_table = _chord_table[arc_type];
  1000. p[0] = p0;
  1001. q[0] = p1;
  1002. level[0] = 0;
  1003. while (n >= 0) /* i.e. while stack is nonempty */
  1004. {
  1005. if (level[n] >= NUM_ARC_SUBDIVISIONS)
  1006. { /* draw line segment */
  1007. _add_line (path, q[n]);
  1008. segments_drawn++;
  1009. n--;
  1010. }
  1011. else /* bisect line segment */
  1012. {
  1013. plVector v;
  1014. plPoint pm, pb;
  1015. v.x = q[n].x - p[n].x; /* chord = line segment from p[n] to q[n] */
  1016. v.y = q[n].y - p[n].y;
  1017. pm.x = p[n].x + 0.5 * v.x; /* midpoint of chord */
  1018. pm.y = p[n].y + 0.5 * v.y;
  1019. /* Compute bisection point. If m=[0 1 -1 0] this just rotates
  1020. the chord clockwise by 90 degrees, and scales it to yield the
  1021. chordal deviation vector, which is used as an offset. */
  1022. pb.x = pm.x +
  1023. our_chord_table[level[n]] * (m[0] * v.x + m[1] * v.y);
  1024. pb.y = pm.y +
  1025. our_chord_table[level[n]] * (m[2] * v.x + m[3] * v.y);
  1026. /* replace line segment by pair; level[n] >= n is an invariant */
  1027. p[n+1] = p[n];
  1028. q[n+1] = pb; /* first half, deal with next */
  1029. level[n+1] = level[n] + 1;
  1030. p[n] = pb;
  1031. q[n] = q[n]; /* second half, deal with later */
  1032. level[n] = level[n] + 1;
  1033. n++;
  1034. }
  1035. }
  1036. }
  1037. /* prepare_chord_table() computes the list of chordal deviation factors
  1038. that _fakearc() needs when it is employed to draw a circular arc of
  1039. subtended angle other than the default angles it supports */
  1040. static void
  1041. _prepare_chord_table (double sagitta, double custom_chord_table[TABULATED_ARC_SUBDIVISIONS])
  1042. {
  1043. double half_chord_length;
  1044. int i;
  1045. half_chord_length = sqrt ( sagitta * (2.0 - sagitta) );
  1046. for (i = 0; i < TABULATED_ARC_SUBDIVISIONS; i++)
  1047. {
  1048. custom_chord_table[i] = 0.5 * sagitta / half_chord_length;
  1049. sagitta = 1.0 - sqrt (1.0 - 0.5 * sagitta);
  1050. half_chord_length = 0.5 * half_chord_length / (1.0 - sagitta);
  1051. }
  1052. }
  1053. /* Flatten a simple path into a path of segment list type, consisting only
  1054. of line segments.
  1055. As supplied, the path may be perfectly general: it may be a segment list
  1056. (not all segments necessarily being line segments), or be a closed
  1057. primitive (box/circle/ellipse). If supplied path already consists only
  1058. of line segments (with an initial moveto and possibly a final
  1059. closepath), it is returned unchanged; this can be tested for by
  1060. comparing pointers for equality. If a new path is returned, it must be
  1061. freed with _delete_plPath(). */
  1062. plPath *
  1063. _flatten_path (const plPath *path)
  1064. {
  1065. plPath *newpath;
  1066. if (path == (plPath *)NULL)
  1067. return (plPath *)NULL;
  1068. switch (path->type)
  1069. {
  1070. case PATH_SEGMENT_LIST:
  1071. {
  1072. bool do_flatten = false;
  1073. int i;
  1074. for (i = 0; i < path->num_segments; i++)
  1075. {
  1076. if (path->segments[i].type != S_MOVETO
  1077. && path->segments[i].type != S_LINE
  1078. && path->segments[i].type != S_CLOSEPATH)
  1079. {
  1080. do_flatten = true;
  1081. break;
  1082. }
  1083. }
  1084. if (do_flatten == false)
  1085. newpath = (plPath *)path; /* just return original path */
  1086. else
  1087. {
  1088. newpath = _new_plPath ();
  1089. for (i = 0; i < path->num_segments; i++)
  1090. {
  1091. switch ((int)(path->segments[i].type))
  1092. {
  1093. case (int)S_MOVETO:
  1094. _add_moveto (newpath, path->segments[i].p);
  1095. break;
  1096. case (int)S_LINE:
  1097. _add_line (newpath, path->segments[i].p);
  1098. break;
  1099. case (int)S_CLOSEPATH:
  1100. _add_closepath (newpath);
  1101. break;
  1102. /* now, the types of segment we flatten: */
  1103. case (int)S_ARC:
  1104. _add_arc_as_lines (newpath,
  1105. path->segments[i].pc,
  1106. path->segments[i].p);
  1107. break;
  1108. case (int)S_ELLARC:
  1109. _add_ellarc_as_lines (newpath,
  1110. path->segments[i].pc,
  1111. path->segments[i].p);
  1112. break;
  1113. case (int)S_QUAD:
  1114. _add_bezier2_as_lines (newpath,
  1115. path->segments[i].pc,
  1116. path->segments[i].p);
  1117. break;
  1118. case (int)S_CUBIC:
  1119. _add_bezier3_as_lines (newpath,
  1120. path->segments[i].pc,
  1121. path->segments[i].pd,
  1122. path->segments[i].p);
  1123. break;
  1124. default: /* shouldn't happen */
  1125. break;
  1126. }
  1127. }
  1128. }
  1129. break;
  1130. }
  1131. case PATH_CIRCLE:
  1132. newpath = _new_plPath ();
  1133. _add_circle_as_lines (newpath,
  1134. path->pc, path->radius, path->clockwise);
  1135. break;
  1136. case PATH_ELLIPSE:
  1137. newpath = _new_plPath ();
  1138. _add_ellipse_as_lines (newpath,
  1139. path->pc, path->rx, path->ry, path->angle,
  1140. path->clockwise);
  1141. break;
  1142. case PATH_BOX:
  1143. newpath = _new_plPath ();
  1144. _add_box_as_lines (newpath, path->p0, path->p1, path->clockwise);
  1145. break;
  1146. default: /* shouldn't happen */
  1147. newpath = _new_plPath ();
  1148. break;
  1149. }
  1150. return newpath;
  1151. }
  1152. /**********************************************************************/
  1153. /* The code below exports the _merge_paths() function, which munges an
  1154. array of plPath objects and returns a new array. Heuristic
  1155. "path-merging" of this sort is performed in g_endpath.c when filling a
  1156. compound path (i.e., a multi-plPath path), if the output driver supports
  1157. only the filling of single plPaths. That is the case for nearly all of
  1158. libplot's output drivers.
  1159. `Child' paths are merged into their `parents', so each location in the
  1160. returned array where a child was present will contain NULL. Also, any
  1161. non-child that had no children will be returned without modification.
  1162. You should take this into account when freeing the returned array of
  1163. plPaths. Only the elements that are (1) non-NULL, and (2) differ from
  1164. the corresponding elements in the originally passed array should have
  1165. _delete_plPath() invoked on them. The array as a whole may be
  1166. deallocated by calling free().
  1167. The _merge_paths() function was inspired by a similar function in
  1168. Wolfgang Glunz's pstoedit, which was originally written by Burkhard
  1169. Plaum <plaum@ipf.uni-stuttgart.de>. */
  1170. /* Note: a well-formed plPath has the form:
  1171. { moveto { line | arc }* { closepath }? }
  1172. The _merge_paths function was written to merge _closed_ plPath's,
  1173. i.e. ones whose endpoint is the same as the startpoint (possibly
  1174. implicitly, i.e. closepath is allowed). However, libplot applies it to
  1175. open paths too, in which case an `implicit closepath' is added to the
  1176. path to close it.
  1177. NOTE: The current release of libplot does not yet support `closepath'
  1178. segments at a higher level. So we regard a pass-in plPath as `closed'
  1179. if its last defining vertex is the same as the first. THIS CONVENTION
  1180. WILL GO AWAY. */
  1181. /* ad hoc structure for an annotated plPath, in particular one that has
  1182. been flattened into line segments and annotated; used only in this file,
  1183. for merging purposes */
  1184. typedef struct subpath_struct
  1185. {
  1186. plPathSegment *segments; /* segment array */
  1187. int num_segments; /* number of segments */
  1188. struct subpath_struct **parents; /* array of pointers to possible parents */
  1189. struct subpath_struct *parent; /* pointer to parent path */
  1190. struct subpath_struct **children; /* array of pointers to child paths */
  1191. int num_children; /* number of children */
  1192. int num_outside; /* number of subpaths outside this one */
  1193. double llx, lly, urx, ury; /* bounding box of the subpath */
  1194. bool inserted; /* subpath has been inserted into result? */
  1195. } subpath;
  1196. /* forward references */
  1197. /* 0. ctors, dtors */
  1198. static subpath * new_subpath (void);
  1199. static subpath ** new_subpath_array (int n);
  1200. static void delete_subpath (subpath *s);
  1201. static void delete_subpath_array (subpath **s, int n);
  1202. /* 1. functions that act on a subpath, i.e. an `annotated path' */
  1203. static bool is_inside_of (const subpath *s, const subpath *other);
  1204. static double _cheap_lower_bound_on_distance (const subpath *path1, const subpath *path2);
  1205. static void linearize_subpath (subpath *s);
  1206. static void read_into_subpath (subpath *s, const plPath *path);
  1207. /* 2. miscellaneous */
  1208. static void find_parents_in_subpath_list (subpath **annotated_paths, int num_paths);
  1209. static void insert_subpath (plPathSegment *parent_segments, const plPathSegment *child_segments, int parent_size, int child_size, int parent_index, int child_index);
  1210. static void _compute_closest (const plPathSegment *p1, const plPathSegment *p2, int size1, int size2, double *distance, int *index1, int *index2);
  1211. /**********************************************************************/
  1212. /* ctor for subpath class */
  1213. static subpath *
  1214. new_subpath (void)
  1215. {
  1216. subpath *s;
  1217. s = (subpath *)_pl_xmalloc (sizeof (subpath));
  1218. s->segments = (plPathSegment *)NULL;
  1219. s->num_segments = 0;
  1220. s->parents = (subpath **)NULL;
  1221. s->parent = (subpath *)NULL;
  1222. s->children = (subpath **)NULL;
  1223. s->num_children = 0;
  1224. s->num_outside = 0;
  1225. s->llx = DBL_MAX;
  1226. s->lly = DBL_MAX;
  1227. s->urx = -DBL_MAX;
  1228. s->ury = -DBL_MAX;
  1229. s->inserted = false;
  1230. return s;
  1231. }
  1232. /* corresponding ctor for a subpath array */
  1233. static subpath **
  1234. new_subpath_array (int n)
  1235. {
  1236. int i;
  1237. subpath **s;
  1238. s = (subpath **)_pl_xmalloc (n * sizeof (subpath *));
  1239. for (i = 0; i < n; i++)
  1240. s[i] = new_subpath ();
  1241. return s;
  1242. }
  1243. /* dtor for subpath class */
  1244. static void
  1245. delete_subpath (subpath *s)
  1246. {
  1247. if (s)
  1248. {
  1249. if (s->segments)
  1250. free (s->segments);
  1251. if (s->children)
  1252. free (s->children);
  1253. if (s->parents)
  1254. free (s->parents);
  1255. free (s);
  1256. }
  1257. }
  1258. /* corresponding dtor for a subpath array */
  1259. static void
  1260. delete_subpath_array (subpath **s, int n)
  1261. {
  1262. int i;
  1263. if (s)
  1264. {
  1265. for (i = 0; i < n; i++)
  1266. delete_subpath (s[i]);
  1267. free (s);
  1268. }
  1269. }
  1270. /* replace every segment in a subpath by a lineto (invoked only on a child
  1271. subpath, i.e. a subpath with an identified parent) */
  1272. static void
  1273. linearize_subpath (subpath *s)
  1274. {
  1275. /* replace first segment (moveto) with a lineto */
  1276. s->segments[0].type = S_LINE;
  1277. /* if final segment is a closepath, also replace with a lineto, back to
  1278. point #0 */
  1279. if (s->segments[s->num_segments-1].type == S_CLOSEPATH)
  1280. {
  1281. s->segments[s->num_segments-1].type = S_LINE;
  1282. s->segments[s->num_segments-1].p = s->segments[0].p;
  1283. }
  1284. }
  1285. /* Read a sequence of plPathSegments from a plPath into a previously empty
  1286. annotated subpath. (This is called only after the plPath has been
  1287. flattened, so the segments include no arcs.)
  1288. Because the way in which _merge_paths() is currently called in libplot,
  1289. we need to handle the possibility that the plPath may not be closed. If
  1290. it isn't, we add a closepath.
  1291. At present, we allow a final lineto to the start vertex to serve the
  1292. same purpose. THIS IS A LIBPLOT CONVENTION THAT WILL GO AWAY. */
  1293. static void
  1294. read_into_subpath (subpath *s, const plPath *path)
  1295. {
  1296. bool need_to_close = false;
  1297. int i;
  1298. /* sanity check */
  1299. if (path->type != PATH_SEGMENT_LIST)
  1300. return;
  1301. /* allocate space for segment array of subpath; add 1 extra slot for
  1302. manual closure, if needed */
  1303. s->segments = (plPathSegment *)_pl_xmalloc((path->num_segments + 1) * sizeof (plPathSegment));
  1304. s->num_segments = path->num_segments;
  1305. /* sanity check */
  1306. if (path->num_segments == 0)
  1307. return;
  1308. /* Is this path closed? If not, we'll close manually the annotated path
  1309. that we'll construct. WE CURRENTLY TREAT FINAL = INITIAL AS
  1310. INDICATING CLOSURE. */
  1311. if (path->segments[path->num_segments - 1].type != S_CLOSEPATH
  1312. &&
  1313. (path->segments[path->num_segments - 1].p.x != path->segments[0].p.x
  1314. || path->segments[path->num_segments - 1].p.y != path->segments[0].p.y))
  1315. need_to_close = true;
  1316. /* copy the segments, updating bounding box to take each juncture point
  1317. into account */
  1318. for (i = 0; i < path->num_segments; i++)
  1319. {
  1320. plPathSegment e;
  1321. e = path->segments[i];
  1322. s->segments[i] = e;
  1323. if (e.p.x < s->llx)
  1324. s->llx = e.p.x;
  1325. if (e.p.y < s->lly)
  1326. s->lly = e.p.y;
  1327. if (e.p.x > s->urx)
  1328. s->urx = e.p.x;
  1329. if (e.p.y > s->ury)
  1330. s->ury = e.p.y;
  1331. }
  1332. if (need_to_close)
  1333. {
  1334. #if 0
  1335. s->segments[path->num_segments].type = S_CLOSEPATH;
  1336. #else /* currently, use line segment instead of closepath */
  1337. s->segments[path->num_segments].type = S_LINE;
  1338. #endif
  1339. s->segments[path->num_segments].p = path->segments[0].p;
  1340. s->num_segments++;
  1341. }
  1342. }
  1343. /* check if a subpath is inside another subpath */
  1344. static bool
  1345. is_inside_of (const subpath *s, const subpath *other)
  1346. {
  1347. int inside = 0;
  1348. int outside = 0;
  1349. int i;
  1350. /* if bbox fails to lie inside the other's bbox, false */
  1351. if (!((s->llx >= other->llx) && (s->lly >= other->lly) &&
  1352. (s->urx <= other->urx) && (s->ury <= other->ury)))
  1353. return false;
  1354. /* otherwise, check all juncture points */
  1355. for (i = 0; i < s->num_segments; i++)
  1356. {
  1357. bool point_is_inside;
  1358. if (s->segments[i].type == S_CLOSEPATH)
  1359. /* should have i = num_segments - 1, no associated juncture point */
  1360. continue;
  1361. /* Check if the vertex s->segments[i].p is inside `other'. Could be
  1362. done in a separate function, but we inline it for speed. */
  1363. {
  1364. /* These two factors should be small positive floating-point
  1365. numbers. They should preferably be incommensurate, to minimize
  1366. the probability of a degenerate case occurring: two line
  1367. segments intersecting at the endpoint of one or the other. */
  1368. #define SMALL_X_FACTOR (M_SQRT2 * M_PI)
  1369. #define SMALL_Y_FACTOR (M_SQRT2 + M_PI)
  1370. /* argument of the now-inlined function (besides `other') */
  1371. plPoint p;
  1372. /* local variables of the now-inlined function */
  1373. int k, crossings;
  1374. /* (x1,y1) is effectively the point at infinity */
  1375. double x1, y1;
  1376. /* (x2,y2) is specified point */
  1377. double x2, y2;
  1378. /* argument of the now-inlined function (besides `other') */
  1379. p = s->segments[i].p;
  1380. /* (x1,y1) is effectively the point at infinity */
  1381. x1 = (DMAX(p.x, other->urx)
  1382. + SMALL_X_FACTOR * (DMAX(p.x, other->urx)
  1383. - DMIN(p.x, other->llx)));
  1384. y1 = (DMAX(p.y, other->ury)
  1385. + SMALL_Y_FACTOR * (DMAX(p.y, other->ury)
  1386. - DMIN(p.y, other->lly)));
  1387. /* (x2,y2) is specified point */
  1388. x2 = p.x;
  1389. y2 = p.y;
  1390. crossings = 0;
  1391. for (k = 0; k < other->num_segments; k++)
  1392. {
  1393. int j;
  1394. double x3, y3, x4, y4, det, det1, det2;
  1395. if (other->segments[k].type == S_CLOSEPATH) /* k > 0 */
  1396. {
  1397. x3 = other->segments[k-1].p.x;
  1398. y3 = other->segments[k-1].p.y;
  1399. }
  1400. else
  1401. {
  1402. x3 = other->segments[k].p.x;
  1403. y3 = other->segments[k].p.y;
  1404. }
  1405. j = (k == other->num_segments - 1 ? 0 : k + 1);
  1406. if (other->segments[j].type == S_CLOSEPATH)
  1407. continue;
  1408. x4 = other->segments[j].p.x;
  1409. y4 = other->segments[j].p.y;
  1410. /* (x3,y3)-(x4,y4) is a line segment in the closed path */
  1411. /* Check whether the line segments (x1,y1)-(x2,y2) and
  1412. (x3-y3)-(x4,y4) cross each other.
  1413. System to solve is:
  1414. [p1 + (p2 - p1) * t1] - [p3 + (p4 - p3) * t2] = 0
  1415. i.e.
  1416. (x2 - x1) * t1 - (x4 - x3) * t2 = x3 - x1;
  1417. (y2 - y1) * t1 - (y4 - y3) * t2 = y3 - y1;
  1418. Solutions are: t1 = det1/det
  1419. t2 = det2/det
  1420. The line segments cross each other (in their interiors) if
  1421. 0.0 < t1 < 1.0 and 0.0 < t2 < 1.0 */
  1422. det = (x2 - x1) * (-(y4 - y3)) - (-(x4 - x3)) * (y2 - y1);
  1423. if (det == 0.0)
  1424. /* line segments are parallel; ignore the degenerate case
  1425. that they might overlap */
  1426. continue;
  1427. det1 = (x3 - x1) * (-(y4 - y3)) - (-(x4 - x3)) * (y3 - y1);
  1428. det2 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
  1429. if ((det<0.0 && (det1>0.0 || det2>0.0 || det1<det || det2<det))
  1430. ||
  1431. (det>0.0 && (det1<0.0 || det2<0.0 || det1>det || det2>det)))
  1432. /* solution for at least one of t1 and t2 is outside the
  1433. interval [0,1], so line segments do not cross */
  1434. continue;
  1435. /* We ignore the possibility that t1, t2 are both in the interval
  1436. [0,1], but
  1437. (t1 == 0.0) || (t1 == 1.0) || (t2 == 0.0) || (t2 == 1.0).
  1438. t1 == 0.0 should never happen, if p1 is effectively
  1439. the point at infinity.
  1440. So this degenerate case occurs only if the line segment
  1441. (x1,y1)-(x2,y2) goes through either (x3,y3) or (x4,y4), or
  1442. the specified point (x2,y2) lies on the line segment
  1443. (x3,y3)-(x4,y4) that is part of the path. */
  1444. crossings++;
  1445. }
  1446. /* our determination of whether the point is inside the path;
  1447. before we inlined this function, this was the return value */
  1448. point_is_inside = (crossings & 1) ? true : false;
  1449. }
  1450. /* increment inside,outside depending on whether or not the juncture
  1451. point was inside the other path */
  1452. if (point_is_inside)
  1453. inside++;
  1454. else
  1455. outside++;
  1456. }
  1457. /* make a democratic decision as to whether the path as a whole is inside
  1458. the other path */
  1459. return (inside > outside ? true : false);
  1460. }
  1461. /* Find parent (if any) of each subpath in a list of subpaths. When this
  1462. is invoked, each subpath should consist of an initial moveto, at least
  1463. one lineto, and a closepath (not currently enforced). */
  1464. static void
  1465. find_parents_in_subpath_list (subpath **annotated_paths, int num_paths)
  1466. {
  1467. int i, j;
  1468. subpath *parent;
  1469. /* determine for each subpath the subpaths that are nominally outside it */
  1470. for (i = 0; i < num_paths; i++)
  1471. {
  1472. annotated_paths[i]->parents = new_subpath_array (num_paths);
  1473. for (j = 0; j < num_paths; j++)
  1474. {
  1475. if (j != i)
  1476. {
  1477. if (is_inside_of (annotated_paths[i], annotated_paths[j]))
  1478. {
  1479. annotated_paths[i]->parents[annotated_paths[i]->num_outside] =
  1480. annotated_paths[j];
  1481. annotated_paths[i]->num_outside++;
  1482. }
  1483. }
  1484. }
  1485. }
  1486. /* Now find the real parent subpaths, i.e. the root subpaths. A subpath
  1487. is a parent subpath if the number of nominally-outside subpaths is
  1488. even, and is a child subpath only if the number is odd. An odd
  1489. number, together with a failure to find a suitable potential parent,
  1490. will flag a path as an isolate: technically a parent, but without
  1491. children. */
  1492. for (i = 0; i < num_paths; i++)
  1493. {
  1494. if ((annotated_paths[i]->num_outside & 1) == 0)
  1495. /* an even number of subpaths outside, definitely a parent
  1496. (i.e. doesn't have a parent itself, may or may not have children) */
  1497. {
  1498. /* allocate space for children (if any) */
  1499. annotated_paths[i]->children = new_subpath_array (num_paths);
  1500. }
  1501. }
  1502. /* now determine which are children, and link them to their parents */
  1503. for (i = 0; i < num_paths; i++)
  1504. {
  1505. if ((annotated_paths[i]->num_outside & 1) == 0)
  1506. /* even number outside, definitely a parent subpath (whether it has
  1507. children remains to be determined) */
  1508. continue;
  1509. else
  1510. /* odd number outside, possibly a child, so search linearly through
  1511. possible parents until we get a hit; if so, this is a child; if
  1512. not, this is an isolate (classed as a parent) */
  1513. {
  1514. for (j = 0; j < annotated_paths[i]->num_outside; j++)
  1515. {
  1516. if (annotated_paths[i]->num_outside ==
  1517. annotated_paths[i]->parents[j]->num_outside + 1)
  1518. /* number outside is one more than the number outside a
  1519. potential parent; flag as a child, and add it to the
  1520. parent's child list */
  1521. {
  1522. parent = annotated_paths[i]->parents[j];
  1523. annotated_paths[i]->parent = parent; /* give it a parent */
  1524. parent->children[parent->num_children] = annotated_paths[i];
  1525. parent->num_children++;
  1526. break;
  1527. }
  1528. }
  1529. }
  1530. }
  1531. }
  1532. /* Compute closest vertices in two paths. Indices of closest vertices, and
  1533. (squared) distance between them, are returned via pointers.
  1534. This is invoked in _merge_paths() only on paths that have been
  1535. flattened, and have had the initial moveto and the optional final
  1536. closepath replaced by line segments. So when this is called, each
  1537. segment type is S_LINE. */
  1538. static void
  1539. _compute_closest (const plPathSegment *p1, const plPathSegment *p2, int size1, int size2, double *distance, int *index1, int *index2)
  1540. {
  1541. int best_i = 0, best_j = 0; /* keep compiler happy */
  1542. double best_distance = DBL_MAX;
  1543. int ii, jj;
  1544. for (ii = 0; ii < size1; ii++)
  1545. {
  1546. plPoint point1;
  1547. point1 = p1[ii].p;
  1548. for (jj = 0; jj < size2; jj++)
  1549. {
  1550. double tmp1, tmp2, distance;
  1551. plPoint point2;
  1552. point2 = p2[jj].p;
  1553. tmp1 = point1.x - point2.x;
  1554. tmp2 = point1.y - point2.y;
  1555. distance = tmp1 * tmp1 + tmp2 * tmp2;
  1556. if (distance < best_distance)
  1557. {
  1558. best_distance = distance;
  1559. best_i = ii;
  1560. best_j = jj;
  1561. }
  1562. }
  1563. }
  1564. /* return the three quantities */
  1565. *distance = best_distance;
  1566. *index1 = best_i;
  1567. *index2 = best_j;
  1568. }
  1569. /* Compute a cheap lower bound on the (squared) distance between two
  1570. subpaths, by looking at their bounding boxes. */
  1571. static double
  1572. _cheap_lower_bound_on_distance (const subpath *path1, const subpath *path2)
  1573. {
  1574. double xdist = 0.0, ydist = 0.0, dist;
  1575. if (path1->urx < path2->llx)
  1576. xdist = path2->llx - path1->urx;
  1577. else if (path2->urx < path1->llx)
  1578. xdist = path1->llx - path2->urx;
  1579. if (path1->ury < path2->lly)
  1580. ydist = path2->lly - path1->ury;
  1581. else if (path2->ury < path1->lly)
  1582. ydist = path1->lly - path2->ury;
  1583. dist = xdist * xdist + ydist * ydist;
  1584. return dist;
  1585. }
  1586. /* Insert a closed child subpath into a closed parent, by connecting the
  1587. two, twice, at a specified vertex of the parent path and a specified
  1588. vertex of the child path. This is the key function invoked by
  1589. _merge_paths().
  1590. Both paths are supplied as segment lists, and all segments are lines;
  1591. the final segment of each is a line back to the starting point. I.e.,
  1592. for both subpaths, the final vertex duplicates the start vertex. So we
  1593. ignore the final vertex of the child (but not that of the parent).
  1594. I.e. if the child vertices are numbered 0..child_size-1, we map the case
  1595. child_index = child_size-1 to child_index = 0.
  1596. The new path has parent_size + child_size + 1 vertices, of which the
  1597. last is a repetition of the first. */
  1598. /* INDEX MAP:
  1599. PARENT -> NEW PATH
  1600. i --> i (if 0 <= i < parent_index + 1)
  1601. i --> i+child_size+1 (if parent_index + 1 <= i < parent_size)
  1602. CHILD -> NEW PATH
  1603. i --> i+parent_index+child_size-child_index (0 <= i < child_index+1)
  1604. i --> i+parent_index-child_index+1 (child_index+1 <= i < child_size-1)
  1605. (0'th element of the child is same as child_size-1 element)
  1606. NEW PATH CONTENTS
  1607. 0..parent_index
  1608. 0..parent_index of PARENT
  1609. parent_index+1
  1610. child_index of CHILD (i.e. ->join)
  1611. parent_index+2..parent_index+child_size-child_index-1
  1612. child_index+1..child_size-2 of CHILD
  1613. parent_index+child_size-child_index..parent_index+child_size
  1614. 0..child_index of CHILD
  1615. parent_index+child_size+1
  1616. parent_index of PARENT (i.e. ->join)
  1617. parent_index+child_size+2..parent_size+child_size
  1618. parent_index+1..parent_size-1 of PARENT
  1619. */
  1620. /* Macros that map from vertices in the child path and the parent path, to
  1621. vertices in the merged path. Here the argument `i' is the index in the
  1622. original path, and each macro evaluates to the index in the merger. */
  1623. /* The first macro should not be applied to i=child_size-1; as noted above,
  1624. that vertex is equivalent to i=0, so apply it to i=0 instead. */
  1625. #define CHILD_VERTEX_IN_MERGED_PATH(i,parent_index,parent_size,child_index,child_size) ((i) <= (child_index) ? (i) + (parent_index) + (child_size) - (child_index) : (i) + (parent_index) - (child_index) + 1)
  1626. #define PARENT_VERTEX_IN_MERGED_PATH(i,parent_index,parent_size,child_index,child_size) ((i) <= (parent_index) ? (i) : (i) + (child_size) + 1)
  1627. static void
  1628. insert_subpath (plPathSegment *parent, const plPathSegment *child, int parent_size, int child_size, int parent_index, int child_index)
  1629. {
  1630. int i;
  1631. plPathSegment e1, e2;
  1632. int src_index;
  1633. /* map case when joining vertex is final vertex of child to case when
  1634. it's the 0'th vertex */
  1635. if (child_index == child_size - 1)
  1636. child_index = 0;
  1637. /* move up: add child_size+1 empty slots to parent path */
  1638. for (i = parent_size - 1; i >= parent_index + 1; i--)
  1639. parent[i + child_size + 1] = parent[i];
  1640. /* add a line segment from specified vertex of parent path to specified
  1641. vertex of child path */
  1642. e1 = child[child_index];
  1643. e1.type = S_LINE; /* unnecessary */
  1644. parent[parent_index + 1] = e1;
  1645. /* copy vertices of child into parent, looping back to start in child if
  1646. necessary; note we skip the last (i.e. child_size-1'th) vertex, since
  1647. the 0'th vertex is the same */
  1648. src_index = child_index;
  1649. for (i = 0; i < child_size - 1; i++)
  1650. {
  1651. src_index++;
  1652. if (src_index == child_size - 1)
  1653. src_index = 0;
  1654. parent[parent_index + 2 + i] = child[src_index];
  1655. }
  1656. /* add a line segment back from specified vertex of child path to
  1657. specified vertex of parent path */
  1658. e2 = parent[parent_index];
  1659. e2.type = S_LINE;
  1660. parent[parent_index + child_size + 1] = e2;
  1661. }
  1662. /* The key function exported by this module, which is used by libplot for
  1663. filling compound paths. */
  1664. plPath **
  1665. _merge_paths (const plPath **paths, int num_paths)
  1666. {
  1667. int i;
  1668. subpath **annotated_paths;
  1669. plPath **flattened_paths;
  1670. plPath **merged_paths;
  1671. /* flatten every path to a list of line segments (some paths may come
  1672. back unaltered; will be able to compare pointers to check for that) */
  1673. flattened_paths = (plPath **)_pl_xmalloc (num_paths * sizeof(plPath *));
  1674. for (i = 0; i < num_paths; i++)
  1675. {
  1676. flattened_paths[i] = _flatten_path (paths[i]);
  1677. #ifdef DEBUG
  1678. fprintf (stderr, "path %d: %d segments, flattened to %d segments\n",
  1679. i, paths[i]->num_segments, flattened_paths[i]->num_segments);
  1680. #endif
  1681. }
  1682. /* Copy each flattened path into a corresponding annotated path
  1683. (`subpath'). Manual closure, if necessary (see above) is performed,
  1684. i.e. we always add a final closepath to close the path. At this stage
  1685. bounding boxes are computed. */
  1686. annotated_paths = new_subpath_array (num_paths);
  1687. for (i = 0; i < num_paths; i++)
  1688. read_into_subpath (annotated_paths[i], flattened_paths[i]);
  1689. /* Flattened paths no longer needed, so delete them carefully (some may
  1690. be the same as the original paths, due to _flatten_path() having
  1691. simply returned its argument) */
  1692. for (i = 0; i < num_paths; i++)
  1693. if (flattened_paths[i] != paths[i])
  1694. _delete_plPath (flattened_paths[i]);
  1695. /* determine which subpaths are parents, children */
  1696. find_parents_in_subpath_list (annotated_paths, num_paths);
  1697. /* in each child, replace each moveto/closepath by a lineto */
  1698. for (i = 0; i < num_paths; i++)
  1699. if (annotated_paths[i]->parent != (subpath *)NULL)
  1700. /* child path */
  1701. linearize_subpath (annotated_paths[i]);
  1702. /* create array of merged paths: parent paths will have child paths
  1703. merged into them, and child paths won't appear */
  1704. /* allocate space for new array, to be returned */
  1705. merged_paths = (plPath **)_pl_xmalloc (num_paths * sizeof(plPath *));
  1706. for (i = 0; i < num_paths; i++)
  1707. {
  1708. int j, k, num_segments_in_merged_path;
  1709. subpath *parent;
  1710. plPath *merged_path;
  1711. double *parent_to_child_distances;
  1712. int *child_best_indices, *parent_best_indices;
  1713. if (annotated_paths[i]->parent != (subpath *)NULL)
  1714. /* child path; original path will be merged into parent */
  1715. {
  1716. merged_paths[i] = (plPath *)NULL;
  1717. continue;
  1718. }
  1719. if (annotated_paths[i]->num_children == 0)
  1720. /* no parent, but no children either, so no merging done; in output
  1721. path array, place original unflattened path */
  1722. {
  1723. merged_paths[i] = (plPath *)paths[i];
  1724. continue;
  1725. }
  1726. /* this path must be a parent, with one or more children to be merged
  1727. into it; so create new empty `merged path' with segments array
  1728. that will hold it, and the merged-in children */
  1729. parent = annotated_paths[i];
  1730. num_segments_in_merged_path = parent->num_segments;
  1731. for (j = 0; j < parent->num_children; j++)
  1732. num_segments_in_merged_path
  1733. += (parent->children[j]->num_segments + 1);
  1734. merged_path = _new_plPath ();
  1735. merged_path->segments = (plPathSegment *)_pl_xmalloc(num_segments_in_merged_path * sizeof (plPathSegment));
  1736. merged_path->num_segments = 0;
  1737. merged_path->segments_len = num_segments_in_merged_path;
  1738. /* copy parent path into new empty path, i.e. initialize the merged
  1739. path */
  1740. for (j = 0; j < parent->num_segments; j++)
  1741. merged_path->segments[j] = parent->segments[j];
  1742. merged_path->num_segments = parent->num_segments;
  1743. /* Create temporary storage for `closest vertex pairs' and inter-path
  1744. distances. We first compute the shortest distance between each
  1745. child path. We also keep track of the shortest distance between
  1746. each child and the merged path being constructed, and update it
  1747. when any child is added. */
  1748. parent_to_child_distances = (double *)_pl_xmalloc(parent->num_children * sizeof (double));
  1749. parent_best_indices = (int *)_pl_xmalloc(parent->num_children * sizeof (int));
  1750. child_best_indices = (int *)_pl_xmalloc(parent->num_children * sizeof (int));
  1751. /* compute closest vertices between merged path (i.e., right now, the
  1752. parent) and any child; these arrays will be updated when any child
  1753. is inserted into the merged path */
  1754. for (j = 0; j < parent->num_children; j++)
  1755. _compute_closest (parent->segments,
  1756. parent->children[j]->segments,
  1757. parent->num_segments,
  1758. parent->children[j]->num_segments,
  1759. &(parent_to_child_distances[j]),
  1760. &(parent_best_indices[j]),
  1761. &(child_best_indices[j]));
  1762. for (k = 0; k < parent->num_children; k++)
  1763. /* insert a child (the closest remaining one!) into the built-up
  1764. merged path; and flag the child as having been inserted so that
  1765. we don't pay attention to it thereafter */
  1766. {
  1767. double min_distance;
  1768. int closest = 0; /* keep compiler happy */
  1769. double *new_parent_to_child_distances;
  1770. int *new_child_best_indices, *new_parent_best_indices;
  1771. /* allocate storage for arrays that will be used to update the
  1772. three abovementioned arrays, with each pass through the loop */
  1773. new_parent_to_child_distances = (double *)_pl_xmalloc(parent->num_children * sizeof (double));
  1774. new_parent_best_indices = (int *)_pl_xmalloc(parent->num_children * sizeof (int));
  1775. new_child_best_indices = (int *)_pl_xmalloc(parent->num_children * sizeof (int));
  1776. /* initially, they're the same as the current arrays */
  1777. for (j = 0; j < parent->num_children; j++)
  1778. {
  1779. new_parent_to_child_distances[j] = parent_to_child_distances[j];
  1780. new_parent_best_indices[j] = parent_best_indices[j];
  1781. new_child_best_indices[j] = child_best_indices[j];
  1782. }
  1783. /* find closest child to merged path, which has not yet been
  1784. inserted */
  1785. min_distance = DBL_MAX;
  1786. for (j = 0; j < parent->num_children; j++)
  1787. {
  1788. if (parent->children[j]->inserted) /* ignore this child */
  1789. continue;
  1790. if (parent_to_child_distances[j] < min_distance)
  1791. {
  1792. closest = j;
  1793. min_distance = parent_to_child_distances[j];
  1794. }
  1795. }
  1796. /* closest remaining child has index `closest'; it will be
  1797. inserted into the current merged path */
  1798. /* loop over all children, skipping inserted ones and also
  1799. skipping `closest', the next child to be inserted */
  1800. for (j = 0; j < parent->num_children; j++)
  1801. {
  1802. double inter_child_distance;
  1803. int inter_child_best_index1, inter_child_best_index2;
  1804. double lower_bound_on_inter_child_distance;
  1805. bool compute_carefully;
  1806. if (parent->children[j]->inserted) /* ignore */
  1807. continue;
  1808. if (j == closest) /* ignore */
  1809. continue;
  1810. /* compute distance (and closest vertex pairs) between
  1811. `closest' and the j'th child; result is only of interest
  1812. if the distance is less than parent_to_child_distances[j],
  1813. so we first compute a cheap lower bound on the result by
  1814. looking at bounding boxes. */
  1815. lower_bound_on_inter_child_distance =
  1816. _cheap_lower_bound_on_distance (parent->children[j],
  1817. parent->children[closest]);
  1818. compute_carefully =
  1819. (lower_bound_on_inter_child_distance <
  1820. parent_to_child_distances[j]) ? true : false;
  1821. if (compute_carefully)
  1822. /* compute accurate inter-child distance; also which two
  1823. vertices yield the minimum distance */
  1824. _compute_closest (parent->children[j]->segments,
  1825. parent->children[closest]->segments,
  1826. parent->children[j]->num_segments,
  1827. parent->children[closest]->num_segments,
  1828. &inter_child_distance,
  1829. &inter_child_best_index1, /* vertex in j */
  1830. &inter_child_best_index2); /* in `closest' */
  1831. /* fill in j'th element of the new arrays
  1832. parent_to_child_distances[], parent_best_indices[] and
  1833. child_best_indices[] so as to take the insertion of the
  1834. child into account; but we don't update the old arrays
  1835. until we do the actual insertion */
  1836. if (compute_carefully &&
  1837. inter_child_distance < parent_to_child_distances[j])
  1838. /* j'th child is nearer to a vertex in `closest', the child
  1839. to be inserted, than to any vertex in the current merged
  1840. path, so all three arrays are affected */
  1841. {
  1842. int nearest_index_in_closest_child;
  1843. new_parent_to_child_distances[j] = inter_child_distance;
  1844. new_child_best_indices[j] = inter_child_best_index1;
  1845. nearest_index_in_closest_child = inter_child_best_index2;
  1846. /* Compute new value of parent_best_indices[j], taking
  1847. into account that `closest' will be inserted into the
  1848. merged path, thereby remapping the relevant index in
  1849. `closest'. The macro doesn't perform correctly if its
  1850. first arg takes the maximum possible value; so
  1851. instead, we map that possibility to `0'. See comment
  1852. above, before the macro definition. */
  1853. if (nearest_index_in_closest_child ==
  1854. parent->children[closest]->num_segments - 1)
  1855. nearest_index_in_closest_child = 0;
  1856. new_parent_best_indices[j] =
  1857. CHILD_VERTEX_IN_MERGED_PATH(nearest_index_in_closest_child,
  1858. parent_best_indices[closest],
  1859. merged_path->num_segments,
  1860. child_best_indices[closest],
  1861. parent->children[closest]->num_segments);
  1862. }
  1863. else
  1864. /* j'th child is nearer to a vertex in the current merged
  1865. path than to any vertex in `closest', the child to be
  1866. inserted into the merged path */
  1867. {
  1868. int nearest_index_in_parent;
  1869. nearest_index_in_parent = parent_best_indices[j];
  1870. /* compute new value of parent_best_indices[j], taking
  1871. into account that `closest' will be inserted into the
  1872. merged path, thereby remapping the relevant index in
  1873. the merged path */
  1874. new_parent_best_indices[j] =
  1875. PARENT_VERTEX_IN_MERGED_PATH(nearest_index_in_parent,
  1876. parent_best_indices[closest],
  1877. merged_path->num_segments,
  1878. child_best_indices[closest],
  1879. parent->children[closest]->num_segments);
  1880. }
  1881. }
  1882. /* do the actual insertion, by adding a pair of lineto's between
  1883. closest vertices; flag child as inserted */
  1884. insert_subpath (merged_path->segments,
  1885. parent->children[closest]->segments,
  1886. merged_path->num_segments,
  1887. parent->children[closest]->num_segments,
  1888. parent_best_indices[closest],
  1889. child_best_indices[closest]);
  1890. merged_path->num_segments +=
  1891. (parent->children[closest]->num_segments + 1);
  1892. parent->children[closest]->inserted = true;
  1893. /* update the old arrays to take insertion into account: replace
  1894. them by the new ones */
  1895. for (j = 0; j < parent->num_children; j++)
  1896. {
  1897. parent_to_child_distances[j] = new_parent_to_child_distances[j];
  1898. parent_best_indices[j] = new_parent_best_indices[j];
  1899. child_best_indices[j] = new_child_best_indices[j];
  1900. }
  1901. free (new_parent_to_child_distances);
  1902. free (new_parent_best_indices);
  1903. free (new_child_best_indices);
  1904. }
  1905. /* End of loop over all children of parent subpath; all >=1 children
  1906. have now been inserted into the parent, i.e. into the `merged
  1907. path' which the parent initialized. However, the merged path's
  1908. segments are all lines; so change the first to a moveto. */
  1909. merged_path->segments[0].type = S_MOVETO;
  1910. merged_paths[i] = merged_path;
  1911. /* NOTE: SHOULD ALSO REPLACE LAST LINE SEGMENT BY A CLOSEPATH! */
  1912. /* delete temporary storage for `closest vertex pairs' and inter-path
  1913. distances */
  1914. free (parent_to_child_distances);
  1915. free (parent_best_indices);
  1916. free (child_best_indices);
  1917. }
  1918. /* end of loop over parent subpaths */
  1919. /* no more annotated paths needed */
  1920. delete_subpath_array (annotated_paths, num_paths);
  1921. return merged_paths;
  1922. }