SourceForge Logo SmoothLine library Sourceforge Project Page

libSmoothLine Documentation

Version 1.2.1

Contents

Introduction

The SmoothLine library provides functions to calculate smooth polylines in two and three dimensions. Given some polyline (i.e. a list of points), a smoothed, finer segmented polyline will be generated. The smoothed polyline hits the original points or alternatively, the length of the smoothed line is equal to the length of the original polyline. The line may optionally be closed.

Additionally, some functions to calculate several curve or polyline parameters (length, max. angle, angle sum, twist and writhe) as well as some functions to solve systems of linear equations are provided.

Functions description

libSmoothLine is written in C++ using templates. The template parameters are fltyp = float, double and dim = 2, 3 (2 or 3 dimensional coordinates).

For the representation of coordinate vectors, the Tiny Vector Matrix library using Expression Templates (tvmet) is used. In the following, the definitions

typedef Vector<fltyp,dim>  Vect;
typedef list<Vect>         l_Vect;

were used.


libSmoothLine provides four smoothing functions:

smooth_connect

int smooth_connect<fltyp,dim>(l_Vect &r, const fltyp &MaxAng, const fltyp &MaxArea, const int &MaxSteps, const bool &closeIt = false)

This function generates a polyline that hits the original points. r is used for input (original points) and for output (smoothed polyline points). The smoothing procedure is iterated until all angles αi between two consecutive line segments si and si+1 are ≤ MaxAng (in radians) and all areas |si| ⋅ |si+1| ⋅ sin(αi) are ≤ MaxArea. The procedure also stops after MaxSteps iterations. If closeIt is true, the polyline will be closed, otherwise it starts/ends at the first/last point of the original point list. Consecutive points in the input list may not be identical. For closed lines, the first point may not be repeated at the end of the list! The calculation cost is proportional to the number of final points.

Return values:

smooth_polyline

int smooth_polyline<fltyp,dim>(l_Vect &r, const fltyp &MaxAng, const fltyp &MaxArea, const int &MaxSteps, const bool &closeIt = false)

This function generates a polyline that has approximately the same line length as the polyline given by the original points. The length of the polyline is typically reduced by less than 1% but in extreme cases, it might be reduced by more than 10%. The parameters and return values are as described above.

smooth_polyline_el

int smooth_polyline_el<fltyp,dim>(l_Vect &r, const fltyp &MaxAng, const fltyp &MaxArea, const int &MaxSteps, const bool &closeIt = false, const bool &enhance = false)

This function generates a polyline that has exactly the same line length as the polyline given by the original points. All parameters and return values are as described above, the additional parameter enhance is used to activate a calculation-intensive procedure (including numerical root-finding) that enhances the quality of the smoothed polyline in some extreme cases.

Disadvantages compared to smooth_polyline:

smooth_polyline_g

int smooth_polyline_g<fltyp,dim>(l_Vect &r, const fltyp &MaxAng, const fltyp &MaxArea, const int &MaxSteps, const bool &closeIt = false)

This function also generates a polyline that has exactly the same line length as the polyline given by the original points. As with smooth_polyline, the result is invariant under point order reversion. The parameters and return values are as described above, but an additional error code may be returned:

Disadvantage compared to the preceding functions:
Additional functions:

calc_maxAngle_Len

int calc_maxAngle_Len<fltyp,dim>(const l_Vect &r, fltyp &MxAng, fltyp &Len, const bool closeIt)

This function calculates the maximum angle MxAng between consecutive line segments (in radians, turning points are omitted) and the length Len of the polyline r, which may optionally be closed. Return values:

If an error is returned (return value < 0), the values of MxAng and Len are trashy.

calc_maxAng_sum_Ang_Len

int calc_maxAng_sumAng_Len<fltyp,dim>(const l_Vect &r, fltyp &MxAng, fltyp &SumAng, fltyp &Len, const bool closeIt)

This function calculates the maximum angle MxAng between consecutive line segments (in radians, turning points are omitted), the sum of these angles SumAng (including turning points) and the length Len of the polyline r, which may optionally be closed. The return values are as described above. If an error is returned (return value < 0), the values of MxAng, SumAng and Len are trashy.

calc_Len

fltyp calc_Len<fltyp,dim>(const l_Vect &r, const bool closeIt)

This function returns the length of the polyline r, which may optionally be closed.

calc_Twist_Writhe

int calc_Twist_Writhe<fltyp>(const l_Vect &r, fltyp &tw, fltyp &wr, const bool closeIt)

