TinySpline  0.7.0
Spline Library for a Multitude of Programming Languages
Classes
tinyspline.h File Reference
#include <stddef.h>

Go to the source code of this file.

Classes

struct  tsStatus
 
struct  tsFrame
 
struct  tsBSpline
 
struct  tsDeBoorNet
 

Macros

Deprecation

The macro TS_DEPRECATED can be used to mark functions as deprecated.

Library Export/Import

If TinySpline is built for Windows, the macros TINYSPLINE_SHARED_EXPORT and TINYSPLINE_SHARED_IMPORT define the Microsoft specific directives __declspec(dllexport) and __declspec(dllimport), respectively. More information on these directives can be found at:

https://docs.microsoft.com/en-us/cpp/cpp/dllexport-dllimport

If TinySpline is built to the ELF (most Unix like environments) or Mach (OS X) object format, TINYSPLINE_SHARED_EXPORT defines the directive attribute ((visibility ("default"))) which, in combination with -fvisibility=hidden, behaves similar to __declspec(dllexport). TINYSPLINE_SHARED_IMPORT is set empty (i.e., it defines nothing).

If none of the above applies, TINYSPLINE_SHARED_EXPORT and TINYSPLINE_SHARED_IMPORT are set empty (i.e., they define nothing).

Depending on whether TinySpline is compiled as shared library or linked against as shared library, TINYSPLINE_API points to TINYSPLINE_SHARED_EXPORT (compiled) or TINYSPLINE_SHARED_IMPORT (linked against). All elements of TinySpline that needs to be exported/imported are annotated with TINYSPLINE_API. This eliminates the need for a module-definition (.def) file. If TinySpline is compiled or linked against as static library, TINYSPLINE_API is set empty (i.e., it defines nothing).

If you consume TinySpline as shared library built for Windows, all you need is to define TINYSPLINE_SHARED. This will automatically import all required symbols. When compiling TinySpline, the build system should set all necessary defines.

Predefined Constants

The following constants have been adjusted to maintain internal consistency and should only be changed with great caution! The values chosen should be suitable for most environments and can be used with float (single) and double precision (see tsReal). If changes are necessary, please read the documentation of the constants in advance.

#define TS_PI   3.14159265358979323846
 
#define TS_MAX_NUM_KNOTS   10000
 
#define TS_DOMAIN_DEFAULT_MIN   0.0f
 
#define TS_DOMAIN_DEFAULT_MAX   1.0f
 
#define TS_KNOT_EPSILON   1e-4f
 
#define TS_POINT_EPSILON   1e-5f
 
#define TS_LENGTH_ZERO   1e-4f
 

Typedefs

API Configuration

In the following section, different aspects of TinySpline's API can be configured (compile-time). It is recommended to configure the API by supplying the corresponding preprocessor definition(s). That said, there is nothing wrong with editing the source code directly.

typedef double tsReal
 

Enumerations

Utility Structs and Enums
enum  tsBSplineType { TS_OPENED = 0 , TS_CLAMPED = 1 , TS_BEZIERS = 2 }
 

Functions

B-Spline Data

