Skip to content

ANSI C library for NURBS, B-Splines and Bézier curves with wrappers for C++11, C#, Java, Python, and Ruby

License

Notifications You must be signed in to change notification settings

giumas/_tinyspline

 
 

Repository files navigation

TinySpline

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.

About

ANSI C library for NURBS, B-Splines and Bézier curves with wrappers for C++11, C#, Java, Python, and Ruby

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C 60.6%
  • CMake 22.4%
  • C++ 12.5%
  • Python 3.8%
  • Ruby 0.7%