tinyspline.h 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. /** @file */
  2. #ifndef TINYSPLINE_H
  3. #define TINYSPLINE_H
  4. #include <stddef.h>
  5. #ifdef __cplusplus
  6. extern "C" {
  7. #endif
  8. /******************************************************************************
  9. * *
  10. * :: System Dependent Configuration *
  11. * *
  12. * The following configuration values must be adapted to your system. Some of *
  13. * them may be configured with preprocessor definitions. The default values *
  14. * should be fine for most modern hardware, such as x86, x86_64, and arm. *
  15. * *
  16. ******************************************************************************/
  17. #ifdef TINYSPLINE_FLOAT_PRECISION
  18. typedef float tsReal;
  19. #else
  20. typedef double tsReal;
  21. #endif
  22. #define FLT_MAX_ABS_ERROR 1e-5
  23. #define FLT_MAX_REL_ERROR 1e-8
  24. /******************************************************************************
  25. * *
  26. * :: Data Types *
  27. * *
  28. * The following section defines all data types available in TinySpline. *
  29. * *
  30. ******************************************************************************/
  31. /**
  32. * Defines the error codes used by various functions to indicate different
  33. * types of errors. The following code snippet shows how to handle errors:
  34. *
  35. * tsError err = ... // any function call here
  36. * if (err) { // or use err != TS_SUCCESS
  37. * printf("we got an error!");
  38. * return err; // you may want to reuse error codes
  39. * }
  40. */
  41. typedef enum
  42. {
  43. /* No error. */
  44. TS_SUCCESS = 0,
  45. /* Unable to allocate memory (using malloc/realloc). */
  46. TS_MALLOC = -1,
  47. /* The dimension of the control points are 0. */
  48. TS_DIM_ZERO = -2,
  49. /* Degree of spline >= number of control points. */
  50. TS_DEG_GE_NCTRLP = -3,
  51. /* Spline is not defined at knot value u. */
  52. TS_U_UNDEFINED = -4,
  53. /* Multiplicity of a knot (s) > order of spline. */
  54. TS_MULTIPLICITY = -5,
  55. /* Decreasing knot vector. */
  56. TS_KNOTS_DECR = -6,
  57. /* Unexpected number of knots. */
  58. TS_NUM_KNOTS = -7,
  59. /* Spline is not derivable */
  60. TS_UNDERIVABLE = -8,
  61. /* len_control_points % dim != 0 */
  62. TS_LCTRLP_DIM_MISMATCH = -10
  63. } tsError;
  64. /**
  65. * Describes the structure of the knot vector of a NURBS/B-Spline. For more
  66. * details, see:
  67. *
  68. * www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve.html
  69. */
  70. typedef enum
  71. {
  72. /* Not available/Undefined. */
  73. TS_NONE = 0,
  74. /* Uniformly spaced knot vector. */
  75. TS_OPENED = 1,
  76. /* Uniformly spaced knot vector with clamped end knots. */
  77. TS_CLAMPED = 2,
  78. /* Uniformly spaced knot vector with s(u) = order of spline. */
  79. TS_BEZIERS = 3
  80. } tsBSplineType;
  81. /**
  82. * Represents a B-Spline which may also be used for NURBS, Bezier curves,
  83. * lines, and points. NURBS are represented by homogeneous coordinates where
  84. * the last component of a control point stores the weight of this control
  85. * point. Bezier curves are B-Splines with 'num_control_points == order' and a
  86. * clamped knot vector, therefore passing through their first and last control
  87. * point (a property which does not necessarily apply to B-Splines and NURBS).
  88. * If a Bezier curve consists of two control points only, we call it a line.
  89. * Points, ultimately, are just very short lines consisting of a single control
  90. * point.
  91. *
  92. * Two dimensional control points are stored as follows:
  93. *
  94. * [x_0, y_0, x_1, y_1, ..., x_n-1, y_n-1]
  95. *
  96. * Tree dimensional control points are stored as follows:
  97. *
  98. * [x_0, y_0, z_0, x_1, y_1, z_1, ..., x_n-1, y_n-1, z_n-1]
  99. *
  100. * ... and so on. NURBS are represented by homogeneous coordinates. For
  101. * example, let's say we have a NURBS in 2D consisting of 11 control points
  102. * where 'w_i' is the weight of the i'th control point. Then, the corresponding
  103. * control points are stored as follows:
  104. *
  105. * [x_0*w_0, y_0*w_0, w_0, x_1*w_1, y_1*w_1, w_1, ..., x_10*w_10, y_10*w_10, w_10]
  106. */
  107. typedef struct
  108. {
  109. struct tsBSplineImpl *pImpl; /**< The actual implementation. */
  110. } tsBSpline;
  111. /**
  112. * Represents the output of De Boor's algorithm. De Boor's algorithm is used to
  113. * evaluate a spline at given knot value 'u' by iteratively computing a net of
  114. * intermediate values until the result is available:
  115. *
  116. * https://en.wikipedia.org/wiki/De_Boor%27s_algorithm
  117. * https://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/de-Boor.html
  118. *
  119. * All points of a net are stored in 'points'. The resulting point is the last
  120. * point in 'points' and, for the sake of convenience, may be accessed with
  121. * 'result':
  122. *
  123. * tsDeBoorNet net = ... // evaluate an arbitrary spline and store
  124. * // the resulting net of points in 'net'
  125. *
  126. * ts_deboornet_result(...) // use 'result' to access the resulting point
  127. *
  128. * Two dimensional points are stored as follows:
  129. *
  130. * [x_0, y_0, x_1, y_1, ..., x_n-1, y_n-1]
  131. *
  132. * Tree dimensional points are stored as follows:
  133. *
  134. * [x_0, y_0, z_0, x_1, y_1, z_1, ..., x_n-1, y_n-1, z_n-1]
  135. *
  136. * ... and so on. The output also supports homogeneous coordinates described
  137. * above.
  138. *
  139. * There is a special case in which the evaluation of a knot value 'u' returns
  140. * two results instead of one. It occurs when the multiplicity of 'u' ( s(u) )
  141. * is equals to a spline's order, indicating that the spline is discontinuous
  142. * at 'u'. This is common practice for B-Splines (and NURBS) consisting of
  143. * connected Bezier curves where the endpoint of curve 'c_i' is equals to the
  144. * start point of curve 'c_i+1'. The end point of 'c_i' and the start point of
  145. * 'c_i+1' may still be completely different though, yielding to a spline
  146. * having a (real and visible) gap at 'u'. Consequently, De Boor's algorithm
  147. * must return two results if 's(u) == order' in order to give access to the
  148. * desired points. In such case, 'points' stores only the two resulting points
  149. * (there is no net to calculate) and 'result' points to the *first* point in
  150. * 'points'. Since having (real) gaps in splines is unusual, both points in
  151. * 'points' are generally equals, making it easy to handle this special case by
  152. * accessing 'result' as already shown above for regular cases:
  153. *
  154. * tsDeBoorNet net = ... // evaluate a spline which is discontinuous at
  155. * // the given knot value, yielding to a net with
  156. * // two results
  157. *
  158. * ts_deboornet_result(...) // use 'result' to access the resulting point
  159. *
  160. * However, you can access both points if necessary:
  161. *
  162. * tsDeBoorNet net = ... // evaluate a spline which is discontinuous at
  163. * // the given knot value, yielding to a net with
  164. * // two results
  165. *
  166. * ts_deboornet_result(...)[0] ... // stores the first component of
  167. * // the first point
  168. *
  169. * ts_deboornet_result(...)[dim(spline)] // stores the first component of
  170. * // the second point
  171. *
  172. * As if this wasn't complicated enough, there is an exception for this special
  173. * case, yielding to exactly one result (just like the regular case) even if
  174. * 's(u) == order'. It occurs when 'u' is the lower or upper bound of a
  175. * spline's domain. For instance, if 'b' is a spline with domain [0, 1] and is
  176. * evaluated at 'u = 0' or 'u = 1' then 'result' is *always* a single point
  177. * regardless of the multiplicity of 'u'. Hence, handling this exception is
  178. * straightforward:
  179. *
  180. * tsDeBoorNet net = ... // evaluate a spline at the lower or upper
  181. * // bound of its domain, for instance, 0 or 1
  182. *
  183. * ts_deboornet_result(...) // use 'result' to access the resulting point
  184. *
  185. * In summary, we have three different types of evaluation. 1) The regular case
  186. * returning all points of the net we used to calculate the resulting point. 2)
  187. * The special case returning exactly two points which is required for splines
  188. * with (real) gaps. 3) The exception of 2) returning exactly one point even if
  189. * 's(u) == order'. All in all this looks quite complex (and actually it is)
  190. * but for most applications you do not have to deal with it. Just use 'result'
  191. * to access the outcome of De Boor's algorithm.
  192. */
  193. typedef struct
  194. {
  195. struct tsDeBoorNetImpl *pImpl; /**< The actual implementation. */
  196. } tsDeBoorNet;
  197. /******************************************************************************
  198. * *
  199. * :: Field Access Functions *
  200. * *
  201. * The following section contains getter and setter functions for the internal *
  202. * state of the structs listed above. *
  203. * *
  204. ******************************************************************************/
  205. /**
  206. * Returns the degree of \p spline.
  207. *
  208. * @param spline
  209. * The spline whose degree is read.
  210. * @return
  211. * The degree of \p spline.
  212. */
  213. size_t ts_bspline_degree(const tsBSpline *spline);
  214. /**
  215. * Sets the degree of \p spline.
  216. *
  217. * @param spline
  218. * The spline whose degree is set.
  219. * @param deg
  220. * The degree to be set.
  221. * @return TS_SUCCESS
  222. * On success.
  223. * @return TS_DEG_GE_NCTRLP
  224. * If \p degree >= ts_bspline_get_control_points(spline).
  225. */
  226. tsError ts_bspline_set_degree(tsBSpline *spline, size_t deg);
  227. /**
  228. * Returns the order (degree + 1) of \p spline.
  229. *
  230. * @param spline
  231. * The spline whose order is read.
  232. * @return
  233. * The order of \p spline.
  234. */
  235. size_t ts_bspline_order(const tsBSpline *spline);
  236. /**
  237. * Sets the order (degree + 1) of \p spline.
  238. *
  239. * @param spline
  240. * The spline whose order is set.
  241. * @param order
  242. * The order to be set.
  243. * @return TS_SUCCESS
  244. * On success.
  245. * @return TS_DEG_GE_NCTRLP
  246. * If \p order > ts_bspline_get_control_points(spline) or if \p order == 0
  247. * ( due to the underflow resulting from: order - 1 => 0 - 1 => INT_MAX
  248. * which always is >= ts_bspline_get_control_points(spline) ).
  249. */
  250. tsError ts_bspline_set_order(tsBSpline *spline, size_t order);
  251. /**
  252. * Returns the dimension of \p spline. The dimension of a spline describes the
  253. * number of components for each point in ts_bspline_get_control_points(spline).
  254. * One-dimensional splines are possible, albeit their benefit might be
  255. * questionable.
  256. *
  257. * @param spline
  258. * The spline whose dimension is read.
  259. * @return
  260. * The dimension of \p spline.
  261. */
  262. size_t ts_bspline_dimension(const tsBSpline *spline);
  263. /**
  264. * Sets the dimension of \p spline. The following conditions must be satisfied:
  265. *
  266. * (1) dim >= 1
  267. * (2) len_control_points % dim == 0
  268. *
  269. * with _len_control_points_ being the length of the control point array of \p
  270. * spline. The dimension of a spline describes the number of components for
  271. * each point in ts_bspline_get_control_points(spline). One-dimensional splines
  272. * are possible, albeit their benefit might be questionable.
  273. *
  274. * @param spline
  275. * The spline whose dimension is set.
  276. * @param dim
  277. * The dimension to be set.
  278. * @return TS_SUCCESS
  279. * On success.
  280. * @return TS_DIM_ZERO
  281. * If \p dimension == 0.
  282. * @return TS_LCTRLP_DIM_MISMATCH
  283. * If len_control_points % \p dim != 0
  284. */
  285. tsError ts_bspline_set_dimension(tsBSpline *spline, size_t dim);
  286. /**
  287. * Returns the length of the control point array of \p spline.
  288. *
  289. * @param spline
  290. * The spline with its control point array whose length is read.
  291. * @return
  292. * The length of the control point array of \p spline.
  293. */
  294. size_t ts_bspline_len_control_points(const tsBSpline *spline);
  295. /**
  296. * Returns the number of control points of \p spline.
  297. *
  298. * @param spline
  299. * The spline whose number of control points is read.
  300. * @return
  301. * The number of control points of \p spline.
  302. */
  303. size_t ts_bspline_num_control_points(const tsBSpline *spline);
  304. /**
  305. * Returns the size of the control point array of \p spline. This function may
  306. * be useful when copying control points using memcpy or memmove.
  307. *
  308. * @param spline
  309. * The spline with its control point array whose size is read.
  310. * @return
  311. * The size of the control point array of \p spline.
  312. */
  313. size_t ts_bspline_sof_control_points(const tsBSpline *spline);
  314. /**
  315. * Returns a deep copy of the control points of \p spline.
  316. *
  317. * @param spline
  318. * The spline whose control points are read.
  319. * @param ctrlp
  320. * The output array.
  321. * @return TS_SUCCESS
  322. * On success.
  323. * @return TS_MALLOC
  324. * If allocating memory failed.
  325. */
  326. tsError ts_bspline_control_points(const tsBSpline *spline, tsReal **ctrlp);
  327. /**
  328. * Sets the control points of \p spline. Creates a deep copy of \p ctrlp.
  329. *
  330. * @param spline
  331. * The spline whose control points are set.
  332. * @param ctrlp
  333. * The values to deep copy.
  334. * @return TS_SUCCESS
  335. * On success.
  336. */
  337. tsError ts_bspline_set_control_points(tsBSpline *spline, const tsReal *ctrlp);
  338. /**
  339. * Returns the number of knots of \p spline.
  340. *
  341. * @param spline
  342. * The spline whose number of knots is read.
  343. * @return
  344. * The number of knots of \p spline.
  345. */
  346. size_t ts_bspline_num_knots(const tsBSpline *spline);
  347. /**
  348. * Returns the size of the knot array of \p spline. This function may be useful
  349. * when copying knots using memcpy or memmove.
  350. *
  351. * @param spline
  352. * The spline with its knot array whose size is read.
  353. * @return TS_SUCCESS
  354. * The size of the knot array of \p spline.
  355. */
  356. size_t ts_bspline_sof_knots(const tsBSpline *spline);
  357. /**
  358. * Returns a deep copy of the knots of \p spline.
  359. *
  360. * @param spline
  361. * The spline whose knots are read.
  362. * @param knots
  363. * The output array.
  364. * @return TS_SUCCESS
  365. * On success.
  366. * @return TS_MALLOC
  367. * If allocating memory failed.
  368. */
  369. tsError ts_bspline_knots(const tsBSpline *spline, tsReal **knots);
  370. /**
  371. * Sets the knots of \p spline. Creates a deep copy of \p knots.
  372. *
  373. * @param spline
  374. * The spline whose knots are set.
  375. * @param knots
  376. * The values to deep copy.
  377. * @return TS_SUCCESS
  378. * On success.
  379. * @return TS_KNOTS_DECR
  380. * If the knot vector is decreasing.
  381. * @return TS_MULTIPLICITY
  382. * If there is a knot with multiplicity > order
  383. */
  384. tsError ts_bspline_set_knots(tsBSpline *spline, const tsReal *knots);
  385. /* ------------------------------------------------------------------------- */
  386. /**
  387. * Returns the knot (sometimes also called 'u' or 't') of \p net.
  388. *
  389. * @param net
  390. * The net whose knot is read.
  391. * @return
  392. * The knot of \p net.
  393. */
  394. tsReal ts_deboornet_knot(const tsDeBoorNet *net);
  395. /**
  396. * Returns the index [u_k, u_k+1) with u being the knot of \p net.
  397. *
  398. * @param net
  399. * The net whose index is read.
  400. * @return
  401. * The index [u_k, u_k+1) with u being the knot of \p net.
  402. */
  403. size_t ts_deboornet_index(const tsDeBoorNet *net);
  404. /**
  405. * Returns the multiplicity of the knot of \p net.
  406. *
  407. * @param net
  408. * The net whose multiplicity is read.
  409. * @return
  410. * The multiplicity of the knot of \p net.
  411. */
  412. size_t ts_deboornet_multiplicity(const tsDeBoorNet *net);
  413. /**
  414. * Returns the number of insertion that were necessary to evaluate the knot of
  415. * \p net.
  416. *
  417. * @param net
  418. * The net with its knot whose number of insertions is read.
  419. * @return
  420. * The number of insertions that were necessary to evaluate the knot of \p
  421. * net.
  422. */
  423. size_t ts_deboornet_num_insertions(const tsDeBoorNet *net);
  424. /**
  425. * Returns the dimension of \p net. The dimension of a net describes the number
  426. * of components for each point in ts_bspline_get_points(spline).
  427. * One-dimensional nets are possible, albeit their benefit might be
  428. * questionable.
  429. *
  430. * @param net
  431. * The net whose dimension is read.
  432. * @return
  433. * The dimension of \p net.
  434. */
  435. size_t ts_deboornet_dimension(const tsDeBoorNet *net);
  436. /**
  437. * Returns the length of the point array of \p net.
  438. *
  439. * @param net
  440. * The net with its point array whose length is read.
  441. * @return
  442. * The length of the point array of \p net.
  443. */
  444. size_t ts_deboornet_len_points(const tsDeBoorNet *net);
  445. /**
  446. * Returns the number of points of \p net.
  447. *
  448. * @param net
  449. * The net whose number of points is read.
  450. * @return
  451. * The number of points of \p net.
  452. */
  453. size_t ts_deboornet_num_points(const tsDeBoorNet *net);
  454. /**
  455. * Returns the size of the point array of \p net. This function may be useful
  456. * when copying points using memcpy or memmove.
  457. *
  458. * @param net
  459. * The net with its point array whose size is read.
  460. * @return
  461. * The size of the point array of \p net.
  462. */
  463. size_t ts_deboornet_sof_points(const tsDeBoorNet *net);
  464. /**
  465. * Returns a deep copy of the points of \p net.
  466. *
  467. * @param net
  468. * The net whose points is read.
  469. * @param points
  470. * The output array.
  471. * @return TS_SUCCESS
  472. * On success.
  473. * @return TS_MALLOC
  474. * If allocating memory failed.
  475. */
  476. tsError ts_deboornet_points(const tsDeBoorNet *net, tsReal **points);
  477. /**
  478. * Returns the length of the result array of \p net.
  479. *
  480. * @param net
  481. * The net with its result array whose length is read.
  482. * @return
  483. * The length of the result array of \p net.
  484. */
  485. size_t ts_deboornet_len_result(const tsDeBoorNet *net);
  486. /**
  487. * Returns the number of points in the result array of \p net
  488. * (1 <= num_result <= 2).
  489. *
  490. * @param net
  491. * The net with its result array whose number of points is read.
  492. * @return
  493. * The number of points in the result array of \p net.
  494. */
  495. size_t ts_deboornet_num_result(const tsDeBoorNet *net);
  496. /**
  497. * Returns the size of the result array of \p net. This function may be useful
  498. * when copying results using memcpy or memmove.
  499. *
  500. * @param net
  501. * The net with its result array whose size is read.
  502. * @return TS_SUCCESS
  503. * The size of the result array of \p net.
  504. */
  505. size_t ts_deboornet_sof_result(const tsDeBoorNet *net);
  506. /**
  507. * Returns a deep copy of the result of \p net.
  508. *
  509. * @param net
  510. * The net whose result is read.
  511. * @param result
  512. * The output array.
  513. * @return TS_SUCCESS
  514. * On success.
  515. * @return TS_MALLOC
  516. * If allocating memory failed.
  517. */
  518. tsError ts_deboornet_result(const tsDeBoorNet *net, tsReal **result);
  519. /******************************************************************************
  520. * *
  521. * :: Constructors, Destructors, Copy, and Move Functions *
  522. * *
  523. * The following section contains functions to create and delete instances of *
  524. * the data types listed above. Additionally, each data type has a copy and *
  525. * move function. *
  526. * *
  527. ******************************************************************************/
  528. /**
  529. * The default constructor of tsBSpline.
  530. *
  531. * All values of \p \_spline\_ are set to 0/NULL.
  532. *
  533. * @param \_spline\_
  534. * The spline whose values are set 0/NULL.
  535. */
  536. void ts_bspline_default(tsBSpline *_spline_);
  537. /**
  538. * A convenient constructor for tsBSpline.
  539. *
  540. * On error, all values of \p \_spline\_ are set to 0/NULL.
  541. *
  542. * @param n_ctrlp
  543. * The number of control points of \p \_spline\_.
  544. * @param dim
  545. * The dimension of each control point in \p \_spline\_.
  546. * @param deg
  547. * The degree of \p \_spline\_.
  548. * @param type
  549. * How to setup the knot vector of \p \_spline\_.
  550. * @param \_spline\_
  551. * The output parameter storing the result of this function.
  552. * @return TS_SUCCESS
  553. * On success.
  554. * @return TS_DIM_ZERO
  555. * If \p deg == 0.
  556. * @return TS_DEG_GE_NCTRLP
  557. * If \p deg >= \p n_ctrlp.
  558. * @return TS_NUM_KNOTS
  559. * If \p type == ::TS_BEZIERS and (\p n_ctrlp % \p deg + 1) != 0.
  560. * @return TS_MALLOC
  561. * If allocating memory failed.
  562. */
  563. tsError ts_bspline_new(size_t n_ctrlp, size_t dim, size_t deg,
  564. tsBSplineType type, tsBSpline *_spline_);
  565. /**
  566. * The copy constructor of tsBSpline.
  567. *
  568. * Creates a deep copy of \p original and stores the result in \p \_copy\_.
  569. *
  570. * On error, all values of \p \_copy\_ are set to 0/NULL. Does nothing, if
  571. * \p original == \p \_copy\_.
  572. *
  573. * @param original
  574. * The spline to deep copy.
  575. * @param \_copy\_
  576. * The output parameter storing the copied values of \p original.
  577. * @return TS_SUCCESS
  578. * On success.
  579. * @return TS_MALLOC
  580. * If allocating memory failed.
  581. */
  582. tsError ts_bspline_copy(const tsBSpline *original, tsBSpline *_copy_);
  583. /**
  584. * The move constructor of tsBSpline.
  585. *
  586. * Moves all values from \p from to \p \_to\_ and calls ::ts_bspline_default
  587. * on \p from afterwards. Does nothing, if \p from == \p \_to\_.
  588. *
  589. * @param from
  590. * The spline whose values are moved to \p \_to\_.
  591. * @param \_to\_
  592. * The output parameter storing the moved values of \p from.
  593. */
  594. void ts_bspline_move(tsBSpline *from, tsBSpline *_to_);
  595. /**
  596. * The destructor of tsBSpline.
  597. *
  598. * Frees all dynamically allocated memory in \p \_spline\_ and calls
  599. * ::ts_bspline_default afterwards.
  600. *
  601. * @param \_spline\_
  602. * The spline to free.
  603. */
  604. void ts_bspline_free(tsBSpline *_spline_);
  605. /* ------------------------------------------------------------------------- */
  606. /**
  607. * The default constructor of tsDeBoorNet.
  608. *
  609. * All values of \p \_deBoorNet\_ are set to 0/NULL.
  610. *
  611. * @param \_deBoorNet\_
  612. * The net whose values are set 0/NULL.
  613. */
  614. void ts_deboornet_default(tsDeBoorNet *_deBoorNet_);
  615. /**
  616. * The copy constructor of tsDeBoorNet.
  617. *
  618. * Creates a deep copy of \p original and stores the result in \p \_copy\_.
  619. *
  620. * On error, all values of \p _copy_ are set to 0/NULL. Does nothing, if
  621. * \p original == \p \_copy\_.
  622. *
  623. * @param original
  624. * The net to deep copy.
  625. * @param \_copy\_
  626. * The output parameter storing the copied values of \p original.
  627. * @return TS_SUCCESS
  628. * On success.
  629. * @return TS_MALLOC
  630. * If allocating memory failed.
  631. */
  632. tsError ts_deboornet_copy(const tsDeBoorNet *original, tsDeBoorNet *_copy_);
  633. /**
  634. * The move constructor of tsDeBoorNet.
  635. *
  636. * Moves all values from \p from to \p \_to\_ and calls ::ts_deboornet_default
  637. * on \p from afterwards. Does nothing, if \p from == \p \_to\_.
  638. *
  639. * @param from
  640. * The net whose values are moved to \p \_to\_.
  641. * @param \_to\_
  642. * The output parameter storing the moved values of \p from.
  643. */
  644. void ts_deboornet_move(tsDeBoorNet *from, tsDeBoorNet *_to_);
  645. /**
  646. * The destructor of tsDeBoorNet.
  647. *
  648. * Frees all dynamically allocated memory in \p \_deBoorNet\_ and calls
  649. * ::ts_deboornet_default afterwards.
  650. *
  651. * @param \_deBoorNet\_
  652. * The net to free.
  653. */
  654. void ts_deboornet_free(tsDeBoorNet *_deBoorNet_);
  655. /******************************************************************************
  656. * *
  657. * :: Interpolation and Approximation Functions *
  658. * *
  659. * The following section contains functions to interpolate and approximate *
  660. * arbitrary splines. *
  661. * *
  662. ******************************************************************************/
  663. /**
  664. * Performs a cubic spline interpolation using the thomas algorithm, see:
  665. *
  666. * https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
  667. * http://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf
  668. * http://www.bakoma-tex.com/doc/generic/pst-bspline/pst-bspline-doc.pdf
  669. *
  670. * The resulting spline is a sequence of bezier curves connecting each point
  671. * in \p points. Each bezier curve _b_ is of degree 3 with \p dim being the
  672. * dimension of the each control point in _b_. The total number of control
  673. * points is (\p n - 1) * 4.
  674. *
  675. * On error, all values of \p \_spline\_ are set to 0/NULL.
  676. *
  677. * Note: \p n is the number of points in \p points and not the length of
  678. * \p points. For instance, the follwing point vector yields to \p n = 4 and
  679. * \p dim = 2:
  680. *
  681. * [x0, y0, x1, y1, x2, y2, x3, y3]
  682. *
  683. * @param points
  684. * The points to interpolate.
  685. * @param n
  686. * The number of points in \p points.
  687. * @param dim
  688. * The dimension of each control point in \p \_spline\_.
  689. * @param \_spline\_
  690. * The output parameter storing the result of this function.
  691. * @return TS_SUCCESS
  692. * On success.
  693. * @return TS_DIM_ZERO
  694. * If \p dim == 0.
  695. * @return TS_DEG_GE_NCTRLP
  696. * If \p n < 2.
  697. * @return TS_MALLOC
  698. * If allocating memory failed.
  699. */
  700. tsError ts_bspline_interpolate_cubic(const tsReal *points, size_t n,
  701. size_t dim, tsBSpline *_spline_);
  702. /******************************************************************************
  703. * *
  704. * :: Query Functions *
  705. * *
  706. * The following section contains functions to query splines. *
  707. * *
  708. ******************************************************************************/
  709. /**
  710. * Evaluates \p spline at knot value \p u and stores the result in
  711. * \p \_deBoorNet\_.
  712. *
  713. * On error, all values of \p \_deBoorNet\_ are set to 0/NULL.
  714. *
  715. * @param spline
  716. * The spline to evaluate.
  717. * @param u
  718. * The knot value to evaluate.
  719. * @param \_deBoorNet\_
  720. * The output parameter storing the evaluation result.
  721. * @return TS_SUCCESS
  722. * On success.
  723. * @return TS_MULTIPLICITY
  724. * If multiplicity s(\p u) > order of \p spline.
  725. * @return TS_U_UNDEFINED
  726. * If \p spline is not defined at knot value \p u.
  727. * @return TS_MALLOC
  728. * If allocating memory failed.
  729. */
  730. tsError ts_bspline_eval(const tsBSpline *spline, tsReal u,
  731. tsDeBoorNet *_deBoorNet_);
  732. /******************************************************************************
  733. * *
  734. * :: Transformation functions *
  735. * *
  736. * TinySpline is a library focusing on transformations. That is, most *
  737. * functions are used to transform splines by modifying their state, e.g., *
  738. * their number of control points, their degree, and so on. Accordingly, each *
  739. * transformation functions specifies an input and output parameter (along *
  740. * with the other parameters required to calculate the actual transformation). *
  741. * By passing a different pointer to the output parameter, the transformation *
  742. * result is calculated and stored without changing the state of the input. *
  743. * This is in particular useful when dealing with errors as the original state *
  744. * will never be modified. For instance, let's have a look at the following *
  745. * code snippet: *
  746. * *
  747. * tsBSpline in = ... // an arbitrary spline *
  748. * tsBSpline out; // result of transformation *
  749. * *
  750. * // Subdivide 'in' into sequence of bezier curves and store the result *
  751. * // in 'out'. Does not change 'in' in any way. *
  752. * tsError err = ts_bspline_to_beziers(&in, &out); *
  753. * if (err != TS_SUCCESS) { *
  754. * // fortunately, 'in' has not been changed *
  755. * } *
  756. * *
  757. * Even if 'ts_bspline_to_beziers' fails, the state of 'in' has not been *
  758. * changed allowing you to handle the error properly. *
  759. * *
  760. * Unless stated otherwise, the order of the parameters for transformation *
  761. * functions is: *
  762. * *
  763. * function(input, [additional_input], output, [additional_output]) *
  764. * *
  765. * 'additional_input' are parameters required to calculate the actual *
  766. * transformation. 'additional_output' are parameters storing further result. *
  767. * *
  768. * Note: None of TinySpline's transformation functions frees the memory of the *
  769. * output parameter. Thus, when using the same output parameter multiple *
  770. * times, make sure to free memory before each call. Otherwise, you will *
  771. * have a bad time with memory leaks: *
  772. * *
  773. * tsBSpline in = ... // an arbitrary spline *
  774. * tsBSpline out; // result of transformations *
  775. * *
  776. * ts_bspline_to_beziers(&in, &out); // first transformation *
  777. * ... // some code *
  778. * ts_bspline_free(&out); // avoid memory leak. *
  779. * ts_bspline_buckle(&in, &out); // next transformation *
  780. * *
  781. * If you want to modify your input directly without having a separate output, *
  782. * pass it as input and output at once: *
  783. * *
  784. * tsBSpline s = ... // an arbitrary spline *
  785. * tsReal *knots = ... // a knot vector *
  786. * *
  787. * ts_bspline_set_knots(&s, knots, &s); // copy 'knots' into 's' *
  788. * *
  789. * Note: If a transformation function fails *and* input != output, all fields *
  790. * of the output parameter are set to 0/NULL. If input == output, your *
  791. * input may have an invalid state in case of errors. *
  792. * *
  793. ******************************************************************************/
  794. /**
  795. * Computes the derivative of \p spline, see:
  796. *
  797. * http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-derv.html
  798. *
  799. * The derivative of a spline _s_ of degree _d_ with _m_ control points and
  800. * _n_ knots is another spline _s'_ of degree _d-1_ with _m-1_ control points
  801. * and _n-2_ knots, defined over _s_ as:
  802. *
  803. * \f{eqnarray*}{
  804. * s'(u) &=& \sum_{i=0}^{n-1} N_{i+1,p-1}(u) *
  805. * (P_{i+1} - P_{i}) * p / (u_{i+p+1}-u_{i+1}) \\
  806. * &=& \sum_{i=1}^{n} N_{i,p-1}(u) *
  807. * (P_{i} - P_{i-1}) * p / (u_{i+p}-u_{i})
  808. * \f}
  809. *
  810. * If _s_ has a clamped knot vector, it can be shown that:
  811. *
  812. * \f{eqnarray*}{
  813. * s'(u) &=& \sum_{i=0}^{n-1} N_{i,p-1}(u) *
  814. * (P_{i+1} - P_{i}) * p / (u_{i+p+1}-u_{i+1})
  815. * \f}
  816. *
  817. * where the multiplicity of the first and the last knot value _u_ is _p_
  818. * rather than _p+1_.
  819. *
  820. * On error, (and if \p spline != \p \_derivative\_) all values of
  821. * \p \_derivative\_ are set to 0/NULL.
  822. *
  823. * @param spline
  824. * The spline to derive.
  825. * @param \_derivative\_
  826. * The output parameter storing the derivative of \p spline.
  827. * @return TS_SUCCESS
  828. * On success.
  829. * @return TS_UNDERIVABLE
  830. * If \p spline->deg < 1, \p spline->n_ctrlp < 2, or the multiplicity of
  831. * an internal knot of \p spline is greater than the degree of \p spline.
  832. * NOTE: This will be fixed in the future.
  833. * @return TS_MALLOC
  834. * If allocating memory failed.
  835. */
  836. tsError ts_bspline_derive(const tsBSpline *spline, tsBSpline *_derivative_);
  837. /**
  838. * Fills the knot vector of \p spline according to \p type with minimum knot
  839. * value \p min to maximum knot value \p max and stores the result in
  840. * \p \_result\_. Creates a deep copy of \p spline, if
  841. * \p spline != \p \_result\_.
  842. *
  843. * On error, (and if \p spline != \p \_result\_) all values of \p \_result\_
  844. * are set to 0/NULL.
  845. *
  846. * @param spline
  847. * The spline to deep copy (if \p spline != \p \_result\_) and whose knot
  848. * vector is filled according to \p type with minimum knot value \p min
  849. * and maximum knot value \p max.
  850. * @param type
  851. * How to fill the knot vector of \p \_result\_.
  852. * @param min
  853. * The minimum knot value of the knot vector of \p \_result\_.
  854. * @param max
  855. * The maximum knot value of the knot vector of \p \_result\_.
  856. * @param \_result\_
  857. * The output parameter storing the result of this function.
  858. * @return TS_SUCCESS
  859. * On success.
  860. * @return TS_DEG_GE_NCTRLP
  861. * If \p spline->n_knots < 2*(\p original->deg+1). We can reuse this
  862. * error code because \p spline->n_knots < 2*(\p spline->deg+1) implies
  863. * \p spline->deg >= \p spline->n_ctrlp. Furthermore, using
  864. * TS_DEG_GE_NCTRLP instead of TS_NUM_KNOTS ensures that TS_NUM_KNOTS is
  865. * not used twice for this function. To be more fail-safe,
  866. * \p spline->deg+1 instead of \p spline->order is used, to make sure
  867. * that \p spline->deg+1 >= 1.
  868. * @return TS_NUM_KNOTS
  869. * If \p type == TS_BEZIERS and
  870. * \p spline->n_knots % \p spline->order != 0.
  871. * @return TS_KNOTS_DECR
  872. * If \p min >= \p max. (::ts_fequals is used to determine whether
  873. * \p min == \p max).
  874. * @return TS_MALLOC
  875. * If \p spline != \p \_result\_ and allocating memory failed.
  876. */
  877. tsError ts_bspline_fill_knots(const tsBSpline *spline, tsBSplineType type,
  878. tsReal min, tsReal max, tsBSpline *_result_);
  879. /**
  880. * Inserts the knot value \p u \p n times into \p spline and stores the result
  881. * in \p \_result\_. Creates a deep copy of \p spline, if
  882. * \p spline != \p \_result\_.
  883. *
  884. * On error, (and if \p spline != \p \_result\_) all values of \p \_result\_
  885. * are set to 0/NULL.
  886. *
  887. * @param spline
  888. * The spline to deep copy (if \p spline != \p \_result\_) and whose knot
  889. * vector is extended with \p u \p n times.
  890. * @param u
  891. * The knot value to insert.
  892. * @param n
  893. * How many times \p u should be inserted.
  894. * @param \_result\_
  895. * The output parameter storing the updated knot vector.
  896. * @param \_k\_
  897. * The output parameter storing the last index of \p u in \p \_result\_.
  898. * @return TS_SUCCESS
  899. * On success.
  900. * @return TS_MALLOC
  901. * If \p spline != \p \_result\_ and allocating memory failed.
  902. */
  903. tsError ts_bspline_insert_knot(const tsBSpline *spline, tsReal u, size_t n,
  904. tsBSpline *_result_, size_t *_k_);
  905. /**
  906. * Resizes \p spline by \p n (number of control points) and stores the result
  907. * in \p \_resized\_. Creates a deep copy of \p spline, if
  908. * \p spline != \p \_result\_. If \p back != 0 \p spline is resized at the
  909. * end. If \p back == 0 \p spline is resized at front.
  910. *
  911. * On error, (and if \p spline != \p \_result\_) all values of \p \_result\_
  912. * are set to 0/NULL.
  913. *
  914. * @return TS_SUCCESS
  915. * On success.
  916. * @return TS_DEG_GE_NCTRLP
  917. * If the degree of \p \_resized\_ would be >= the number of the control
  918. * points of \p \_resized\_.
  919. * @return TS_DIM_ZERO
  920. * If \p spline != \p \_result\_ and \p spline->dim == 0.
  921. * @return TS_DEG_GE_NCTRLP
  922. * If \p spline != \p \_result\_ and
  923. * \p spline->deg >= \p spline->n_ctrlp.
  924. * @return TS_MALLOC
  925. * If \p spline != \p \_result\_ and allocating memory failed.
  926. */
  927. tsError ts_bspline_resize(const tsBSpline *spline, int n, int back,
  928. tsBSpline *_resized_);
  929. /**
  930. * Splits \p spline at \p u and stores the result in \p \_split\_. That is,
  931. * \p u is inserted _n_ times such that s(\p u) == \p \_split\_->order.
  932. * Creates a deep copy of \p spline, if \p spline != \p \_split\_.
  933. *
  934. * On error, (and if \p spline != \p \_split\_) all values of \p \_split\_
  935. * are set to 0/NULL.
  936. *
  937. * @param spline
  938. * The spline to deep copy (if \p spline != \p \_result\_) and split.
  939. * @param u
  940. * The split point.
  941. * @param \_split\_
  942. * The output parameter storing the split spline.
  943. * @param \_k\_
  944. * The output parameter storing the last index of \p u in \p \_split\_.
  945. * @return TS_SUCCESS
  946. * On success.
  947. * @return TS_MALLOC
  948. * If \p spline != \p \_split\_ and allocating memory failed.
  949. */
  950. tsError ts_bspline_split(const tsBSpline *spline, tsReal u, tsBSpline *_split_,
  951. size_t *_k_);
  952. /**
  953. * Buckles \p spline by \p b and stores the result in \p \_buckled\_. Creates
  954. * a deep copy of \p spline, if \p spline != \p \_buckled\_.
  955. *
  956. * This function is based on:
  957. *
  958. * Holten, Danny. "Hierarchical edge bundles: Visualization of adjacency
  959. * relations in hierarchical data." Visualization and Computer Graphics,
  960. * IEEE Transactions on 12.5 (2006): 741-748.
  961. *
  962. * Holten calls it "straightening" (page 744, equation 1).
  963. *
  964. * Usually, the range of \p b is: 0.0 <= \p b <= 1.0 with 0 yielding to a line
  965. * connecting the first and the last control point (no buckle) and 1 keeping
  966. * the original shape (maximum buckle). If \b < 0 or \b > 1 the behaviour is
  967. * undefined, though, it will not result in an error.
  968. *
  969. * On error, (and if \p spline != \p \_buckled\_) all values of \p \_buckled\_
  970. * are set to 0/NULL.
  971. *
  972. * @param spline
  973. * The spline to buckle by \p b.
  974. * @param b
  975. * The buckle factor (usually 0.0 <= \p b <= 1.0).
  976. * @param \_buckled\_
  977. * The output parameter storing the buckled spline.
  978. * @return TS_SUCCESS
  979. * On success.
  980. * @return TS_MALLOC
  981. * If \p spline != \p \_buckled\_ and allocating memory failed.
  982. */
  983. tsError ts_bspline_buckle(const tsBSpline *spline, tsReal b,
  984. tsBSpline *_buckled_);
  985. /**
  986. * Subdivides \p spline into a sequence of Bezier curvs by splitting it at
  987. * each internal knot value. Creates a deep copy of \p spline, if
  988. * \p spline != \p \_beziers\_.
  989. *
  990. * On error, (and if \p spline != \p \_beziers\_) all values of \p \_beziers\_
  991. * are set to 0/NULL.
  992. *
  993. * @param spline
  994. * The spline to subdivide into a sequence of Bezier curves.
  995. * @param \_beziers\_
  996. * The output parameter storing the sequence of Bezier curves.
  997. * @return TS_SUCCESS
  998. * On success.
  999. * @return TS_MALLOC
  1000. * If \p spline != \p \_beizers\_ and allocating memory failed.
  1001. */
  1002. tsError ts_bspline_to_beziers(const tsBSpline *spline, tsBSpline *_beziers_);
  1003. /******************************************************************************
  1004. * *
  1005. * :: Utility Functions *
  1006. * *
  1007. * The following section contains utility functions used by TinySpline which *
  1008. * also may be helpful when using this library. *
  1009. * *
  1010. ******************************************************************************/
  1011. /**
  1012. * Compares the tsReal values \p x and \p y using an absolute and relative
  1013. * epsilon environment.
  1014. *
  1015. * @param x
  1016. * The x value to compare.
  1017. * @param y
  1018. * The y value to compare.
  1019. * @return 1
  1020. * If \p x is equals to \p y.
  1021. * @return 0
  1022. * Otherwise.
  1023. */
  1024. int ts_fequals(tsReal x, tsReal y);
  1025. /**
  1026. * Returns the error message associated to \p err. Returns "unknown error" if
  1027. * \p err is no associated (indicating a bug) or is TS_SUCCESS (which is not
  1028. * an actual error).
  1029. */
  1030. const char* ts_enum_str(tsError err);
  1031. /**
  1032. * Returns the error code associated to \p str or TS_SUCCESS if \p str is not
  1033. * associated. Keep in mind that by concept "unknown error" is not associated,
  1034. * though, TS_SUCCESS is returned.
  1035. */
  1036. tsError ts_str_enum(const char *str);
  1037. /**
  1038. * Fills the given array \p arr with \p val from \p arr+0 to \p arr+ \p num
  1039. * (exclusive).
  1040. */
  1041. void ts_arr_fill(tsReal *arr, size_t num, tsReal val);
  1042. /**
  1043. * Returns the euclidean distance of \p x and \p y consisting of \p dim
  1044. * components, respectively.
  1045. *
  1046. * @param x
  1047. * The x value.
  1048. * @param y
  1049. * The y value.
  1050. * @param dim
  1051. * The dimension of \p x and \p y.
  1052. * @return
  1053. * The euclidean distanc of \p x and \p y.
  1054. */
  1055. tsReal ts_ctrlp_dist2(const tsReal *x, const tsReal *y, size_t dim);
  1056. #ifdef __cplusplus
  1057. }
  1058. #endif
  1059. #endif /* TINYSPLINE_H */