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.

Github星跟蹤圖

TinySpline

Build Status
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 library is
implemented in ANSI C (C89) and provides a wrapper for C++ along with
auto-generated bindings for C#, D, Go, Java, Lua, Octave, PHP, Python, R, and
Ruby.

License

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

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 in the form of easy-to-use macros. All you need to do is to
 * embed your code into TS_TRY/TS_END_TRY 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 in TS_CATCH. TS_FINALLY contains code that is executed
 * in any case, therefore being perfectly suitable for cleaning up resources.
 * Yet, error handling is entirely optional. You may omit TS_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, &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;
}

Installation

Prebuilt Binaries

Snapshot releases are available at
releases.

Compiling From Source

TinySpline uses the CMake build system to compile and package its interfaces.
The following compiler suites are tested: GCC, Clang, and MSVC. In order to
create the bindings, Swig (3.0.1 or later) must be available. Each binding may
have further dependencies to generate the source code of the target language.
The following table gives an overview:

Language, Dependencies to Generate Source, (Relative) Output Directory
--------, -------------------------------, ---------------------------
C#, csharp
D, -, dlang
Golang, -, go
Java, Java Development Kit, org/tinyspline
Lua, Lua headers, lua
Octave, Octave headers, octave
PHP, PHP (Zend) headers *, php
Python, Python headers, python
R, R headers and RCPP, r
Ruby, Ruby headers, ruby

  • Please note that macOS comes with PHP, but does not provide the Zend headers.
    It is recommended to use a package manager (such as Homebrew) to obtain the
    headers.

The following tools are required if you want to compile and package the
the source code files of the corresponding binding:

Language, Required Tool(s), Output File
--------, --------------------------------, ----------------
C#, Any of: csc, mcs, dmcs, gmcs, TinySpline.dll
Java, javac and jar (available in JDK), tinyspline.jar

Checkout the repository and cd into it:

git clone git@github.com:msteinbeck/tinyspline.git tinyspline
cd tinyspline

Afterwards, create a build directory and cd into it:

mkdir build
cd build

Finally, run CMake and build the project:

cmake ..
cmake --build .

If you want to build a specific binding, use -DTINYSPLINE_ENABLE_<LANGUAGE>
when setting up cmake (<LANGUAGE> is interface you want to build) . For
example:

cmake -DTINYSPLINE_ENABLE_PYTHON=True ..
cmake --build .

To enable all interfaces, use -DTINYSPLINE_ENABLE_ALL_INTERFACES:

cmake -DTINYSPLINE_ENABLE_ALL_INTERFACES=True ..
cmake --build .

You will find the resultant libraries and packages in tinyspline/build/lib.

Python 2 vs. Python 3

While generating the Python binding, Swig needs to distinguish between Python 2
and Python 3. That is, Swig uses the command line parameter -py to generate
Python 2 compatible code and -py3 to generate Python 3 compatible code.
Accordingly, Swig is configured depending on the Python version found by CMake
during initialization. On systems with multiple versions of Python installed,
CMake usually chooses the more recent one. If you want to use a specific
version of Python instead, set the environment variable
'TINYSPLINE_PYTHON_VERSION' to '2' or '3'.TINYSPLINE_VERSION

The following example shows how to force CMake to use Python 2 rather than
Python 3:

TINYSPLINE_PYTHON_VERSION=2 cmake ..

Install the C and C++ Libraries

The following command installs TinySpline to your system:

cmake --build . --target install

This command also installs a set of CMake config scripts and pkg-config files
(for the C and C++ interface respectively). The CMake config script of the C
interface exports the following variables:

  • TINYSPLINE_INCLUDE_DIRS: Contain the header files.
  • TINYSPLINE_LIBRARY_DIRS: Contain the libraries.
  • TINYSPLINE_LIBRARIES: Shared libraries to link against.
  • TINYSPLINE_DEFINITIONS: Definitions to add with add_definitions.
  • TINYSPLINE_VERSION: The version string.

The CMake config script of the C++ interface exports the same variables except
that they have prefix TINYSPLINECXX, e.g. TINYSPLINECXX_INCLUDE_DIRS.

Use the CMake commands find_package(tinyspline) (C) and
find_package(tinysplinecxx) (C++) to include TinySpline into your project.

Install the Bindings

Depending on your configuration, binding-related distribution files are
generated within the root of your build directory. For example, the file
setup.py is generated if Python is enabled. Currently, the following
build tools are supported: Setuptools (Python), Maven (Java), and
Luarocks (Lua).

Theoretical Backgrounds

(http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/bspline-curve.html) is a very good starting point for B-Splines.

(http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/B-spline/de-Boor.html) explains De Boor's Algorithm and gives some pseudo code.

(http://www.codeproject.com/Articles/996281/NURBS-curve-made-easy) provides a good overview of NURBS with some mathematical background.

(http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/NURBS/NURBS-def.html) is useful if you want to use NURBS in TinySpline.

主要指標

概覽
名稱與所有者msteinbeck/tinyspline
主編程語言C
編程語言CMake (語言數: 13)
平台
許可證MIT License
所有者活动
創建於2014-09-25 20:13:48
推送於2024-09-03 22:18:21
最后一次提交2024-04-11 08:56:08
發布數6
最新版本名稱v0.6.0 (發布於 )
第一版名稱0.1.3 (發布於 )
用户参与
星數1.3k
關注者數63
派生數211
提交數2.4k
已啟用問題?
問題數190
打開的問題數24
拉請求數48
打開的拉請求數2
關閉的拉請求數13
项目设置
已啟用Wiki?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?