This function calculates the twist tw and the writhe wr of the polyline r (dim=3 only), which may optionally be closed (see here, method 2a, for a description of the calculation method). Return values:

If an error is returned, the values of tw and wr are trashy.

calc_Twist

int calc_Twist<fltyp>(const l_Vect &r, fltyp &tw, const bool closeIt)

This function calculates the twist tw of the polyline r (dim=3 only), which may optionally be closed. The return values are as described above but -5 = MethodFail cannot occur. If an error is returned, the value of tw is trashy.

Functions to solve systems of linear equations

Please look into the files SysLinEqu.h and test_SysLinEqu.cpp.

Examples

Code example

A code example using the libSmoothLine functions can be found in the file test_smooth.cpp. The files testdata/*.dat may be used as input files for test_smooth.

Smoothing examples

Here is a typical example (closeIt=true):
typical smooth_connect example typical smooth_polyline example

When closeIt=true, a regular polygon is always transformed into a circle. In such a special case, the line length is also exactly preserved by smooth_polyline, i.e. the results of smooth_polyline, smooth_polyline_el and smooth_polyline_g are identical. See the results for a regular triangle with closeIt=true and closeIt=false:
regular triangle closed regular triangle open

Last but not least an extreme example, a stair. With closeIt=false, nothing strange happens, but it's suitable for showing the non-invariance of smooth_polyline_el under point order reversion. With closeIt=true, smooth_polyline_el without enhancement produces a surprising bend. Here, the result of smooth_polyline_el with enhance=true is much better while smooth_polyline_g clearly produces the best result.
stair open stair closed

Method

The smoothing procedure is iterative. In every iteration cycle, each polyline segment that has to be smoothed further is replaced by two segments of approximately half the length. Firstly, the bisecting lines ai of the angles between adjacent segments si-1 and si and the perpendicular bisecting planes Bi of the segments si were calculated. (In two dimensions, the Bi are also lines.) Then the intersection points pi,1 and pi,2 of a plane Bi with the two neighboring lines ai and ai+1 and the lines bi,1 and bi,2 in the plane Bi through the points pi,1 and pi,2, respectively, and crossing the segment si were determined. In the next step, provisional new segments s'i,1 and s'i,2 were constructed by calculating the base side of the isosceles triangles with the equal sides ai and bi,1 or bi,2 and ai+1, respectively.

In smooth_connect, the base sides of the isosceles triangles (i.e. the provisional new segments) are positioned such that they hit the points ri and ri+1. In smooth_polyline, smooth_polyline_el and smooth_polyline_g, they are positioned such that its lengths are equal to half the length of the old segment si. Generally, the end points of adjacent provisional segments s'j do not coincide, i.e. the segments are not connected. (In the case of smooth_connect, every other connection is okay.)
smooth_connect method smooth_polyline method

In smooth_connect and in smooth_polyline, the final new segments were determined by taking the center points cj of each two end points of the s'j which have to be connected as the corners r'j of the new polyline. In smooth_connect_el, a new corner point is determined by rotating the provisional segments s'j-1 and s'j around their outer end points such that the inner endpoints hit each other. In three dimensions, the resulting triangle is then rotated around its baseline in order to minimize the distance between its upper tip (the junction point) and the center point cj.
smooth_polyline_el method

If enhancement is activated, the lengths of the two sides of that triangle (i.e. the two segments) are varied to minimize the distance between its upper tip and the center point cj while keeping the sum of these lengths as well as the triangle's baseline constant. This operation requires (one dimensional) numerical root-finding.

In smooth_connect_g, a global optimization procedure is applied. The positions of all new corner points are varied simultaneously to minimize the sum of the squared distances between the corner points and the corresponding center points cj while forcing the total length of the new polyline to the length of the original one. This operation requires multidimensional numerical root-finding, i.e. the numerical solution of a system of nonlinear equations.

So far the basic principles. If you are interested in the details, please look into the code!

Download

You can download libSmoothLine here.

Dependencies, Compilation, Linking

You also need the Tiny Vector Matrix library using Expression Templates (tvmet) and the GNU Scientific Library (GSL).

Compilation is tested with g++ (GCC) 4.7.1.

Example:
g++ -g -O2 -Wl,--gc-sections -o test_smooth test_smooth.cpp smoothline.cpp -lgsl -lcblas -lblas

License

Copyright (C) 2008-2012 Eberhard Kümmerle

This library is free software; you can redistribute and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

History

The basic method was developed in the course of a scientific work that aimed at generating supercoiled models of plasmids by means of a Monte Carlo procedure. If you are interested, see the original article or the pre-press version.


Author: