ProHolz / tinyspline

ANSI C library for NURBS, B-Splines, and Bézier curves with interfaces for C++, C#, D, Go, Java, Lua, Octave, PHP, Python, R, and Ruby.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TinySpline

CI Language grade: C/C++

TinySpline is a small, yet powerful library for interpolating, transforming, and querying arbitrary NURBS, B-Splines, and Bézier curves. The core of the library is written in ANSI C (C89) with a C++ wrapper for an object-oriented programming model. Based on the C++ wrapper, auto-generated bindings for C#, D, Go, Java, Javascript, Lua, Octave, PHP, Python, R, and Ruby are provided.

License

MIT License - see the LICENSE file in the source distribution.

Installation

Pre-built Binaries

Releases can be downloaded from the releases page.

In addition, the following package manager are supported:

Conan (C/C++):
https://conan.io/center/tinyspline

Luarocks (Lua; currently only Linux and macOS):

luarocks install --server=https://msteinbeck.github.io/tinyspline/luarocks tinyspline

Maven (Java):

<dependency>
   <groupId>org.tinyspline</groupId>
   <artifactId>tinyspline</artifactId>
   <version>0.3.0-2</version>
</dependency>

PyPI (Python):

python -m pip install tinyspline

Compiling From Source

See BUILD.md.

Getting Started

The following listing uses the ANSI C interface:

#include "tinyspline.h"
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
	tsStatus status;   /**< Used for error handling. */

	tsBSpline spline;  /**< The spline to setup. */
	tsReal *ctrlp;     /**< Pointer to the control points of `spline`. */

	tsBSpline beziers; /**< `spline` as a sequence of bezier curves. */

	tsDeBoorNet net;   /**< Used to evaluate `spline` and `beziers`. */
	tsReal *result;    /**< Pointer to the result of `net`. */

/* ------------------------------------------------------------------------- */
/* TinySpline includes a powerful, system-independent, and thread-safe error
 * handling system. Embed your code into a TS_TRY/TS_END_TRY block and use
 * TS_CALL when calling a TinySpline function. Likewise, you can use any of
 * the TS_THROW macros to raise an error if an external function (e.g.,
 * malloc) failed.
 *
 * Errors can be handled with TS_CATCH. TS_FINALLY contains code that is
 * executed in any case, therefore being perfectly suitable for cleaning up
 * resources. That said, error handling is entirely optional. You may omit
 * TS_TRY/TS_END_TRY, TS_CALL, and TS_THROW and pass NULL instead of a pointer
 * to a tsStatus object. */

	spline = ts_bspline_init();
	beziers = ts_bspline_init();
	net = ts_deboornet_init();
	ctrlp = result = NULL;
	TS_TRY(try, status.code, &status)
		/* Create a spline... */
		TS_CALL(try, status.code, ts_bspline_new(
			7, /* ... consisting of 7 control points... */
			2, /* ... in 2D... */
			3, /* ... of degree 3... */
			TS_CLAMPED, /* ... using a clamped knot vector. */
			&spline, &status))

		/* Setup control points of `spline`. */
		TS_CALL(try, status.code, ts_bspline_control_points(
			&spline, &ctrlp, &status))
		ctrlp[0]  = -1.75f; /* x0 */
		ctrlp[1]  = -1.0f;  /* y0 */
		ctrlp[2]  = -1.5f;  /* x1 */
		ctrlp[3]  = -0.5f;  /* y1 */
		ctrlp[4]  = -1.5f;  /* x2 */
		ctrlp[5]  =  0.0f;  /* y2 */
		ctrlp[6]  = -1.25f; /* x3 */
		ctrlp[7]  =  0.5f;  /* y3 */
		ctrlp[8]  = -0.75f; /* x4 */
		ctrlp[9]  =  0.75f; /* y4 */
		ctrlp[10] =  0.0f;  /* x5 */
		ctrlp[11] =  0.5f;  /* y5 */
		ctrlp[12] =  0.5f;  /* x6 */
		ctrlp[13] =  0.0f;  /* y6 */
		TS_CALL(try, status.code, ts_bspline_set_control_points(
			&spline, ctrlp, &status))

		/* Evaluate `spline` at u = 0.4. */
		TS_CALL(try, status.code, ts_bspline_eval(
			&spline, 0.4f, &net, &status))
		TS_CALL(try, status.code, ts_deboornet_result(
			&net, &result, &status))
		printf("x = %f, y = %f\n", result[0], result[1]);

		/* Derive `spline` ... */
		TS_CALL(try, status.code, ts_bspline_derive(
			&spline, 1, TS_CONTROL_POINT_EPSILON,
			&beziers, &status))
		/* ... and subdivide it into a sequence of Bezier curves. */
		TS_CALL(try, status.code, ts_bspline_to_beziers(
			&beziers, &beziers, &status))

		ts_deboornet_free(&net);
		free(result);
		/* Evaluate `beziers` at u = 0.3. */
		TS_CALL(try, status.code, ts_bspline_eval(
			&beziers, 0.3f, &net, &status))
		TS_CALL(try, status.code, ts_deboornet_result(
			&net, &result, &status))
		printf("x = %f, y = %f\n", result[0], result[1]);
	TS_CATCH(status.code)
		puts(status.message);
	TS_FINALLY
		ts_bspline_free(&spline);
		ts_bspline_free(&beziers);
		ts_deboornet_free(&net);
		if (ctrlp)
			free(ctrlp);
		if (result)
			free(result);
	TS_END_TRY

	return status.code? 1 : 0;
}

