You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1707 lines
36 KiB

  1. #define TINYSPLINE_EXPORT
  2. #include "tinysplinecxx.h"
  3. #include <stdlib.h>
  4. #include <cstring>
  5. #include <stdexcept>
  6. #include <cstdio>
  7. #include <sstream>
  8. /* Suppress some useless MSVC warnings. */
  9. #ifdef _MSC_VER
  10. #pragma warning(push)
  11. /* address of dllimport */
  12. #pragma warning(disable:4232)
  13. /* binding rvalues to non-const references */
  14. #pragma warning(disable:4350)
  15. /* unreferenced inline function */
  16. #pragma warning(disable:4514)
  17. /* function not inlined */
  18. #pragma warning(disable:4710)
  19. /* byte padding */
  20. #pragma warning(disable:4820)
  21. /* meaningless deprecation */
  22. #pragma warning(disable:4996)
  23. /* Spectre mitigation */
  24. #pragma warning(disable:5045)
  25. #endif
  26. /*! @name Swig Type Mapping
  27. *
  28. * See tinysplinecxx.h for more details.
  29. *
  30. * @{
  31. */
  32. #ifdef SWIG
  33. #define std_real_vector_init(var) \
  34. std_real_vector_out var = new std::vector<tinyspline::real>
  35. #define std_real_vector_read(var) var->
  36. #else
  37. #define std_real_vector_init(var) \
  38. std_real_vector_out var
  39. #define std_real_vector_read(var) var.
  40. #endif
  41. /*! @} */
  42. /*! @name Vec2
  43. *
  44. * @{
  45. */
  46. tinyspline::Vec2::Vec2()
  47. {
  48. const real v = (real) 0.0;
  49. ts_vec2_init(m_vals, v, v);
  50. }
  51. tinyspline::Vec2::Vec2(real x,
  52. real y)
  53. {
  54. ts_vec2_init(m_vals, x, y);
  55. }
  56. tinyspline::Vec2
  57. tinyspline::Vec2::operator+(const Vec2 &other)
  58. {
  59. return add(other);
  60. }
  61. tinyspline::Vec2
  62. tinyspline::Vec2::operator-(const Vec2 &other)
  63. {
  64. return subtract(other);
  65. }
  66. tinyspline::Vec2
  67. tinyspline::Vec2::operator*(real scalar)
  68. {
  69. return multiply(scalar);
  70. }
  71. tinyspline::real
  72. tinyspline::Vec2::x() const
  73. {
  74. return m_vals[0];
  75. }
  76. void
  77. tinyspline::Vec2::setX(real val)
  78. {
  79. m_vals[0] = val;
  80. }
  81. tinyspline::real
  82. tinyspline::Vec2::y() const
  83. {
  84. return m_vals[1];
  85. }
  86. void
  87. tinyspline::Vec2::setY(real val)
  88. {
  89. m_vals[1] = val;
  90. }
  91. std::vector<tinyspline::real>
  92. tinyspline::Vec2::values() const
  93. {
  94. return std::vector<real>({ x(), y() });
  95. }
  96. tinyspline::Vec2
  97. tinyspline::Vec2::add(const Vec2 &other) const
  98. {
  99. Vec2 vec;
  100. ts_vec_add(m_vals, other.m_vals, 2, vec.m_vals);
  101. return vec;
  102. }
  103. tinyspline::Vec2
  104. tinyspline::Vec2::subtract(const Vec2 &other) const
  105. {
  106. Vec2 vec;
  107. ts_vec_sub(m_vals, other.m_vals, 2, vec.m_vals);
  108. return vec;
  109. }
  110. tinyspline::Vec2
  111. tinyspline::Vec2::multiply(real scalar) const
  112. {
  113. Vec2 vec;
  114. ts_vec_mul(m_vals, 2, scalar, vec.m_vals);
  115. return vec;
  116. }
  117. tinyspline::Vec2
  118. tinyspline::Vec2::normalize() const
  119. {
  120. Vec2 vec;
  121. ts_vec_norm(m_vals, 2, vec.m_vals);
  122. return vec;
  123. }
  124. tinyspline::Vec2
  125. tinyspline::Vec2::norm() const
  126. {
  127. return normalize();
  128. }
  129. tinyspline::real
  130. tinyspline::Vec2::magnitude() const
  131. {
  132. return ts_vec_mag(m_vals, 2);
  133. }
  134. tinyspline::real
  135. tinyspline::Vec2::dot(const Vec2 &other) const
  136. {
  137. return ts_vec_dot(m_vals, other.m_vals, 2);
  138. }
  139. tinyspline::real
  140. tinyspline::Vec2::angle(const Vec2 &other) const
  141. {
  142. real buf[4];
  143. return ts_vec_angle(m_vals, other.m_vals, buf, 2);
  144. }
  145. tinyspline::real
  146. tinyspline::Vec2::distance(const Vec2 &other) const
  147. {
  148. return ts_distance(m_vals, other.m_vals, 2);
  149. }
  150. std::string
  151. tinyspline::Vec2::toString() const
  152. {
  153. std::ostringstream oss;
  154. oss << "Vec2{"
  155. << "x: " << x()
  156. << ", y: " << y()
  157. << "}";
  158. return oss.str();
  159. }
  160. /*! @} */
  161. /*! @name Vec3
  162. *
  163. * @{
  164. */
  165. tinyspline::Vec3::Vec3()
  166. {
  167. const real v = (real) 0.0;
  168. ts_vec3_init(m_vals, v, v, v);
  169. }
  170. tinyspline::Vec3::Vec3(real x,
  171. real y,
  172. real z)
  173. {
  174. ts_vec3_init(m_vals, x, y, z);
  175. }
  176. tinyspline::Vec3
  177. tinyspline::Vec3::operator+(const Vec3 &other)
  178. {
  179. return add(other);
  180. }
  181. tinyspline::Vec3
  182. tinyspline::Vec3::operator-(const Vec3 &other)
  183. {
  184. return subtract(other);
  185. }
  186. tinyspline::Vec3
  187. tinyspline::Vec3::operator*(real scalar)
  188. {
  189. return multiply(scalar);
  190. }
  191. tinyspline::real
  192. tinyspline::Vec3::x() const
  193. {
  194. return m_vals[0];
  195. }
  196. void
  197. tinyspline::Vec3::setX(real val)
  198. {
  199. m_vals[0] = val;
  200. }
  201. tinyspline::real
  202. tinyspline::Vec3::y() const
  203. {
  204. return m_vals[1];
  205. }
  206. void
  207. tinyspline::Vec3::setY(real val)
  208. {
  209. m_vals[1] = val;
  210. }
  211. tinyspline::real
  212. tinyspline::Vec3::z() const
  213. {
  214. return m_vals[2];
  215. }
  216. void
  217. tinyspline::Vec3::setZ(real val)
  218. {
  219. m_vals[2] = val;
  220. }
  221. std::vector<tinyspline::real>
  222. tinyspline::Vec3::values() const
  223. {
  224. return std::vector<real>({ x(), y(), z() });
  225. }
  226. tinyspline::Vec3
  227. tinyspline::Vec3::add(const Vec3 &other) const
  228. {
  229. Vec3 vec;
  230. ts_vec_add(m_vals, other.m_vals, 3, vec.m_vals);
  231. return vec;
  232. }
  233. tinyspline::Vec3
  234. tinyspline::Vec3::subtract(const Vec3 &other) const
  235. {
  236. Vec3 vec;
  237. ts_vec_sub(m_vals, other.m_vals, 3, vec.m_vals);
  238. return vec;
  239. }
  240. tinyspline::Vec3
  241. tinyspline::Vec3::multiply(real scalar) const
  242. {
  243. Vec3 vec;
  244. ts_vec_mul(m_vals, 3, scalar, vec.m_vals);
  245. return vec;
  246. }
  247. tinyspline::Vec3
  248. tinyspline::Vec3::cross(const Vec3 &other) const
  249. {
  250. Vec3 vec;
  251. ts_vec3_cross(m_vals, other.m_vals, vec.m_vals);
  252. return vec;
  253. }
  254. tinyspline::Vec3
  255. tinyspline::Vec3::normalize() const
  256. {
  257. Vec3 vec;
  258. ts_vec_norm(m_vals, 3, vec.m_vals);
  259. return vec;
  260. }
  261. tinyspline::Vec3
  262. tinyspline::Vec3::norm() const
  263. {
  264. return normalize();
  265. }
  266. tinyspline::real
  267. tinyspline::Vec3::magnitude() const
  268. {
  269. return ts_vec_mag(m_vals, 3);
  270. }
  271. tinyspline::real
  272. tinyspline::Vec3::dot(const Vec3 &other) const
  273. {
  274. return ts_vec_dot(m_vals, other.m_vals, 3);
  275. }
  276. tinyspline::real
  277. tinyspline::Vec3::angle(const Vec3 &other) const
  278. {
  279. real buf[6];
  280. return ts_vec_angle(m_vals, other.m_vals, buf, 3);
  281. }
  282. tinyspline::real
  283. tinyspline::Vec3::distance(const Vec3 &other) const
  284. {
  285. return ts_distance(m_vals, other.m_vals, 3);
  286. }
  287. std::string
  288. tinyspline::Vec3::toString() const
  289. {
  290. std::ostringstream oss;
  291. oss << "Vec3{"
  292. << "x: " << x()
  293. << ", y: " << y()
  294. << ", z: " << z()
  295. << "}";
  296. return oss.str();
  297. }
  298. /*! @} */
  299. /*! @name Vec4
  300. *
  301. * @{
  302. */
  303. tinyspline::Vec4::Vec4()
  304. {
  305. const real v = (real) 0.0;
  306. ts_vec4_init(m_vals, v, v, v, v);
  307. }
  308. tinyspline::Vec4::Vec4(real x,
  309. real y,
  310. real z,
  311. real w)
  312. {
  313. ts_vec4_init(m_vals, x, y, z, w);
  314. }
  315. tinyspline::Vec4
  316. tinyspline::Vec4::operator+(const Vec4 &other)
  317. {
  318. return add(other);
  319. }
  320. tinyspline::Vec4
  321. tinyspline::Vec4::operator-(const Vec4 &other)
  322. {
  323. return subtract(other);
  324. }
  325. tinyspline::Vec4
  326. tinyspline::Vec4::operator*(real scalar)
  327. {
  328. return multiply(scalar);
  329. }
  330. tinyspline::real
  331. tinyspline::Vec4::x() const
  332. {
  333. return m_vals[0];
  334. }
  335. void
  336. tinyspline::Vec4::setX(real val)
  337. {
  338. m_vals[0] = val;
  339. }
  340. tinyspline::real
  341. tinyspline::Vec4::y() const
  342. {
  343. return m_vals[1];
  344. }
  345. void
  346. tinyspline::Vec4::setY(real val)
  347. {
  348. m_vals[1] = val;
  349. }
  350. tinyspline::real
  351. tinyspline::Vec4::z() const
  352. {
  353. return m_vals[2];
  354. }
  355. void
  356. tinyspline::Vec4::setZ(real val)
  357. {
  358. m_vals[2] = val;
  359. }
  360. tinyspline::real
  361. tinyspline::Vec4::w() const
  362. {
  363. return m_vals[3];
  364. }
  365. void
  366. tinyspline::Vec4::setW(real val)
  367. {
  368. m_vals[3] = val;
  369. }
  370. std::vector<tinyspline::real>
  371. tinyspline::Vec4::values() const
  372. {
  373. return std::vector<real>({ x(), y(), z(), w() });
  374. }
  375. tinyspline::Vec4
  376. tinyspline::Vec4::add(const Vec4 &other) const
  377. {
  378. Vec4 vec;
  379. ts_vec_add(m_vals, other.m_vals, 4, vec.m_vals);
  380. return vec;
  381. }
  382. tinyspline::Vec4
  383. tinyspline::Vec4::subtract(const Vec4 &other) const
  384. {
  385. Vec4 vec;
  386. ts_vec_sub(m_vals, other.m_vals, 4, vec.m_vals);
  387. return vec;
  388. }
  389. tinyspline::Vec4
  390. tinyspline::Vec4::multiply(real scalar) const
  391. {
  392. Vec4 vec;
  393. ts_vec_mul(m_vals, 4, scalar, vec.m_vals);
  394. return vec;
  395. }
  396. tinyspline::Vec4
  397. tinyspline::Vec4::normalize() const
  398. {
  399. Vec4 vec;
  400. ts_vec_norm(m_vals, 4, vec.m_vals);
  401. return vec;
  402. }
  403. tinyspline::Vec4
  404. tinyspline::Vec4::norm() const
  405. {
  406. return normalize();
  407. }
  408. tinyspline::real
  409. tinyspline::Vec4::magnitude() const
  410. {
  411. return ts_vec_mag(m_vals, 4);
  412. }
  413. tinyspline::real
  414. tinyspline::Vec4::dot(const Vec4 &other) const
  415. {
  416. return ts_vec_dot(m_vals, other.m_vals, 4);
  417. }
  418. tinyspline::real
  419. tinyspline::Vec4::angle(const Vec4 &other) const
  420. {
  421. real buf[8];
  422. return ts_vec_angle(m_vals, other.m_vals, buf, 4);
  423. }
  424. tinyspline::real
  425. tinyspline::Vec4::distance(const Vec4 &other) const
  426. {
  427. return ts_distance(m_vals, other.m_vals, 4);
  428. }
  429. std::string
  430. tinyspline::Vec4::toString() const
  431. {
  432. std::ostringstream oss;
  433. oss << "Vec4{"
  434. << "x: " << x()
  435. << ", y: " << y()
  436. << ", z: " << z()
  437. << ", w: " << w()
  438. << "}";
  439. return oss.str();
  440. }
  441. /*! @} */
  442. /*! @name Frame
  443. *
  444. * @{
  445. */
  446. tinyspline::Frame::Frame(Vec3 &position,
  447. Vec3 &tangent,
  448. Vec3 &normal,
  449. Vec3 &binormal)
  450. : m_position(position),
  451. m_tangent(tangent),
  452. m_normal(normal),
  453. m_binormal(binormal)
  454. {}
  455. tinyspline::Vec3
  456. tinyspline::Frame::position() const
  457. {
  458. return m_position;
  459. }
  460. tinyspline::Vec3
  461. tinyspline::Frame::tangent() const
  462. {
  463. return m_tangent;
  464. }
  465. tinyspline::Vec3
  466. tinyspline::Frame::normal() const
  467. {
  468. return m_normal;
  469. }
  470. tinyspline::Vec3
  471. tinyspline::Frame::binormal() const
  472. {
  473. return m_binormal;
  474. }
  475. std::string
  476. tinyspline::Frame::toString() const
  477. {
  478. std::ostringstream oss;
  479. oss << "Frame{"
  480. << "position: " << position().toString()
  481. << ", tangent: " << tangent().toString()
  482. << ", normal: " << normal().toString()
  483. << ", binormal: " << binormal().toString()
  484. << "}";
  485. return oss.str();
  486. }
  487. /*! @} */
  488. /*! @name FrameSeq
  489. *
  490. * @{
  491. */
  492. tinyspline::FrameSeq::FrameSeq()
  493. : m_frames(nullptr), m_size(0)
  494. {}
  495. tinyspline::FrameSeq::FrameSeq(tsFrame *frames,
  496. size_t len)
  497. : m_frames(frames), m_size(len)
  498. {}
  499. tinyspline::FrameSeq::FrameSeq(const FrameSeq &other)
  500. : m_frames(nullptr), m_size(other.m_size)
  501. {
  502. m_frames = new tsFrame[m_size];
  503. std::copy(other.m_frames,
  504. other.m_frames + m_size,
  505. m_frames);
  506. }
  507. tinyspline::FrameSeq::FrameSeq(FrameSeq &&other)
  508. : m_frames(nullptr), m_size(other.m_size)
  509. {
  510. m_frames = other.m_frames;
  511. other.m_frames = nullptr;
  512. other.m_size = 0;
  513. }
  514. tinyspline::FrameSeq::~FrameSeq()
  515. {
  516. delete [] m_frames;
  517. m_size = 0;
  518. }
  519. tinyspline::FrameSeq &
  520. tinyspline::FrameSeq::operator=(const FrameSeq &other)
  521. {
  522. if (&other != this) {
  523. tsFrame *data = new tsFrame[other.m_size];
  524. std::copy(other.m_frames,
  525. other.m_frames + other.m_size,
  526. data);
  527. delete [] m_frames;
  528. m_frames = data;
  529. m_size = other.m_size;
  530. }
  531. return *this;
  532. }
  533. tinyspline::FrameSeq &
  534. tinyspline::FrameSeq::operator=(FrameSeq &&other)
  535. {
  536. if (&other != this) {
  537. delete [] m_frames;
  538. m_frames = other.m_frames;
  539. m_size = other.m_size;
  540. other.m_frames = nullptr;
  541. other.m_size = 0;
  542. }
  543. return *this;
  544. }
  545. size_t
  546. tinyspline::FrameSeq::size() const
  547. {
  548. return m_size;
  549. }
  550. tinyspline::Frame
  551. tinyspline::FrameSeq::at(size_t idx) const
  552. {
  553. if (idx >= m_size)
  554. throw std::out_of_range( "idx >= size");
  555. tsFrame frame = m_frames[idx];
  556. Vec3 position = Vec3(frame.position[0],
  557. frame.position[1],
  558. frame.position[2]);
  559. Vec3 tangent = Vec3(frame.tangent[0],
  560. frame.tangent[1],
  561. frame.tangent[2]);
  562. Vec3 normal = Vec3(frame.normal[0],
  563. frame.normal[1],
  564. frame.normal[2]);
  565. Vec3 binormal = Vec3(frame.binormal[0],
  566. frame.binormal[1],
  567. frame.binormal[2]);
  568. return Frame(position, tangent, normal, binormal);
  569. }
  570. std::string
  571. tinyspline::FrameSeq::toString() const
  572. {
  573. std::ostringstream oss;
  574. oss << "FrameSeq{"
  575. << "frames: " << size()
  576. << "}";
  577. return oss.str();
  578. }
  579. /*! @} */
  580. /*! @name Domain
  581. *
  582. * @{
  583. */
  584. tinyspline::Domain::Domain(real min,
  585. real max)
  586. : m_min(min), m_max(max)
  587. {}
  588. tinyspline::real
  589. tinyspline::Domain::min() const
  590. {
  591. return m_min;
  592. }
  593. tinyspline::real
  594. tinyspline::Domain::max() const
  595. {
  596. return m_max;
  597. }
  598. std::string
  599. tinyspline::Domain::toString() const
  600. {
  601. std::ostringstream oss;
  602. oss << "Domain{"
  603. << "min: " << min()
  604. << ", max: " << max()
  605. << "}";
  606. return oss.str();
  607. }
  608. /*! @} */
  609. /*! @name DeBoorNet
  610. *
  611. * @{
  612. */
  613. tinyspline::DeBoorNet::DeBoorNet(tsDeBoorNet &data)
  614. : net(ts_deboornet_init())
  615. {
  616. ts_deboornet_move(&data, &net);
  617. }
  618. tinyspline::DeBoorNet::DeBoorNet(const DeBoorNet &other)
  619. : net(ts_deboornet_init())
  620. {
  621. tsStatus status;
  622. if (ts_deboornet_copy(&other.net, &net, &status))
  623. throw std::runtime_error(status.message);
  624. }
  625. tinyspline::DeBoorNet::DeBoorNet(DeBoorNet &&other)
  626. : net(ts_deboornet_init())
  627. {
  628. ts_deboornet_move(&other.net, &net);
  629. }
  630. tinyspline::DeBoorNet::~DeBoorNet()
  631. {
  632. ts_deboornet_free(&net);
  633. }
  634. tinyspline::DeBoorNet &
  635. tinyspline::DeBoorNet::operator=(const DeBoorNet &other)
  636. {
  637. if (&other != this) {
  638. tsDeBoorNet data = ts_deboornet_init();
  639. tsStatus status;
  640. if (ts_deboornet_copy(&other.net, &data, &status))
  641. throw std::runtime_error(status.message);
  642. ts_deboornet_free(&net);
  643. ts_deboornet_move(&data, &net);
  644. }
  645. return *this;
  646. }
  647. tinyspline::DeBoorNet &
  648. tinyspline::DeBoorNet::operator=(DeBoorNet && other)
  649. {
  650. if (&other != this) {
  651. ts_deboornet_free(&net);
  652. ts_deboornet_move(&other.net, &net);
  653. }
  654. return *this;
  655. }
  656. tinyspline::real
  657. tinyspline::DeBoorNet::knot() const
  658. {
  659. return ts_deboornet_knot(&net);
  660. }
  661. size_t
  662. tinyspline::DeBoorNet::index() const
  663. {
  664. return ts_deboornet_index(&net);
  665. }
  666. size_t
  667. tinyspline::DeBoorNet::multiplicity() const
  668. {
  669. return ts_deboornet_multiplicity(&net);
  670. }
  671. size_t
  672. tinyspline::DeBoorNet::numInsertions() const
  673. {
  674. return ts_deboornet_num_insertions(&net);
  675. }
  676. size_t
  677. tinyspline::DeBoorNet::dimension() const
  678. {
  679. return ts_deboornet_dimension(&net);
  680. }
  681. std::vector<tinyspline::real>
  682. tinyspline::DeBoorNet::points() const
  683. {
  684. const real *points = ts_deboornet_points_ptr(&net);
  685. size_t len = ts_deboornet_len_points(&net);
  686. return std::vector<real>(points, points + len);
  687. }
  688. std::vector<tinyspline::real>
  689. tinyspline::DeBoorNet::result() const
  690. {
  691. const real *result = ts_deboornet_result_ptr(&net);
  692. size_t len = ts_deboornet_len_result(&net);
  693. return std::vector<real>(result, result + len);
  694. }
  695. tinyspline::Vec2
  696. tinyspline::DeBoorNet::resultVec2(size_t idx) const
  697. {
  698. Vec4 vec4 = resultVec4(idx);
  699. return Vec2(vec4.x(), vec4.y());
  700. }
  701. tinyspline::Vec3
  702. tinyspline::DeBoorNet::resultVec3(size_t idx) const
  703. {
  704. Vec4 vec4 = resultVec4(idx);
  705. return Vec3(vec4.x(), vec4.y(), vec4.z());
  706. }
  707. tinyspline::Vec4
  708. tinyspline::DeBoorNet::resultVec4(size_t idx) const
  709. {
  710. if (idx >= ts_deboornet_num_result(&net))
  711. throw std::out_of_range( "idx >= num(result)");
  712. const real *result = ts_deboornet_result_ptr(&net);
  713. real vals[4];
  714. ts_vec4_set(vals, result + idx * dimension(), dimension());
  715. return Vec4(vals[0], vals[1], vals[2], vals[3]);
  716. }
  717. std::string
  718. tinyspline::DeBoorNet::toString() const
  719. {
  720. std::ostringstream oss;
  721. oss << "DeBoorNet{"
  722. << "knot: " << knot()
  723. << ", index: " << index()
  724. << ", multiplicity: " << multiplicity()
  725. << ", insertions: " << numInsertions()
  726. << ", dimension: " << dimension()
  727. << ", points: " << ts_deboornet_num_points(&net)
  728. << "}";
  729. return oss.str();
  730. }
  731. /*! @} */
  732. /******************************************************************************
  733. * *
  734. * BSpline *
  735. * *
  736. ******************************************************************************/
  737. tinyspline::BSpline::BSpline(tsBSpline &data)
  738. : spline(ts_bspline_init())
  739. {
  740. ts_bspline_move(&data, &spline);
  741. }
  742. tinyspline::BSpline::BSpline()
  743. : spline(ts_bspline_init())
  744. {
  745. tsStatus status;
  746. if (ts_bspline_new_with_control_points(1,
  747. 3,
  748. 0,
  749. TS_CLAMPED,
  750. &spline,
  751. &status,
  752. 0.0, 0.0, 0.0))
  753. throw std::runtime_error(status.message);
  754. }
  755. tinyspline::BSpline::BSpline(const tinyspline::BSpline &other)
  756. : spline(ts_bspline_init())
  757. {
  758. tsStatus status;
  759. if (ts_bspline_copy(&other.spline, &spline, &status))
  760. throw std::runtime_error(status.message);
  761. }
  762. tinyspline::BSpline::BSpline(BSpline &&other)
  763. : spline(ts_bspline_init())
  764. {
  765. ts_bspline_move(&other.spline, &spline);
  766. }
  767. tinyspline::BSpline::BSpline(size_t numControlPoints,
  768. size_t dimension,
  769. size_t degree,
  770. Type type)
  771. : spline(ts_bspline_init())
  772. {
  773. tsBSplineType c_type = TS_CLAMPED;
  774. switch (type) {
  775. case Opened:
  776. c_type = TS_OPENED;
  777. break;
  778. case Clamped:
  779. c_type = TS_CLAMPED;
  780. break;
  781. case Beziers:
  782. c_type = TS_BEZIERS;
  783. break;
  784. default:
  785. throw std::runtime_error("unknown type");
  786. }
  787. tsStatus status;
  788. if (ts_bspline_new(numControlPoints,
  789. dimension,
  790. degree,
  791. c_type,
  792. &spline,
  793. &status))
  794. throw std::runtime_error(status.message);
  795. }
  796. tinyspline::BSpline::~BSpline()
  797. {
  798. ts_bspline_free(&spline);
  799. }
  800. tinyspline::BSpline tinyspline::BSpline::interpolateCubicNatural(
  801. std_real_vector_in points, size_t dimension)
  802. {
  803. if (dimension == 0)
  804. throw std::runtime_error("unsupported dimension: 0");
  805. if (std_real_vector_read(points)size() % dimension != 0)
  806. throw std::runtime_error("#points % dimension != 0");
  807. tsBSpline data = ts_bspline_init();
  808. tsStatus status;
  809. if (ts_bspline_interpolate_cubic_natural(
  810. std_real_vector_read(points)data(),
  811. std_real_vector_read(points)size()/dimension,
  812. dimension, &data, &status))
  813. throw std::runtime_error(status.message);
  814. return BSpline(data);
  815. }
  816. tinyspline::BSpline
  817. tinyspline::BSpline::interpolateCatmullRom(std_real_vector_in points,
  818. size_t dimension,
  819. real alpha,
  820. std::vector<real> *first,
  821. std::vector<real> *last,
  822. real epsilon)
  823. {
  824. if (dimension == 0)
  825. throw std::runtime_error("unsupported dimension: 0");
  826. if (std_real_vector_read(points)size() % dimension != 0)
  827. throw std::runtime_error("#points % dimension != 0");
  828. real *fst = nullptr;
  829. if (first && first->size() >= dimension)
  830. fst = first->data();
  831. real *lst = nullptr;
  832. if (last && last->size() >= dimension)
  833. lst = last->data();
  834. tsBSpline data = ts_bspline_init();
  835. tsStatus status;
  836. if (ts_bspline_interpolate_catmull_rom(
  837. std_real_vector_read(points)data(),
  838. std_real_vector_read(points)size()/dimension,
  839. dimension, alpha, fst, lst, epsilon, &data,
  840. &status))
  841. throw std::runtime_error(status.message);
  842. return BSpline(data);
  843. }
  844. tinyspline::BSpline tinyspline::BSpline::parseJson(std::string json)
  845. {
  846. tsBSpline data = ts_bspline_init();
  847. tsStatus status;
  848. if (ts_bspline_parse_json(json.c_str(), &data, &status))
  849. throw std::runtime_error(status.message);
  850. return BSpline(data);
  851. }
  852. tinyspline::BSpline tinyspline::BSpline::load(std::string path)
  853. {
  854. tsBSpline data = ts_bspline_init();
  855. tsStatus status;
  856. if (ts_bspline_load(path.c_str(), &data, &status))
  857. throw std::runtime_error(status.message);
  858. return BSpline(data);
  859. }
  860. bool
  861. tinyspline::BSpline::knotsEqual(real x, real y)
  862. {
  863. return ts_knots_equal(x, y);
  864. }
  865. tinyspline::BSpline &
  866. tinyspline::BSpline::operator=(const BSpline &other)
  867. {
  868. if (&other != this) {
  869. tsBSpline data = ts_bspline_init();
  870. tsStatus status;
  871. if (ts_bspline_copy(&other.spline, &data, &status))
  872. throw std::runtime_error(status.message);
  873. ts_bspline_free(&spline);
  874. ts_bspline_move(&data, &spline);
  875. }
  876. return *this;
  877. }
  878. tinyspline::BSpline &
  879. tinyspline::BSpline::operator=(BSpline &&other)
  880. {
  881. if (&other != this) {
  882. ts_bspline_free(&spline);
  883. ts_bspline_move(&other.spline, &spline);
  884. }
  885. return *this;
  886. }
  887. tinyspline::DeBoorNet tinyspline::BSpline::operator()(tinyspline::real u) const
  888. {
  889. return eval(u);
  890. }
  891. size_t tinyspline::BSpline::degree() const
  892. {
  893. return ts_bspline_degree(&spline);
  894. }
  895. size_t tinyspline::BSpline::order() const
  896. {
  897. return ts_bspline_order(&spline);
  898. }
  899. size_t tinyspline::BSpline::dimension() const
  900. {
  901. return ts_bspline_dimension(&spline);
  902. }
  903. std::vector<tinyspline::real>
  904. tinyspline::BSpline::controlPoints() const
  905. {
  906. const real *ctrlps = ts_bspline_control_points_ptr(&spline);
  907. const size_t len = ts_bspline_len_control_points(&spline);
  908. return std::vector<real>(ctrlps, ctrlps + len);
  909. }
  910. tinyspline::Vec2
  911. tinyspline::BSpline::controlPointVec2At(size_t idx) const
  912. {
  913. const Vec4 vec4 = controlPointVec4At(idx);
  914. return Vec2(vec4.x(), vec4.y());
  915. }
  916. tinyspline::Vec3
  917. tinyspline::BSpline::controlPointVec3At(size_t idx) const
  918. {
  919. const Vec4 vec4 = controlPointVec4At(idx);
  920. return Vec3(vec4.x(), vec4.y(), vec4.z());
  921. }
  922. tinyspline::Vec4
  923. tinyspline::BSpline::controlPointVec4At(size_t idx) const
  924. {
  925. const real *ctrlp;
  926. tsStatus status;
  927. if (ts_bspline_control_point_at_ptr(&spline,
  928. idx,
  929. &ctrlp,
  930. &status))
  931. throw std::runtime_error(status.message);
  932. real vals[4];
  933. ts_vec4_set(vals, ctrlp, dimension());
  934. return Vec4(vals[0], vals[1], vals[2], vals[3]);
  935. }
  936. std::vector<tinyspline::real>
  937. tinyspline::BSpline::knots() const
  938. {
  939. const real *knots = ts_bspline_knots_ptr(&spline);
  940. size_t num = ts_bspline_num_knots(&spline);
  941. return std::vector<real>(knots, knots + num);
  942. }
  943. tinyspline::real tinyspline::BSpline::knotAt(size_t index) const
  944. {
  945. real knot;
  946. tsStatus status;
  947. if (ts_bspline_knot_at(&spline, index, &knot, &status))
  948. throw std::runtime_error(status.message);
  949. return knot;
  950. }
  951. size_t tinyspline::BSpline::numControlPoints() const
  952. {
  953. return ts_bspline_num_control_points(&spline);
  954. }
  955. tinyspline::DeBoorNet tinyspline::BSpline::eval(tinyspline::real u) const
  956. {
  957. tsDeBoorNet net = ts_deboornet_init();
  958. tsStatus status;
  959. if (ts_bspline_eval(&spline, u, &net, &status))
  960. throw std::runtime_error(status.message);
  961. return tinyspline::DeBoorNet(net);
  962. }
  963. tinyspline::std_real_vector_out
  964. tinyspline::BSpline::evalAll(std_real_vector_in knots) const
  965. {
  966. const size_t num_knots = std_real_vector_read(knots)size();
  967. const real *knots_ptr = std_real_vector_read(knots)data();
  968. tinyspline::real *points;
  969. tsStatus status;
  970. if (ts_bspline_eval_all(&spline,
  971. knots_ptr,
  972. num_knots,
  973. &points,
  974. &status)) {
  975. throw std::runtime_error(status.message);
  976. }
  977. real *first = points;
  978. real *last = first + num_knots * dimension();
  979. std_real_vector_init(vec)(first, last);
  980. std::free(points);
  981. return vec;
  982. }
  983. tinyspline::std_real_vector_out
  984. tinyspline::BSpline::sample(size_t num) const
  985. {
  986. tinyspline::real *points;
  987. size_t actualNum;
  988. tsStatus status;
  989. if (ts_bspline_sample(&spline,
  990. num,
  991. &points,
  992. &actualNum,
  993. &status)) {
  994. throw std::runtime_error(status.message);
  995. }
  996. real *first = points;
  997. real *last = first + actualNum * dimension();
  998. std_real_vector_init(vec)(first, last);
  999. std::free(points);
  1000. return vec;
  1001. }
  1002. tinyspline::DeBoorNet tinyspline::BSpline::bisect(real value,
  1003. real epsilon,
  1004. bool persnickety,
  1005. size_t index,
  1006. bool ascending,
  1007. size_t maxIter) const
  1008. {
  1009. tsDeBoorNet net = ts_deboornet_init();
  1010. tsStatus status;
  1011. if (ts_bspline_bisect(&spline,
  1012. value,
  1013. epsilon,
  1014. persnickety,
  1015. index,
  1016. ascending,
  1017. maxIter,
  1018. &net,
  1019. &status))
  1020. throw std::runtime_error(status.message);
  1021. return DeBoorNet(net);
  1022. }
  1023. tinyspline::Domain tinyspline::BSpline::domain() const
  1024. {
  1025. real min, max;
  1026. ts_bspline_domain(&spline, &min, &max);
  1027. return Domain(min, max);
  1028. }
  1029. bool tinyspline::BSpline::isClosed(tinyspline::real epsilon) const
  1030. {
  1031. int closed = 0;
  1032. tsStatus status;
  1033. if (ts_bspline_is_closed(&spline, epsilon, &closed, &status))
  1034. throw std::runtime_error(status.message);
  1035. return closed == 1;
  1036. }
  1037. tinyspline::FrameSeq
  1038. tinyspline::BSpline::computeRMF(std_real_vector_in knots,
  1039. tinyspline::Vec3 *firstNormal) const
  1040. {
  1041. tsStatus status;
  1042. size_t num = std_real_vector_read(knots)size();
  1043. const real *knots_ptr = std_real_vector_read(knots)data();
  1044. tsFrame *frames = new tsFrame[num];
  1045. if (firstNormal && num > 0) {
  1046. ts_vec3_init(frames[0].normal,
  1047. firstNormal->x(),
  1048. firstNormal->y(),
  1049. firstNormal->z());
  1050. }
  1051. if (ts_bspline_compute_rmf(&spline,
  1052. knots_ptr,
  1053. num,
  1054. firstNormal != nullptr,
  1055. frames,
  1056. &status))
  1057. throw std::runtime_error(status.message);
  1058. FrameSeq seq = FrameSeq(frames, num);
  1059. return seq;
  1060. }
  1061. tinyspline::BSpline
  1062. tinyspline::BSpline::subSpline(real knot0, real knot1) const
  1063. {
  1064. tsBSpline data = ts_bspline_init();
  1065. tsStatus status;
  1066. if (ts_bspline_sub_spline(&spline,
  1067. knot0,
  1068. knot1,
  1069. &data,
  1070. &status))
  1071. throw std::runtime_error(status.message);
  1072. return BSpline(data);
  1073. }
  1074. tinyspline::std_real_vector_out
  1075. tinyspline::BSpline::uniformKnotSeq(size_t num) const
  1076. {
  1077. std_real_vector_init(knots)(num);
  1078. real *knots_ptr = std_real_vector_read(knots)data();
  1079. ts_bspline_uniform_knot_seq(&spline, num, knots_ptr);
  1080. return knots;
  1081. }
  1082. tinyspline::std_real_vector_out
  1083. tinyspline::BSpline::equidistantKnotSeq(size_t num,
  1084. size_t numSamples) const
  1085. {
  1086. tsStatus status;
  1087. std_real_vector_init(knots)(num);
  1088. real *knots_ptr = std_real_vector_read(knots)data();
  1089. if (ts_bspline_equidistant_knot_seq(&spline,
  1090. num,
  1091. knots_ptr,
  1092. numSamples,
  1093. &status))
  1094. throw std::runtime_error(status.message);
  1095. return knots;
  1096. }
  1097. tinyspline::ChordLengths
  1098. tinyspline::BSpline::chordLengths(std_real_vector_in knots) const
  1099. {
  1100. tsStatus status;
  1101. size_t num = std_real_vector_read(knots)size();
  1102. real *knotsArr = new real[num];
  1103. real *lengths = new real[num];
  1104. std::copy(std_real_vector_read(knots)begin(),
  1105. std_real_vector_read(knots)end(),
  1106. knotsArr);
  1107. if (ts_bspline_chord_lengths(&spline,
  1108. knotsArr,
  1109. num,
  1110. lengths,
  1111. &status))
  1112. throw std::runtime_error(status.message);
  1113. return ChordLengths(*this, knotsArr, lengths, num);
  1114. }
  1115. tinyspline::ChordLengths
  1116. tinyspline::BSpline::chordLengths(size_t numSamples) const
  1117. {
  1118. return chordLengths(uniformKnotSeq(numSamples));
  1119. }
  1120. std::string tinyspline::BSpline::toJson() const
  1121. {
  1122. char *json;
  1123. tsStatus status;
  1124. if (ts_bspline_to_json(&spline, &json, &status))
  1125. throw std::runtime_error(status.message);
  1126. std::string string(json);
  1127. std::free(json);
  1128. return string;
  1129. }
  1130. void tinyspline::BSpline::save(std::string path) const
  1131. {
  1132. tsStatus status;
  1133. if (ts_bspline_save(&spline, path.c_str(), &status))
  1134. throw std::runtime_error(status.message);
  1135. }
  1136. void tinyspline::BSpline::setControlPoints(
  1137. const std::vector<tinyspline::real> &ctrlp)
  1138. {
  1139. size_t expected = ts_bspline_len_control_points(&spline);
  1140. size_t actual = ctrlp.size();
  1141. if (expected != actual) {
  1142. std::ostringstream oss;
  1143. oss << "Expected size: " << expected
  1144. << ", Actual size: " << actual;
  1145. throw std::runtime_error(oss.str());
  1146. }
  1147. tsStatus status;
  1148. if (ts_bspline_set_control_points(&spline, ctrlp.data(), &status))
  1149. throw std::runtime_error(status.message);
  1150. }
  1151. void
  1152. tinyspline::BSpline::setControlPointVec2At(size_t idx, Vec2 &cp)
  1153. {
  1154. Vec4 vec4(cp.x(), cp.y(), (real) 0.0, (real) 0.0);
  1155. setControlPointVec4At(idx, vec4);
  1156. }
  1157. void
  1158. tinyspline::BSpline::setControlPointVec3At(size_t idx, Vec3 &cp)
  1159. {
  1160. Vec4 vec4(cp.x(), cp.y(), cp.z(), (real) 0.0);
  1161. setControlPointVec4At(idx, vec4);
  1162. }
  1163. void
  1164. tinyspline::BSpline::setControlPointVec4At(size_t idx, Vec4 &cp)
  1165. {
  1166. std::vector<real> vals(dimension());
  1167. for (size_t i = 0; i < vals.size(); i++)
  1168. vals[i] = (real) 0.0;
  1169. if (vals.size() >= 4) vals[3] = cp.w();
  1170. if (vals.size() >= 3) vals[2] = cp.z();
  1171. if (vals.size() >= 2) vals[1] = cp.y();
  1172. if (vals.size() >= 1) vals[0] = cp.x();
  1173. tsStatus status;
  1174. if (ts_bspline_set_control_point_at(&spline,
  1175. idx,
  1176. vals.data(),
  1177. &status))
  1178. throw std::runtime_error(status.message);
  1179. }
  1180. void
  1181. tinyspline::BSpline::setKnots(const std::vector<real> &knots)
  1182. {
  1183. size_t expected = ts_bspline_num_knots(&spline);
  1184. size_t actual = knots.size();
  1185. if (expected != actual) {
  1186. std::ostringstream oss;
  1187. oss << "Expected size: " << expected
  1188. << ", Actual size: " << actual;
  1189. throw std::runtime_error(oss.str());
  1190. }
  1191. tsStatus status;
  1192. if (ts_bspline_set_knots(&spline,
  1193. knots.data(),
  1194. &status))
  1195. throw std::runtime_error(status.message);
  1196. }
  1197. void tinyspline::BSpline::setKnotAt(size_t index, tinyspline::real knot)
  1198. {
  1199. tsStatus status;
  1200. if (ts_bspline_set_knot_at(&spline, index, knot, &status))
  1201. throw std::runtime_error(status.message);
  1202. }
  1203. tinyspline::BSpline tinyspline::BSpline::insertKnot(tinyspline::real u,
  1204. size_t n) const
  1205. {
  1206. tsBSpline data = ts_bspline_init();
  1207. size_t k;
  1208. tsStatus status;
  1209. if (ts_bspline_insert_knot(&spline, u, n, &data, &k, &status))
  1210. throw std::runtime_error(status.message);
  1211. return BSpline(data);
  1212. }
  1213. tinyspline::BSpline tinyspline::BSpline::split(tinyspline::real u) const
  1214. {
  1215. tsBSpline data = ts_bspline_init();
  1216. size_t k;
  1217. tsStatus status;
  1218. if (ts_bspline_split(&spline, u, &data, &k, &status))
  1219. throw std::runtime_error(status.message);
  1220. return BSpline(data);
  1221. }
  1222. tinyspline::BSpline tinyspline::BSpline::tension(
  1223. tinyspline::real tension) const
  1224. {
  1225. tsBSpline data = ts_bspline_init();
  1226. tsStatus status;
  1227. if (ts_bspline_tension(&spline, tension, &data, &status))
  1228. throw std::runtime_error(status.message);
  1229. return BSpline(data);
  1230. }
  1231. tinyspline::BSpline tinyspline::BSpline::toBeziers() const
  1232. {
  1233. tsBSpline data = ts_bspline_init();
  1234. tsStatus status;
  1235. if (ts_bspline_to_beziers(&spline, &data, &status))
  1236. throw std::runtime_error(status.message);
  1237. return BSpline(data);
  1238. }
  1239. tinyspline::BSpline tinyspline::BSpline::derive(size_t n, real epsilon) const
  1240. {
  1241. tsBSpline data = ts_bspline_init();
  1242. tsStatus status;
  1243. if (ts_bspline_derive(&spline, n, epsilon, &data, &status))
  1244. throw std::runtime_error(status.message);
  1245. return BSpline(data);
  1246. }
  1247. tinyspline::BSpline tinyspline::BSpline::elevateDegree(
  1248. size_t amount, real epsilon) const
  1249. {
  1250. tsBSpline data = ts_bspline_init();
  1251. tsStatus status;
  1252. if (ts_bspline_elevate_degree(&spline, amount, epsilon,
  1253. &data, &status)) {
  1254. throw std::runtime_error(status.message);
  1255. }
  1256. return BSpline(data);
  1257. }
  1258. tinyspline::BSpline tinyspline::BSpline::alignWith(
  1259. const BSpline &other, BSpline &otherAligned, real epsilon) const
  1260. {
  1261. tsBSpline data = ts_bspline_init();
  1262. tsBSpline deleteIf_Other_And_OtherAligned_AreDifferent =
  1263. otherAligned.spline;
  1264. tsStatus status;
  1265. if (ts_bspline_align(&spline, &other.spline, epsilon, &data,
  1266. &otherAligned.spline, &status)) {
  1267. throw std::runtime_error(status.message);
  1268. }
  1269. if (&other != &otherAligned)
  1270. ts_bspline_free(&deleteIf_Other_And_OtherAligned_AreDifferent);
  1271. return BSpline(data);
  1272. }
  1273. tinyspline::Morphism tinyspline::BSpline::morphTo(
  1274. const BSpline &other, real epsilon) const
  1275. {
  1276. return Morphism(*this, other, epsilon);
  1277. }
  1278. std::string tinyspline::BSpline::toString() const
  1279. {
  1280. Domain d = domain();
  1281. std::ostringstream oss;
  1282. oss << "BSpline{"
  1283. << "dimension: " << dimension()
  1284. << ", degree: " << degree()
  1285. << ", domain: [" << d.min() << ", " << d.max() << "]"
  1286. << ", control points: " << numControlPoints()
  1287. << ", knots: " << ts_bspline_num_knots(&spline)
  1288. << "}";
  1289. return oss.str();
  1290. }
  1291. /*! @name Morphism
  1292. *
  1293. * @{
  1294. */
  1295. tinyspline::Morphism::Morphism(const BSpline &origin,
  1296. const BSpline &target,
  1297. real epsilon)
  1298. : m_origin(origin), m_target(target), m_epsilon(epsilon)
  1299. {
  1300. m_originAligned = origin.alignWith(target, m_targetAligned, epsilon);
  1301. // Make buffer compatible by copying one of the aligned splines.
  1302. m_buffer = m_originAligned;
  1303. }
  1304. tinyspline::BSpline
  1305. tinyspline::Morphism::eval(real t)
  1306. {
  1307. tsStatus status;
  1308. if (t <= 0) return m_origin;
  1309. if (t >= 1) return m_target;
  1310. if (ts_bspline_morph(&m_originAligned.spline,
  1311. &m_targetAligned.spline,
  1312. t, m_epsilon,
  1313. &m_buffer.spline, &status)) {
  1314. throw std::runtime_error(status.message);
  1315. }
  1316. return m_buffer;
  1317. }
  1318. tinyspline::BSpline
  1319. tinyspline::Morphism::origin() const
  1320. {
  1321. return m_origin;
  1322. }
  1323. tinyspline::BSpline
  1324. tinyspline::Morphism::target() const
  1325. {
  1326. return m_target;
  1327. }
  1328. tinyspline::real
  1329. tinyspline::Morphism::epsilon() const
  1330. {
  1331. return m_epsilon;
  1332. }
  1333. tinyspline::BSpline
  1334. tinyspline::Morphism::operator()(real t)
  1335. {
  1336. return eval(t);
  1337. }
  1338. std::string tinyspline::Morphism::toString() const
  1339. {
  1340. std::ostringstream oss;
  1341. oss << "Morphism{"
  1342. << "buffer: " << m_buffer.toString()
  1343. << ", epsilon: " << epsilon()
  1344. << "}";
  1345. return oss.str();
  1346. }
  1347. /*! @} */
  1348. /*! @name ChordLenghts
  1349. * @{
  1350. */
  1351. tinyspline::ChordLengths::ChordLengths()
  1352. : m_spline(),
  1353. m_knots(nullptr),
  1354. m_chordLengths(nullptr),
  1355. m_size(0)
  1356. {}
  1357. tinyspline::ChordLengths::ChordLengths(const BSpline &spline,
  1358. real *knots,
  1359. real *chordLengths,
  1360. size_t size)
  1361. : m_spline(spline),
  1362. m_knots(knots),
  1363. m_chordLengths(chordLengths),
  1364. m_size(size)
  1365. {}
  1366. tinyspline::ChordLengths::ChordLengths(const ChordLengths &other)
  1367. : m_spline(other.m_spline),
  1368. m_knots(nullptr),
  1369. m_chordLengths(nullptr),
  1370. m_size(other.m_size)
  1371. {
  1372. m_knots = new real[m_size];
  1373. std::copy(other.m_knots,
  1374. other.m_knots + m_size,
  1375. m_knots);
  1376. m_chordLengths = new real[m_size];
  1377. std::copy(other.m_chordLengths,
  1378. other.m_chordLengths + m_size,
  1379. m_chordLengths);
  1380. }
  1381. tinyspline::ChordLengths::ChordLengths(ChordLengths &&other)
  1382. : m_spline(),
  1383. m_knots(nullptr),
  1384. m_chordLengths(nullptr),
  1385. m_size(0)
  1386. {
  1387. *this = std::move(other);
  1388. }
  1389. tinyspline::ChordLengths::~ChordLengths()
  1390. {
  1391. delete [] m_knots;
  1392. delete [] m_chordLengths;
  1393. m_size = 0;
  1394. }
  1395. tinyspline::ChordLengths &
  1396. tinyspline::ChordLengths::operator=(const ChordLengths &other)
  1397. {
  1398. if (&other != this) {
  1399. real *knots = new real[other.m_size];
  1400. std::copy(other.m_knots,
  1401. other.m_knots + other.m_size,
  1402. knots);
  1403. real *chordLengths = new real[other.m_size];
  1404. std::copy(other.m_chordLengths,
  1405. other.m_chordLengths + other.m_size,
  1406. chordLengths);
  1407. delete [] m_knots;
  1408. delete [] m_chordLengths;
  1409. m_spline = other.m_spline;
  1410. m_knots = knots;
  1411. m_chordLengths = chordLengths;
  1412. m_size = other.m_size;
  1413. }
  1414. return *this;
  1415. }
  1416. tinyspline::ChordLengths &
  1417. tinyspline::ChordLengths::operator=(ChordLengths &&other)
  1418. {
  1419. if (&other != this) {
  1420. delete [] m_knots;
  1421. delete [] m_chordLengths;
  1422. m_spline = other.m_spline;
  1423. m_knots = other.m_knots;
  1424. m_chordLengths = other.m_chordLengths;
  1425. m_size = other.m_size;
  1426. other.m_spline = BSpline();
  1427. other.m_knots = nullptr;
  1428. other.m_chordLengths = nullptr;
  1429. other.m_size = 0;
  1430. }
  1431. return *this;
  1432. }
  1433. tinyspline::BSpline
  1434. tinyspline::ChordLengths::spline() const
  1435. {
  1436. return m_spline;
  1437. }
  1438. std::vector<tinyspline::real>
  1439. tinyspline::ChordLengths::knots() const
  1440. {
  1441. return std::vector<real>(m_knots,
  1442. m_knots + m_size);
  1443. }
  1444. std::vector<tinyspline::real>
  1445. tinyspline::ChordLengths::values() const
  1446. {
  1447. return std::vector<real>(m_chordLengths,
  1448. m_chordLengths + m_size);
  1449. }
  1450. size_t
  1451. tinyspline::ChordLengths::size() const
  1452. {
  1453. return m_size;
  1454. }
  1455. tinyspline::real
  1456. tinyspline::ChordLengths::arcLength() const
  1457. {
  1458. return m_size == 0 ? 0 : m_chordLengths[m_size - 1];
  1459. }
  1460. tinyspline::real
  1461. tinyspline::ChordLengths::lengthToKnot(real len) const
  1462. {
  1463. tsStatus status;
  1464. real knot;
  1465. if (ts_chord_lengths_length_to_knot(m_knots,
  1466. m_chordLengths,
  1467. m_size,
  1468. len,
  1469. &knot,
  1470. &status))
  1471. throw std::runtime_error(status.message);
  1472. return knot;
  1473. }
  1474. tinyspline::real
  1475. tinyspline::ChordLengths::tToKnot(real t) const
  1476. {
  1477. tsStatus status;
  1478. real knot;
  1479. if (ts_chord_lengths_t_to_knot(m_knots,
  1480. m_chordLengths,
  1481. m_size,
  1482. t,
  1483. &knot,
  1484. &status))
  1485. throw std::runtime_error(status.message);
  1486. return knot;
  1487. }
  1488. std::string
  1489. tinyspline::ChordLengths::toString() const
  1490. {
  1491. std::ostringstream oss;
  1492. oss << "ChordLengths{"
  1493. << "spline: " << m_spline.toString()
  1494. << ", values: " << m_size
  1495. << "}";
  1496. return oss.str();
  1497. }
  1498. /*! @} */
  1499. #ifdef _MSC_VER
  1500. #pragma warning(pop)
  1501. #endif