Update tinysplice to latest

A few years worth of bug fixes
This commit is contained in:
Marek Roszko 2022-12-06 22:28:09 -05:00
parent 61119fbf64
commit 24ca892afb
11 changed files with 11207 additions and 2563 deletions

View File

@ -1316,7 +1316,7 @@ void DXF_IMPORT_PLUGIN::insertArc( const VECTOR2D& aSegStart, const VECTOR2D& aS
} }
#include "tinysplinecpp.h" #include "tinysplinecxx.h"
void DXF_IMPORT_PLUGIN::insertSpline( double aWidth ) void DXF_IMPORT_PLUGIN::insertSpline( double aWidth )
{ {
@ -1367,11 +1367,11 @@ void DXF_IMPORT_PLUGIN::insertSpline( double aWidth )
tinyspline::BSpline dxfspline( m_curr_entity.m_SplineControlPointList.size(), tinyspline::BSpline dxfspline( m_curr_entity.m_SplineControlPointList.size(),
/* coord dim */ 2, m_curr_entity.m_SplineDegree ); /* coord dim */ 2, m_curr_entity.m_SplineDegree );
dxfspline.setCtrlp( ctrlp ); dxfspline.setControlPoints( ctrlp );
dxfspline.setKnots( m_curr_entity.m_SplineKnotsList ); dxfspline.setKnots( m_curr_entity.m_SplineKnotsList );
tinyspline::BSpline beziers( dxfspline.toBeziers() ); tinyspline::BSpline beziers( dxfspline.toBeziers() );
coords = beziers.ctrlp(); coords = beziers.controlPoints();
} }
catch( const std::runtime_error& ) //tinyspline throws everything including data validation as runtime errors catch( const std::runtime_error& ) //tinyspline throws everything including data validation as runtime errors
{ {

View File

@ -1,6 +1,7 @@
set(TINYSPLINE_LIB_SRCS set(TINYSPLINE_LIB_SRCS
tinyspline.c tinyspline.c
tinysplinecpp.cpp tinysplinecxx.cxx
parson.c
) )
add_library(tinyspline_lib STATIC ${TINYSPLINE_LIB_SRCS}) add_library(tinyspline_lib STATIC ${TINYSPLINE_LIB_SRCS})

View File

@ -1,3 +1,7 @@
MIT License
Copyright (c) 2016 Marcel Steinbeck
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
@ -14,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.

2079
thirdparty/tinyspline_lib/parson.c vendored Normal file

File diff suppressed because it is too large Load Diff

234
thirdparty/tinyspline_lib/parson.h vendored Normal file
View File

@ -0,0 +1,234 @@
/*
Parson ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2017 Krzysztof Gabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef parson_parson_h
#define parson_parson_h
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h> /* size_t */
/* Types and enums */
typedef struct json_object_t JSON_Object;
typedef struct json_array_t JSON_Array;
typedef struct json_value_t JSON_Value;
enum json_value_type {
JSONError = -1,
JSONNull = 1,
JSONString = 2,
JSONNumber = 3,
JSONObject = 4,
JSONArray = 5,
JSONBoolean = 6
};
typedef int JSON_Value_Type;
enum json_result_t {
JSONSuccess = 0,
JSONFailure = -1
};
typedef int JSON_Status;
typedef void * (*JSON_Malloc_Function)(size_t);
typedef void (*JSON_Free_Function)(void *);
/* Call only once, before calling any other function from parson API. If not called, malloc and free
from stdlib will be used for all allocations */
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
/* Parses first JSON value in a file, returns NULL in case of error */
JSON_Value * json_parse_file(const char *filename);
/* Parses first JSON value in a file and ignores comments (/ * * / and //),
returns NULL in case of error */
JSON_Value * json_parse_file_with_comments(const char *filename);
/* Parses first JSON value in a string, returns NULL in case of error */
JSON_Value * json_parse_string(const char *string);
/* Parses first JSON value in a string and ignores comments (/ * * / and //),
returns NULL in case of error */
JSON_Value * json_parse_string_with_comments(const char *string);
/* Serialization */
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
char * json_serialize_to_string(const JSON_Value *value);
/* Pretty serialization */
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
char * json_serialize_to_string_pretty(const JSON_Value *value);
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
/* Comparing */
int json_value_equals(const JSON_Value *a, const JSON_Value *b);
/* Validation
This is *NOT* JSON Schema. It validates json by checking if object have identically
named fields with matching types.
For example schema {"name":"", "age":0} will validate
{"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
In case of arrays, only first value in schema is checked against all values in tested array.
Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
null validates values of every type.
*/
JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
/*
* JSON Object
*/
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
const char * json_object_get_string (const JSON_Object *object, const char *name);
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* dotget functions enable addressing values with dot notation in nested objects,
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
Because valid names in JSON can contain dots, some values may be inaccessible
this way. */
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
const char * json_object_dotget_string (const JSON_Object *object, const char *name);
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* Functions to get available names */
size_t json_object_get_count (const JSON_Object *object);
const char * json_object_get_name (const JSON_Object *object, size_t index);
JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index);
JSON_Value * json_object_get_wrapping_value(const JSON_Object *object);
/* Functions to check if object has a value with a specific name. Returned value is 1 if object has
* a value and 0 if it doesn't. dothas functions behave exactly like dotget functions. */
int json_object_has_value (const JSON_Object *object, const char *name);
int json_object_has_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
int json_object_dothas_value (const JSON_Object *object, const char *name);
int json_object_dothas_value_of_type(const JSON_Object *object, const char *name, JSON_Value_Type type);
/* Creates new name-value pair or frees and replaces old value with a new one.
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
/* Works like dotget functions, but creates whole hierarchy if necessary.
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
/* Frees and removes name-value pair */
JSON_Status json_object_remove(JSON_Object *object, const char *name);
/* Works like dotget function, but removes name-value pair only on exact match. */
JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
/* Removes all name-value pairs in object */
JSON_Status json_object_clear(JSON_Object *object);
/*
*JSON Array
*/
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
const char * json_array_get_string (const JSON_Array *array, size_t index);
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
size_t json_array_get_count (const JSON_Array *array);
JSON_Value * json_array_get_wrapping_value(const JSON_Array *array);
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
* Order of values in array may change during execution. */
JSON_Status json_array_remove(JSON_Array *array, size_t i);
/* Frees and removes from array value at given index and replaces it with given one.
* Does nothing and returns JSONFailure if index doesn't exist.
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
/* Frees and removes all values from array */
JSON_Status json_array_clear(JSON_Array *array);
/* Appends new value at the end of array.
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
JSON_Status json_array_append_number(JSON_Array *array, double number);
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
JSON_Status json_array_append_null(JSON_Array *array);
/*
*JSON Value
*/
JSON_Value * json_value_init_object (void);
JSON_Value * json_value_init_array (void);
JSON_Value * json_value_init_string (const char *string); /* copies passed string */
JSON_Value * json_value_init_number (double number);
JSON_Value * json_value_init_boolean(int boolean);
JSON_Value * json_value_init_null (void);
JSON_Value * json_value_deep_copy (const JSON_Value *value);
void json_value_free (JSON_Value *value);
JSON_Value_Type json_value_get_type (const JSON_Value *value);
JSON_Object * json_value_get_object (const JSON_Value *value);
JSON_Array * json_value_get_array (const JSON_Value *value);
const char * json_value_get_string (const JSON_Value *value);
double json_value_get_number (const JSON_Value *value);
int json_value_get_boolean(const JSON_Value *value);
JSON_Value * json_value_get_parent (const JSON_Value *value);
/* Same as above, but shorter */
JSON_Value_Type json_type (const JSON_Value *value);
JSON_Object * json_object (const JSON_Value *value);
JSON_Array * json_array (const JSON_Value *value);
const char * json_string (const JSON_Value *value);
double json_number (const JSON_Value *value);
int json_boolean(const JSON_Value *value);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,493 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 Marcel Steinbeck
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "tinysplinecpp.h"
#include <stdexcept>
/********************************************************
* *
* DeBoorNet *
* *
********************************************************/
tinyspline::DeBoorNet::DeBoorNet()
{
ts_deboornet_default( &deBoorNet );
}
tinyspline::DeBoorNet::DeBoorNet( const tinyspline::DeBoorNet& other )
{
const tsError err = ts_deboornet_copy( &other.deBoorNet, &deBoorNet );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
tinyspline::DeBoorNet::~DeBoorNet()
{
ts_deboornet_free( &deBoorNet );
}
tinyspline::DeBoorNet& tinyspline::DeBoorNet::operator=( const tinyspline::DeBoorNet& other )
{
if( &other != this )
{
const tsError err = ts_deboornet_copy(
&other.deBoorNet, &deBoorNet );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
return *this;
}
tinyspline::real tinyspline::DeBoorNet::u() const
{
return deBoorNet.u;
}
size_t tinyspline::DeBoorNet::k() const
{
return deBoorNet.k;
}
size_t tinyspline::DeBoorNet::s() const
{
return deBoorNet.s;
}
size_t tinyspline::DeBoorNet::h() const
{
return deBoorNet.h;
}
size_t tinyspline::DeBoorNet::dim() const
{
return deBoorNet.dim;
}
size_t tinyspline::DeBoorNet::nPoints() const
{
return deBoorNet.n_points;
}
std::vector<tinyspline::real> tinyspline::DeBoorNet::points() const
{
const tinyspline::real* begin = deBoorNet.points;
const tinyspline::real* end = begin + deBoorNet.n_points * deBoorNet.dim;
return std::vector<tinyspline::real>( begin, end );
}
std::vector<tinyspline::real> tinyspline::DeBoorNet::result() const
{
const tinyspline::real* begin = deBoorNet.result;
const tinyspline::real* end = begin + deBoorNet.dim;
return std::vector<tinyspline::real>( begin, end );
}
tsDeBoorNet* tinyspline::DeBoorNet::data()
{
return &deBoorNet;
}
#ifndef TINYSPLINE_DISABLE_CXX11_FEATURES
tinyspline::DeBoorNet::DeBoorNet( tinyspline::DeBoorNet&& other ) noexcept
{
ts_deboornet_default( &deBoorNet );
swap( other );
}
tinyspline::DeBoorNet& tinyspline::DeBoorNet::operator=( tinyspline::DeBoorNet&& other ) noexcept
{
if( &other != this )
{
ts_deboornet_free( &deBoorNet );
swap( other );
}
return *this;
}
void tinyspline::DeBoorNet::swap( tinyspline::DeBoorNet& other )
{
if( &other != this )
{
std::swap( deBoorNet.u, other.deBoorNet.u );
std::swap( deBoorNet.k, other.deBoorNet.k );
std::swap( deBoorNet.s, other.deBoorNet.s );
std::swap( deBoorNet.h, other.deBoorNet.h );
std::swap( deBoorNet.dim, other.deBoorNet.dim );
std::swap( deBoorNet.n_points, other.deBoorNet.n_points );
std::swap( deBoorNet.points, other.deBoorNet.points );
std::swap( deBoorNet.result, other.deBoorNet.result );
}
}
#endif
/********************************************************
* *
* BSpline *
* *
********************************************************/
tinyspline::BSpline::BSpline()
{
ts_bspline_default( &bspline );
}
tinyspline::BSpline::BSpline( const tinyspline::BSpline& other )
{
const tsError err = ts_bspline_copy( &other.bspline, &bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
tinyspline::BSpline::BSpline( const size_t nCtrlp, const size_t dim,
const size_t deg, const tinyspline::BSpline::type type )
{
const tsError err = ts_bspline_new( nCtrlp, dim, deg, type, &bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
tinyspline::BSpline::~BSpline()
{
ts_bspline_free( &bspline );
}
tinyspline::BSpline& tinyspline::BSpline::operator=( const tinyspline::BSpline& other )
{
if( &other != this )
{
const tsError err = ts_bspline_copy( &other.bspline, &bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
return *this;
}
tinyspline::DeBoorNet tinyspline::BSpline::operator()( const tinyspline::real u ) const
{
return evaluate( u );
}
size_t tinyspline::BSpline::deg() const
{
return bspline.deg;
}
size_t tinyspline::BSpline::order() const
{
return bspline.order;
}
size_t tinyspline::BSpline::dim() const
{
return bspline.dim;
}
size_t tinyspline::BSpline::nCtrlp() const
{
return bspline.n_ctrlp;
}
size_t tinyspline::BSpline::nKnots() const
{
return bspline.n_knots;
}
std::vector<tinyspline::real> tinyspline::BSpline::ctrlp() const
{
const tinyspline::real* begin = bspline.ctrlp;
const tinyspline::real* end = begin + bspline.n_ctrlp * bspline.dim;
return std::vector<tinyspline::real>( begin, end );
}
std::vector<tinyspline::real> tinyspline::BSpline::knots() const
{
const tinyspline::real* begin = bspline.knots;
const tinyspline::real* end = begin + bspline.n_knots;
return std::vector<tinyspline::real>( begin, end );
}
tsBSpline* tinyspline::BSpline::data()
{
return &bspline;
}
tinyspline::DeBoorNet tinyspline::BSpline::evaluate( const tinyspline::real u ) const
{
tinyspline::DeBoorNet deBoorNet;
const tsError err = ts_bspline_evaluate( &bspline, u, deBoorNet.data() );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return deBoorNet;
}
void tinyspline::BSpline::setCtrlp( const std::vector<tinyspline::real>& ctrlp )
{
if( ctrlp.size() != nCtrlp() * dim() )
{
throw std::runtime_error( "The number of values must be equals"
"to the spline's number of control points multiplied"
"by the dimension of each control point." );
}
const tsError err = ts_bspline_set_ctrlp(
&bspline, ctrlp.data(), &bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
void tinyspline::BSpline::setKnots( const std::vector<tinyspline::real>& knots )
{
if( knots.size() != nKnots() )
{
throw std::runtime_error( "The number of values must be equals"
"to the spline's number of knots." );
}
const tsError err = ts_bspline_set_knots(
&bspline, knots.data(), &bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
}
tinyspline::BSpline tinyspline::BSpline::fillKnots( const tsBSplineType type,
const tinyspline::real min,
const tinyspline::real max ) const
{
tinyspline::BSpline bs;
const tsError err = ts_bspline_fill_knots(
&bspline, type, min, max, &bs.bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
tinyspline::BSpline tinyspline::BSpline::insertKnot( const tinyspline::real u,
const size_t n ) const
{
tinyspline::BSpline bs;
size_t k;
const tsError err = ts_bspline_insert_knot(
&bspline, u, n, &bs.bspline, &k );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
tinyspline::BSpline tinyspline::BSpline::resize( const int n, const int back ) const
{
tinyspline::BSpline bs;
const tsError err = ts_bspline_resize( &bspline, n, back, &bs.bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
tinyspline::BSpline tinyspline::BSpline::split( const tinyspline::real u ) const
{
tinyspline::BSpline bs;
size_t k;
const tsError err = ts_bspline_split( &bspline, u, &bs.bspline, &k );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
tinyspline::BSpline tinyspline::BSpline::buckle( const tinyspline::real b ) const
{
tinyspline::BSpline bs;
const tsError err = ts_bspline_buckle( &bspline, b, &bs.bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
tinyspline::BSpline tinyspline::BSpline::toBeziers() const
{
tinyspline::BSpline bs;
const tsError err = ts_bspline_to_beziers( &bspline, &bs.bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
tinyspline::BSpline tinyspline::BSpline::derive() const
{
tinyspline::BSpline bs;
const tsError err = ts_bspline_derive( &bspline, &bs.bspline );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bs;
}
#ifndef TINYSPLINE_DISABLE_CXX11_FEATURES
tinyspline::BSpline::BSpline( tinyspline::BSpline&& other ) noexcept
{
ts_bspline_default( &bspline );
swap( other );
}
tinyspline::BSpline& tinyspline::BSpline::operator=( tinyspline::BSpline&& other ) noexcept
{
if( &other != this )
{
ts_bspline_free( &bspline );
swap( other );
}
return *this;
}
void tinyspline::BSpline::swap( tinyspline::BSpline& other )
{
if( &other != this )
{
std::swap( bspline.deg, other.bspline.deg );
std::swap( bspline.order, other.bspline.order );
std::swap( bspline.dim, other.bspline.dim );
std::swap( bspline.n_ctrlp, other.bspline.n_ctrlp );
std::swap( bspline.n_knots, other.bspline.n_knots );
std::swap( bspline.ctrlp, other.bspline.ctrlp );
std::swap( bspline.knots, other.bspline.knots );
}
}
#endif
/********************************************************
* *
* Utils *
* *
********************************************************/
tinyspline::BSpline tinyspline::Utils::interpolateCubic(
const std::vector<tinyspline::real>* points,
const size_t dim )
{
if( dim == 0 )
throw std::runtime_error( ts_enum_str( TS_DIM_ZERO ) );
if( points->size() % dim != 0 )
throw std::runtime_error( "#points % dim == 0 failed" );
tinyspline::BSpline bspline;
const tsError err = ts_bspline_interpolate_cubic(
points->data(), points->size() / dim, dim, bspline.data() );
if( err < 0 )
throw std::runtime_error( ts_enum_str( err ) );
return bspline;
}
bool tinyspline::Utils::fequals( const tinyspline::real x, const tinyspline::real y )
{
return ts_fequals( x, y ) == 1;
}
std::string tinyspline::Utils::enum_str( const tsError err )
{
return std::string( ts_enum_str( err ) );
}
tsError tinyspline::Utils::str_enum( const std::string str )
{
return ts_str_enum( str.c_str() );
}

View File

@ -1,143 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 Marcel Steinbeck
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "tinyspline.h"
#include <vector>
#include <string>
namespace tinyspline {
typedef tsReal real;
class DeBoorNet
{
public:
/* Constructors & Destructors */
DeBoorNet();
DeBoorNet( const DeBoorNet& other );
~DeBoorNet();
/* Operators */
DeBoorNet& operator=( const DeBoorNet& other );
/* Getter */
real u() const;
size_t k() const;
size_t s() const;
size_t h() const;
size_t dim() const;
size_t nPoints() const;
std::vector<real> points() const;
std::vector<real> result() const;
tsDeBoorNet* data();
/* C++11 features */
#ifndef TINYSPLINE_DISABLE_CXX11_FEATURES
DeBoorNet( DeBoorNet&& other ) noexcept;
DeBoorNet& operator=( DeBoorNet&& other ) noexcept;
void swap( DeBoorNet& other );
friend void swap( DeBoorNet& left, DeBoorNet& right )
{
left.swap( right );
}
#endif
private:
tsDeBoorNet deBoorNet;
};
class BSpline
{
public:
typedef tsBSplineType type;
/* Constructors & Destructors */
BSpline();
BSpline( const BSpline& other );
explicit BSpline( size_t nCtrlp, size_t dim = 2, size_t deg = 3,
tinyspline::BSpline::type type = TS_CLAMPED );
~BSpline();
/* Operators */
BSpline& operator=( const BSpline& other );
DeBoorNet operator()( real u ) const;
/* Getter */
size_t deg() const;
size_t order() const;
size_t dim() const;
size_t nCtrlp() const;
size_t nKnots() const;
std::vector<real> ctrlp() const;
std::vector<real> knots() const;
tsBSpline* data();
DeBoorNet evaluate( real u ) const;
/* Modifications */
void setCtrlp( const std::vector<real>& ctrlp );
void setKnots( const std::vector<real>& knots );
/* Transformations */
BSpline fillKnots( tsBSplineType type, real min, real max ) const;
BSpline insertKnot( real u, size_t n ) const;
BSpline resize( int n, int back ) const;
BSpline split( real u ) const;
BSpline buckle( real b ) const;
BSpline toBeziers() const;
BSpline derive() const;
/* C++11 features */
#ifndef TINYSPLINE_DISABLE_CXX11_FEATURES
BSpline( BSpline&& other ) noexcept;
BSpline& operator=( BSpline&& other ) noexcept;
void swap( BSpline& other );
friend void swap( BSpline& left, BSpline& right )
{
left.swap( right );
}
#endif
private:
tsBSpline bspline;
};
class Utils
{
public:
static BSpline interpolateCubic( const std::vector<real>* points, size_t dim );
static bool fequals( real x, real y );
static std::string enum_str( tsError err );
static tsError str_enum( std::string str );
private:
Utils() {}
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,960 @@
/** @file */
#pragma once
#include "tinyspline.h"
#include <vector>
#include <string>
#ifndef TINYSPLINECXX_API
#define TINYSPLINECXX_API TINYSPLINE_API
#endif
/*! @name Emscripten Extensions
*
* Please see the following references for more details on how to use
* Emscripten with C++:
*
* https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html
* https://emscripten.org/docs/api_reference/bind.h.html
*
* @{
*/
#ifdef TINYSPLINE_EMSCRIPTEN
// Additional includes and namespaces.
#include <stdexcept>
#include <emscripten/bind.h>
using namespace emscripten;
/* Used by value_objects to guard read-only properties. */
void inline
cannotWrite()
{ throw std::runtime_error("cannot write read-only property"); }
/* Allow clients to read exception messages in the Javascript binding. */
std::string
exceptionMessage(int ptr)
{ return std::string(reinterpret_cast<std::exception *>(ptr)->what()); }
// Map: std::vector <--> JS array
// https://github.com/emscripten-core/emscripten/issues/11070#issuecomment-717675128
namespace emscripten {
namespace internal {
template <typename T, typename Allocator>
struct BindingType<std::vector<T, Allocator>> {
using ValBinding = BindingType<val>;
using WireType = ValBinding::WireType;
static WireType
toWireType(const std::vector<T, Allocator> &vec)
{ return ValBinding::toWireType(val::array(vec)); }
static std::vector<T, Allocator>
fromWireType(WireType value)
{ return vecFromJSArray<T>(ValBinding::fromWireType(value)); }
};
template <typename T>
struct TypeID<T, // this is ridiculous...
typename std::enable_if_t<std::is_same<
typename Canonicalized<T>::type,
std::vector<typename Canonicalized<T>::type::value_type,
typename Canonicalized<T>::type::allocator_type>>::value>> {
static constexpr TYPEID
get() { return TypeID<val>::get(); }
};
} // namespace internal
} // namespace emscripten
#endif
/*! @} */
namespace tinyspline {
/*! @name API Configuration
*
* @{
*/
typedef tsReal real;
/*! @} */
/*! @name Swig Type Mapping
*
* Methods that do not return or set the value of a class attribute (let's call
* these methods `non-accessor methods') must return/take instances of
* std::vector as pointer. Otherwise, they aren't type mapped by Swig to the
* std::vector representation of the target language.
*
* @{
*/
#ifdef SWIG
using std_real_vector_in = std::vector<tinyspline::real> *;
using std_real_vector_out = std::vector<tinyspline::real> *;
#else
using std_real_vector_in = const std::vector<tinyspline::real> &;
using std_real_vector_out = std::vector<tinyspline::real>;
#endif
/*! @} */
/*! @name Vector Math
*
* Wrapper classes for TinySpline's vector math.
*
* @{
*/
class TINYSPLINECXX_API Vec2 {
public:
Vec2();
Vec2(real x, real y);
Vec2 operator+(const Vec2 &other);
Vec2 operator-(const Vec2 &other);
Vec2 operator*(real scalar);
real x() const;
void setX(real val);
real y() const;
void setY(real val);
std::vector<real> values() const;
Vec2 add(const Vec2 &other) const;
Vec2 subtract(const Vec2 &other) const;
Vec2 multiply(real scalar) const;
Vec2 normalize() const;
TS_DEPRECATED Vec2 norm() const;
real magnitude() const;
real dot(const Vec2 &other) const;
real angle(const Vec2 &other) const;
real distance(const Vec2 &other) const;
std::string toString() const;
private:
real m_vals[2];
#ifdef TINYSPLINE_EMSCRIPTEN
public:
void setValues(std::vector<real>) { cannotWrite(); }
#endif
};
class TINYSPLINECXX_API Vec3 {
public:
Vec3();
Vec3(real x, real y, real z);
Vec3 operator+(const Vec3 &other);
Vec3 operator-(const Vec3 &other);
Vec3 operator*(real scalar);
real x() const;
void setX(real val);
real y() const;
void setY(real val);
real z() const;
void setZ(real val);
std::vector<real> values() const;
Vec3 add(const Vec3 &other) const;
Vec3 subtract(const Vec3 &other) const;
Vec3 multiply(real scalar) const;
Vec3 cross(const Vec3 &other) const;
Vec3 normalize() const;
TS_DEPRECATED Vec3 norm() const;
real magnitude() const;
real dot(const Vec3 &other) const;
real angle(const Vec3 &other) const;
real distance(const Vec3 &other) const;
std::string toString() const;
private:
real m_vals[3];
#ifdef TINYSPLINE_EMSCRIPTEN
public:
void setValues(std::vector<real>) { cannotWrite(); }
#endif
};
class TINYSPLINECXX_API Vec4 {
public:
Vec4();
Vec4(real x, real y, real z, real w);
Vec4 operator+(const Vec4 &other);
Vec4 operator-(const Vec4 &other);
Vec4 operator*(real scalar);
real x() const;
void setX(real val);
real y() const;
void setY(real val);
real z() const;
void setZ(real val);
real w() const;
void setW(real val);
std::vector<real> values() const;
Vec4 add(const Vec4 &other) const;
Vec4 subtract(const Vec4 &other) const;
Vec4 multiply(real scalar) const;
Vec4 normalize() const;
TS_DEPRECATED Vec4 norm() const;
real magnitude() const;
real dot(const Vec4 &other) const;
real angle(const Vec4 &other) const;
real distance(const Vec4 &other) const;
std::string toString() const;
private:
real m_vals[4];
#ifdef TINYSPLINE_EMSCRIPTEN
public:
void setValues(std::vector<real>) { cannotWrite(); }
#endif
};
#ifdef TINYSPLINE_EMSCRIPTEN
class VecMath {
public:
/*! @name Add
*
* @{
*/
static Vec2
add2(const Vec2 &a, const Vec2 &b)
{ return a.add(b); }
static Vec3
add3(const Vec3 &a, const Vec3 &b)
{ return a.add(b); }
static Vec4
add4(const Vec4 &a, const Vec4 &b)
{ return a.add(b); }
/*! @} */
/*! @name Subtract
*
* @{
*/
static Vec2
subtract2(const Vec2 &a, const Vec2 &b)
{ return a.subtract(b); }
static Vec3
subtract3(const Vec3 &a, const Vec3 &b)
{ return a.subtract(b); }
static Vec4
subtract4(const Vec4 &a, const Vec4 &b)
{ return a.subtract(b); }
/*! @} */
/*! @name Multiply
*
* @{
*/
static Vec2
multiply2(const Vec2 &vec, real scalar)
{ return vec.multiply(scalar); }
static Vec3
multiply3(const Vec3 &vec, real scalar)
{ return vec.multiply(scalar); }
static Vec4
multiply4(const Vec4 &vec, real scalar)
{ return vec.multiply(scalar); }
/*! @} */
/*! @name Cross
*
* @{
*/
static Vec3
cross3(const Vec3 &a, Vec3 &b)
{ return a.cross(b); }
/*! @} */
/*! @name Normalize
*
* @{
*/
static Vec2
normalize2(const Vec2 &vec)
{ return vec.normalize(); }
static Vec3
normalize3(const Vec3 &vec)
{ return vec.normalize(); }
static Vec4
normalize4(const Vec4 &vec)
{ return vec.normalize(); }
/*! @} */
/*! @name Magnitude
*
* @{
*/
static real
magnitude2(const Vec2 &vec)
{ return vec.magnitude(); }
static real
magnitude3(const Vec3 &vec)
{ return vec.magnitude(); }
static real
magnitude4(const Vec4 &vec)
{ return vec.magnitude(); }
/*! @} */
/*! @name Dot
*
* @{
*/
static real
dot2(const Vec2 &a, Vec2 &b)
{ return a.dot(b); }
static real
dot3(const Vec3 &a, Vec3 &b)
{ return a.dot(b); }
static real
dot4(const Vec4 &a, Vec4 &b)
{ return a.dot(b); }
/*! @} */
/*! @name Angle
*
* @{
*/
static real
angle2(const Vec2 &a, Vec2 &b)
{ return a.angle(b); }
static real
angle3(const Vec3 &a, Vec3 &b)
{ return a.angle(b); }
static real
angle4(const Vec4 &a, Vec4 &b)
{ return a.angle(b); }
/*! @} */
/*! @name Distance
*
* @{
*/
static real
distance2(const Vec2 &a, Vec2 &b)
{ return a.distance(b); }
static real
distance3(const Vec3 &a, Vec3 &b)
{ return a.distance(b); }
static real
distance4(const Vec4 &a, Vec4 &b)
{ return a.distance(b); }
/*! @} */
};
#endif
/*! @} */
/*! @name Spline Framing
*
* Object-oriented representation of ::tsFrame (::Frame) and sequences of
* ::tsFrame (::FrameSeq). Instances of ::FrameSeq are created by
* ::BSpline::computeRMF.
*
* @{
*/
class TINYSPLINECXX_API Frame {
public:
Frame(Vec3 &position,
Vec3 &tangent,
Vec3 &normal,
Vec3 &binormal);
Vec3 position() const;
Vec3 tangent() const;
Vec3 normal() const;
Vec3 binormal() const;
std::string toString() const;
private:
Vec3 m_position,
m_tangent,
m_normal,
m_binormal;
#ifdef TINYSPLINE_EMSCRIPTEN
public:
Frame() {}
void setPosition(Vec3) { cannotWrite(); }
void setTangent(Vec3) { cannotWrite(); }
void setNormal(Vec3) { cannotWrite(); }
void setBinormal(Vec3) { cannotWrite(); }
#endif
};
class TINYSPLINECXX_API FrameSeq {
public:
FrameSeq();
FrameSeq(const FrameSeq &other);
FrameSeq(FrameSeq &&other);
virtual ~FrameSeq();
FrameSeq &operator=(const FrameSeq &other);
FrameSeq &operator=(FrameSeq &&other);
size_t size() const;
Frame at(size_t idx) const;
std::string toString() const;
private:
tsFrame *m_frames;
size_t m_size;
FrameSeq(tsFrame *frames,
size_t len);
friend class BSpline;
};
/*! @} */
/*! @name Utility Classes
*
* Little helper classes, such as value classes or classes with only static
* methods. These are primarily classes that do not really fit into another
* group or are too small to form their own group.
*
* @{
*/
class TINYSPLINECXX_API Domain {
public:
/* Constructors & Destructors */
Domain(real min, real max);
/* Accessors */
real min() const;
real max() const;
/* Debug */
std::string toString() const;
private:
real m_min,
m_max;
#ifdef TINYSPLINE_EMSCRIPTEN
public:
Domain()
: Domain(TS_DOMAIN_DEFAULT_MIN, TS_DOMAIN_DEFAULT_MAX)
{}
void setMin(real) { cannotWrite(); }
void setMax(real) { cannotWrite(); }
#endif
};
/*! @} */
class TINYSPLINECXX_API DeBoorNet {
public:
/* Constructors & Destructors */
DeBoorNet(const DeBoorNet &other);
DeBoorNet(DeBoorNet &&other);
virtual ~DeBoorNet();
/* Operators */
DeBoorNet & operator=(const DeBoorNet &other);
DeBoorNet & operator=(DeBoorNet &&other);
/* Accessors */
real knot() const;
size_t index() const;
size_t multiplicity() const;
size_t numInsertions() const;
size_t dimension() const;
std::vector<real> points() const;
std::vector<real> result() const;
/**
* Returns the result at \p idx as ::Vec2. Note that, by design, \p idx
* cannot be greater than \c 1. It is safe to call this method even if
* ::dimension is less than \c 2. In this case, the missing components
* are set to \c 0. If ::dimension is greater than \c 2, the excess
* values are ignored.
*
* @return
* The result at \p idx as ::Vec2.
* @throws std::out_of_range
* If \p idx is greater than \c 1, or if \p idx is \c 1, but there
* is only one result.
*/
Vec2 resultVec2(size_t idx = 0) const;
/**
* Returns the result at \p idx as ::Vec3. Note that, by design, \p idx
* cannot be greater than \c 1. It is safe to call this method even if
* ::dimension is less than \c 3. In this case, the missing components
* are set to \c 0. If ::dimension is greater than \c 3, the excess
* values are ignored.
*
* @return
* The result at \p idx as ::Vec3.
* @throws std::out_of_range
* If \p idx is greater than \c 1, or if \p idx is \c 1, but there
* is only one result.
*/
Vec3 resultVec3(size_t idx = 0) const;
/**
* Returns the result at \p idx as ::Vec4. Note that, by design, \p idx
* cannot be greater than \c 1. It is safe to call this method even if
* ::dimension is less than \c 4. In this case, the missing components
* are set to \c 0. If ::dimension is greater than \c 4, the excess
* values are ignored.
*
* @return
* The result at \p idx as ::Vec4.
* @throws std::out_of_range
* If \p idx is greater than \c 1, or if \p idx is \c 1, but there
* is only one result.
*/
Vec4 resultVec4(size_t idx = 0) const;
/* Debug */
std::string toString() const;
private:
tsDeBoorNet net;
/* Constructors & Destructors */
explicit DeBoorNet(tsDeBoorNet &data);
friend class BSpline;
#ifdef TINYSPLINE_EMSCRIPTEN
public:
DeBoorNet() : net(ts_deboornet_init()) {}
void setKnot(real) { cannotWrite(); }
void setIndex(size_t) { cannotWrite(); }
void setMultiplicity(size_t) { cannotWrite(); }
void setNumInsertions(size_t) { cannotWrite(); }
void setDimension(size_t) { cannotWrite(); }
void setPoints(std::vector<real>) { cannotWrite(); }
void setResult(std::vector<real>) { cannotWrite(); }
#endif
};
class Morphism;
class ChordLengths;
class TINYSPLINECXX_API BSpline {
public:
enum Type { Opened, Clamped, Beziers };
/* Constructors & Destructors */
BSpline();
BSpline(const BSpline &other);
BSpline(BSpline &&other);
explicit BSpline(size_t numControlPoints,
size_t dimension = 2,
size_t degree = 3,
Type type = Type::Clamped);
virtual ~BSpline();
/* Create from static method */
static BSpline interpolateCubicNatural(std_real_vector_in points,
size_t dimension);
static BSpline interpolateCatmullRom(std_real_vector_in points,
size_t dimension,
real alpha = (real) 0.5,
std::vector<real> *first = nullptr,
std::vector<real> *last = nullptr,
real epsilon = TS_POINT_EPSILON);
static BSpline parseJson(std::string json);
static BSpline load(std::string path);
static bool knotsEqual(real x, real y);
/* Operators */
BSpline & operator=(const BSpline &other);
BSpline & operator=(BSpline &&other);
DeBoorNet operator()(real u) const;
/* Accessors */
size_t degree() const;
size_t order() const;
size_t dimension() const;
std::vector<real> controlPoints() const;
Vec2 controlPointVec2At(size_t idx) const;
Vec3 controlPointVec3At(size_t idx) const;
Vec4 controlPointVec4At(size_t idx) const;
std::vector<real> knots() const;
real knotAt(size_t index) const;
/* Query */
size_t numControlPoints() const;
DeBoorNet eval(real u) const;
std_real_vector_out evalAll(std_real_vector_in knots) const;
std_real_vector_out sample(size_t num = 0) const;
DeBoorNet bisect(real value,
real epsilon = (real) 0.0,
bool persnickety = false,
size_t index = 0,
bool ascending = true,
size_t maxIter = 50) const;
Domain domain() const;
bool isClosed(real epsilon = TS_POINT_EPSILON) const;
FrameSeq computeRMF(std_real_vector_in knots,
Vec3 *firstNormal = nullptr) const;
BSpline subSpline(real knot0, real knot1) const;
std_real_vector_out uniformKnotSeq(size_t num = 100) const;
std_real_vector_out equidistantKnotSeq(size_t num = 100,
size_t numSamples = 0) const;
ChordLengths chordLengths(std_real_vector_in knots) const;
ChordLengths chordLengths(size_t numSamples = 200) const;
/* Serialization */
std::string toJson() const;
void save(std::string path) const;
/* Modifications */
void setControlPoints(const std::vector<real> &ctrlp);
void setControlPointVec2At(size_t idx, Vec2 &cp);
void setControlPointVec3At(size_t idx, Vec3 &cp);
void setControlPointVec4At(size_t idx, Vec4 &cp);
void setKnots(const std::vector<real> &knots);
void setKnotAt(size_t index, real knot);
/* Transformations */
BSpline insertKnot(real u, size_t n) const;
BSpline split(real u) const;
BSpline tension(real tension) const;
BSpline toBeziers() const;
BSpline derive(size_t n = 1,
real epsilon = TS_POINT_EPSILON) const;
BSpline elevateDegree(size_t amount,
real epsilon = TS_POINT_EPSILON) const;
BSpline alignWith(const BSpline &other, BSpline &otherAligned,
real epsilon = TS_POINT_EPSILON) const;
Morphism morphTo(const BSpline &other,
real epsilon = TS_POINT_EPSILON) const;
/* Debug */
std::string toString() const;
private:
tsBSpline spline;
/* Constructors & Destructors */
explicit BSpline(tsBSpline &data);
/* Needs to access ::spline. */
friend class Morphism;
#ifdef TINYSPLINE_EMSCRIPTEN
public:
std_real_vector_out sample0() const { return sample(); }
std_real_vector_out sample1(size_t num) const { return sample(num); }
BSpline derive0() const { return derive(); }
BSpline derive1(size_t n) const { return derive(n); }
BSpline derive2(size_t n, real eps) const { return derive(n, eps); }
#endif
};
/*! @name Spline Morphing
*
* @{
*/
class TINYSPLINECXX_API Morphism {
public:
Morphism(const BSpline &origin,
const BSpline &target,
real epsilon = TS_POINT_EPSILON);
BSpline origin() const;
BSpline target() const;
real epsilon() const;
BSpline eval(real t);
BSpline operator()(real t);
std::string toString() const;
private:
BSpline m_origin, m_target;
real m_epsilon;
BSpline m_originAligned, m_targetAligned;
BSpline m_buffer;
};
/*! @} */
/*! @name Reparametrization by Arc Length
* @{
*/
class TINYSPLINECXX_API ChordLengths {
public:
ChordLengths();
ChordLengths(const ChordLengths &other);
ChordLengths(ChordLengths &&other);
virtual ~ChordLengths();
ChordLengths &operator=(const ChordLengths &other);
ChordLengths &operator=(ChordLengths &&other);
BSpline spline() const;
std::vector<real> knots() const;
std::vector<real> values() const;
size_t size() const;
real arcLength() const;
real lengthToKnot(real len) const;
real tToKnot(real t) const;
std::string toString() const;
private:
BSpline m_spline;
real *m_knots, *m_chordLengths;
size_t m_size;
ChordLengths(const BSpline &spline,
real *knots,
real *chordLengths,
size_t size);
friend class BSpline;
};
/*! @} */
}
#ifdef TINYSPLINE_EMSCRIPTEN
using namespace tinyspline;
EMSCRIPTEN_BINDINGS(tinyspline) {
function("exceptionMessage", &exceptionMessage);
// Vector Math
value_object<Vec2>("Vec2")
.field("x",
&Vec2::x,
&Vec2::setX)
.field("y",
&Vec2::y,
&Vec2::setY)
.field("values",
&Vec2::values,
&Vec2::setValues)
;
value_object<Vec3>("Vec3")
.field("x",
&Vec3::x,
&Vec3::setX)
.field("y",
&Vec3::y,
&Vec3::setY)
.field("z",
&Vec3::z,
&Vec3::setZ)
.field("values",
&Vec3::values,
&Vec3::setValues)
;
value_object<Vec4>("Vec4")
.field("x",
&Vec4::x,
&Vec4::setX)
.field("y",
&Vec4::y,
&Vec4::setY)
.field("z",
&Vec4::z,
&Vec4::setZ)
.field("w",
&Vec4::w,
&Vec4::setW)
.field("values",
&Vec4::values,
&Vec4::setValues)
;
class_<VecMath>("VecMath")
.class_function("add", &VecMath::add2)
.class_function("add", &VecMath::add3)
.class_function("add", &VecMath::add4)
.class_function("subtract", &VecMath::subtract2)
.class_function("subtract", &VecMath::subtract3)
.class_function("subtract", &VecMath::subtract4)
.class_function("multiply", &VecMath::multiply2)
.class_function("multiply", &VecMath::multiply3)
.class_function("multiply", &VecMath::multiply4)
.class_function("cross", &VecMath::cross3)
.class_function("normalize", &VecMath::normalize2)
.class_function("normalize", &VecMath::normalize3)
.class_function("normalize", &VecMath::normalize4)
.class_function("magnitude", &VecMath::magnitude2)
.class_function("magnitude", &VecMath::magnitude3)
.class_function("magnitude", &VecMath::magnitude4)
.class_function("dot", &VecMath::dot2)
.class_function("dot", &VecMath::dot3)
.class_function("dot", &VecMath::dot4)
.class_function("angle", &VecMath::angle2)
.class_function("angle", &VecMath::angle3)
.class_function("angle", &VecMath::angle4)
.class_function("distance", &VecMath::distance2)
.class_function("distance", &VecMath::distance3)
.class_function("distance", &VecMath::distance4)
;
// Spline Framing
value_object<Frame>("Frame")
.field("position",
&Frame::position,
&Frame::setPosition)
.field("tangent",
&Frame::tangent,
&Frame::setTangent)
.field("normal",
&Frame::normal,
&Frame::setNormal)
.field("binormal",
&Frame::normal,
&Frame::setNormal)
;
class_<FrameSeq>("FrameSeq")
.constructor<>()
.constructor<FrameSeq>()
.function("size", &FrameSeq::size)
.function("at", &FrameSeq::at)
.function("toString", &FrameSeq::toString)
;
// Utility Classes
value_object<Domain>("Domain")
.field("min",
&Domain::min,
&Domain::setMin)
.field("max",
&Domain::max,
&Domain::setMax)
;
value_object<DeBoorNet>("DeBoorNet")
.field("knot",
&DeBoorNet::knot,
&DeBoorNet::setKnot)
.field("index",
&DeBoorNet::index,
&DeBoorNet::setIndex)
.field("multiplicity",
&DeBoorNet::multiplicity,
&DeBoorNet::setMultiplicity)
.field("numInsertions",
&DeBoorNet::numInsertions,
&DeBoorNet::setNumInsertions)
.field("dimension",
&DeBoorNet::dimension,
&DeBoorNet::setDimension)
.field("points",
&DeBoorNet::points,
&DeBoorNet::setPoints)
.field("result",
&DeBoorNet::result,
&DeBoorNet::setResult)
;
class_<BSpline>("BSpline")
.constructor<>()
//.constructor<BSpline>()
.constructor<size_t>()
.constructor<size_t, size_t>()
.constructor<size_t, size_t, size_t>()
.constructor<size_t, size_t, size_t, BSpline::Type>()
.class_function("interpolateCubicNatural",
&BSpline::interpolateCubicNatural)
.class_function("interpolateCatmullRom",
&BSpline::interpolateCatmullRom,
allow_raw_pointers())
.class_function("parseJson", &BSpline::parseJson)
.property("degree", &BSpline::degree)
.property("order", &BSpline::order)
.property("dimension", &BSpline::dimension)
.property("controlPoints", &BSpline::controlPoints,
&BSpline::setControlPoints)
.property("knots", &BSpline::knots, &BSpline::setKnots)
.property("domain", &BSpline::domain)
/* Property by index */
.function("knotAt", &BSpline::knotAt)
.function("setKnotAt", &BSpline::setKnotAt)
/* Query */
.function("numControlPoints", &BSpline::numControlPoints)
.function("eval", &BSpline::eval)
.function("evalAll", &BSpline::evalAll)
.function("sample",
select_overload<std_real_vector_out() const>
(&BSpline::sample0))
.function("sample",
select_overload<std_real_vector_out(size_t) const>
(&BSpline::sample1))
.function("sample", &BSpline::sample)
.function("bisect", &BSpline::bisect)
.function("isClosed", &BSpline::isClosed)
/* Serialization */
.function("toJson", &BSpline::toJson)
/* Transformations */
.function("insertKnot", &BSpline::insertKnot)
.function("split", &BSpline::split)
.function("tension", &BSpline::tension)
.function("toBeziers", &BSpline::toBeziers)
.function("derive",
select_overload<BSpline() const>
(&BSpline::derive0))
.function("derive",
select_overload<BSpline(size_t) const>
(&BSpline::derive1))
.function("derive",
select_overload<BSpline(size_t, real) const>
(&BSpline::derive2))
/* Debug */
.function("toString", &BSpline::toString)
;
enum_<BSpline::Type>("BSplineType")
.value("Opened", BSpline::Type::Opened)
.value("Clamped", BSpline::Type::Clamped)
.value("Beziers", BSpline::Type::Beziers)
;
}
#endif