SWIG and CGAL-Bindings

SWIG

The Simplified Wrapper and Interface Generator (SWIG) is an open-source software tool used to connect computer programs or libraries written in C or C++ with scripting languages.

How it works

The aim is to allow the calling of native functions (that were written in C or C++) by other programming languages, passing complex data types to those functions, keeping memory from being inappropriately freed, inheriting object classes across languages, etc. The programmer writes an interface file containing a list of C/C++ functions to be made visible to an interpreter. SWIG will compile the interface file and generate code in regular C/C++ and the target programming language. SWIG will generate conversion code for functions with simple arguments; conversion code for complex types of arguments must be written by the programmer. The SWIG tool creates source code that provides the glue between C/C++ and the target language.

SWIG Documentation

More explication

Simple example

This example is extract from the link above just in case the link becomes unavailable. However, the link remains much more complete.

For the example, let’s take this very simple C++ class:

#ifndef NOMBRE_H
#define NOMBRE_H

class Nombre
{
public:
    Nombre();
    Nombre(double v);
    void setV(double v);
    double getV();
    double carre();

private:
    double valeur;
};

#endif // NOMBRE_H

And here is the simplest SWIG interface file ever:

%module myext
%{
#include "nombre.h"
%}
%include "nombre.h"

This file actually has three instructions.

  • The first, %module myext, indicates the name of the extension, in this case myext. This is the name that will be used with Python or Ruby for import or require.

  • The second instruction consists of the block framed by the tags %{ and %}. Everything between these tags will be reported directly in the header of the generated wrap file. As our file is supposed to be the interface between our scripting language and our class, it seems logical to include the header of our Number class.

  • Finally, the last instruction %include “number.h” indicates to include the header number.h in this place. This actually has the same effect as copying the contents of the file over to that location. This part is the part SWIG is being asked to interface.

Of course this one can be much more complete and complex (see the links) but this one is sufficient for a first use.

CGAL-Bindings

The CGAL (Computational Geometry Algorithms Library) Bindings project allows to use some packages of CGAL, the Computational Algorithms Library, in languages other than C++, as for example Java and Python. The bindings are implemented with SWIG.

The project is still experimental.

Wiki

CGAL

Debug in command prompt

In order to be able to use CGAL in a command prompt (for debuging or test), please follow the following steps:

  • Go to code tympan build debug folder :
    • cd C:\projects\code_tympan_build_d

  • Activate Python virtual env
    • C:\dists\python\venv37tympan\Scripts\activate.bat

  • Setting up the Tympanum environment :
    • SetEnvTympanTests.bat

  • Launch the python interpreter :
    • Python

  • Declare the path to the CGAL_BINDINGS module to be able to import the python packages; these are the first lines of altimetry/__init__.py :
    • Import os

    • Import sys

    • CGAL_BINDINGS_PATH = os.environ.get(“CGAL_BINDINGS_PATH”)

    • Sys.path.append(CGAL_BINDINGS_PATH)

Simple example

The main use of CGAL in Tympan turn around the Delaunay triangulation.

CGAL provides us with an example that comes close to our use case (the example uses triangulation_2 and we use triangulation_plus_2 but the behavior is very similar):

from CGAL.CGAL_Kernel import Point_2
from CGAL.CGAL_Triangulation_2 import Constrained_Delaunay_triangulation_2
from CGAL.CGAL_Triangulation_2 import Constrained_Delaunay_triangulation_2_Vertex_handle
from CGAL import CGAL_Mesh_2

cdt=Constrained_Delaunay_triangulation_2()

#construct a constrained triangulation
va = cdt.insert(Point_2( 5., 5.))
vb = cdt.insert(Point_2(-5., 5.))
vc = cdt.insert(Point_2( 4., 3.))
vd = cdt.insert(Point_2( 5.,-5.))
ve = cdt.insert(Point_2( 6., 6.))
vf = cdt.insert(Point_2(-6., 6.))
vg = cdt.insert(Point_2(-6.,-6.))
vh = cdt.insert(Point_2( 6.,-6.))

cdt.insert_constraint(va,vb)
cdt.insert_constraint(vb,vc)
cdt.insert_constraint(vc,vd)
cdt.insert_constraint(vd,va)
cdt.insert_constraint(ve,vf)
cdt.insert_constraint(vf,vg)
cdt.insert_constraint(vg,vh)
cdt.insert_constraint(vh,ve)

print "Number of vertices before: ", cdt.number_of_vertices()

#make it conforming Delaunay
CGAL_Mesh_2.make_conforming_Delaunay_2(cdt)

print "Number of vertices after make_conforming_Delaunay_2: ", cdt.number_of_vertices()

#then make it conforming Gabriel
CGAL_Mesh_2.make_conforming_Gabriel_2(cdt)

print "Number of vertices after make_conforming_Gabriel_2: ", cdt.number_of_vertices()

Issue with CGAL and CGAL Bindings

On April 4, 2022, following a decision to upgrade CGAL (to 5.4) and the corresponding version of CGAL bindings, a bug was discovered traced in the following issue: Issue