Claw  1.7.3
Bézier curves

The claw::math::curve class is a C++ implementation of the parametrized curves known as Bézier curves.


The Bézier curves are defined by a starting point P0, an end point Pn and a sequence of points (P1, …, Pn-1) controlling the direction of the curve between P0 and Pn. The points of the curve are then defined for a given fraction t ∈ [0, 1] of the length of the curve by the following equations:

\[ B(t) = \sum_{j=0}^n \left( \begin{array}{c} n \\ j \end{array}\right) P_jt^j(1-t)^{n-j} \quad t \in [0, 1] \]

A curve in Claw is defined by a sequence of points pj through which the curve goes. A section sj of the curve is then defined as two successive points (pj, pj+1). The equations of Bézier, restricted to the cubic case (n=3), are used to describe the shape of each section. This shape is controlled by the output direction oj of its first point and the input direction ij+1 of its last point. The equation of a section sj is written as follows:

\[ B_j(t) = (1-t)^3p_j + 3(1-t)^2to_j + 3(1-t)t^2i_{j+1} + t^3p_{j+1} \quad t \in [0, 1] \]

One can then build complex curves by concatenating several sections.

The library provides the following functionalities:

The curve class

The curve class is defined as follows:

template< typename C, typename Traits = coordinate_traits<C> >
class curve
typedef C coordinate_type;
typedef Traits traits_type;
typedef typename traits_type::value_type value_type;
// see below for the details
class control_point;
typedef implementation_defined iterator;
typedef implementation_defined const_iterator;
// see below for the details
class section
// see below for the details
class resolved_point;
}; // class section
void push_back( const control_point& p );
void push_front( const control_point& p );
void insert( const iterator& pos, const control_point& p );
section get_section( const const_iterator& pos ) const;
std::vector<typename section::resolved_point>
get_point_at_x( value_type x, bool off_domain = false ) const;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
}; // class curve

The curve class is parametrized by the type of the coordinates, named C, and the traits to use to access their properties, named Traits.

The class claw::math::coordinate_2d is a good candidate for C, but any class can be used as long as Traits provides an implementation for the the following interface:

struct traits_interface
typedef implementation_defined coordinate_type;
typedef implementation_defined value_type;
static value_type get_x( const coordinate_type& c );
static value_type get_y( const coordinate_type& c );
static coordinate_type make_coordinate( value_type x, value_type y );
}; // struct traits_interface

The control_point class

The control point class is the aggregation of a coordinate through which the curve goes (the position of the point), and two points defining the direction from which the curve respectively "enters and leaves" the point. Those input and output points are relative to the same origin than the curve's point (i.e. their coordinates are not relative to the curve's point itself).

The interface of the class is as follows:

class control_point
explicit control_point( const coordinate_type& p );
( const coordinate_type& p, const coordinate_type& input_direction,
const coordinate_type& output_direction );
const coordinate_type& get_position() const;
const coordinate_type& get_input_direction() const;
const coordinate_type& get_output_direction() const;
}; // class control_point

Note: building a control point as follows

coordinate_type c;
control_point p( c )

is equivalent to the following code

coordinate_type c;
control_point p( c, c, c )

Accessing the control points of a curve

The control points of the curve can be accessed using iterators implementing the concept of ForwardIterator and BackwardIterator. The begin() and end() methods return an iterator respectively on the first control point of the curve or just past the last control point of the curve. If the call is done on a const curve then a const_iterator is returned.

Adding a control point to a curve

Several methods can be used to insert a control point in a curve:

Note: Please note that inserting a point in the curve between the beginning and the end of a section will invalidate the section.

The resolved_point class

The resolved point class represents the result of the computation of a point on the curve from an other parameter than t.

The interface of the class is defined as follows:

class resolved_point
const coordinate_type& get_position() const;
const section& get_section() const;
double get_date() const;
}; // class resolved_point

The interface presents the following methods:

The section class

A section describes a part of a curve represented by two successive control points. One can access the section starting from the point represented by an iterator it in the curve c using this code:

section s( c.get_section(it) );

The interface of the section class is as follows:

class section
typedef curve::const_iterator iterator_type;
section( const iterator_type& origin, const iterator_type& end );
coordinate_type get_point_at( double t ) const;
coordinate_type get_tangent_at( double t ) const;
get_point_at_x( value_type x, bool off_domain = false ) const;
bool empty() const;
}; // class section

Computing the points of the curve

The main procedure to compute the coordinates of a point of the curve is to obtain a section of the curve and call

section::get_point_at( double t )

to get the coordinates of the point at a given t on the section.

If t is unknown, one can use the method get_point_at_x( value_type x, bool off_domain ) defined in claw::math::curve and claw::math::curve::section to obtain all the points of the curve or section having the given x-coordinate. If the argument off_domain is set to true, then the following applies:

Other properties of the curve.

The section::get_tangent_at( double t ) returns the tangent to the curve at a given t on a given section.