The same example using the C++ interface:

#include <iostream>
#include "tinysplinecpp.h"

int main(int argc, char **argv)
{
	// Create a cubic spline with 7 control points in 2D using
	// a clamped knot vector. This call is equivalent to:
	// tinyspline::BSpline spline(7, 2, 3, TS_CLAMPED);
	tinyspline::BSpline spline(7);

	// Setup control points.
	std::vector<tinyspline::real> ctrlp = spline.controlPoints();
	ctrlp[0]  = -1.75; // x0
	ctrlp[1]  = -1.0;  // y0
	ctrlp[2]  = -1.5;  // x1
	ctrlp[3]  = -0.5;  // y1
	ctrlp[4]  = -1.5;  // x2
	ctrlp[5]  =  0.0;  // y2
	ctrlp[6]  = -1.25; // x3
	ctrlp[7]  =  0.5;  // y3
	ctrlp[8]  = -0.75; // x4
	ctrlp[9]  =  0.75; // y4
	ctrlp[10] =  0.0;  // x5
	ctrlp[11] =  0.5;  // y5
	ctrlp[12] =  0.5;  // x6
	ctrlp[13] =  0.0;  // y6
	spline.setControlPoints(ctrlp);

	// Evaluate `spline` at u = 0.4 using 'eval'.
	std::vector<tinyspline::real> result = spline.eval(0.4).result();
	std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl;

	// Derive `spline` and subdivide it into a sequence of Bezier curves.
	tinyspline::BSpline beziers = spline.derive().toBeziers();

	// Evaluate `beziers` at u = 0.3 using '()' instead of 'eval'.
	result = beziers(0.3).result();
	std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl;

	return 0;
}

Theoretical Backgrounds

[1] is a very good starting point for B-Splines.

[2] explains De Boor's Algorithm and gives some pseudo code.

[3] provides a good overview of NURBS with some mathematical background.

[4] is useful if you want to use NURBS in TinySpline.

About

ANSI C library for NURBS, B-Splines, and Bézier curves with interfaces for C++, C#, D, Go, Java, Lua, Octave, PHP, Python, R, and Ruby.

License:MIT License


Languages

Language:C 63.8%Language:CMake 19.7%Language:Shell 5.0%Language:C++ 5.0%Language:SWIG 4.5%Language:Dockerfile 1.9%Language:Makefile 0.1%