The internal state of tsBSpline is protected using the PIMPL design pattern (see https://en.cppreference.com/w/cpp/language/pimpl for more details). The data of an instance can be accessed with the functions listed in this section.

size_t TINYSPLINE_API ts_bspline_degree (const tsBSpline *spline)
 
size_t TINYSPLINE_API ts_bspline_order (const tsBSpline *spline)
 
size_t TINYSPLINE_API ts_bspline_dimension (const tsBSpline *spline)
 
size_t TINYSPLINE_API ts_bspline_len_control_points (const tsBSpline *spline)
 
size_t TINYSPLINE_API ts_bspline_num_control_points (const tsBSpline *spline)
 
size_t TINYSPLINE_API ts_bspline_sof_control_points (const tsBSpline *spline)
 
const tsReal TINYSPLINE_API * ts_bspline_control_points_ptr (const tsBSpline *spline)
 
tsError TINYSPLINE_API ts_bspline_control_points (const tsBSpline *spline, tsReal **ctrlp, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_control_point_at_ptr (const tsBSpline *spline, size_t index, const tsReal **ctrlp, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_set_control_points (tsBSpline *spline, const tsReal *ctrlp, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_set_control_point_at (tsBSpline *spline, size_t index, const tsReal *ctrlp, tsStatus *status)
 
size_t TINYSPLINE_API ts_bspline_num_knots (const tsBSpline *spline)
 
size_t TINYSPLINE_API ts_bspline_sof_knots (const tsBSpline *spline)
 
const tsReal TINYSPLINE_API * ts_bspline_knots_ptr (const tsBSpline *spline)
 
tsError TINYSPLINE_API ts_bspline_knots (const tsBSpline *spline, tsReal **knots, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_knot_at (const tsBSpline *spline, size_t index, tsReal *knot, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_set_knots (tsBSpline *spline, const tsReal *knots, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_set_knots_varargs (tsBSpline *spline, tsStatus *status, tsReal knot0, double knot1,...)
 
tsError TINYSPLINE_API ts_bspline_set_knot_at (tsBSpline *spline, size_t index, tsReal knot, tsStatus *status)
 
B-Spline Initialization

The following functions are used to create and release tsBSpline instances as well as to copy and move the internal data of a tsBSpline instance to another instance.

Note: It is recommended to initialize an instance with ts_bspline_init. This way, ts_bspline_free can be called in ::TS_CATCH and ::TS_FINALLY blocks (see Section Error Handling for more details) without further checking. For example:

tsBSpline spline = ts_bspline_init();
TS_TRY(...)
    ...
TS_FINALLY
    ts_bspline_free(&spline);
TS_END_TRY
tsBSpline TINYSPLINE_API ts_bspline_init (void)
 
tsError TINYSPLINE_API ts_bspline_new (size_t num_control_points, size_t dimension, size_t degree, tsBSplineType type, tsBSpline *spline, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_new_with_control_points (size_t num_control_points, size_t dimension, size_t degree, tsBSplineType type, tsBSpline *spline, tsStatus *status, double first,...)
 
tsError TINYSPLINE_API ts_bspline_copy (const tsBSpline *src, tsBSpline *dest, tsStatus *status)
 
void TINYSPLINE_API ts_bspline_move (tsBSpline *src, tsBSpline *dest)
 
void TINYSPLINE_API ts_bspline_free (tsBSpline *spline)
 
De Boor Net Data

The internal state of tsDeBoorNet is protected using the PIMPL design pattern (see https://en.cppreference.com/w/cpp/language/pimpl for more details). The data of an instance can be accessed with the functions listed in this section.

tsReal TINYSPLINE_API ts_deboornet_knot (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_index (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_multiplicity (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_num_insertions (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_dimension (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_len_points (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_num_points (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_sof_points (const tsDeBoorNet *net)
 
const tsReal TINYSPLINE_API * ts_deboornet_points_ptr (const tsDeBoorNet *net)
 
tsError TINYSPLINE_API ts_deboornet_points (const tsDeBoorNet *net, tsReal **points, tsStatus *status)
 
size_t TINYSPLINE_API ts_deboornet_len_result (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_num_result (const tsDeBoorNet *net)
 
size_t TINYSPLINE_API ts_deboornet_sof_result (const tsDeBoorNet *net)
 
const tsReal TINYSPLINE_API * ts_deboornet_result_ptr (const tsDeBoorNet *net)
 
tsError TINYSPLINE_API ts_deboornet_result (const tsDeBoorNet *net, tsReal **result, tsStatus *status)
 
De Boor Net Initialization

The following functions are used to create and release tsDeBoorNet instances as well as to copy and move the internal data of a tsDeBoorNet instance to another instance.

Note: It is recommended to initialize an instance with ts_deboornet_init. This way, ts_deboornet_free can be called in ::TS_CATCH and ::TS_FINALLY blocks (see Section Error Handling for more details) without further checking. For example:

tsDeBoorNet net = ts_deboornet_init();
TS_TRY(...)
    ...
TS_FINALLY
    ts_deboornet_free(&net);
TS_END_TRY
tsDeBoorNet TINYSPLINE_API ts_deboornet_init (void)
 
tsError TINYSPLINE_API ts_deboornet_copy (const tsDeBoorNet *src, tsDeBoorNet *dest, tsStatus *status)
 
void TINYSPLINE_API ts_deboornet_move (tsDeBoorNet *src, tsDeBoorNet *dest)
 
void TINYSPLINE_API ts_deboornet_free (tsDeBoorNet *net)
 
Interpolation and Approximation Functions

Given a set (or a sequence) of points, interpolate/approximate a spline that follows these points.

Note: Approximations have not yet been implemented. Pull requests are welcome.

tsError TINYSPLINE_API ts_bspline_interpolate_cubic_natural (const tsReal *points, size_t num_points, size_t dimension, tsBSpline *spline, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_interpolate_catmull_rom (const tsReal *points, size_t num_points, size_t dimension, tsReal alpha, const tsReal *first, const tsReal *last, tsReal epsilon, tsBSpline *spline, tsStatus *status)
 
Query Functions

Functions for querying different kinds of data from splines.

tsError TINYSPLINE_API ts_bspline_eval (const tsBSpline *spline, tsReal knot, tsDeBoorNet *net, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_eval_all (const tsBSpline *spline, const tsReal *knots, size_t num, tsReal **points, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_sample (const tsBSpline *spline, size_t num, tsReal **points, size_t *actual_num, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_bisect (const tsBSpline *spline, tsReal value, tsReal epsilon, int persnickety, size_t index, int ascending, size_t max_iter, tsDeBoorNet *net, tsStatus *status)
 
void TINYSPLINE_API ts_bspline_domain (const tsBSpline *spline, tsReal *min, tsReal *max)
 
tsError TINYSPLINE_API ts_bspline_is_closed (const tsBSpline *spline, tsReal epsilon, int *closed, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_compute_rmf (const tsBSpline *spline, const tsReal *knots, size_t num, int has_first_normal, tsFrame *frames, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_chord_lengths (const tsBSpline *spline, const tsReal *knots, size_t num, tsReal *lengths, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_sub_spline (const tsBSpline *spline, tsReal knot0, tsReal knot1, tsBSpline *sub, tsStatus *status)
 
void TINYSPLINE_API ts_bspline_uniform_knot_seq (const tsBSpline *spline, size_t num, tsReal *knots)
 
tsError TINYSPLINE_API ts_bspline_equidistant_knot_seq (const tsBSpline *spline, size_t num, tsReal *knots, size_t num_samples, tsStatus *status)
 
Transformation Functions

Transformations modify the internal state of a spline—e.g., the number of control points, the structure of the knot vector, the degree, and so on. Some transformations modify the state without changing the shape of the spline (e.g., ts_bspline_elevate_degree). All transformations specify at least three parameters: i) an input spline (the spline to be transformed), ii) an output spline (the spline which receives the result of the transformation), and iii) a tsStatus object (output parameter for error handling). Along with these parameters, additional parameters may be necessary to i) calculate the transformation (such as ts_bspline_tension) and ii) store additional results (such as ts_bspline_insert_knot). Unless stated otherwise, the order of the parameters of a transformation function, t, is:

t(input, [additional_input], output, [additional_output], status)

Note: Transformation functions do not releases the memory of the output spline before assigning the result of the transformation to it. Thus, when using the same output spline multiple times, make sure to release its memory before each call (after the first one). If not, severe memory leaks are to be expected:

tsBSpline in = ...                   // an arbitrary spline
tsBSpline out = ts_bspline_init();   // stores the result

ts_bspline_to_beziers(&in, &out);    // first transformation
...                                  // some code
ts_bspline_free(&out);               // avoid memory leak.
ts_bspline_tension(&in, 0.85, &out); // next transformation

It is possible to pass a spline as input and output argument at the same time. In this case, the called transformation uses a temporary buffer to store the working data. If the transformation succeeds, the memory of the supplied spline is released and the result is assigned to it. So even if a transformation fails, the internal state of the supplied splines stays intact (i.e., it remains unchanged).

Note: It is not necessary to release the memory of a spline which is passed as input and output argument at the same time before calling the next transformation (in fact that would fail due to a null pointer):

tsBSpline spline = ...                      // an arbitrary spline
ts_bspline_to_beziers(&spline, &spline);    // first transformation
ts_bspline_tension(&spline, 0.85, &spline); // next transformation
tsError TINYSPLINE_API ts_bspline_derive (const tsBSpline *spline, size_t n, tsReal epsilon, tsBSpline *deriv, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_insert_knot (const tsBSpline *spline, tsReal knot, size_t num, tsBSpline *result, size_t *k, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_split (const tsBSpline *spline, tsReal knot, tsBSpline *split, size_t *k, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_tension (const tsBSpline *spline, tsReal beta, tsBSpline *out, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_to_beziers (const tsBSpline *spline, tsBSpline *beziers, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_elevate_degree (const tsBSpline *spline, size_t amount, tsReal epsilon, tsBSpline *elevated, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_align (const tsBSpline *s1, const tsBSpline *s2, tsReal epsilon, tsBSpline *s1_out, tsBSpline *s2_out, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_morph (const tsBSpline *origin, const tsBSpline *target, tsReal t, tsReal epsilon, tsBSpline *out, tsStatus *status)
 
Serialization and Persistence

The following functions can be used to serialize and persist (i.e., store the serialized data in a file) splines. There are also functions to load serialized splines.

tsError TINYSPLINE_API ts_bspline_to_json (const tsBSpline *spline, char **json, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_parse_json (const char *json, tsBSpline *spline, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_save (const tsBSpline *spline, const char *path, tsStatus *status)
 
tsError TINYSPLINE_API ts_bspline_load (const char *path, tsBSpline *spline, tsStatus *status)
 
Vector Math

Vector math is a not insignificant part of TinySpline, and so it's not surprising that some utility functions around vectors are needed. Because these functions might be useful for others, they are part of TinySpline's public API. However, note that the code is not highly optimized (with, for example, instruction set extensions like SSE). If high performance vector math is needed, other libraries should be used instead.

void TINYSPLINE_API ts_vec2_init (tsReal *out, tsReal x, tsReal y)
 
void TINYSPLINE_API ts_vec3_init (tsReal *out, tsReal x, tsReal y, tsReal z)
 
void TINYSPLINE_API ts_vec4_init (tsReal *out, tsReal x, tsReal y, tsReal z, tsReal w)
 
void TINYSPLINE_API ts_vec2_set (tsReal *out, const tsReal *x, size_t dim)
 
void TINYSPLINE_API ts_vec3_set (tsReal *out, const tsReal *x, size_t dim)
 
void TINYSPLINE_API ts_vec4_set (tsReal *out, const tsReal *x, size_t dim)
 
void TINYSPLINE_API ts_vec_add (const tsReal *x, const tsReal *y, size_t dim, tsReal *out)
 
void TINYSPLINE_API ts_vec_sub (const tsReal *x, const tsReal *y, size_t dim, tsReal *out)
 
tsReal TINYSPLINE_API ts_vec_dot (const tsReal *x, const tsReal *y, size_t dim)
 
tsReal TINYSPLINE_API ts_vec_angle (const tsReal *x, const tsReal *y, tsReal *buf, size_t dim)
 
void TINYSPLINE_API ts_vec3_cross (const tsReal *x, const tsReal *y, tsReal *out)
 
void TINYSPLINE_API ts_vec_norm (const tsReal *x, size_t dim, tsReal *out)
 
tsReal TINYSPLINE_API ts_vec_mag (const tsReal *x, size_t dim)
 
void TINYSPLINE_API ts_vec_mul (const tsReal *x, size_t dim, tsReal val, tsReal *out)
 
Chord Length Method

Functions for processing the cumulative chord lengths of a spline as computed by ts_bspline_chord_lengths.

tsError TINYSPLINE_API ts_chord_lengths_length_to_knot (const tsReal *knots, const tsReal *lengths, size_t num, tsReal len, tsReal *knot, tsStatus *status)
 
tsError TINYSPLINE_API ts_chord_lengths_t_to_knot (const tsReal *knots, const tsReal *lengths, size_t num, tsReal t, tsReal *knot, tsStatus *status)
 
tsError TINYSPLINE_API ts_chord_lengths_equidistant_knot_seq (const tsReal *knots, const tsReal *lengths, size_t num, size_t num_knot_seq, tsReal *knot_seq, tsStatus *status)
 
Utility Functions
int TINYSPLINE_API ts_knots_equal (tsReal x, tsReal y)
 
void TINYSPLINE_API ts_arr_fill (tsReal *arr, size_t num, tsReal val)
 
tsReal TINYSPLINE_API ts_distance (const tsReal *x, const tsReal *y, size_t dim)
 

Error Handling

There are three types of error handling in TinySpline.

  1. Return value: Functions that can fail return a special error code (tsError). If the error code is not 0 (TS_SUCCESS), an error occurred during execution. For example:
    if ( ts_bspline_to_beziers(&spline, &beziers, NULL) ) {
         ... An error occurred ...
    }
    
    It is of course possible to check the actual type of error:
    tsError error = ts_bspline_to_beziers(&spline, &beziers, NULL);
    if (error == TS_MALLOC) {
         ... Out of memory ...
    } else if (error == ...
    
    This type of error handling is used in many C programs. The disadvantage is that there is no additional error message besides the error code (with which the cause of an error could be specified in more detail). Some libraries make do with global variables in which error messages are stored for later purpose (e.g., errno and strerror). Unfortunately, however, this approach (by design) is often not thread-safe. The second error handling option solves this issue.
  2. tsStatus objects: Functions that can fail do not only return an error code, but also take a pointer to a tsStatus object as an optional parameter. In the event of an error, and if the supplied pointer is not NULL, the error message is stored in tsStatus::message and can be accessed by the caller. Using a tsStatus object, the example given in 1. can be modified as follows:
    tsStatus status;
    if ( ts_bspline_to_beziers(&spline, &beziers, &status) ) {
        status.code; // error code
        status.message; // error message
    }
    
    Note that tsStatus objects can be reused:
    tsStatus status;
    if ( ts_bspline_to_beziers(&spline, &beziers, &status) ) {
        ...
    }
    ...
    if ( ts_bspline_derive(&beziers, 1, 0.001, &beziers, &status) ) {
        ...
    }
    
    If you would like to use this type of error handling in your own functions (in particular the optional tsStatus parameter), you may wonder whether there is an easy way to return error codes and format error messages. This is where the macros ::TS_RETURN_0 – ::TS_RETURN_4 come into play. They can, for example, be used as follows:
    tsError my_function(..., tsStatus *status, ...)
    {
        ...
        tsReal *points = (tsReal *) malloc(len * sizeof(tsReal));
        if (!points)
            TS_RETURN_0(status, TS_MALLOC, "out of memory")
        ...
    }
    
    The N in TS_RETURN_<N> denotes the number of format specifier in the supplied format string (cf. sprintf(char *, const char *, ... )).
  3. Try-catch-finally blocks: TinySpline provides a set of macros that can be used when a complex control flow is necessary. The macros create a structure that is similar to the exception handling mechanisms of high-level languages such as C++. The basic structure is as follows:

    TS_TRY(try, error, status) // `status' may be NULL
        ...
        TS_CALL( try, error, ts_bspline_to_beziers(
            &spline, &beziers, status) )
        ...
    TS_CATCH(error)
        ... Executed in case of an error ...
        ... `error' (tsError) indicates the type of error.
        ... `status' (tsStatus) contains the error code and message ...
    TS_FINALLY
        ... Executed in any case ...
    TS_END_TRY
    

    ::TS_TRY and ::TS_END_TRY mark the boundaries of a try-catch-finally block. Every block has an identifier (name) that must be unique within a scope. The name of a block is set via the first argument of ::TS_TRY (try in the example listed above). The control flow of a try-catch-finally block is directed via the second and third argument of ::TS_TRY (error and status in the example listed above) and the utility macro ::TS_CALL. The second argument of ::TS_TRY, a tsError, is mandatory. The third argument of ::TS_TRY, a tsStatus object, is optional, that is, it may be NULL. ::TS_CALL serves as a wrapper for functions with return type tsError. If the called functions fails (more on that later), ::TS_CALL immediately jumps into the ::TS_CATCH section where error and status can be evaluated as needed (note that status may be NULL). The ::TS_FINALLY section is executed in any case and is in particularly helpful when resources (such as heap-memory, file-handles etc.) must be released.

    While ::TS_CALL can be used to wrap functions with return type tsError, sooner or later it will be necessary to delegate the failure of other kinds of functions (i.e., functions outside of TinySpline; e.g., malloc(size_t)). This is the purpose of the ::TS_THROW_0 – ::TS_THROW_4 macros. It is not by coincidence that the signature of the TS_THROW_<N> macros is quite similar to that of the TS_RETURN_<N> macros. Both "macro groups" are used to report errors. The difference between TS_RETURN_<N> and TS_THROW_<N>, however, is that the former exits a function (i.e., a return statement is inserted by these macros) while the latter jumps into a catch block (the catch block to jump into is set via the first argument of TS_THROW_<N>):

    tsBSpline spline = ts_bspline_init();
    tsReal *points = NULL;
    TS_TRY(try, error, status)
        ...
        tsReal *points = (tsReal *) malloc(len * sizeof(tsReal));
        if (!points)
            TS_THROW_0(try, status, TS_MALLOC, "out of memory")
        ...
        TS_CALL( try, error, ts_bspline_interpolate_cubic_natural(
            points, len / dim, dim, &spline, status) )
        ...
    TS_CATCH(error)
        ... Log error message ...
    TS_FINALLY
        ts_bspline_free(&spline);
        if (points)
            free(points);
    TS_END_TRY
    

    In all likelihood, you are already familiar with this kind error handling. Actually, there are a plethora of examples available online showing how exception-like error handling can be implemented in C. What most of these examples have in common is that they suggest to wrap the functions setjmp and longjmp (see setjmp.h) with macros. While this undoubtedly is a clever trick, setjmp and longjmp have no viable (i.e, thread-safe) solution for propagating the cause of an error (in the form of a human-readable error message) back to the client of a library. Therefore, TinySpline implements try-catch-finally blocks with if statements, labels, and goto statements (TS_THROW_<N>).

    ::TS_TRY is flexible enough to be used in functions that are in turn embedded into TinySpline's error handling system:

    tsError my_function(..., tsStatus *status, ...)
    {
        tsError error;
        TS_TRY(try, error, status)
            ...
        TS_END_TRY
        return error;
    }
    

    as well as functions forming the root of a call stack that uses TinySpline's error handling system:

    tsStatus status;
    TS_TRY(try, status.code, &status)
        ...
    TS_END_TRY
    

    There is some utility macros that might be useful when dealing with try-catch-finally blocks:

    • ::TS_END_TRY_RETURN: Returns the supplied error code immediately after completing the corresponding block. Can be used as follows:
      tsError my_function(..., tsStatus *status, ...)
      {
          tsError error;
          TS_TRY(try, error, status)
              ...
          TS_END_TRY_RETURN(error)
      }
      
    • ::TS_END_TRY_ROE: Like ::TS_END_TRY_RETURN but returns the supplied error code, e, if e is not TS_SUCCESS (ROE means Return On Error). Can be used as follows:
      tsError my_function(..., tsStatus *status, ...)
      {
          tsError error;
          TS_TRY(try, error, status)
              ...
          TS_END_TRY_ROE(error)
          ... Additional code. The code is executed only if `error' is
              TS_SUCCESS, that is, if no error occurred in the try block
              above ...
      }
      
    • ::TS_CALL_ROE: Calls the supplied function and returns its error code, e, if e is not TS_SUCCESS. This macro can be seen as a minified try block (a dedicated try block is not needed).
    • ::TS_RETURN_SUCCESS: Shortcut for ::TS_RETURN_0 with error code TS_SUCCESS and an empty error message.
#define TS_TRY(label, error, status)
 
#define TS_CALL(label, error, call)
 
#define TS_CATCH(error)    } if ((error)) {
 
#define TS_FINALLY    } {
 
#define TS_END_TRY
 
#define TS_END_TRY_RETURN(error)    TS_END_TRY return (error);
 
#define TS_END_TRY_ROE(error)    TS_END_TRY if ((error)) return error;
 
#define TS_CALL_ROE(error, call)
 
#define TS_RETURN_SUCCESS(status)
 
#define TS_RETURN_0(status, error, msg)
 
#define TS_RETURN_1(status, error, msg, arg1)
 
#define TS_RETURN_2(status, error, msg, arg1, arg2)
 
#define TS_RETURN_3(status, error, msg, arg1, arg2, arg3)
 
#define TS_RETURN_4(status, error, msg, arg1, arg2, arg3, arg4)
 
#define TS_THROW_0(label, error, status, val, msg)
 
#define TS_THROW_1(label, error, status, val, msg, arg1)
 
#define TS_THROW_2(label, error, status, val, msg, arg1, arg2)
 
#define TS_THROW_3(label, error, status, val, msg, arg1, arg2, arg3)
 
#define TS_THROW_4(label, error, status, val, msg, arg1, arg2, arg3, arg4)
 
enum  tsError {
  TS_SUCCESS = 0 , TS_MALLOC = -1 , TS_DIM_ZERO = -2 , TS_DEG_GE_NCTRLP = -3 ,
  TS_U_UNDEFINED = -4 , TS_MULTIPLICITY = -5 , TS_KNOTS_DECR = -6 , TS_NUM_KNOTS = -7 ,
  TS_UNDERIVABLE = -8 , TS_LCTRLP_DIM_MISMATCH = -10 , TS_IO_ERROR = -11 , TS_PARSE_ERROR = -12 ,
  TS_INDEX_ERROR = -13 , TS_NO_RESULT = -14 , TS_NUM_POINTS = -15
}
 

Macro Definition Documentation

◆ TS_CALL

#define TS_CALL (   label,
  error,
  call 
)
Value:
(error) = (call); \
if ((error)) goto __ ## label ## __;

◆ TS_CALL_ROE

#define TS_CALL_ROE (   error,
  call 
)
Value:
{ \
(error) = (call); \
if ((error)) return error; \
}

◆ TS_DOMAIN_DEFAULT_MAX

#define TS_DOMAIN_DEFAULT_MAX   1.0f

The maximum of the domain of newly created splines. Must be greater than TS_DOMAIN_DEFAULT_MIN. This constant is used only when creating new splines. After creation, the domain of a spline can be adjusted as needed.

◆ TS_DOMAIN_DEFAULT_MIN

#define TS_DOMAIN_DEFAULT_MIN   0.0f

The minimum of the domain of newly created splines. Must be less than TS_DOMAIN_DEFAULT_MAX. This constant is used only when creating new splines. After creation, the domain of a spline can be adjusted as needed.

◆ TS_END_TRY

#define TS_END_TRY
Value:
} \
}

◆ TS_KNOT_EPSILON

#define TS_KNOT_EPSILON   1e-4f

If the distance between two knots falls below this threshold, they are considered equal. Must be positive ( > 0 ). This constant is strongly related to TS_MAX_NUM_KNOTS in that the more precise TS_KNOT_EPSILON is (i.e., knots with smaller distance are considered equal), the less TS_MAX_NUM_KNOTS has to be. Likewise, the larger TS_MAX_NUM_KNOTS is, the less precise TS_KNOT_EPSILON has to be (i.e., knots with greater distance are considered equal). By default, the relation between TS_KNOT_EPSILON and TS_MAX_NUM_KNOTS is as follows:

TS_KNOT_EPSILON = 1 / TS_MAX_NUM_KNOTS

It is recommended that TS_KNOT_EPSILON is aligned to the span of TS_DOMAIN_DEFAULT_MIN and TS_DOMAIN_DEFAULT_MAX. That is, adjacent floating point values in the domain [TS_DOMAIN_DEFAULT_MIN, TS_DOMAIN_DEFAULT_MAX] should not be equal according to TS_KNOT_EPSILON. This is in particular recommended when TS_KNOT_EPSILON and TS_MAX_NUM_KNOTS are related to each other as described above.

◆ TS_LENGTH_ZERO

#define TS_LENGTH_ZERO   1e-4f

If the length of an element (e.g., a vector) is less than this threshold, the length is considered 0. Must be positive ( > 0 ).

◆ TS_MAX_NUM_KNOTS

#define TS_MAX_NUM_KNOTS   10000

The maximum number of knots a spline can have. This constant is strongly related to TS_KNOT_EPSILON in that the larger TS_MAX_NUM_KNOTS is, the less precise TS_KNOT_EPSILON has to be (i.e., knots with greater distance are considered equal). Likewise, the more precise TS_KNOT_EPSILON is (i.e., knots with smaller distance are considered equal), the less TS_MAX_NUM_KNOTS has to be. By default, the relation between TS_MAX_NUM_KNOTS and TS_KNOT_EPSILON is as follows:

TS_MAX_NUM_KNOTS = 1 / TS_KNOTS_EPSILON

◆ TS_PI

#define TS_PI   3.14159265358979323846

The mathematical constant pi.

◆ TS_POINT_EPSILON

#define TS_POINT_EPSILON   1e-5f

If the distance between two (control) points is less than or equal to this threshold, they are considered equal. This constant is not used directly by the C interface. Rather, it serves as a viable default value for functions requiring an epsilon environment to decide whether two (control) points are equal or not. The C++ interface, for example, uses this as default value for optional parameters.

◆ TS_RETURN_0

#define TS_RETURN_0 (   status,
  error,
  msg 
)
Value:
{ \
if ((status) != NULL) { \
(status)->code = error; \
sprintf((status)->message, msg); \
} \
return error; \
}

◆ TS_RETURN_1

#define TS_RETURN_1 (   status,
  error,
  msg,
  arg1 
)
Value:
{ \
if ((status) != NULL) { \
(status)->code = error; \
sprintf((status)->message, msg, arg1); \
} \
return error; \
}

◆ TS_RETURN_2

#define TS_RETURN_2 (   status,
  error,
  msg,
  arg1,
  arg2 
)
Value:
{ \
if ((status) != NULL) { \
(status)->code = error; \
sprintf((status)->message, msg, arg1, arg2); \
} \
return error; \
}

◆ TS_RETURN_3

#define TS_RETURN_3 (   status,
  error,
  msg,
  arg1,
  arg2,
  arg3 
)
Value:
{ \
if ((status) != NULL) { \
(status)->code = error; \
sprintf((status)->message, msg, arg1, arg2, arg3); \
} \
return error; \
}

◆ TS_RETURN_4

#define TS_RETURN_4 (   status,
  error,
  msg,
  arg1,
  arg2,
  arg3,
  arg4 
)
Value:
{ \
if ((status) != NULL) { \
(status)->code = error; \
sprintf((status)->message, msg, arg1, arg2, arg3, arg4); \
} \
return error; \
}

◆ TS_RETURN_SUCCESS

#define TS_RETURN_SUCCESS (   status)
Value:
{ \
if ((status) != NULL) { \
(status)->code = TS_SUCCESS; \
(status)->message[0] = '\0'; \
} \
return TS_SUCCESS; \
}
@ TS_SUCCESS
Definition: tinyspline.h:428

◆ TS_THROW_0

#define TS_THROW_0 (   label,
  error,
  status,
  val,
  msg 
)
Value:
{ \
(error) = val; \
if ((status) != NULL) { \
(status)->code = val; \
sprintf((status)->message, msg); \
} \
goto __ ## label ## __; \
}

◆ TS_THROW_1

#define TS_THROW_1 (   label,
  error,
  status,
  val,
  msg,
  arg1 
)
Value:
{ \
(error) = val; \
if ((status) != NULL) { \
(status)->code = val; \
sprintf((status)->message, msg, arg1); \
} \
goto __ ## label ## __; \
}

◆ TS_THROW_2

#define TS_THROW_2 (   label,
  error,
  status,
  val,
  msg,
  arg1,
  arg2 
)
Value:
{ \
(error) = val; \
if ((status) != NULL) { \
(status)->code = val; \
sprintf((status)->message, msg, arg1, arg2); \
} \
goto __ ## label ## __; \
}

◆ TS_THROW_3

#define TS_THROW_3 (   label,
  error,
  status,
  val,
  msg,
  arg1,
  arg2,
  arg3 
)
Value:
{ \
(error) = val; \
if ((status) != NULL) { \
(status)->code = val; \
sprintf((status)->message, msg, arg1, arg2, arg3); \
} \
goto __ ## label ## __; \
}

◆ TS_THROW_4

#define TS_THROW_4 (   label,
  error,
  status,
  val,
  msg,
  arg1,
  arg2,
  arg3,
  arg4 
)
Value:
{ \
(error) = val; \
if ((status) != NULL) { \
(status)->code = val; \
sprintf((status)->message, msg, arg1, arg2, arg3, arg4); \
} \
goto __ ## label ## __; \
}

◆ TS_TRY

#define TS_TRY (   label,
  error,
  status 
)
Value:
{ \
(error) = TS_SUCCESS; \
if ((status) != NULL) { \
(status)->code = TS_SUCCESS; \
(status)->message[0] = '\0'; \
} \
__ ## label ## __: \
if (!(error)) {

Typedef Documentation

◆ tsReal

typedef double tsReal

TinySpline uses its own typedef for floating point numbers. Supported are floats (single precision) and doubles (double precision). By default, doubles are used. Note that this typedef affects the entire API (i.e., types are not mixed; all structs and functions rely only on tsReal). Float precision is primarily used in combination with GLUT because GLUT's API doesn't support doubles:

https://www.glprogramming.com/red/chapter12.html

Generally, double precision is the right choice. Floats are mainly supported for legacy reasons. Yet, floats are not considered deprecated! If necessary, tsReal can also be typedefed to any other floating point representation. In this case, make sure to adjust TS_MAX_NUM_KNOTS and TS_KNOT_EPSILON (cf. Section "Predefined Constants").

Enumeration Type Documentation

◆ tsBSplineType

Describes the structure of the knot vector. More details can be found at:

www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve.html
Enumerator
TS_OPENED 

Uniformly spaced knot vector with opened end knots.

TS_CLAMPED 

Uniformly spaced knot vector with clamped end knots.

TS_BEZIERS 

Uniformly spaced knot vector where the multiplicity of each knot is equal to the order of the spline.

◆ tsError

enum tsError

Defines different error codes.

Enumerator
TS_SUCCESS 

No error.

TS_MALLOC 

Memory cannot be allocated (malloc, realloc etc.).

TS_DIM_ZERO 

Points have dimensionality 0.

TS_DEG_GE_NCTRLP 

degree >= num(control_points).

TS_U_UNDEFINED 

Knot is not within the domain.

TS_MULTIPLICITY 

multiplicity(knot) > order

TS_KNOTS_DECR 

Decreasing knot vector.

TS_NUM_KNOTS 

Unexpected number of knots.

TS_UNDERIVABLE 

Spline is not derivable.

TS_LCTRLP_DIM_MISMATCH 

len(control_points) % dimension != 0.

TS_IO_ERROR 

Error while reading/writing a file.

TS_PARSE_ERROR 

Error while parsing a serialized entity.

TS_INDEX_ERROR 

Index does not exist (e.g., when accessing an array).

TS_NO_RESULT 

Function returns without result (e.g., approximations).

TS_NUM_POINTS 

Unexpected number of points.

Function Documentation

◆ ts_arr_fill()

void TINYSPLINE_API ts_arr_fill ( tsReal arr,
size_t  num,
tsReal  val 
)

Fills the given array arr with val.

Parameters
[in]arrThe array to be filled.
[in]numFill length.
[in]valThe value to fill into arr.

◆ ts_bspline_align()

tsError TINYSPLINE_API ts_bspline_align ( const tsBSpline s1,
const tsBSpline s2,
tsReal  epsilon,
tsBSpline s1_out,
tsBSpline s2_out,
tsStatus status 
)

Modifies the splines s1 and s2 such that they have same the degree and number of control points/knots (without modifying the shape of s1 and s2). The resulting splines are stored in s1_out and s2_out. If s1 != s1_out, the internal state of s1 is not modified, that is, s1_out is a new, independent tsBSpline instance. The same is true for s2 and s2_out.

Parameters
[in]s1The spline which is to be aligned with s2.
[in]s2The spline which is to be aligned with s1.
[in]epsilonSpline alignment relies on degree elevation. This parameter is used in ts_bspline_elevate_degree to check whether two control points, p1 and p2, are "equal", that is, the distance between p1 and p2 is less than or equal to epsilon. A viable default value is TS_POINT_EPSILON.
[out]s1_outThe aligned version of s1.
[out]s2_outThe aligned version of s2.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_bisect()

tsError TINYSPLINE_API ts_bspline_bisect ( const tsBSpline spline,
tsReal  value,
tsReal  epsilon,
int  persnickety,
size_t  index,
int  ascending,
size_t  max_iter,
tsDeBoorNet net,
tsStatus status 
)

Tries to find a point P on spline such that:

ts_distance(P[index], value, 1) <= fabs(epsilon)

This function is using the bisection method to determine P. Accordingly, it is expected that the control points of spline are sorted at component index either in ascending order (if ascending != 0) or in descending order (if ascending == 0). If the control points of spline are not sorted at component index, the behaviour of this function is undefined. For the sake of fail-safeness, the distance of P[index] and value is compared with the absolute value of epsilon (using fabs).

The bisection method is an iterative approach which minimizes the error (epsilon) with each iteration step until an "optimum" was found. However, there may be no point P satisfying the distance condition. Thus, the number of iterations must be limited (max_iter). Depending on the domain of the control points of spline at component index and epsilon, max_iter ranges from 7 to 50. In most cases max_iter == 30 should be fine though. The parameter persnickety allows to define the behaviour of this function is case no point was found after max_iter iterations. If enabled (!= 0), TS_NO_RESULT is returned. If disabled (== 0), the best fitting point is returned.

Parameters
[in]splineThe spline to evaluate
[in]valueThe value (point at component index) to find.
[in]epsilonThe maximum distance (inclusive).
[in]persnicketyIndicates whether TS_NO_RESULT should be returned if there is no point P satisfying the distance condition (!= 0 to enable, == 0 to disable). If disabled, the best fitting point is returned.
[in]indexThe point's component.
[in]ascendingIndicates whether the control points of spline are sorted in ascending (!= 0) or in descending (== 0) order at component index.
[in]max_iterThe maximum number of iterations (30 is a sane default value).
[out]netThe output parameter.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_INDEX_ERROR If the dimension of the control points of spline <= index.
TS_NO_RESULT If persnickety is enabled (!= 0) and there is no point P satisfying the distance condition.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_chord_lengths()

tsError TINYSPLINE_API ts_bspline_chord_lengths ( const tsBSpline spline,
const tsReal knots,
size_t  num,
tsReal lengths,
tsStatus status 
)

Computes the cumulative chord lengths of the points of the given knots. Note that the first length (i.e., lengths[0]) is always 0, even if the minimum of the domain of spline is less than the first knot (i.e., knots[0]). Also, the returned lengths may be inaccurate if spline is discontinuous (i.e., the multiplicity of one of the interior knots is equal to the order of spline) with unequal evaluation points—in such case only the first result of the evaluation is included in the calculation.

Precondition
knots and lengths have length num.
Parameters
[in]splineThe spline to query.
[in]knotsThe knots to evaluate spline at.
[in]numNumber of knots in knots.
[out]lengthsThe cumulative chord lengths. lengths[i] is the length of spline at knot i (knots[i]).
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_U_UNDEFINED If spline is not defined at one of the knots in knots.
TS_KNOTS_DECR If knots is not monotonically increasing.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_compute_rmf()

tsError TINYSPLINE_API ts_bspline_compute_rmf ( const tsBSpline spline,
const tsReal knots,
size_t  num,
int  has_first_normal,
tsFrame frames,
tsStatus status 
)

Computes a sequence of three-dimensional frames (see tsFrame) for the spline spline. The position of the frames corresponds to the knots in knots. The implementation is based on:

@article{10.1145/1330511.1330513,
  author =       {Wang, Wenping and J\"{u}ttler, Bert and Zheng, Dayue
                  and Liu, Yang},
  title =        {Computation of Rotation Minimizing Frames},
  year =         {2008},
  issue_date =   {March 2008},
  publisher =    {Association for Computing Machinery},
  address =      {New York, NY, USA},
  volume =       {27},
  number =       {1},
  issn =         {0730-0301},
  url =          {https://doi.org/10.1145/1330511.1330513},
  doi =          {10.1145/1330511.1330513},
  abstract =     {Due to its minimal twist, the rotation minimizing
                  frame (RMF) is widely used in computer graphics,
                  including sweep or blending surface modeling, motion
                  design and control in computer animation and
                  robotics, streamline visualization, and tool path
                  planning in CAD/CAM. We present a novel simple and
                  efficient method for accurate and stable computation
                  of RMF of a curve in 3D. This method, called the
                  double reflection method, uses two reflections to
                  compute each frame from its preceding one to yield a
                  sequence of frames to approximate an exact RMF. The
                  double reflection method has the fourth order global
                  approximation error, thus it is much more accurate
                  than the two currently prevailing methods with the
                  second order approximation error—the projection
                  method by Klok and the rotation method by
                  Bloomenthal, while all these methods have nearly the
                  same per-frame computational cost. Furthermore, the
                  double reflection method is much simpler and faster
                  than using the standard fourth order Runge-Kutta
                  method to integrate the defining ODE of the RMF,
                  though they have the same accuracy. We also
                  investigate further properties and extensions of the
                  double reflection method, and discuss the
                  variational principles in design moving frames with
                  boundary conditions, based on RMF.},
  journal =      {ACM Trans. Graph.},
  month =        mar,
  articleno =    {2},
  numpages =     {18},
  keywords =     {motion design, sweep surface, motion, differential
                  geometry, Curve, rotation minimizing frame}
}
Precondition
knots and frames have num entries.
Parameters
[in]splineThe spline to query.
[in]knotsThe knots to query spline at.
[in]numNumber of elements in knots and frames. Can be 0.
[in]has_first_normalIndicates whether the normal of the first element of frames should be taken as starting value for the algorithm. If 0, the starting normal is determined based on the tangent of spline at knots[0]. Note that, if the argument value is not 0, it is up to the caller of this function to ensure that the supplied normal is valid. The function only normalizes the supplied value.
[in,out]framesStores the computed frames.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_control_point_at_ptr()

tsError TINYSPLINE_API ts_bspline_control_point_at_ptr ( const tsBSpline spline,
size_t  index,
const tsReal **  ctrlp,
tsStatus status 
)

Returns the pointer to the control point of spline at index. Note that the type of the out parameter ctrlp is const for a reason. Clients should only read the returned array. When suppressing the constness of ctrlp and writing to the array against better knowledge, the client is on its own with regard to the consistency of the internal state of spline. If one of the control points of a spline needs to be changed, use ts_bspline_set_control_points to copy the new control point to the spline.

Parameters
[in]splineThe spline whose pointer to the control point at index is returned.
[in]indexZero-based index of the control point to be returned.
[out]ctrlpPointer to the control point of spline at index.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_INDEX_ERROR If index is out of range.

◆ ts_bspline_control_points()

tsError TINYSPLINE_API ts_bspline_control_points ( const tsBSpline spline,
tsReal **  ctrlp,
tsStatus status 
)

Returns a deep copy of the control points of spline.

Parameters
[in]splineThe spline whose control points are read.
[out]ctrlpThe output array. Note: It is the responsibility of the client to release the allocated memory after use.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_control_points_ptr()

const tsReal TINYSPLINE_API* ts_bspline_control_points_ptr ( const tsBSpline spline)

Returns the pointer to the control point array of spline. Note that the return type of this function is const for a reason. Clients should only read the returned array. When suppressing the constness and writing to the array against better knowledge, the client is on its own with regard to the consistency of the internal state of spline. If the control points of a spline need to be changed, use ts_bspline_control_points to obtain a copy of the control point array and ts_bspline_set_control_points to copy the changed values back to the spline.

Parameters
[in]splineThe spline whose pointer to the control point array is returned.
Returns
Pointer to the control point array of spline.

◆ ts_bspline_copy()

tsError TINYSPLINE_API ts_bspline_copy ( const tsBSpline src,
tsBSpline dest,
tsStatus status 
)

Creates a deep copy of src and stores the copied data in dest. src and dest can be the same instance.

Note: Unlike memcpy and memmove, the first parameter is the source and the second parameter is the destination.

Parameters
[in]srcThe spline to be deep copied.
[out]destThe output spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_degree()

size_t TINYSPLINE_API ts_bspline_degree ( const tsBSpline spline)

Returns the degree of spline.

Parameters
[in]splineThe spline whose degree is read.
Returns
The degree of spline.

◆ ts_bspline_derive()

tsError TINYSPLINE_API ts_bspline_derive ( const tsBSpline spline,
size_t  n,
tsReal  epsilon,
tsBSpline deriv,
tsStatus status 
)

Returns the n'th derivative of spline as tsBSpline instance. The derivative of a spline s of degree d (d > 0) with m control points and n knots is another spline s' of degree d-1 with m-1 control points and n-2 knots, defined over s as:

\begin{eqnarray*} s'(u) &=& \sum_{i=0}^{n-1} N_{i+1,p-1}(u) * (P_{i+1} - P_{i}) * p / (u_{i+p+1}-u_{i+1}) \\ &=& \sum_{i=1}^{n} N_{i,p-1}(u) * (P_{i} - P_{i-1}) * p / (u_{i+p}-u_{i}) \end{eqnarray*}

If s has a clamped knot vector, it can be shown that:

\begin{eqnarray*} s'(u) &=& \sum_{i=0}^{n-1} N_{i,p-1}(u) * (P_{i+1} - P_{i}) * p / (u_{i+p+1}-u_{i+1}) \end{eqnarray*}

where the multiplicity of the first and the last knot value u is p rather than p+1. The derivative of a point (degree 0) is another point with coordinate 0. For more details, see:

http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-derv.html

If spline != deriv, the internal state of spline is not modified, that is, deriv is a new, independent tsBSpline instance.

Parameters
[in]splineThe spline to be derived.
[in]nNumber of derivations.
[in]epsilonThe maximum distance of discontinuous points. If negative, discontinuity is ignored and the derivative is computed based on the first result of the corresponding tsDeBoorNet.
[out]derivThe derivative of spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_UNDERIVABLE If spline is discontinuous at an internal knot and the distance between the corresponding points is greater than epsilon.
TS_MALLOC If allocating memory failed.

< Stores the intermediate result.

< Pointer to the control points of worker.

< Pointer to the knots of worker.

< Used in for loops.

< Pointer to first and second control point.

< Distance between fst and snd.

< Knots at i+deg+1 and i+1.

< Distance between kid1 and ki1.

< Used to swap worker and derivative.

◆ ts_bspline_dimension()

size_t TINYSPLINE_API ts_bspline_dimension ( const tsBSpline spline)

Returns the dimensionality of spline, that is, the number of components of its control points (ts_bspline_control_points). One-dimensional splines are possible, albeit their benefit might be questionable.

Parameters
[in]splineThe spline whose dimension is read.
Returns
The dimension of spline (>= 1).

◆ ts_bspline_domain()

void TINYSPLINE_API ts_bspline_domain ( const tsBSpline spline,
tsReal min,
tsReal max 
)

Returns the domain of spline.

Parameters
[in]splineThe spline to query.
[out]minThe lower bound of the domain of spline.
[out]maxThe upper bound of the domain of spline.

◆ ts_bspline_elevate_degree()

tsError TINYSPLINE_API ts_bspline_elevate_degree ( const tsBSpline spline,
size_t  amount,
tsReal  epsilon,
tsBSpline elevated,
tsStatus status 
)

Elevates the degree of spline by amount and stores the result in elevated. If spline != elevated, the internal state of spline is not modified, that is, elevated is a new, independent tsBSpline instance.

Parameters
[in]splineThe spline to be elevated.
[in]amountHow often to elevate the degree of spline.
[in]epsilonIn order to elevate the degree of a spline, it must be decomposed into a sequence of bezier curves (see ts_bspline_to_beziers). After degree elevation, the split points of the bezier curves are merged again. This parameter is used to distinguish between the split points of the decomposition process and discontinuity points that should be retained. A viable default value is TS_POINT_EPSILON. If negative, the resulting spline, elevated, forms a sequence of bezier curves.
[out]elevatedThe elevated spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_equidistant_knot_seq()

tsError TINYSPLINE_API ts_bspline_equidistant_knot_seq ( const tsBSpline spline,
size_t  num,
tsReal knots,
size_t  num_samples,
tsStatus status 
)

Short-cut function for ts_chord_lengths_equidistant_knot_seq. The ordering of the parameters (in particular, num_samples after knots) is aligned to ts_bspline_uniform_knot_seq so that it is easier for users to replace one call with the other.

Parameters
[in]splineThe spline to query.
[in]numNumber of knots in knots.
[out]knotsStores the generated knot sequence.
[in]num_samplesNumber of knots to be sampled for the 'reparametrization by arc length'. 200 yields a quite precise mapping (subpixel accuracy). For very, very high precision requirements, 500 should be sufficient. If 0, the default value 200 is used as fallback.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_eval()

tsError TINYSPLINE_API ts_bspline_eval ( const tsBSpline spline,
tsReal  knot,
tsDeBoorNet net,
tsStatus status 
)

Evaluates spline at knot and stores the result (see tsDeBoorNet) in net.

Parameters
[in]splineThe spline to evaluate.
[in]knotThe knot to evaluate spline at.
[out]netStores the evaluation result.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_U_UNDEFINED If spline is not defined at knot.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_eval_all()

tsError TINYSPLINE_API ts_bspline_eval_all ( const tsBSpline spline,
const tsReal knots,
size_t  num,
tsReal **  points,
tsStatus status 
)

Evaluates spline at each knot in knots and stores the evaluated points (see ts_deboornet_result) in points. If knots contains one or more knots where spline is discontinuous at, only the first point of the corresponding evaluation result is taken. After calling this function points contains exactly

num * ts_bspline_dimension(spline)
size_t TINYSPLINE_API ts_bspline_dimension(const tsBSpline *spline)
Definition: tinyspline.c:177

values.

This function is in particular useful in cases where a multitude of knots need to be evaluated, because only a single instance of tsDeBoorNet is created and reused for all evaluation tasks (therefore the memory footprint is reduced to a minimum).

Parameters
[in]splineThe spline to evaluate.
[in]knotsThe knot values to evaluate.
[in]numThe number of knots in us.
[out]pointsThe output parameter.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_U_UNDEFINED If spline is not defined at one of the knot values in us.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_free()

void TINYSPLINE_API ts_bspline_free ( tsBSpline spline)

Releases the data of spline. After calling this function, the data of spline points to NULL.

Parameters
[out]splineThe spline to be released.

◆ ts_bspline_init()

tsBSpline TINYSPLINE_API ts_bspline_init ( void  )

Creates a new spline whose data points to NULL.

Returns
A new spline whose data points to NULL.

◆ ts_bspline_insert_knot()

tsError TINYSPLINE_API ts_bspline_insert_knot ( const tsBSpline spline,
tsReal  knot,
size_t  num,
tsBSpline result,
size_t *  k,
tsStatus status 
)

Inserts knot num times into the knot vector of spline. The operation fails if result would have an invalid knot vector (i.e., multiplicity(knot) > order(result)). If spline != result, the internal state of spline is not modified, that is, result is a new, independent tsBSpline instance.

Parameters
[in]splineThe spline into which knot is inserted num times.
[in]knotThe knot to be inserted.
[in]numNumber of insertions.
[out]resultThe output spline.
[out]kStores the last index of knot in result.
statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_U_UNDEFINED If knot is not within the domain of spline.
TS_MULTIPLICITY If the multiplicity of knot in spline plus num is greater than the order of spline.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_interpolate_catmull_rom()

tsError TINYSPLINE_API ts_bspline_interpolate_catmull_rom ( const tsReal points,
size_t  num_points,
size_t  dimension,
tsReal  alpha,
const tsReal first,
const tsReal last,
tsReal  epsilon,
tsBSpline spline,
tsStatus status 
)

Interpolates a piecewise cubic spline by translating the given catmull-rom control points into a sequence of bezier curves. In order to avoid division by zero, successive control points with distance less than or equal to epsilon are filtered out. If the resultant sequence contains only a single point, a cubic point (i.e., a spline with four times the same control point) is created. Optionally, the first and last control point can be specified (see first and last).

Parameters
[in]pointsThe points to be interpolated.
[in]num_pointsThe number of points in points. If 1, a cubic point (i.e., a spline with four times the same control point) is created.
[in]dimensionThe dimensionality of the points.
[in]alphaKnot parameterization: 0 => uniform, 0.5 => centripetal, 1 => chordal. The input value is clamped to the domain [0, 1].
[in]firstThe first control point of the catmull-rom sequence. If NULL, an appropriate point is generated based on the first two points in points. If the distance between first and the first control point in points is less than or equals to epsilon, first is treated as NULL. This is necessary to avoid division by zero.
[in]lastThe last control point of the catmull-rom sequence. If NULL, an appropriate point is generated based on the last two points in points. If the distance between last and the last control point in points is less than or equals to epsilon, last is treated as NULL. This is necessary to avoid division by zero.
[in]epsilonThe maximum distance between points with "same" coordinates. That is, if the distance between neighboring points is less than or equal to epsilon, they are considered equal. For the sake of fail-safeness, the sign is removed with fabs. It is advisable to pass a value greater than zero, however, it is not necessary.
[out]splineThe interpolated spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_DIM_ZERO If dimension is 0.
TS_NUM_POINTS If num_points is 0.
TS_MALLOC If allocating memory failed.

< The points to interpolate based on points.

< Used in for loops.

< Local error handling.

< Catmull-Rom knots.

< Used to calculate derivatives.

< Processed Catmull-Rom points.

◆ ts_bspline_interpolate_cubic_natural()

tsError TINYSPLINE_API ts_bspline_interpolate_cubic_natural ( const tsReal points,
size_t  num_points,
size_t  dimension,
tsBSpline spline,
tsStatus status 
)

Interpolates a cubic spline with natural end conditions. For more details see:

https://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
http://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf
http://www.bakoma-tex.com/doc/generic/pst-bspline/pst-bspline-doc.pdf

The interpolated spline is a sequence of bezier curves connecting each point in points. Each bezier curve is of degree 3 with dimensionality dimension. The total number of control points is:

min(1, \p num_points - 1) * 4

Note: num_points is the number of points in points and not the length of points. For instance, the following point vector has num_points = 4 and dimension = 2:

[x0, y0, x1, y1, x2, y2, x3, y3]
Parameters
[in]pointsThe points to be interpolated.
[in]num_pointsThe number of points in points. If 1, a cubic point (i.e., a spline with four times the same control point) is created.
[in]dimensionThe dimensionality of the points.
[out]splineThe interpolated spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_DIM_ZERO If dimension is 0.
TS_NUM_POINTS If num_points is 0.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_is_closed()

tsError TINYSPLINE_API ts_bspline_is_closed ( const tsBSpline spline,
tsReal  epsilon,
int *  closed,
tsStatus status 
)

Checks whether the distance of the endpoints of spline is less than or equal to epsilon for the first 'ts_bspline_degree - 1' derivatives (starting with the zeroth derivative).

Parameters
[in]splineThe spline to query.
[in]epsilonThe maximum distance.
[out]closedThe output parameter. 1 if true, 0 otherwise.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_knot_at()

tsError TINYSPLINE_API ts_bspline_knot_at ( const tsBSpline spline,
size_t  index,
tsReal knot,
tsStatus status 
)

Returns the knot of spline at index.

Parameters
[in]splineThe spline whose knot is read at index.
[in]indexZero-based index of the knot to be read.
[out]knotThe output value.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_INDEX_ERROR If index is out of range.

◆ ts_bspline_knots()

tsError TINYSPLINE_API ts_bspline_knots ( const tsBSpline spline,
tsReal **  knots,
tsStatus status 
)

Returns a deep copy of the knots of spline.

Parameters
[in]splineThe spline whose knots are read.
[out]knotsThe output array. Note: It is the responsibility of the client to release the allocated memory after use.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_knots_ptr()

const tsReal TINYSPLINE_API* ts_bspline_knots_ptr ( const tsBSpline spline)

Returns the pointer to the knot vector of spline. Note that the return type of this function is const for a reason. Clients should only read the returned array. When suppressing the constness and writing to the array against better knowledge, the client is on its own with regard to the consistency of the internal state of spline. If the knot vector of a spline needs to be changed, use ts_bspline_knots to obtain a copy of the knot vector and ts_bspline_set_knots to copy the changed values back to the spline.

Parameters
[in]splineThe spline whose pointer to the knot vector is returned.
Returns
Pointer to the knot vector of spline.

◆ ts_bspline_len_control_points()

size_t TINYSPLINE_API ts_bspline_len_control_points ( const tsBSpline spline)

Returns the length of the control point array of spline.

Parameters
[in]splineThe spline whose length of the control point array is read.
Returns
The length of the control point array of spline.

◆ ts_bspline_load()

tsError TINYSPLINE_API ts_bspline_load ( const char *  path,
tsBSpline spline,
tsStatus status 
)

Loads spline from a JSON ASCII file.

Parameters
[in]pathPath of the JSON file to be loaded.
[out]splineThe output spline.
[ou]status The status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_IO_ERROR If path does not exist.
TS_PARSE_ERROR If an error occurred while parsing the contents of path.
TS_DIM_ZERO If the dimension is 0.
TS_LCTRLP_DIM_MISMATCH If the length of the control point array modulo dimension is not 0.
TS_DEG_GE_NCTRLP If the degree is greater or equals to the number of control points.
TS_NUM_KNOTS If the number of knots does not match to the number of control points plus the degree of the spline.
TS_KNOTS_DECR If the knot vector is decreasing.
TS_MULTIPLICITY If there is a knot with multiplicity greater than order.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_morph()

tsError TINYSPLINE_API ts_bspline_morph ( const tsBSpline origin,
const tsBSpline target,
tsReal  t,
tsReal  epsilon,
tsBSpline out,
tsStatus status 
)

Interpolates between origin and target with respect to the time parameter t (domain: [0, 1]; clamped if necessary). The resulting spline is stored in out. Because it is to be expected that this function is called several times in a row (e.g., to have a smooth transition from one spline to another), memory for out is allocated only if it points to NULL or if it has to be enlarged to store the result of the interpolation (which can only happen if origin or target—or both—have been changed since the last call). This way, this function can be used as follows:

tsReal t;
tsBSpline origin = ...
tsBSpline target = ...
tsBSpline morph = ts_bspline_init();
for (t = (tsReal) 0.0; t <= (tsReal) 1.0; t += (tsReal) 0.001)
    ts_bspline_morph(&origin, &target, t, ..., &morph, ...);
ts_bspline_free(&morph);

It should be noted that this function, if necessary, aligns origin and target using ts_bspline_align. In order to avoid the overhead of spline alignment, origin and target should be aligned in advance.

Parameters
[in]originOrigin spline.
[in]targetTarget spline.
[in]tThe time parameter. If 0, out becomes origin. If 1, out becomes target. Note that the value passed is clamped to the domain [0, 1].
[in]epsilonIf origin and target must be aligned, this parameter is passed ts_bspline_elevate_degree to check whether two control points, p1 and p2, are "equal", that is, the distance between p1 and p2 is less than or equal to epsilon. A viable default value is TS_POINT_EPSILON.
[out]outThe resulting spline.
Returns
[out] TS_SUCCESS On success.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_move()

void TINYSPLINE_API ts_bspline_move ( tsBSpline src,
tsBSpline dest 
)

Moves the ownership of the data of src to dest. After calling this function, the data of src points to NULL. Does not release the data of dest. src and dest can be the same instance (in this case, the data of src remains).

Parameters
[in,out]srcThe spline whose data is moved to dest.
[out]destThe spline that receives the data of src.

◆ ts_bspline_new()

tsError TINYSPLINE_API ts_bspline_new ( size_t  num_control_points,
size_t  dimension,
size_t  degree,
tsBSplineType  type,
tsBSpline spline,
tsStatus status 
)

Creates a new spline and stores the result in spline.

Parameters
[in]num_control_pointsThe number of control points of spline.
[in]dimensionThe dimension of the control points of spline.
[in]degreeThe degree of spline.
[in]typeHow to setup the knot vector of spline.
[out]splineThe output spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_DIM_ZERO If dimension is 0.
TS_DEG_GE_NCTRLP If degree >= num_control_points.
TS_NUM_KNOTS If type is TS_BEZIERS and (num_control_points % degree + 1) != 0.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_new_with_control_points()

tsError TINYSPLINE_API ts_bspline_new_with_control_points ( size_t  num_control_points,
size_t  dimension,
size_t  degree,
tsBSplineType  type,
tsBSpline spline,
tsStatus status,
double  first,
  ... 
)

Creates a new spline with given control points (varargs) and stores the result in spline. As all splines have at least one control point (with minimum dimensionality one), the first component of the first control point has a named parameter. Note that, by design of varargs in C, the last named parameter must not be float. Thus, first is of type double instead of tsReal.

Parameters
[in]num_control_pointsThe number of control points of spline.
[in]dimensionThe dimension of the control points of spline.
[in]degreeThe degree of spline.
[in]typeHow to setup the knot vector of spline.
[out]splineThe output spline.
[out]statusThe status of this function. May be NULL.
[in]firstThe first component of the first control point.
[in]...The remaining components (control points).
Returns
TS_SUCCESS On success.
TS_DIM_ZERO If dimension is 0.
TS_DEG_GE_NCTRLP If degree >= num_control_points.
TS_NUM_KNOTS If type is TS_BEZIERS and (num_control_points % degree + 1) != 0.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_num_control_points()

size_t TINYSPLINE_API ts_bspline_num_control_points ( const tsBSpline spline)

Returns the number of control points of spline.

Parameters
[in]splineThe spline whose number of control points is read.
Returns
The number of control points of spline.

◆ ts_bspline_num_knots()

size_t TINYSPLINE_API ts_bspline_num_knots ( const tsBSpline spline)

Returns the number of knots of spline.

Parameters
[in]splineThe spline whose number of knots is read.
Returns
The number of knots of spline.

◆ ts_bspline_order()

size_t TINYSPLINE_API ts_bspline_order ( const tsBSpline spline)

Returns the order (degree + 1) of spline.

Parameters
[in]splineThe spline whose order is read.
Returns
The order of spline.

◆ ts_bspline_parse_json()

tsError TINYSPLINE_API ts_bspline_parse_json ( const char *  json,
tsBSpline spline,
tsStatus status 
)

Parses json and stores the result in spline.

Parameters
[in]jsonThe JSON string to be parsed.
[out]splineThe output spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_PARSE_ERROR If an error occurred while parsing json.
TS_DIM_ZERO If the dimension is 0.
TS_LCTRLP_DIM_MISMATCH If the length of the control point array modulo dimension is not 0.
TS_DEG_GE_NCTRLP If the degree is greater or equals to the number of control points.
TS_NUM_KNOTS If the number of knots does not match to the number of control points plus the degree of the spline.
TS_KNOTS_DECR If the knot vector is decreasing.
TS_MULTIPLICITY If there is a knot with multiplicity greater than order.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_sample()

tsError TINYSPLINE_API ts_bspline_sample ( const tsBSpline spline,
size_t  num,
tsReal **  points,
size_t *  actual_num,
tsStatus status 
)

Generates a sequence of num different knots, passes this sequence to ts_bspline_eval_all, and stores the resultant points in points. The sequence of knots is generated using ts_bspline_uniform_knot_seq. If num is 0, the default value 100 is used as fallback.

For the sake of stability regarding future changes, the actual number of generated knots (which only differs from num if num is 0) is stored in actual_num. If num is 1, the point located at the minimum of the domain of spline is evaluated.

Parameters
[in]splineThe spline to be evaluate.
[in]numThe number of knots to be generate.
[out]pointsThe output parameter.
[out]actual_numThe actual number of generated knots. Differs from num only if num is 0. Must not be NULL.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_save()

tsError TINYSPLINE_API ts_bspline_save ( const tsBSpline spline,
const char *  path,
tsStatus status 
)

Saves spline as JSON ASCII file.

Parameters
[in]splineThe spline to be saved.
[in]pathPath of the JSON file.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_IO_ERROR If an error occurred while saving spline.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_set_control_point_at()

tsError TINYSPLINE_API ts_bspline_set_control_point_at ( tsBSpline spline,
size_t  index,
const tsReal ctrlp,
tsStatus status 
)

Sets the control point of spline at index. Creates a deep copy of ctrlp.

Precondition
ctrlp has length ts_bspline_dimension.
Parameters
[out]splineThe spline whose control point is set at index.
[in]indexZero-based index of the control point to be set.
[in]ctrlpThe value.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_INDEX_ERROR If index is out of range.

◆ ts_bspline_set_control_points()

tsError TINYSPLINE_API ts_bspline_set_control_points ( tsBSpline spline,
const tsReal ctrlp,
tsStatus status 
)

Sets the control points of spline. Creates a deep copy of ctrlp.

Precondition
ctrlp has length ts_bspline_len_control_points.
Parameters
[out]splineThe spline whose control points are set.
[in]ctrlpThe value.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.

◆ ts_bspline_set_knot_at()

tsError TINYSPLINE_API ts_bspline_set_knot_at ( tsBSpline spline,
size_t  index,
tsReal  knot,
tsStatus status 
)

Sets the knot of spline at index.

Parameters
[in]splineThe spline whose knot is set at index.
[in]indexZero-based index of the knot to be set.
[in]knotThe value.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_INDEX_ERROR If index is out of range.
TS_KNOTS_DECR If setting the knot at index results in a decreasing knot vector.
TS_MULTIPLICITY If setting the knot at index results in a knot vector containing knot with multiplicity greater than the order of spline.

◆ ts_bspline_set_knots()

tsError TINYSPLINE_API ts_bspline_set_knots ( tsBSpline spline,
const tsReal knots,
tsStatus status 
)

Sets the knots of spline. Creates a deep copy of knots.

Precondition
knots has length ts_bspline_num_knots.
Parameters
[out]splineThe spline whose knots are set.
[in]knotsThe value.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_KNOTS_DECR If the knot vector is decreasing.
TS_MULTIPLICITY If there is a knot with multiplicity > order

◆ ts_bspline_set_knots_varargs()

tsError TINYSPLINE_API ts_bspline_set_knots_varargs ( tsBSpline spline,
tsStatus status,
tsReal  knot0,
double  knot1,
  ... 
)

Sets the knots of spline supplied as varargs. As all splines have at least two knots, the first two knots have a named parameter. Note that, by design of varargs in C, the last named parameter must not be float. Thus, knot1 is of type double instead of tsReal.

Precondition
ts_bspline_num_knots knots are supplied as varargs.
Parameters
[out]splineThe spline whose knots are set.
[out]statusThe status of this function. May be NULL.
[in]knot0The first knot.
[in]knot1the second knot.
[in]...The remaining knots.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.
TS_KNOTS_DECR If the knot vector is decreasing.
TS_MULTIPLICITY If there is a knot with multiplicity > order

◆ ts_bspline_sof_control_points()

size_t TINYSPLINE_API ts_bspline_sof_control_points ( const tsBSpline spline)

Returns the size of the control point array of spline. This function may be useful when copying control points using memcpy or memmove.

Parameters
[in]splineThe spline whose size of the control point array is read.
Returns
The size of the control point array of spline.

◆ ts_bspline_sof_knots()

size_t TINYSPLINE_API ts_bspline_sof_knots ( const tsBSpline spline)

Returns the size of the knot array of spline. This function may be useful when copying knots using memcpy or memmove.

Parameters
[in]splineThe spline whose size of the knot array is read.
Returns
TS_SUCCESS The size of the knot array of spline.

◆ ts_bspline_split()

tsError TINYSPLINE_API ts_bspline_split ( const tsBSpline spline,
tsReal  knot,
tsBSpline split,
size_t *  k,
tsStatus status 
)

Splits spline at knot. That is, knot is inserted into spline n times such that the multiplicity of knot is equal the spline's order. If spline != split, the internal state of spline is not modified, that is, split is a new, independent tsBSpline instance.

Parameters
[in]splineThe spline to be split.
[in]knotThe split point (knot).
[out]splitThe split spline.
[out]kStores the last index of knot in split.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_U_UNDEFINED If spline is not defined at knot.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_sub_spline()

tsError TINYSPLINE_API ts_bspline_sub_spline ( const tsBSpline spline,
tsReal  knot0,
tsReal  knot1,
tsBSpline sub,
tsStatus status 
)

Extracts a sub-spline from spline with respect to the given domain [knot0, knot1]. The knots knot0 and knot1 must lie within the domain of spline and must not be equal according to ts_knots_equal. However, knot0 can be greater than knot1. In this case, the control points of the sub-spline are reversed.

Parameters
[in]splineThe spline to query.
[in]knot0Lower bound of the domain of the queried sub-spline if knot0 is less than knot1. Upper bound otherwise.
[in]knot1Upper bound of the domain of the queried sub-spline if knot1 is greater than knot0. Lower bound otherwise.
[out]subThe queried sub-spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_U_UNDEFINED If spline is not defined at knot0 or knot1.
TS_NO_RESULT If knot0 and knot1 are equal according to ts_knots_equal.
TS_MALLOC If memory allocation failed.

◆ ts_bspline_tension()

tsError TINYSPLINE_API ts_bspline_tension ( const tsBSpline spline,
tsReal  beta,
tsBSpline out,
tsStatus status 
)

Straightens the control points of spline according to beta (0 yields a line connecting the first and the last control point; 1 keeps the original shape). The value of beta is clamped to [0, 1]. If spline != out, the internal state of spline is not modified, that is, out is a new, independent tsBSpline instance.

This function is based on:

@ARTICLE{10.1109/TVCG.2006.147,
  author =       {Holten, Danny},
  journal =      {IEEE Transactions on Visualization and Computer
                  Graphics},
  title =        {Hierarchical Edge Bundles: Visualization of
                  Adjacency Relations in Hierarchical Data},
  year =         {2006},
  volume =       {12},
  number =       {5},
  pages =        {741-748},
  abstract =     {A compound graph is a frequently encountered type of
                  data set. Relations are given between items, and a
                  hierarchy is defined on the items as well. We
                  present a new method for visualizing such compound
                  graphs. Our approach is based on visually bundling
                  the adjacency edges, i.e., non-hierarchical edges,
                  together. We realize this as follows. We assume that
                  the hierarchy is shown via a standard tree
                  visualization method. Next, we bend each adjacency
                  edge, modeled as a B-spline curve, toward the
                  polyline defined by the path via the inclusion edges
                  from one node to another. This hierarchical bundling
                  reduces visual clutter and also visualizes implicit
                  adjacency edges between parent nodes that are the
                  result of explicit adjacency edges between their
                  respective child nodes. Furthermore, hierarchical
                  edge bundling is a generic method which can be used
                  in conjunction with existing tree visualization
                  techniques. We illustrate our technique by providing
                  example visualizations and discuss the results based
                  on an informal evaluation provided by potential
                  users of such visualizations.},
  keywords =     {},
  doi =          {10.1109/TVCG.2006.147},
  ISSN =         {1941-0506},
  month =        {Sep.},
}

Holten calls it "straightening" (page 744, equation 1).

Parameters
[in]splineThe spline to be straightened.
[in]betaThe straightening factor. The value is clamped to the domain [0, 1].
[out]outThe straightened spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

< The straightening factor.

< Pointer to the control points of ‘out’.

< Used in for loops.

< Straightening vector.

◆ ts_bspline_to_beziers()

tsError TINYSPLINE_API ts_bspline_to_beziers ( const tsBSpline spline,
tsBSpline beziers,
tsStatus status 
)

Decomposes spline into a sequence of Bezier curves by splitting it at each internal knot. If spline != beziers, the internal state of spline is not modified, that is, beziers is a new, independent tsBSpline instance.

Parameters
[in]splineThe spline to be decomposed.
[out]beziersThe bezier decomposition of spline.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

< Number of control points to add/remove.

< Index of the split knot value.

< Minimum of the knot values.

< Maximum of the knot values.

< Temporarily stores the result.

< Pointer to the knots of tmp.

< Number of knots in tmp.

◆ ts_bspline_to_json()

tsError TINYSPLINE_API ts_bspline_to_json ( const tsBSpline spline,
char **  json,
tsStatus status 
)

Serializes spline to a null-terminated JSON string and stores the result in json.

Parameters
[in]splineThe spline to be serialized.
[out]jsonThe serialized JSON string.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_bspline_uniform_knot_seq()

void TINYSPLINE_API ts_bspline_uniform_knot_seq ( const tsBSpline spline,
size_t  num,
tsReal knots 
)

Generates a sequence of num knots with uniform distribution. Uniform means that consecutive knots in knots have the same distance.

Parameters
[in]splineThe spline to query.
[in]numNumber of knots in knots.
[out]knotsStores the generated knot sequence.

◆ ts_chord_lengths_equidistant_knot_seq()

tsError TINYSPLINE_API ts_chord_lengths_equidistant_knot_seq ( const tsReal knots,
const tsReal lengths,
size_t  num,
size_t  num_knot_seq,
tsReal knot_seq,
tsStatus status 
)

Generates a sequence of num_knot_seq knots with equidistant distribution. Equidistant means that the points evaluated from consecutive knots in knot_seq have the same distance along the spline. This is also known as 'reparametrization by arc length'.

Precondition
lengths is monotonically increasing and contains only non-negative values (distances cannot be negative).
Parameters
[in]knotsKnots that were passed to ts_bspline_chord_lengths.
[in]lengthsCumulative chord lengths as computed by ts_bspline_chord_lengths.
[in]numNumber of values in knots and lengths.
[in]num_knot_seqNumber of knots in knot_seq.
[out]knot_seqStores the generated knot sequence.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_NO_RESULT If num is 0.

◆ ts_chord_lengths_length_to_knot()

tsError TINYSPLINE_API ts_chord_lengths_length_to_knot ( const tsReal knots,
const tsReal lengths,
size_t  num,
tsReal  len,
tsReal knot,
tsStatus status 
)

Maps len to a knot, k, such that ts_bspline_eval(..., k ...) yields a point whose length, with respect to knots[0], is close to len. Note that len is clamped to the domain of lengths. The domain of the result, knot, is [knots[0], knots[num-1]].

The precision of the mapping depends on the resolution of knots and lengths. That is, the more chord lengths were computed, the more precise the length-to-knot-mapping becomes. Generally, 200 chord lengths yields a quite precise mapping (subpixel accuracy). For very, very high precision requirements, 500 chord lengths should be sufficient.

Returns TS_NO_RESULT if num is 0.

Precondition
lengths is monotonically increasing and contains only non-negative values (distances cannot be negative).
Parameters
[in]knotsKnots that were passed to ts_bspline_chord_lengths.
[in]lengthsCumulative chord lengths as computed by ts_bspline_chord_lengths.
[in]numNumber of values in knots and lengths.
[in]lenLength to be mapped. Clamped to the domain of lengths.
[out]knotA knot, such that ts_bspline_eval(..., knot ...) yields a point whose length, with respect to knots[0], is close to len.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_NO_RESULT If num is 0.

◆ ts_chord_lengths_t_to_knot()

tsError TINYSPLINE_API ts_chord_lengths_t_to_knot ( const tsReal knots,
const tsReal lengths,
size_t  num,
tsReal  t,
tsReal knot,
tsStatus status 
)

Same as ts_chord_lengths_length_to_knot, except that this function takes a chord length parameter, t, with domain [0, 1] (clamped), which indicates the to be evaluated relative proportion of the total length (lengths[num-1]).

Precondition
lengths is monotonically increasing and contains only non-negative values (distances cannot be negative).
Parameters
[in]knotsKnots that were passed to ts_bspline_chord_lengths.
[in]lengthsCumulative chord lengths as computed by ts_bspline_chord_lengths.
[in]numNumber of values in knots and lengths.
[in]tChord length parameter (relative proportion of the total length). Clamped to the domain [0, 1].
[out]knotA knot, such that ts_bspline_eval(..., knot ...) yields a point whose length, with respect to knots[0], is close to t * lengths[num-1]
[out]status The status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_NO_RESULT If num is 0.

◆ ts_deboornet_copy()

tsError TINYSPLINE_API ts_deboornet_copy ( const tsDeBoorNet src,
tsDeBoorNet dest,
tsStatus status 
)

Creates a deep copy of src and stores the copied data in dest. src and dest can be the same instance.

Note: Unlike memcpy and memmove, the first parameter is the source and the second parameter is the destination.

Parameters
[in]srcThe net to be deep copied.
[out]destThe output net.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_deboornet_dimension()

size_t TINYSPLINE_API ts_deboornet_dimension ( const tsDeBoorNet net)

Returns the dimensionality of net, that is, the number of components of its points (ts_deboornet_points) and result (ts_deboornet_result). One-dimensional nets are possible, albeit their benefit might be questionable.

Parameters
[in]netThe net whose dimension is read.
Returns
The dimensionality of net (>= 1).

◆ ts_deboornet_free()

void TINYSPLINE_API ts_deboornet_free ( tsDeBoorNet net)

Releases the data of net. After calling this function, the data of net points to NULL.

Parameters
[out]netThe net to be released.

◆ ts_deboornet_index()

size_t TINYSPLINE_API ts_deboornet_index ( const tsDeBoorNet net)

Returns the index of the knot of net.

Parameters
[in]netThe net whose index is read.
Returns
The index [u_k, u_k+1) with u being the knot of net.

◆ ts_deboornet_init()

tsDeBoorNet TINYSPLINE_API ts_deboornet_init ( void  )

Creates a new net whose data points to NULL.

Returns
A new net whose data points to NULL.

◆ ts_deboornet_knot()

tsReal TINYSPLINE_API ts_deboornet_knot ( const tsDeBoorNet net)

Returns the knot (sometimes also referred to as u or t) of net.

Parameters
[in]netThe net whose knot is read.
Returns
The knot of net.

◆ ts_deboornet_len_points()

size_t TINYSPLINE_API ts_deboornet_len_points ( const tsDeBoorNet net)

Returns the length of the point array of net.

Parameters
[in]netThe net whose length of the point array is read.
Returns
The length of the point array of net.

◆ ts_deboornet_len_result()

size_t TINYSPLINE_API ts_deboornet_len_result ( const tsDeBoorNet net)

Returns the length of the result array of net.

Parameters
[in]netThe net whose length of the result array is read.
Returns
The length of the result array of net.

◆ ts_deboornet_move()

void TINYSPLINE_API ts_deboornet_move ( tsDeBoorNet src,
tsDeBoorNet dest 
)

Moves the ownership of the data of src to dest. After calling this function, the data of src points to NULL. Does not release the data of dest. src and dest can be the same instance (in this case, the data of src remains).

Parameters
[out]srcThe net whose data is moved to dest.
[out]destThe net that receives the data of src.

◆ ts_deboornet_multiplicity()

size_t TINYSPLINE_API ts_deboornet_multiplicity ( const tsDeBoorNet net)

Returns the multiplicity of the knot of net.

Parameters
[in]netThe net whose multiplicity is read.
Returns
The multiplicity of the knot of net.

◆ ts_deboornet_num_insertions()

size_t TINYSPLINE_API ts_deboornet_num_insertions ( const tsDeBoorNet net)

Returns the number of insertion that were necessary to evaluate the knot of net.

Parameters
[in]netThe net whose number of insertions of its knot is read.
Returns
The number of insertions that were necessary to evaluate the knot of net.

◆ ts_deboornet_num_points()

size_t TINYSPLINE_API ts_deboornet_num_points ( const tsDeBoorNet net)

Returns the number of points of net.

Parameters
[in]netThe net whose number of points is read.
Returns
The number of points of net.

◆ ts_deboornet_num_result()

size_t TINYSPLINE_API ts_deboornet_num_result ( const tsDeBoorNet net)

Returns the number of points in the result array of net (1 <= num_result <= 2).

Parameters
[in]netThe net whose number of points in the result array is read.
Returns
The number of points in the result array of net.

◆ ts_deboornet_points()

tsError TINYSPLINE_API ts_deboornet_points ( const tsDeBoorNet net,
tsReal **  points,
tsStatus status 
)

Returns a deep copy of the points of net.

Parameters
[in]netThe net whose points are read.
[out]pointsThe output array. Note: It is the responsibility of the client to release the allocated memory after use.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_deboornet_points_ptr()

const tsReal TINYSPLINE_API* ts_deboornet_points_ptr ( const tsDeBoorNet net)

Returns the pointer to the point array of net. Note that the return type of this function is const for a reason. Clients should only read the returned array. When suppressing the constness and writing to the array against better knowledge, the client is on its own with regard to the consistency of the internal state of net. To obtain a copy of the points of net, use ts_deboornet_points.

Parameters
[in]netThe net whose pointer to the point array is returned.
Returns
Pointer to the point array of net.

◆ ts_deboornet_result()

tsError TINYSPLINE_API ts_deboornet_result ( const tsDeBoorNet net,
tsReal **  result,
tsStatus status 
)

Returns a deep copy of the result of net.

Parameters
[in]netThe net whose result is read.
[out]resultThe output array. Note: It is the responsibility of the client to release the allocated memory after use.
[out]statusThe status of this function. May be NULL.
Returns
TS_SUCCESS On success.
TS_MALLOC If allocating memory failed.

◆ ts_deboornet_result_ptr()

const tsReal TINYSPLINE_API* ts_deboornet_result_ptr ( const tsDeBoorNet net)

Returns the pointer to the result array of net. Note that the return type of this function is const for a reason. Clients should only read the returned array. When suppressing the constness and writing to the array against better knowledge, the client is on its own with regard to the consistency of the internal state of net. To obtain a copy of the result of net, use ts_deboornet_result.

Parameters
[in]netThe net whose pointer to the result array is returned.
Returns
Pointer to the result array of net.

◆ ts_deboornet_sof_points()

size_t TINYSPLINE_API ts_deboornet_sof_points ( const tsDeBoorNet net)

Returns the size of the point array of net. This function may be useful when copying points using memcpy or memmove.

Parameters
[in]netThe net whose size of the point array is read.
Returns
The size of the point array of net.

◆ ts_deboornet_sof_result()

size_t TINYSPLINE_API ts_deboornet_sof_result ( const tsDeBoorNet net)

Returns the size of the result array of net. This function may be useful when copying results using memcpy or memmove.

Parameters
[in]netThe net whose size of the result array is read.
Returns
TS_SUCCESS The size of the result array of net.

◆ ts_distance()

tsReal TINYSPLINE_API ts_distance ( const tsReal x,
const tsReal y,
size_t  dim 
)

Returns the euclidean distance of the points x and y.

Parameters
[in]xFirst point.
[in]ySecond point.
[in]dimDimensionality of x and y.
Returns
The euclidean distance of the points x and y.

◆ ts_knots_equal()

int TINYSPLINE_API ts_knots_equal ( tsReal  x,
tsReal  y 
)

Returns whether the knots x and y are equal with respect to the epsilon environment TS_KNOT_EPSILON (i.e., their distance is less than TS_KNOT_EPSILON).

Parameters
[in]xFirst knot.
[in]ySecond knot.
Returns
1 If x and y are equal.
0 If x and y are not equal.

◆ ts_vec2_init()

void TINYSPLINE_API ts_vec2_init ( tsReal out,
tsReal  x,
tsReal  y 
)

Initializes vector out with x and y.

Precondition
out has dimensionality 2.
Parameters
[out]outTarget vector.
[in]xThe x value.
[in]yThe y value.

◆ ts_vec2_set()

void TINYSPLINE_API ts_vec2_set ( tsReal out,
const tsReal x,
size_t  dim 
)

Copies the values of vector x (a vector with dimensionality dim) to vector out (a vector with dimensionality 2). If dim is less than 2, the remaining values of out are set to 0. Excess values in x (i.e., dim is greater than 2) are ignored.

Precondition
out has dimensionality 2.
Parameters
[out]outTarget vector.
[in]xVector to read the values from.
[in]dimDimensionality of x.

◆ ts_vec3_cross()

void TINYSPLINE_API ts_vec3_cross ( const tsReal x,
const tsReal y,
tsReal out 
)

Computes the cross product (also known as vector product or directed area product) of the vectors x and y.

Precondition
x and y have dimensionality 3.
Parameters
[in]xFirst vector.
[in]ySecond vector.
[out]outResult vector. Can be same as x or y, i.e., the result can be stored in-place.

◆ ts_vec3_init()

void TINYSPLINE_API ts_vec3_init ( tsReal out,
tsReal  x,
tsReal  y,
tsReal  z 
)

Initializes vector out with x, y, and z.

Precondition
out has dimensionality 3.
Parameters
[out]outTarget vector.
[in]xThe x value.
[in]yThe y value.
[in]zThe z value.

◆ ts_vec3_set()

void TINYSPLINE_API ts_vec3_set ( tsReal out,
const tsReal x,
size_t  dim 
)

Copies the values of vector x (a vector with dimensionality dim) to vector out (a vector with dimensionality 3). If dim is less than 3, the remaining values of out are set to 0. Excess values in x (i.e., dim is greater than 3) are ignored.

Precondition
out has dimensionality 3.
Parameters
[out]outTarget vector.
[in]xVector to read the values from.
[in]dimDimensionality of x.

◆ ts_vec4_init()

void TINYSPLINE_API ts_vec4_init ( tsReal out,
tsReal  x,
tsReal  y,
tsReal  z,
tsReal  w 
)

Initializes vector out with x, y, z, and w.

Precondition
out has dimensionality 4.
Parameters
[out]outTarget vector.
[in]xThe x value.
[in]yThe y value.
[in]zThe z value.
[in]wThe w value.

◆ ts_vec4_set()

void TINYSPLINE_API ts_vec4_set ( tsReal out,
const tsReal x,
size_t  dim 
)

Copies the values of vector x (a vector with dimensionality dim) to vector out (a vector with dimensionality 4). If dim is less than 4, the remaining values of out are set to 0. Excess values in x (i.e., dim is greater than 4) are ignored.

Precondition
out has dimensionality 4.
Parameters
[out]outTarget vector.
[in]xVector to read the values from.
[in]dimDimensionality of x.

◆ ts_vec_add()

void TINYSPLINE_API ts_vec_add ( const tsReal x,
const tsReal y,
size_t  dim,
tsReal out 
)

Adds vector y to vector x and stores the result in vector out.

Parameters
[in]xFirst vector.
[in]ySecond vector.
[in]dimDimensionality of x, y, and out.
[out]outResult vector. Can be same as x or y, i.e., the result can be stored in-place.

◆ ts_vec_angle()

tsReal TINYSPLINE_API ts_vec_angle ( const tsReal x,
const tsReal y,
tsReal buf,
size_t  dim 
)

Computes the angle in degrees between the vectors x and y. The angle returned is unsigned, that is, the smaller of the two possible angles is computed. The nullable parameter buf servers as a buffer in case x or y (or both) are not normalized. If buf is NULL, it is expected that x and y are already normalized. If buf is not NULL, a storage twice the size of dim is expected in which the normalized vectors of x and y are stored.

Precondition
buf is either NULL or has length 2 * dim.
Parameters
[in]xFirst vector.
[in]ySecond vector.
[out]bufA buffer in which the normalized vectors of x and \y are stored. If NULL, it is expected that x and y are already normalized.
[in]dimDimensionality of x and y.
Returns
The angle between x and \y with 0.0 <= angle <= 180.0.

◆ ts_vec_dot()

tsReal TINYSPLINE_API ts_vec_dot ( const tsReal x,
const tsReal y,
size_t  dim 
)

Computes the dot product (also known as scalar product) of the vectors x and y.

Postcondition
0 if dim is 0.
Parameters
[in]xFirst vector.
[in]ySecond vector.
[in]dimDimensionality of x and y.
Returns
The dot product of x and \y.

◆ ts_vec_mag()

tsReal TINYSPLINE_API ts_vec_mag ( const tsReal x,
size_t  dim 
)

Determines the length of vector x.

Postcondition
0 if dim is 0.
Parameters
[in]xA vector.
[in]dimDimensionality of x.

◆ ts_vec_mul()

void TINYSPLINE_API ts_vec_mul ( const tsReal x,
size_t  dim,
tsReal  val,
tsReal out 
)

Multiplies vector x with scalar val and stores the result in vector out.

Parameters
[in]xA vector.
[in]dimDimensionality of x.
[in]valScalar value.
[out]outResult vector. Can be same as x, i.e., the result can be stored in-place.

◆ ts_vec_norm()

void TINYSPLINE_API ts_vec_norm ( const tsReal x,
size_t  dim,
tsReal out 
)

Normalizes vector x.

Postcondition
0 if the length of x (see ts_vec_mag) is less than TS_LENGTH_ZERO.
Parameters
[in]xA vector.
[in]dimDimensionality of x.
[out]outResult vector. Can be same as x, i.e., the result can be stored in-place.

◆ ts_vec_sub()

void TINYSPLINE_API ts_vec_sub ( const tsReal x,
const tsReal y,
size_t  dim,
tsReal out 
)

Subtracts vector y from vector x and stores the result in vector out.

Parameters
[in]xFirst vector.
[in]ySecond vector.
[in]dimDimensionality of x, y, and out.
[out]outResult vector. Can be same as x or y, i.e., the result can be stored in-place.