agg_curves.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. //----------------------------------------------------------------------------
  2. // Anti-Grain Geometry - Version 2.4
  3. // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
  4. // Copyright (C) 2005 Tony Juricic (tonygeek@yahoo.com)
  5. //
  6. // Permission to copy, use, modify, sell and distribute this software
  7. // is granted provided this copyright notice appears in all copies.
  8. // This software is provided "as is" without express or implied
  9. // warranty, and with no claim as to its suitability for any purpose.
  10. //
  11. //----------------------------------------------------------------------------
  12. // Contact: mcseem@antigrain.com
  13. // mcseemagg@yahoo.com
  14. // http://www.antigrain.com
  15. //----------------------------------------------------------------------------
  16. #ifndef AGG_CURVES_INCLUDED
  17. #define AGG_CURVES_INCLUDED
  18. #include "agg_array.h"
  19. namespace agg
  20. {
  21. // See Implementation agg_curves.cpp
  22. //--------------------------------------------curve_approximation_method_e
  23. enum curve_approximation_method_e
  24. {
  25. curve_inc,
  26. curve_div
  27. };
  28. //--------------------------------------------------------------curve3_inc
  29. class curve3_inc
  30. {
  31. public:
  32. curve3_inc() :
  33. m_num_steps(0), m_step(0), m_scale(1.0) { }
  34. curve3_inc(double x1, double y1,
  35. double x2, double y2,
  36. double x3, double y3) :
  37. m_num_steps(0), m_step(0), m_scale(1.0)
  38. {
  39. init(x1, y1, x2, y2, x3, y3);
  40. }
  41. void reset() { m_num_steps = 0; m_step = -1; }
  42. void init(double x1, double y1,
  43. double x2, double y2,
  44. double x3, double y3);
  45. void approximation_method(curve_approximation_method_e) {}
  46. curve_approximation_method_e approximation_method() const { return curve_inc; }
  47. void approximation_scale(double s);
  48. double approximation_scale() const;
  49. void angle_tolerance(double) {}
  50. double angle_tolerance() const { return 0.0; }
  51. void cusp_limit(double) {}
  52. double cusp_limit() const { return 0.0; }
  53. void rewind(unsigned path_id);
  54. unsigned vertex(double* x, double* y);
  55. private:
  56. int m_num_steps;
  57. int m_step;
  58. double m_scale;
  59. double m_start_x;
  60. double m_start_y;
  61. double m_end_x;
  62. double m_end_y;
  63. double m_fx;
  64. double m_fy;
  65. double m_dfx;
  66. double m_dfy;
  67. double m_ddfx;
  68. double m_ddfy;
  69. double m_saved_fx;
  70. double m_saved_fy;
  71. double m_saved_dfx;
  72. double m_saved_dfy;
  73. };
  74. //-------------------------------------------------------------curve3_div
  75. class curve3_div
  76. {
  77. public:
  78. curve3_div() :
  79. m_approximation_scale(1.0),
  80. m_angle_tolerance(0.0),
  81. m_count(0)
  82. {}
  83. curve3_div(double x1, double y1,
  84. double x2, double y2,
  85. double x3, double y3) :
  86. m_approximation_scale(1.0),
  87. m_angle_tolerance(0.0),
  88. m_count(0)
  89. {
  90. init(x1, y1, x2, y2, x3, y3);
  91. }
  92. void reset() { m_points.remove_all(); m_count = 0; }
  93. void init(double x1, double y1,
  94. double x2, double y2,
  95. double x3, double y3);
  96. void approximation_method(curve_approximation_method_e) {}
  97. curve_approximation_method_e approximation_method() const { return curve_div; }
  98. void approximation_scale(double s) { m_approximation_scale = s; }
  99. double approximation_scale() const { return m_approximation_scale; }
  100. void angle_tolerance(double a) { m_angle_tolerance = a; }
  101. double angle_tolerance() const { return m_angle_tolerance; }
  102. void cusp_limit(double) {}
  103. double cusp_limit() const { return 0.0; }
  104. void rewind(unsigned)
  105. {
  106. m_count = 0;
  107. }
  108. unsigned vertex(double* x, double* y)
  109. {
  110. if(m_count >= m_points.size()) return path_cmd_stop;
  111. const point_d& p = m_points[m_count++];
  112. *x = p.x;
  113. *y = p.y;
  114. return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
  115. }
  116. private:
  117. void bezier(double x1, double y1,
  118. double x2, double y2,
  119. double x3, double y3);
  120. void recursive_bezier(double x1, double y1,
  121. double x2, double y2,
  122. double x3, double y3,
  123. unsigned level);
  124. double m_approximation_scale;
  125. double m_distance_tolerance_square;
  126. double m_angle_tolerance;
  127. unsigned m_count;
  128. pod_bvector<point_d> m_points;
  129. };
  130. //-------------------------------------------------------------curve4_points
  131. struct curve4_points
  132. {
  133. double cp[8];
  134. curve4_points() {}
  135. curve4_points(double x1, double y1,
  136. double x2, double y2,
  137. double x3, double y3,
  138. double x4, double y4)
  139. {
  140. cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
  141. cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
  142. }
  143. void init(double x1, double y1,
  144. double x2, double y2,
  145. double x3, double y3,
  146. double x4, double y4)
  147. {
  148. cp[0] = x1; cp[1] = y1; cp[2] = x2; cp[3] = y2;
  149. cp[4] = x3; cp[5] = y3; cp[6] = x4; cp[7] = y4;
  150. }
  151. double operator [] (unsigned i) const { return cp[i]; }
  152. double& operator [] (unsigned i) { return cp[i]; }
  153. };
  154. //-------------------------------------------------------------curve4_inc
  155. class curve4_inc
  156. {
  157. public:
  158. curve4_inc() :
  159. m_num_steps(0), m_step(0), m_scale(1.0) { }
  160. curve4_inc(double x1, double y1,
  161. double x2, double y2,
  162. double x3, double y3,
  163. double x4, double y4) :
  164. m_num_steps(0), m_step(0), m_scale(1.0)
  165. {
  166. init(x1, y1, x2, y2, x3, y3, x4, y4);
  167. }
  168. curve4_inc(const curve4_points& cp) :
  169. m_num_steps(0), m_step(0), m_scale(1.0)
  170. {
  171. init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  172. }
  173. void reset() { m_num_steps = 0; m_step = -1; }
  174. void init(double x1, double y1,
  175. double x2, double y2,
  176. double x3, double y3,
  177. double x4, double y4);
  178. void init(const curve4_points& cp)
  179. {
  180. init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  181. }
  182. void approximation_method(curve_approximation_method_e) {}
  183. curve_approximation_method_e approximation_method() const { return curve_inc; }
  184. void approximation_scale(double s);
  185. double approximation_scale() const;
  186. void angle_tolerance(double) {}
  187. double angle_tolerance() const { return 0.0; }
  188. void cusp_limit(double) {}
  189. double cusp_limit() const { return 0.0; }
  190. void rewind(unsigned path_id);
  191. unsigned vertex(double* x, double* y);
  192. private:
  193. int m_num_steps;
  194. int m_step;
  195. double m_scale;
  196. double m_start_x;
  197. double m_start_y;
  198. double m_end_x;
  199. double m_end_y;
  200. double m_fx;
  201. double m_fy;
  202. double m_dfx;
  203. double m_dfy;
  204. double m_ddfx;
  205. double m_ddfy;
  206. double m_dddfx;
  207. double m_dddfy;
  208. double m_saved_fx;
  209. double m_saved_fy;
  210. double m_saved_dfx;
  211. double m_saved_dfy;
  212. double m_saved_ddfx;
  213. double m_saved_ddfy;
  214. };
  215. //-------------------------------------------------------catrom_to_bezier
  216. inline curve4_points catrom_to_bezier(double x1, double y1,
  217. double x2, double y2,
  218. double x3, double y3,
  219. double x4, double y4)
  220. {
  221. // Trans. matrix Catmull-Rom to Bezier
  222. //
  223. // 0 1 0 0
  224. // -1/6 1 1/6 0
  225. // 0 1/6 1 -1/6
  226. // 0 0 1 0
  227. //
  228. return curve4_points(
  229. x2,
  230. y2,
  231. (-x1 + 6*x2 + x3) / 6,
  232. (-y1 + 6*y2 + y3) / 6,
  233. ( x2 + 6*x3 - x4) / 6,
  234. ( y2 + 6*y3 - y4) / 6,
  235. x3,
  236. y3);
  237. }
  238. //-----------------------------------------------------------------------
  239. inline curve4_points
  240. catrom_to_bezier(const curve4_points& cp)
  241. {
  242. return catrom_to_bezier(cp[0], cp[1], cp[2], cp[3],
  243. cp[4], cp[5], cp[6], cp[7]);
  244. }
  245. //-----------------------------------------------------ubspline_to_bezier
  246. inline curve4_points ubspline_to_bezier(double x1, double y1,
  247. double x2, double y2,
  248. double x3, double y3,
  249. double x4, double y4)
  250. {
  251. // Trans. matrix Uniform BSpline to Bezier
  252. //
  253. // 1/6 4/6 1/6 0
  254. // 0 4/6 2/6 0
  255. // 0 2/6 4/6 0
  256. // 0 1/6 4/6 1/6
  257. //
  258. return curve4_points(
  259. (x1 + 4*x2 + x3) / 6,
  260. (y1 + 4*y2 + y3) / 6,
  261. (4*x2 + 2*x3) / 6,
  262. (4*y2 + 2*y3) / 6,
  263. (2*x2 + 4*x3) / 6,
  264. (2*y2 + 4*y3) / 6,
  265. (x2 + 4*x3 + x4) / 6,
  266. (y2 + 4*y3 + y4) / 6);
  267. }
  268. //-----------------------------------------------------------------------
  269. inline curve4_points
  270. ubspline_to_bezier(const curve4_points& cp)
  271. {
  272. return ubspline_to_bezier(cp[0], cp[1], cp[2], cp[3],
  273. cp[4], cp[5], cp[6], cp[7]);
  274. }
  275. //------------------------------------------------------hermite_to_bezier
  276. inline curve4_points hermite_to_bezier(double x1, double y1,
  277. double x2, double y2,
  278. double x3, double y3,
  279. double x4, double y4)
  280. {
  281. // Trans. matrix Hermite to Bezier
  282. //
  283. // 1 0 0 0
  284. // 1 0 1/3 0
  285. // 0 1 0 -1/3
  286. // 0 1 0 0
  287. //
  288. return curve4_points(
  289. x1,
  290. y1,
  291. (3*x1 + x3) / 3,
  292. (3*y1 + y3) / 3,
  293. (3*x2 - x4) / 3,
  294. (3*y2 - y4) / 3,
  295. x2,
  296. y2);
  297. }
  298. //-----------------------------------------------------------------------
  299. inline curve4_points
  300. hermite_to_bezier(const curve4_points& cp)
  301. {
  302. return hermite_to_bezier(cp[0], cp[1], cp[2], cp[3],
  303. cp[4], cp[5], cp[6], cp[7]);
  304. }
  305. //-------------------------------------------------------------curve4_div
  306. class curve4_div
  307. {
  308. public:
  309. curve4_div() :
  310. m_approximation_scale(1.0),
  311. m_angle_tolerance(0.0),
  312. m_cusp_limit(0.0),
  313. m_count(0)
  314. {}
  315. curve4_div(double x1, double y1,
  316. double x2, double y2,
  317. double x3, double y3,
  318. double x4, double y4) :
  319. m_approximation_scale(1.0),
  320. m_angle_tolerance(0.0),
  321. m_cusp_limit(0.0),
  322. m_count(0)
  323. {
  324. init(x1, y1, x2, y2, x3, y3, x4, y4);
  325. }
  326. curve4_div(const curve4_points& cp) :
  327. m_approximation_scale(1.0),
  328. m_angle_tolerance(0.0),
  329. m_count(0)
  330. {
  331. init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  332. }
  333. void reset() { m_points.remove_all(); m_count = 0; }
  334. void init(double x1, double y1,
  335. double x2, double y2,
  336. double x3, double y3,
  337. double x4, double y4);
  338. void init(const curve4_points& cp)
  339. {
  340. init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  341. }
  342. void approximation_method(curve_approximation_method_e) {}
  343. curve_approximation_method_e approximation_method() const
  344. {
  345. return curve_div;
  346. }
  347. void approximation_scale(double s) { m_approximation_scale = s; }
  348. double approximation_scale() const { return m_approximation_scale; }
  349. void angle_tolerance(double a) { m_angle_tolerance = a; }
  350. double angle_tolerance() const { return m_angle_tolerance; }
  351. void cusp_limit(double v)
  352. {
  353. m_cusp_limit = (v == 0.0) ? 0.0 : pi - v;
  354. }
  355. double cusp_limit() const
  356. {
  357. return (m_cusp_limit == 0.0) ? 0.0 : pi - m_cusp_limit;
  358. }
  359. void rewind(unsigned)
  360. {
  361. m_count = 0;
  362. }
  363. unsigned vertex(double* x, double* y)
  364. {
  365. if(m_count >= m_points.size()) return path_cmd_stop;
  366. const point_d& p = m_points[m_count++];
  367. *x = p.x;
  368. *y = p.y;
  369. return (m_count == 1) ? path_cmd_move_to : path_cmd_line_to;
  370. }
  371. private:
  372. void bezier(double x1, double y1,
  373. double x2, double y2,
  374. double x3, double y3,
  375. double x4, double y4);
  376. void recursive_bezier(double x1, double y1,
  377. double x2, double y2,
  378. double x3, double y3,
  379. double x4, double y4,
  380. unsigned level);
  381. double m_approximation_scale;
  382. double m_distance_tolerance_square;
  383. double m_angle_tolerance;
  384. double m_cusp_limit;
  385. unsigned m_count;
  386. pod_bvector<point_d> m_points;
  387. };
  388. //-----------------------------------------------------------------curve3
  389. class curve3
  390. {
  391. public:
  392. curve3() : m_approximation_method(curve_div) {}
  393. curve3(double x1, double y1,
  394. double x2, double y2,
  395. double x3, double y3) :
  396. m_approximation_method(curve_div)
  397. {
  398. init(x1, y1, x2, y2, x3, y3);
  399. }
  400. void reset()
  401. {
  402. m_curve_inc.reset();
  403. m_curve_div.reset();
  404. }
  405. void init(double x1, double y1,
  406. double x2, double y2,
  407. double x3, double y3)
  408. {
  409. if(m_approximation_method == curve_inc)
  410. {
  411. m_curve_inc.init(x1, y1, x2, y2, x3, y3);
  412. }
  413. else
  414. {
  415. m_curve_div.init(x1, y1, x2, y2, x3, y3);
  416. }
  417. }
  418. void approximation_method(curve_approximation_method_e v)
  419. {
  420. m_approximation_method = v;
  421. }
  422. curve_approximation_method_e approximation_method() const
  423. {
  424. return m_approximation_method;
  425. }
  426. void approximation_scale(double s)
  427. {
  428. m_curve_inc.approximation_scale(s);
  429. m_curve_div.approximation_scale(s);
  430. }
  431. double approximation_scale() const
  432. {
  433. return m_curve_inc.approximation_scale();
  434. }
  435. void angle_tolerance(double a)
  436. {
  437. m_curve_div.angle_tolerance(a);
  438. }
  439. double angle_tolerance() const
  440. {
  441. return m_curve_div.angle_tolerance();
  442. }
  443. void cusp_limit(double v)
  444. {
  445. m_curve_div.cusp_limit(v);
  446. }
  447. double cusp_limit() const
  448. {
  449. return m_curve_div.cusp_limit();
  450. }
  451. void rewind(unsigned path_id)
  452. {
  453. if(m_approximation_method == curve_inc)
  454. {
  455. m_curve_inc.rewind(path_id);
  456. }
  457. else
  458. {
  459. m_curve_div.rewind(path_id);
  460. }
  461. }
  462. unsigned vertex(double* x, double* y)
  463. {
  464. if(m_approximation_method == curve_inc)
  465. {
  466. return m_curve_inc.vertex(x, y);
  467. }
  468. return m_curve_div.vertex(x, y);
  469. }
  470. private:
  471. curve3_inc m_curve_inc;
  472. curve3_div m_curve_div;
  473. curve_approximation_method_e m_approximation_method;
  474. };
  475. //-----------------------------------------------------------------curve4
  476. class curve4
  477. {
  478. public:
  479. curve4() : m_approximation_method(curve_div) {}
  480. curve4(double x1, double y1,
  481. double x2, double y2,
  482. double x3, double y3,
  483. double x4, double y4) :
  484. m_approximation_method(curve_div)
  485. {
  486. init(x1, y1, x2, y2, x3, y3, x4, y4);
  487. }
  488. curve4(const curve4_points& cp) :
  489. m_approximation_method(curve_div)
  490. {
  491. init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  492. }
  493. void reset()
  494. {
  495. m_curve_inc.reset();
  496. m_curve_div.reset();
  497. }
  498. void init(double x1, double y1,
  499. double x2, double y2,
  500. double x3, double y3,
  501. double x4, double y4)
  502. {
  503. if(m_approximation_method == curve_inc)
  504. {
  505. m_curve_inc.init(x1, y1, x2, y2, x3, y3, x4, y4);
  506. }
  507. else
  508. {
  509. m_curve_div.init(x1, y1, x2, y2, x3, y3, x4, y4);
  510. }
  511. }
  512. void init(const curve4_points& cp)
  513. {
  514. init(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
  515. }
  516. void approximation_method(curve_approximation_method_e v)
  517. {
  518. m_approximation_method = v;
  519. }
  520. curve_approximation_method_e approximation_method() const
  521. {
  522. return m_approximation_method;
  523. }
  524. void approximation_scale(double s)
  525. {
  526. m_curve_inc.approximation_scale(s);
  527. m_curve_div.approximation_scale(s);
  528. }
  529. double approximation_scale() const { return m_curve_inc.approximation_scale(); }
  530. void angle_tolerance(double v)
  531. {
  532. m_curve_div.angle_tolerance(v);
  533. }
  534. double angle_tolerance() const
  535. {
  536. return m_curve_div.angle_tolerance();
  537. }
  538. void cusp_limit(double v)
  539. {
  540. m_curve_div.cusp_limit(v);
  541. }
  542. double cusp_limit() const
  543. {
  544. return m_curve_div.cusp_limit();
  545. }
  546. void rewind(unsigned path_id)
  547. {
  548. if(m_approximation_method == curve_inc)
  549. {
  550. m_curve_inc.rewind(path_id);
  551. }
  552. else
  553. {
  554. m_curve_div.rewind(path_id);
  555. }
  556. }
  557. unsigned vertex(double* x, double* y)
  558. {
  559. if(m_approximation_method == curve_inc)
  560. {
  561. return m_curve_inc.vertex(x, y);
  562. }
  563. return m_curve_div.vertex(x, y);
  564. }
  565. private:
  566. curve4_inc m_curve_inc;
  567. curve4_div m_curve_div;
  568. curve_approximation_method_e m_approximation_method;
  569. };
  570. }
  571. #endif