|
|
#define TINYSPLINE_EXPORT
#include "tinysplinecxx.h"
#include <stdlib.h>
#include <cstring>
#include <stdexcept>
#include <cstdio>
#include <sstream>
/* Suppress some useless MSVC warnings. */#ifdef _MSC_VER
#pragma warning(push)
/* address of dllimport */#pragma warning(disable:4232)
/* binding rvalues to non-const references */#pragma warning(disable:4350)
/* unreferenced inline function */#pragma warning(disable:4514)
/* function not inlined */#pragma warning(disable:4710)
/* byte padding */#pragma warning(disable:4820)
/* meaningless deprecation */#pragma warning(disable:4996)
/* Spectre mitigation */#pragma warning(disable:5045)
#endif
/*! @name Swig Type Mapping
* * See tinysplinecxx.h for more details. * * @{ */#ifdef SWIG
#define std_real_vector_init(var) \
std_real_vector_out var = new std::vector<tinyspline::real>#define std_real_vector_read(var) var->
#else
#define std_real_vector_init(var) \
std_real_vector_out var#define std_real_vector_read(var) var.
#endif
/*! @} */
/*! @name Vec2
* * @{ */tinyspline::Vec2::Vec2(){ const real v = (real) 0.0; ts_vec2_init(m_vals, v, v);}
tinyspline::Vec2::Vec2(real x, real y){ ts_vec2_init(m_vals, x, y);}
tinyspline::Vec2tinyspline::Vec2::operator+(const Vec2 &other){ return add(other);}
tinyspline::Vec2tinyspline::Vec2::operator-(const Vec2 &other){ return subtract(other);}
tinyspline::Vec2tinyspline::Vec2::operator*(real scalar){ return multiply(scalar);}
tinyspline::realtinyspline::Vec2::x() const{ return m_vals[0];}
voidtinyspline::Vec2::setX(real val){ m_vals[0] = val;}
tinyspline::realtinyspline::Vec2::y() const{ return m_vals[1];}
voidtinyspline::Vec2::setY(real val){ m_vals[1] = val;}
std::vector<tinyspline::real>tinyspline::Vec2::values() const{ return std::vector<real>({ x(), y() });}
tinyspline::Vec2tinyspline::Vec2::add(const Vec2 &other) const{ Vec2 vec; ts_vec_add(m_vals, other.m_vals, 2, vec.m_vals); return vec;}
tinyspline::Vec2tinyspline::Vec2::subtract(const Vec2 &other) const{ Vec2 vec; ts_vec_sub(m_vals, other.m_vals, 2, vec.m_vals); return vec;}
tinyspline::Vec2tinyspline::Vec2::multiply(real scalar) const{ Vec2 vec; ts_vec_mul(m_vals, 2, scalar, vec.m_vals); return vec;}
tinyspline::Vec2tinyspline::Vec2::normalize() const{ Vec2 vec; ts_vec_norm(m_vals, 2, vec.m_vals); return vec;}
tinyspline::Vec2tinyspline::Vec2::norm() const{ return normalize();}
tinyspline::realtinyspline::Vec2::magnitude() const{ return ts_vec_mag(m_vals, 2);}
tinyspline::realtinyspline::Vec2::dot(const Vec2 &other) const{ return ts_vec_dot(m_vals, other.m_vals, 2);}
tinyspline::realtinyspline::Vec2::angle(const Vec2 &other) const{ real buf[4]; return ts_vec_angle(m_vals, other.m_vals, buf, 2);}
tinyspline::realtinyspline::Vec2::distance(const Vec2 &other) const{ return ts_distance(m_vals, other.m_vals, 2);}
std::stringtinyspline::Vec2::toString() const{ std::ostringstream oss; oss << "Vec2{" << "x: " << x() << ", y: " << y() << "}"; return oss.str();}/*! @} */
/*! @name Vec3
* * @{ */tinyspline::Vec3::Vec3(){ const real v = (real) 0.0; ts_vec3_init(m_vals, v, v, v);}
tinyspline::Vec3::Vec3(real x, real y, real z){ ts_vec3_init(m_vals, x, y, z);}
tinyspline::Vec3tinyspline::Vec3::operator+(const Vec3 &other){ return add(other);}
tinyspline::Vec3tinyspline::Vec3::operator-(const Vec3 &other){ return subtract(other);}
tinyspline::Vec3tinyspline::Vec3::operator*(real scalar){ return multiply(scalar);}
tinyspline::realtinyspline::Vec3::x() const{ return m_vals[0];}
voidtinyspline::Vec3::setX(real val){ m_vals[0] = val;}
tinyspline::realtinyspline::Vec3::y() const{ return m_vals[1];}
voidtinyspline::Vec3::setY(real val){ m_vals[1] = val;}
tinyspline::realtinyspline::Vec3::z() const{ return m_vals[2];}
voidtinyspline::Vec3::setZ(real val){ m_vals[2] = val;}
std::vector<tinyspline::real>tinyspline::Vec3::values() const{ return std::vector<real>({ x(), y(), z() });}
tinyspline::Vec3tinyspline::Vec3::add(const Vec3 &other) const{ Vec3 vec; ts_vec_add(m_vals, other.m_vals, 3, vec.m_vals); return vec;}
tinyspline::Vec3tinyspline::Vec3::subtract(const Vec3 &other) const{ Vec3 vec; ts_vec_sub(m_vals, other.m_vals, 3, vec.m_vals); return vec;}
tinyspline::Vec3tinyspline::Vec3::multiply(real scalar) const{ Vec3 vec; ts_vec_mul(m_vals, 3, scalar, vec.m_vals); return vec;}
tinyspline::Vec3tinyspline::Vec3::cross(const Vec3 &other) const{ Vec3 vec; ts_vec3_cross(m_vals, other.m_vals, vec.m_vals); return vec;}
tinyspline::Vec3tinyspline::Vec3::normalize() const{ Vec3 vec; ts_vec_norm(m_vals, 3, vec.m_vals); return vec;}
tinyspline::Vec3tinyspline::Vec3::norm() const{ return normalize();}
tinyspline::realtinyspline::Vec3::magnitude() const{ return ts_vec_mag(m_vals, 3);}
tinyspline::realtinyspline::Vec3::dot(const Vec3 &other) const{ return ts_vec_dot(m_vals, other.m_vals, 3);}
tinyspline::realtinyspline::Vec3::angle(const Vec3 &other) const{ real buf[6]; return ts_vec_angle(m_vals, other.m_vals, buf, 3);}
tinyspline::realtinyspline::Vec3::distance(const Vec3 &other) const{ return ts_distance(m_vals, other.m_vals, 3);}
std::stringtinyspline::Vec3::toString() const{ std::ostringstream oss; oss << "Vec3{" << "x: " << x() << ", y: " << y() << ", z: " << z() << "}"; return oss.str();}/*! @} */
/*! @name Vec4
* * @{ */tinyspline::Vec4::Vec4(){ const real v = (real) 0.0; ts_vec4_init(m_vals, v, v, v, v);}
tinyspline::Vec4::Vec4(real x, real y, real z, real w){ ts_vec4_init(m_vals, x, y, z, w);}
tinyspline::Vec4tinyspline::Vec4::operator+(const Vec4 &other){ return add(other);}
tinyspline::Vec4tinyspline::Vec4::operator-(const Vec4 &other){ return subtract(other);}
tinyspline::Vec4tinyspline::Vec4::operator*(real scalar){ return multiply(scalar);}
tinyspline::realtinyspline::Vec4::x() const{ return m_vals[0];}
voidtinyspline::Vec4::setX(real val){ m_vals[0] = val;}
tinyspline::realtinyspline::Vec4::y() const{ return m_vals[1];}
voidtinyspline::Vec4::setY(real val){ m_vals[1] = val;}
tinyspline::realtinyspline::Vec4::z() const{ return m_vals[2];}
voidtinyspline::Vec4::setZ(real val){ m_vals[2] = val;}
tinyspline::realtinyspline::Vec4::w() const{ return m_vals[3];}
voidtinyspline::Vec4::setW(real val){ m_vals[3] = val;}
std::vector<tinyspline::real>tinyspline::Vec4::values() const{ return std::vector<real>({ x(), y(), z(), w() });}
tinyspline::Vec4tinyspline::Vec4::add(const Vec4 &other) const{ Vec4 vec; ts_vec_add(m_vals, other.m_vals, 4, vec.m_vals); return vec;}
tinyspline::Vec4tinyspline::Vec4::subtract(const Vec4 &other) const{ Vec4 vec; ts_vec_sub(m_vals, other.m_vals, 4, vec.m_vals); return vec;}
tinyspline::Vec4tinyspline::Vec4::multiply(real scalar) const{ Vec4 vec; ts_vec_mul(m_vals, 4, scalar, vec.m_vals); return vec;}
tinyspline::Vec4tinyspline::Vec4::normalize() const{ Vec4 vec; ts_vec_norm(m_vals, 4, vec.m_vals); return vec;}
tinyspline::Vec4tinyspline::Vec4::norm() const{ return normalize();}
tinyspline::realtinyspline::Vec4::magnitude() const{ return ts_vec_mag(m_vals, 4);}
tinyspline::realtinyspline::Vec4::dot(const Vec4 &other) const{ return ts_vec_dot(m_vals, other.m_vals, 4);}
tinyspline::realtinyspline::Vec4::angle(const Vec4 &other) const{ real buf[8]; return ts_vec_angle(m_vals, other.m_vals, buf, 4);}
tinyspline::realtinyspline::Vec4::distance(const Vec4 &other) const{ return ts_distance(m_vals, other.m_vals, 4);}
std::stringtinyspline::Vec4::toString() const{ std::ostringstream oss; oss << "Vec4{" << "x: " << x() << ", y: " << y() << ", z: " << z() << ", w: " << w() << "}"; return oss.str();}/*! @} */
/*! @name Frame
* * @{ */tinyspline::Frame::Frame(Vec3 &position, Vec3 &tangent, Vec3 &normal, Vec3 &binormal): m_position(position), m_tangent(tangent), m_normal(normal), m_binormal(binormal){}
tinyspline::Vec3tinyspline::Frame::position() const{ return m_position;}
tinyspline::Vec3tinyspline::Frame::tangent() const{ return m_tangent;}
tinyspline::Vec3tinyspline::Frame::normal() const{ return m_normal;}
tinyspline::Vec3tinyspline::Frame::binormal() const{ return m_binormal;}
std::stringtinyspline::Frame::toString() const{ std::ostringstream oss; oss << "Frame{" << "position: " << position().toString() << ", tangent: " << tangent().toString() << ", normal: " << normal().toString() << ", binormal: " << binormal().toString() << "}"; return oss.str();}/*! @} */
/*! @name FrameSeq
* * @{ */tinyspline::FrameSeq::FrameSeq(): m_frames(nullptr), m_size(0){}
tinyspline::FrameSeq::FrameSeq(tsFrame *frames, size_t len): m_frames(frames), m_size(len){}
tinyspline::FrameSeq::FrameSeq(const FrameSeq &other): m_frames(nullptr), m_size(other.m_size){ m_frames = new tsFrame[m_size]; std::copy(other.m_frames, other.m_frames + m_size, m_frames);}
tinyspline::FrameSeq::FrameSeq(FrameSeq &&other): m_frames(nullptr), m_size(other.m_size){ m_frames = other.m_frames; other.m_frames = nullptr; other.m_size = 0;}
tinyspline::FrameSeq::~FrameSeq(){ delete [] m_frames; m_size = 0;}
tinyspline::FrameSeq &tinyspline::FrameSeq::operator=(const FrameSeq &other){ if (&other != this) { tsFrame *data = new tsFrame[other.m_size]; std::copy(other.m_frames, other.m_frames + other.m_size, data); delete [] m_frames; m_frames = data; m_size = other.m_size; } return *this;}
tinyspline::FrameSeq &tinyspline::FrameSeq::operator=(FrameSeq &&other){ if (&other != this) { delete [] m_frames; m_frames = other.m_frames; m_size = other.m_size; other.m_frames = nullptr; other.m_size = 0; } return *this;}
size_ttinyspline::FrameSeq::size() const{ return m_size;}
tinyspline::Frametinyspline::FrameSeq::at(size_t idx) const{ if (idx >= m_size) throw std::out_of_range( "idx >= size"); tsFrame frame = m_frames[idx]; Vec3 position = Vec3(frame.position[0], frame.position[1], frame.position[2]); Vec3 tangent = Vec3(frame.tangent[0], frame.tangent[1], frame.tangent[2]); Vec3 normal = Vec3(frame.normal[0], frame.normal[1], frame.normal[2]); Vec3 binormal = Vec3(frame.binormal[0], frame.binormal[1], frame.binormal[2]); return Frame(position, tangent, normal, binormal);}
std::stringtinyspline::FrameSeq::toString() const{ std::ostringstream oss; oss << "FrameSeq{" << "frames: " << size() << "}"; return oss.str();}/*! @} */
/*! @name Domain
* * @{ */tinyspline::Domain::Domain(real min, real max): m_min(min), m_max(max){}
tinyspline::realtinyspline::Domain::min() const{ return m_min;}
tinyspline::realtinyspline::Domain::max() const{ return m_max;}
std::stringtinyspline::Domain::toString() const{ std::ostringstream oss; oss << "Domain{" << "min: " << min() << ", max: " << max() << "}"; return oss.str();}/*! @} */
/*! @name DeBoorNet
* * @{ */tinyspline::DeBoorNet::DeBoorNet(tsDeBoorNet &data): net(ts_deboornet_init()){ ts_deboornet_move(&data, &net);}
tinyspline::DeBoorNet::DeBoorNet(const DeBoorNet &other): net(ts_deboornet_init()){ tsStatus status; if (ts_deboornet_copy(&other.net, &net, &status)) throw std::runtime_error(status.message);}
tinyspline::DeBoorNet::DeBoorNet(DeBoorNet &&other): net(ts_deboornet_init()){ ts_deboornet_move(&other.net, &net);}
tinyspline::DeBoorNet::~DeBoorNet(){ ts_deboornet_free(&net);}
tinyspline::DeBoorNet &tinyspline::DeBoorNet::operator=(const DeBoorNet &other){ if (&other != this) { tsDeBoorNet data = ts_deboornet_init(); tsStatus status; if (ts_deboornet_copy(&other.net, &data, &status)) throw std::runtime_error(status.message); ts_deboornet_free(&net); ts_deboornet_move(&data, &net); } return *this;}
tinyspline::DeBoorNet &tinyspline::DeBoorNet::operator=(DeBoorNet && other){ if (&other != this) { ts_deboornet_free(&net); ts_deboornet_move(&other.net, &net); } return *this;}
tinyspline::realtinyspline::DeBoorNet::knot() const{ return ts_deboornet_knot(&net);}
size_ttinyspline::DeBoorNet::index() const{ return ts_deboornet_index(&net);}
size_ttinyspline::DeBoorNet::multiplicity() const{ return ts_deboornet_multiplicity(&net);}
size_ttinyspline::DeBoorNet::numInsertions() const{ return ts_deboornet_num_insertions(&net);}
size_ttinyspline::DeBoorNet::dimension() const{ return ts_deboornet_dimension(&net);}
std::vector<tinyspline::real>tinyspline::DeBoorNet::points() const{ const real *points = ts_deboornet_points_ptr(&net); size_t len = ts_deboornet_len_points(&net); return std::vector<real>(points, points + len);}
std::vector<tinyspline::real>tinyspline::DeBoorNet::result() const{ const real *result = ts_deboornet_result_ptr(&net); size_t len = ts_deboornet_len_result(&net); return std::vector<real>(result, result + len);}
tinyspline::Vec2tinyspline::DeBoorNet::resultVec2(size_t idx) const{ Vec4 vec4 = resultVec4(idx); return Vec2(vec4.x(), vec4.y());}
tinyspline::Vec3tinyspline::DeBoorNet::resultVec3(size_t idx) const{ Vec4 vec4 = resultVec4(idx); return Vec3(vec4.x(), vec4.y(), vec4.z());}
tinyspline::Vec4tinyspline::DeBoorNet::resultVec4(size_t idx) const{ if (idx >= ts_deboornet_num_result(&net)) throw std::out_of_range( "idx >= num(result)"); const real *result = ts_deboornet_result_ptr(&net); real vals[4]; ts_vec4_set(vals, result + idx * dimension(), dimension()); return Vec4(vals[0], vals[1], vals[2], vals[3]);}
std::stringtinyspline::DeBoorNet::toString() const{ std::ostringstream oss; oss << "DeBoorNet{" << "knot: " << knot() << ", index: " << index() << ", multiplicity: " << multiplicity() << ", insertions: " << numInsertions() << ", dimension: " << dimension() << ", points: " << ts_deboornet_num_points(&net) << "}"; return oss.str();}/*! @} */
/******************************************************************************
* ** BSpline ** *******************************************************************************/tinyspline::BSpline::BSpline(tsBSpline &data): spline(ts_bspline_init()){ ts_bspline_move(&data, &spline);}
tinyspline::BSpline::BSpline(): spline(ts_bspline_init()){ tsStatus status; if (ts_bspline_new_with_control_points(1, 3, 0, TS_CLAMPED, &spline, &status, 0.0, 0.0, 0.0)) throw std::runtime_error(status.message);}
tinyspline::BSpline::BSpline(const tinyspline::BSpline &other): spline(ts_bspline_init()){ tsStatus status; if (ts_bspline_copy(&other.spline, &spline, &status)) throw std::runtime_error(status.message);}
tinyspline::BSpline::BSpline(BSpline &&other): spline(ts_bspline_init()){ ts_bspline_move(&other.spline, &spline);}
tinyspline::BSpline::BSpline(size_t numControlPoints, size_t dimension, size_t degree, Type type): spline(ts_bspline_init()){ tsBSplineType c_type = TS_CLAMPED; switch (type) { case Opened: c_type = TS_OPENED; break; case Clamped: c_type = TS_CLAMPED; break; case Beziers: c_type = TS_BEZIERS; break; default: throw std::runtime_error("unknown type"); } tsStatus status; if (ts_bspline_new(numControlPoints, dimension, degree, c_type, &spline, &status)) throw std::runtime_error(status.message);}
tinyspline::BSpline::~BSpline(){ ts_bspline_free(&spline);}
tinyspline::BSpline tinyspline::BSpline::interpolateCubicNatural( std_real_vector_in points, size_t dimension){ if (dimension == 0) throw std::runtime_error("unsupported dimension: 0"); if (std_real_vector_read(points)size() % dimension != 0) throw std::runtime_error("#points % dimension != 0"); tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_interpolate_cubic_natural( std_real_vector_read(points)data(), std_real_vector_read(points)size()/dimension, dimension, &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSplinetinyspline::BSpline::interpolateCatmullRom(std_real_vector_in points, size_t dimension, real alpha, std::vector<real> *first, std::vector<real> *last, real epsilon){ if (dimension == 0) throw std::runtime_error("unsupported dimension: 0"); if (std_real_vector_read(points)size() % dimension != 0) throw std::runtime_error("#points % dimension != 0"); real *fst = nullptr; if (first && first->size() >= dimension) fst = first->data(); real *lst = nullptr; if (last && last->size() >= dimension) lst = last->data(); tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_interpolate_catmull_rom( std_real_vector_read(points)data(), std_real_vector_read(points)size()/dimension, dimension, alpha, fst, lst, epsilon, &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::parseJson(std::string json){ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_parse_json(json.c_str(), &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::load(std::string path){ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_load(path.c_str(), &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
booltinyspline::BSpline::knotsEqual(real x, real y){ return ts_knots_equal(x, y);}
tinyspline::BSpline &tinyspline::BSpline::operator=(const BSpline &other){ if (&other != this) { tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_copy(&other.spline, &data, &status)) throw std::runtime_error(status.message); ts_bspline_free(&spline); ts_bspline_move(&data, &spline); } return *this;}
tinyspline::BSpline &tinyspline::BSpline::operator=(BSpline &&other){ if (&other != this) { ts_bspline_free(&spline); ts_bspline_move(&other.spline, &spline); } return *this;}
tinyspline::DeBoorNet tinyspline::BSpline::operator()(tinyspline::real u) const{ return eval(u);}
size_t tinyspline::BSpline::degree() const{ return ts_bspline_degree(&spline);}
size_t tinyspline::BSpline::order() const{ return ts_bspline_order(&spline);}
size_t tinyspline::BSpline::dimension() const{ return ts_bspline_dimension(&spline);}
std::vector<tinyspline::real>tinyspline::BSpline::controlPoints() const{ const real *ctrlps = ts_bspline_control_points_ptr(&spline); const size_t len = ts_bspline_len_control_points(&spline); return std::vector<real>(ctrlps, ctrlps + len);}
tinyspline::Vec2tinyspline::BSpline::controlPointVec2At(size_t idx) const{ const Vec4 vec4 = controlPointVec4At(idx); return Vec2(vec4.x(), vec4.y());}
tinyspline::Vec3tinyspline::BSpline::controlPointVec3At(size_t idx) const{ const Vec4 vec4 = controlPointVec4At(idx); return Vec3(vec4.x(), vec4.y(), vec4.z());}
tinyspline::Vec4tinyspline::BSpline::controlPointVec4At(size_t idx) const{ const real *ctrlp; tsStatus status; if (ts_bspline_control_point_at_ptr(&spline, idx, &ctrlp, &status)) throw std::runtime_error(status.message); real vals[4]; ts_vec4_set(vals, ctrlp, dimension()); return Vec4(vals[0], vals[1], vals[2], vals[3]);}
std::vector<tinyspline::real>tinyspline::BSpline::knots() const{ const real *knots = ts_bspline_knots_ptr(&spline); size_t num = ts_bspline_num_knots(&spline); return std::vector<real>(knots, knots + num);}
tinyspline::real tinyspline::BSpline::knotAt(size_t index) const{ real knot; tsStatus status; if (ts_bspline_knot_at(&spline, index, &knot, &status)) throw std::runtime_error(status.message); return knot;}
size_t tinyspline::BSpline::numControlPoints() const{ return ts_bspline_num_control_points(&spline);}
tinyspline::DeBoorNet tinyspline::BSpline::eval(tinyspline::real u) const{ tsDeBoorNet net = ts_deboornet_init(); tsStatus status; if (ts_bspline_eval(&spline, u, &net, &status)) throw std::runtime_error(status.message); return tinyspline::DeBoorNet(net);}
tinyspline::std_real_vector_outtinyspline::BSpline::evalAll(std_real_vector_in knots) const{ const size_t num_knots = std_real_vector_read(knots)size(); const real *knots_ptr = std_real_vector_read(knots)data(); tinyspline::real *points; tsStatus status; if (ts_bspline_eval_all(&spline, knots_ptr, num_knots, &points, &status)) { throw std::runtime_error(status.message); } real *first = points; real *last = first + num_knots * dimension(); std_real_vector_init(vec)(first, last); std::free(points); return vec;}
tinyspline::std_real_vector_outtinyspline::BSpline::sample(size_t num) const{ tinyspline::real *points; size_t actualNum; tsStatus status; if (ts_bspline_sample(&spline, num, &points, &actualNum, &status)) { throw std::runtime_error(status.message); } real *first = points; real *last = first + actualNum * dimension(); std_real_vector_init(vec)(first, last); std::free(points); return vec;}
tinyspline::DeBoorNet tinyspline::BSpline::bisect(real value, real epsilon, bool persnickety, size_t index, bool ascending, size_t maxIter) const{ tsDeBoorNet net = ts_deboornet_init(); tsStatus status; if (ts_bspline_bisect(&spline, value, epsilon, persnickety, index, ascending, maxIter, &net, &status)) throw std::runtime_error(status.message); return DeBoorNet(net);}
tinyspline::Domain tinyspline::BSpline::domain() const{ real min, max; ts_bspline_domain(&spline, &min, &max); return Domain(min, max);}
bool tinyspline::BSpline::isClosed(tinyspline::real epsilon) const{ int closed = 0; tsStatus status; if (ts_bspline_is_closed(&spline, epsilon, &closed, &status)) throw std::runtime_error(status.message); return closed == 1;}
tinyspline::FrameSeqtinyspline::BSpline::computeRMF(std_real_vector_in knots, tinyspline::Vec3 *firstNormal) const{ tsStatus status; size_t num = std_real_vector_read(knots)size(); const real *knots_ptr = std_real_vector_read(knots)data(); tsFrame *frames = new tsFrame[num]; if (firstNormal && num > 0) { ts_vec3_init(frames[0].normal, firstNormal->x(), firstNormal->y(), firstNormal->z()); } if (ts_bspline_compute_rmf(&spline, knots_ptr, num, firstNormal != nullptr, frames, &status)) throw std::runtime_error(status.message); FrameSeq seq = FrameSeq(frames, num); return seq;}
tinyspline::BSplinetinyspline::BSpline::subSpline(real knot0, real knot1) const{ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_sub_spline(&spline, knot0, knot1, &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::std_real_vector_outtinyspline::BSpline::uniformKnotSeq(size_t num) const{ std_real_vector_init(knots)(num); real *knots_ptr = std_real_vector_read(knots)data(); ts_bspline_uniform_knot_seq(&spline, num, knots_ptr); return knots;}
tinyspline::std_real_vector_outtinyspline::BSpline::equidistantKnotSeq(size_t num, size_t numSamples) const{ tsStatus status; std_real_vector_init(knots)(num); real *knots_ptr = std_real_vector_read(knots)data(); if (ts_bspline_equidistant_knot_seq(&spline, num, knots_ptr, numSamples, &status)) throw std::runtime_error(status.message); return knots;}
tinyspline::ChordLengthstinyspline::BSpline::chordLengths(std_real_vector_in knots) const{ tsStatus status; size_t num = std_real_vector_read(knots)size(); real *knotsArr = new real[num]; real *lengths = new real[num]; std::copy(std_real_vector_read(knots)begin(), std_real_vector_read(knots)end(), knotsArr); if (ts_bspline_chord_lengths(&spline, knotsArr, num, lengths, &status)) throw std::runtime_error(status.message); return ChordLengths(*this, knotsArr, lengths, num);}
tinyspline::ChordLengthstinyspline::BSpline::chordLengths(size_t numSamples) const{ return chordLengths(uniformKnotSeq(numSamples));}
std::string tinyspline::BSpline::toJson() const{ char *json; tsStatus status; if (ts_bspline_to_json(&spline, &json, &status)) throw std::runtime_error(status.message); std::string string(json); std::free(json); return string;}
void tinyspline::BSpline::save(std::string path) const{ tsStatus status; if (ts_bspline_save(&spline, path.c_str(), &status)) throw std::runtime_error(status.message);}
void tinyspline::BSpline::setControlPoints( const std::vector<tinyspline::real> &ctrlp){ size_t expected = ts_bspline_len_control_points(&spline); size_t actual = ctrlp.size(); if (expected != actual) { std::ostringstream oss; oss << "Expected size: " << expected << ", Actual size: " << actual; throw std::runtime_error(oss.str()); } tsStatus status; if (ts_bspline_set_control_points(&spline, ctrlp.data(), &status)) throw std::runtime_error(status.message);}
voidtinyspline::BSpline::setControlPointVec2At(size_t idx, Vec2 &cp){ Vec4 vec4(cp.x(), cp.y(), (real) 0.0, (real) 0.0); setControlPointVec4At(idx, vec4);}
voidtinyspline::BSpline::setControlPointVec3At(size_t idx, Vec3 &cp){ Vec4 vec4(cp.x(), cp.y(), cp.z(), (real) 0.0); setControlPointVec4At(idx, vec4);}
voidtinyspline::BSpline::setControlPointVec4At(size_t idx, Vec4 &cp){ std::vector<real> vals(dimension()); for (size_t i = 0; i < vals.size(); i++) vals[i] = (real) 0.0; if (vals.size() >= 4) vals[3] = cp.w(); if (vals.size() >= 3) vals[2] = cp.z(); if (vals.size() >= 2) vals[1] = cp.y(); if (vals.size() >= 1) vals[0] = cp.x(); tsStatus status; if (ts_bspline_set_control_point_at(&spline, idx, vals.data(), &status)) throw std::runtime_error(status.message);}
voidtinyspline::BSpline::setKnots(const std::vector<real> &knots){ size_t expected = ts_bspline_num_knots(&spline); size_t actual = knots.size(); if (expected != actual) { std::ostringstream oss; oss << "Expected size: " << expected << ", Actual size: " << actual; throw std::runtime_error(oss.str()); } tsStatus status; if (ts_bspline_set_knots(&spline, knots.data(), &status)) throw std::runtime_error(status.message);}
void tinyspline::BSpline::setKnotAt(size_t index, tinyspline::real knot){ tsStatus status; if (ts_bspline_set_knot_at(&spline, index, knot, &status)) throw std::runtime_error(status.message);}
tinyspline::BSpline tinyspline::BSpline::insertKnot(tinyspline::real u, size_t n) const{ tsBSpline data = ts_bspline_init(); size_t k; tsStatus status; if (ts_bspline_insert_knot(&spline, u, n, &data, &k, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::split(tinyspline::real u) const{ tsBSpline data = ts_bspline_init(); size_t k; tsStatus status; if (ts_bspline_split(&spline, u, &data, &k, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::tension( tinyspline::real tension) const{ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_tension(&spline, tension, &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::toBeziers() const{ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_to_beziers(&spline, &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::derive(size_t n, real epsilon) const{ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_derive(&spline, n, epsilon, &data, &status)) throw std::runtime_error(status.message); return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::elevateDegree( size_t amount, real epsilon) const{ tsBSpline data = ts_bspline_init(); tsStatus status; if (ts_bspline_elevate_degree(&spline, amount, epsilon, &data, &status)) { throw std::runtime_error(status.message); } return BSpline(data);}
tinyspline::BSpline tinyspline::BSpline::alignWith( const BSpline &other, BSpline &otherAligned, real epsilon) const{ tsBSpline data = ts_bspline_init(); tsBSpline deleteIf_Other_And_OtherAligned_AreDifferent = otherAligned.spline; tsStatus status; if (ts_bspline_align(&spline, &other.spline, epsilon, &data, &otherAligned.spline, &status)) { throw std::runtime_error(status.message); } if (&other != &otherAligned) ts_bspline_free(&deleteIf_Other_And_OtherAligned_AreDifferent); return BSpline(data);}
tinyspline::Morphism tinyspline::BSpline::morphTo( const BSpline &other, real epsilon) const{ return Morphism(*this, other, epsilon);}
std::string tinyspline::BSpline::toString() const{ Domain d = domain(); std::ostringstream oss; oss << "BSpline{" << "dimension: " << dimension() << ", degree: " << degree() << ", domain: [" << d.min() << ", " << d.max() << "]" << ", control points: " << numControlPoints() << ", knots: " << ts_bspline_num_knots(&spline) << "}"; return oss.str();}
/*! @name Morphism
* * @{ */tinyspline::Morphism::Morphism(const BSpline &origin, const BSpline &target, real epsilon): m_origin(origin), m_target(target), m_epsilon(epsilon){ m_originAligned = origin.alignWith(target, m_targetAligned, epsilon); // Make buffer compatible by copying one of the aligned splines.
m_buffer = m_originAligned;}
tinyspline::BSplinetinyspline::Morphism::eval(real t){ tsStatus status; if (t <= 0) return m_origin; if (t >= 1) return m_target; if (ts_bspline_morph(&m_originAligned.spline, &m_targetAligned.spline, t, m_epsilon, &m_buffer.spline, &status)) { throw std::runtime_error(status.message); } return m_buffer;}
tinyspline::BSplinetinyspline::Morphism::origin() const{ return m_origin;}
tinyspline::BSplinetinyspline::Morphism::target() const{ return m_target;}
tinyspline::realtinyspline::Morphism::epsilon() const{ return m_epsilon;}
tinyspline::BSplinetinyspline::Morphism::operator()(real t){ return eval(t);}
std::string tinyspline::Morphism::toString() const{ std::ostringstream oss; oss << "Morphism{" << "buffer: " << m_buffer.toString() << ", epsilon: " << epsilon() << "}"; return oss.str();}/*! @} */
/*! @name ChordLenghts
* @{ */tinyspline::ChordLengths::ChordLengths(): m_spline(), m_knots(nullptr), m_chordLengths(nullptr), m_size(0){}
tinyspline::ChordLengths::ChordLengths(const BSpline &spline, real *knots, real *chordLengths, size_t size): m_spline(spline), m_knots(knots), m_chordLengths(chordLengths), m_size(size){}
tinyspline::ChordLengths::ChordLengths(const ChordLengths &other): m_spline(other.m_spline), m_knots(nullptr), m_chordLengths(nullptr), m_size(other.m_size){ m_knots = new real[m_size]; std::copy(other.m_knots, other.m_knots + m_size, m_knots); m_chordLengths = new real[m_size]; std::copy(other.m_chordLengths, other.m_chordLengths + m_size, m_chordLengths);}
tinyspline::ChordLengths::ChordLengths(ChordLengths &&other): m_spline(), m_knots(nullptr), m_chordLengths(nullptr), m_size(0){ *this = std::move(other);}
tinyspline::ChordLengths::~ChordLengths(){ delete [] m_knots; delete [] m_chordLengths; m_size = 0;}
tinyspline::ChordLengths &tinyspline::ChordLengths::operator=(const ChordLengths &other){ if (&other != this) { real *knots = new real[other.m_size]; std::copy(other.m_knots, other.m_knots + other.m_size, knots); real *chordLengths = new real[other.m_size]; std::copy(other.m_chordLengths, other.m_chordLengths + other.m_size, chordLengths); delete [] m_knots; delete [] m_chordLengths; m_spline = other.m_spline; m_knots = knots; m_chordLengths = chordLengths; m_size = other.m_size; } return *this;}
tinyspline::ChordLengths &tinyspline::ChordLengths::operator=(ChordLengths &&other){ if (&other != this) { delete [] m_knots; delete [] m_chordLengths; m_spline = other.m_spline; m_knots = other.m_knots; m_chordLengths = other.m_chordLengths; m_size = other.m_size; other.m_spline = BSpline(); other.m_knots = nullptr; other.m_chordLengths = nullptr; other.m_size = 0; } return *this;}
tinyspline::BSplinetinyspline::ChordLengths::spline() const{ return m_spline;}
std::vector<tinyspline::real>tinyspline::ChordLengths::knots() const{ return std::vector<real>(m_knots, m_knots + m_size);}
std::vector<tinyspline::real>tinyspline::ChordLengths::values() const{ return std::vector<real>(m_chordLengths, m_chordLengths + m_size);}
size_ttinyspline::ChordLengths::size() const{ return m_size;}
tinyspline::realtinyspline::ChordLengths::arcLength() const{ return m_size == 0 ? 0 : m_chordLengths[m_size - 1];}
tinyspline::realtinyspline::ChordLengths::lengthToKnot(real len) const{ tsStatus status; real knot; if (ts_chord_lengths_length_to_knot(m_knots, m_chordLengths, m_size, len, &knot, &status)) throw std::runtime_error(status.message); return knot;}
tinyspline::realtinyspline::ChordLengths::tToKnot(real t) const{ tsStatus status; real knot; if (ts_chord_lengths_t_to_knot(m_knots, m_chordLengths, m_size, t, &knot, &status)) throw std::runtime_error(status.message); return knot;}
std::stringtinyspline::ChordLengths::toString() const{ std::ostringstream oss; oss << "ChordLengths{" << "spline: " << m_spline.toString() << ", values: " << m_size << "}"; return oss.str();}/*! @} */
#ifdef _MSC_VER
#pragma warning(pop)
#endif
|