TinySpline is library for NURBS, B-Splines, and Bézier curves giving you access to several operations on splines. The library has been implemented in C (C89) and provides a wrapper for C++ (C++11) along with bindings for C#, Java, Python, and Ruby. The focus of TinySpline is to be very small by design with a minimum set of dependencies. Nonetheless, the interface has been developed to be convenient for non-experts without lacking enhanced features.
###License MIT License - see the LICENSE file in the source distribution.
###Some Features of This Library
- Use a single struct for NURBS, B-Splines, Bézier curves, lines, and points.
- Support for opened and clamped splines.
- Create splines of any degree and dimension.
- Evaluate splines using De Boor's algorithm.
- Interpolate cubic splines using the Thomas algorithm.
- Insert knots and split splines without modifying the shape.
- Derive splines of any degree.
- Subdivide splines into Bézier curves.
- A wrapper for C++ (C++11) and bindings for C#, Java, Python, and Ruby.
- Easy to use with OpenGL.
Feel free to ask for special features or to contribute to TinySpline :).
###Project Structure
The source distribution of TinySpline consists of two sub projects. The first one is the
library itself that is located in the library
directory. It contains all files that
are required to build TinySpline. The second sub project provides some basic examples and
is located in the examples
directory.
The core of TinySpline has been implemented in C and consists of the files tinyspline.h
and tinyspline.c
. In order to use the C interface of TinySpline you can either copy
those files into your project or use CMake to create a static or shared library.
The C++ wrapper consists of the files tinysplinecpp.h
and tinysplinecpp.cpp
. As for
the C interface, you can copy those files (along with tinyspline.h
and tinyspline.c
)
into your project or use CMake to create a static or shared library.
All bindings of TinySpline work on top of the C++ wrapper and are generated with
Swig. The file tinyspline.i
is used to configure language
independent settings. The file tinysplineXYZ
adds language related features (e.g.
properties for Python). Using CMake to create the bindings is recommended.
Note: Use the file debugging.h
to add some debugging features to the C interface.
###Getting Started The following listing uses the C++ wrapper to give a short example of TinySpline:
// Create a clamped spline of degree 3 in 2D consisting of 7 control points.
ts::BSpline spline(3, 2, 7, TS_CLAMPED);
// Setup the control points.
std::vector<float> ctrlp = spline.ctrlp();
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
spline.setCtrlp(ctrlp);
// Evaluate `spline` at u = 0.4
std::vector<float> result = spline.evaluate(0.4f).result();
std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl;
// Derive `spline` and subdivide it into a sequence of Bezier curves.
ts::BSpline beziers = spline.derive().toBeziers();
// Evaluate `beziers` at u = 0.3
result = beziers(0.3f).result(); // you can use '()' instead of 'evaluate'
std::cout << "x = " << result[0] << ", y = " << result[1] << std::endl;
###Installation
####Compiling From Source TinySpline uses the CMake build system to compile and package the interfaces. The C library has been implemented in C89 and, thus, should be compilable with nearly every compiler. All other features of TinySpline are optional and will be disabled if CMake does not find the required dependencies. However, CMake and an appropriate C/C++ compiler must be available, regardless of the interface you want to build. TinySpline supports any of the following compiler suites: gcc, clang, and msvc. In order to compile the C++ wrapper or any of the bindings, your compiler suite (e.g. gcc) must support C++11. Additionally, Swig (in version 3.0.1 or above) is required to generate the bindings. Along Swig, 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 |
Java | JNI headers | so/tinyspline |
Python | Python headers | python |
Ruby | Ruby headers | ruby |
To simplify the usage of the bindings, the generated source files will be compiled and/or packaged if necessary. That is, for instance, the generated Java files will be compiled to .class files and packaged into a single jar archive. Thus, the following tools are required if you want to package 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 |
The remaining bindings do not need to be packaged (usually the script languages).
Now let's start building TinySpline. First of all, check out the repository and change into the root directory:
git clone git@github.com:retuxx/tinyspline.git tinyspline
cd tinyspline
Afterwards, create a build directory and change into it:
mkdir build
cd build
Finally, run CMake and build the libraries:
cmake ..
cmake --build .
You will find the resulting libraries, jars, etc. in tinyspline/build/library
.
####Cross Compiling
In order to cross compile the C and C++ library, use one of the provided toolchain files.
Currently, toolchain files for MinGW, ARM, and AVR are available at the root directory of
the source distribution (e.g. Toolchain-arm.cmake
). Use the following command within
your build directory to cross compile TinySpline to the desired platform:
cmake -DCMAKE_TOOLCHAIN_FILE=<path to root dir of tinypsline>/Toolchain-*.cmake ..
####Python 2 vs. Python 3
Swig needs to distinguish between Python 2 and Python 3 in order to generate source code
that is compatible with the used environment. That is, Swig requires the parameter -py
to generate Python 2 compatible code and -py3
to generate Python 3 compatible code.
Thus, the CMake file used to compile and package the libraries, configures Swig according
to the version of the Python instance that was found during initialization. On systems
with multiple versions of Python installed, CMake aims to use the most recent one. If you,
on the other hand, want to use a specific version of Python, the environment variables
PYTHON_LIBRARY
and PYTHON_INCLUDE_DIR
need to be defined. Use PYTHON_LIBRARY
to set
the location of the shared library of the desired Python version and PYTHON_INCLUDE_DIR
to set the location of the appropriate header files. CMake requires both environment
variables to be defined to properly detect the right Python instance. Thus, the default
behaviour is used if one of them is undefined.
The following example shows how to force CMake to use Python 2 rather than Python 3 on Ubuntu:
export PYTHON_LIBRARY=/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so
export PYTHON_INCLUDE_DIR=/usr/include/python2.7
cmake ..
####Ruby Interface File
Unlike other programming languages such as Java and C#, Ruby bindings do not require
additional interface files (.rb files) in order to give access to the underlaying C/C++
functions. However, the CMakeLists.txt
file located in library
creates such a file to
provide a more convenient interface. That is, the default module name tinysplineruby
(created by CMake and SWIG) is renamed to Tinyspline
. Furthermore, set properties are
added to the classes BSpline
and DeBoorNet
in order to simplify the assignment of
control points and knots. Thus, the usage of the interface file tinyspline.rb
is
recommended.
####Install the C and C++ Libraries The following command installs TinySpline:
cmake --build . --target install
However, there are several binding related files that CMake does not install with this command because some languages use their own approach to install files to your system. Python, for instance, uses Distutils/Setuptools to copy the resulting files to Python specific installation directories CMake is not aware of. Thus, TinySpline ships further, language related distribution tools that will be explained in the following sections.
####Install the Python Binding
The root directory of TinySpline contains the Python script setup.py
which uses
Setuptools to wrap the CMake build process. Additionally, it copies the resulting files to
the appropriate Python installation directory. Use the following command to build and
install the Python binding of TinySpline:
python setup.py install
Note that you may need root privileges to copy the files to the desired installation directory.
Unfortunately, the script is not able to determine the location of the Python library and
header files of the Python instance that was used to run the script. Thus, you may have to
use the approach explained above in case your system provides Python 2 and Python 3
simultaneously. Otherwise, CMake may generate a binding for Python 3 which gets installed
to a Python 2 directory. The following examples shows how to define the environment
variables PYTHON_LIBRARY
and PYTHON_INCLUDE_DIR
to make sure CMake generates a Python
2 binding on Ubuntu:
export PYTHON_LIBRARY=/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so
export PYTHON_INCLUDE_DIR=/usr/include/python2.7
python setup.py install
####Install the Java Binding
There are several tools to manage the build process of software implemented in Java.
TinySpline uses Maven to create and install the Java binding as Maven is used in many
other projects and is well supported by various integrated development environments. You
will find the pom.xml
file that is used to configure Maven in the root directory of the
source distribution. This file follows the usual mantra of wrapping the CMake build
process to create the binding. Additionally, the shared library that is required to use
the binding gets packaged into the jar archive. Use the following command to create and
install the archive into your local maven repository:
mvn install
If you run the above command on systems that do not support Unix makefiles by default (for
instance the Windows operating system), you may get the following error message: "CMake
Error: Could not create named generator Unix makefiles". This error results from the
cmake-maven-project plug-in
that requires an actual CMake generator to properly wrap the build process. That is, if
you skip the generator configuration of cmake-maven-project
, it fails with: "The
parameters 'generator' for goal
com.googlecode.cmake-maven-project:cmake-maven-plugin:3.4.1-b1:generate are missing or
invalid". Thus, Maven has been configured to use the Unix makefiles generator by default.
However, open the file pom.xml
with you preferred text editor and replace the line:
<generator>Unix Makefiles</generator>
with one of the generators listed at: http://www.cmake.org/cmake/help/v2.8.10/cmake.html#section_Generators. Afterwards, build TinySpline with your new generator configuration:
maven clean install
####Install the C# and Ruby Bindings Currently, TinySpline does not provide tools to install the bindings for C# and Ruby. However, adding such tools is planned for the future. If you have experience with, for instance, Ruby gems and Rake, feel free to create a pull request :).
###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.