contour Class Reference

#include <contour.h>


Detailed Description

Calculate contour lines from a two-dimensional data set.

Basic Usage

The data should be stored so that the y-index is first, i.e. data[iy][ix]. One can always switch x_fun and y_fun if this is not the case. The data is copied by set_data(), so changing the data will not change the contours unless set_data() is called again. The functions set_levels() and calc() can be called several times for the same data without calling set_data() again.

Linear interpolation is used to decide whether or not a line segment and a contour cross. This choice is intentional, since (in addition to making the algorithm much simpler) it is the user (and not the class) which is likely best able to refine the data. In case a simple refinement scheme is desired, the method regrid_data() is provided which uses cubic spline interpolation to refine the data and thus make the curves more continuous.

Since linear interpolation is used, the contour calculation implicitly assumes that there is not more than one intersection of any contour level with any line segment, so if this is the case, then either a more refined data set should be specified or regrid_data() should be used. For contours which do not close inside the region of interest, the results will always end at either the minimum or maximum values of x_fun or y_fun (no extrapolation is ever done).

As an example, for the function

\[ 15 e^{-(x-20)^2/400-(y-5)^2/25}+ 40 e^{-(x-70)^2/4900-(y-2)^2/4} \]

a 10x10 grid gives the contours:

contourg.png

contourg.png

While after a call to regrid_data(3,3), the contours are a little smoother:

contourg2.png

contourg2.png

Mathematica gives a similar result:

contourg3.png

contourg3.png

The Algorithm:

This works by viewing the data as defining a square two-dimensional grid. The function calc() exhaustively enumerates every line segment in the grid which involves a level crossing and then organizing the points defined by the intersection of a line segment with a level curve into a full contour.

Representing Contours by Fill Regions

If the user wants to "shade" the contours to provide a shaded or colored contour plot, then it is useful to provide a set of closed contours to be shaded instead of the (possibly) open contours returned by calc_contours(). After a call to calc_contours(), the function regions() can be used to organize the closed contours into regions to be shaded. Open contours are closed by adding points defining lines along the edges of the data and closed contours are inverted (if necessary) by adding an external line emanating from the closed contour and properly including the boundary edges.

Todo:

Definition at line 126 of file contour.h.


Public Member Functions

Basic usage
template<class vec_t, class mat_t>
int set_data (size_t sizex, size_t sizey, const vec_t &x_fun, const vec_t &y_fun, const mat_t &udata)
 Set the data.
template<class vec_t>
int set_levels (size_t nlevels, vec_t &ulevels)
 Set the contour levels.
template<class vec_t>
int calc_contours (vec_t &new_levels, bool debug=false)
 Calculate the contours.
int get_contour_size (int index)
 Return the number of points in the specified contour.
template<class vec_t>
int get_contour (int index, double &val, int &csize, vec_t &x, vec_t &y)
 Get a contour.
int regions (bool larger)
 Compute closed contour regions (unfinished).
Regrid function
int regrid_data (size_t xfact, size_t yfact)
 Regrid the data.
Obtain internal data
int get_data (size_t &sizex, size_t &sizey, const ovector *&x_fun, const ovector *&y_fun, const ovector **&udata)
 Get the data.
int get_edges (const std::vector< omatrix_int * > *rints, const std::vector< omatrix_int * > *bints, const std::vector< omatrix * > *rpoints, const std::vector< omatrix * > *bpoints)
 Return the edges used to compute the contours.
int get_edges_for_level (size_t nl, omatrix_int &rints, omatrix_int &bints, omatrix &rpoints, omatrix &bpoints)
 Return the edges used to compute the contours.

Data Fields

int verbose
 Verbosity parameter.
double lev_adjust
 (default $ 10^{-8} $)

Protected Member Functions

int find_next_point_right (int j, int k, int &jnext, int &knext, int &dir_next, int nsw=1)
 Find next point starting from a point on a right edge.
int find_next_point_bottom (int j, int k, int &jnext, int &knext, int &dir_next, int nsw=1)
 Find next point starting from a point on a bottom edge.
int find_intersections (size_t ilev, double &level)
 Find all of the intersections of the edges with the contour level.
int right_edges (double level, o2scl::sm_interp *si)
 Interpolate all right edge crossings.
int bottom_edges (double level, o2scl::sm_interp *si)
 Interpolate all bottom edge crossings.
int process_line (int j, int k, int dir, std::vector< double > &x, std::vector< double > &y, bool first=true)
 Create a contour line from a starting edge.
bool is_point_inside_old (double x1, double y1, const ovector_view &x, const ovector_view &y, double xscale=0.01, double yscale=0.01)
 Test if a point is inside a closed contour (unfinished).
int free_memory ()
 Free memory.
bool lines_cross_old (double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
 Check if lines cross.
int check_data ()
 Check to ensure the x- and y-arrays are monotonic.
int smooth_contours (size_t nfact)
 Smooth the contours by adding internal points using cubic interpolation (this doesn't work).

Protected Attributes

int new_debug
pinside pi
 Object to find if a point is inside a polygon.
User-specified data
int nx
int ny
ovectorxfun
ovectoryfun
ovector ** data
User-specified contour levels
int nlev
ovector levels
bool levels_set
Generated curves
int ncurves
std::vector< int > csizes
std::vector< double > vals
std::vector< std::vector
< double > > 
xc
std::vector< std::vector
< double > > 
yc
Storage for edges
std::vector< omatrix * > redges
std::vector< omatrix * > bedges
std::vector< omatrix_int * > re
std::vector< omatrix_int * > be
omatrix_intrep
omatrix_intbep
omatrixredgesp
omatrixbedgesp

Static Protected Attributes

Edge direction
static const int dright = 0
static const int dbottom = 1
Edge status
static const int empty = 0
static const int edge = 1
static const int contourp = 2
static const int endpoint = 3
Edge found or not found
static const int efound = 1
static const int enot_found = 0

Member Function Documentation

int set_data ( size_t  sizex,
size_t  sizey,
const vec_t &  x_fun,
const vec_t &  y_fun,
const mat_t &  udata 
) [inline]

Set the data.

The types vec_t and mat_t can be any types which have operator[] and operator[][] for array and matrix indexing.

Note that this method copies all of the user-specified data to local storage so that changes in the data after calling this function will not be reflected in the contours that are generated.

Definition at line 147 of file contour.h.

int set_levels ( size_t  nlevels,
vec_t &  ulevels 
) [inline]

Set the contour levels.

This is separate from the function calc_contours() so that the user can compute the contours for different data sets using the same levels

Definition at line 183 of file contour.h.

int calc_contours ( vec_t &  new_levels,
bool  debug = false 
) [inline]

Calculate the contours.

The function calc_contours() returns the total number of contours found. Since there may be more than one disconnected contours for the same contour level, or no contours for a given level, the total number of contours may be less than or greater than the number of levels given by set_levels().

If an error occurs, zero is returned.

Definition at line 205 of file contour.h.

int get_contour ( int  index,
double &  val,
int &  csize,
vec_t &  x,
vec_t &  y 
) [inline]

Get a contour.

Given the index, which is between 0 and the number of contours returned by calc_contours() minus 1 (inclusive), this returns the level for this contour with the x and y-values in x and y which are both of length csize. The vectors x and y must have been previously allocated. The user can obtain the necessary size for x and y by calling get_contour_size().

Definition at line 384 of file contour.h.

int regrid_data ( size_t  xfact,
size_t  yfact 
)

Regrid the data.

The uses cubic spline interpolation to refine the data set, ideally used before attempting to calculate the contour levels. If the original number of data points is $(\mathrm{nx},\mathrm{ny})$, then the new number of data points is

\[ (\mathrm{xfact}~(\mathrm{nx}-1)+1, \mathrm{yfact}~(\mathrm{ny}-1)+1) \]

int get_data ( size_t &  sizex,
size_t &  sizey,
const ovector *&  x_fun,
const ovector *&  y_fun,
const ovector **&  udata 
) [inline]

Get the data.

This is useful to see how the data has changed after a call to regrid_data().

Definition at line 434 of file contour.h.

int get_edges_for_level ( size_t  nl,
omatrix_int rints,
omatrix_int bints,
omatrix rpoints,
omatrix bpoints 
)

Return the edges used to compute the contours.

This function allocates memory for rints, bints, rpoints, and bpoints and fills them with a copy of the data that the class is using. As such, there is no need for them to be const.

bool is_point_inside_old ( double  x1,
double  y1,
const ovector_view x,
const ovector_view y,
double  xscale = 0.01,
double  yscale = 0.01 
) [protected]

Test if a point is inside a closed contour (unfinished).

This returns true if the point (x1,y1) is "inside" the contour (i.e. a collection of line segments) given in x and y. The arrays x and y must be "ordered" so that adjacent points are placed at adjacent entries. The result is undefined if this is not the case or if the contours are not properly closed. The first and last points in x and y should be the same to indicate a closed contour. The values xscale and yscale should be an approximate scale for the contours x and y.

Note:
This function is deprecated and has been replaced by pinside

bool lines_cross_old ( double  x1,
double  y1,
double  x2,
double  y2,
double  x3,
double  y3,
double  x4,
double  y4 
) [protected]

Check if lines cross.

Returns true if the line segment defined by (x1,y1) and (x2,y2) and the line segment defined by (x3,y3) and (x4,y4) have an intersection point that is between the endpoints of both segments. The function handles vertical and horizontal lines appropriately. This function will fail if x1==y1 and x2==y2 or if x3==y3 and x4==y4, i.e. if the points do not really define a line. If the function fails, it returns false.

Note:
This function is deprecated and has been replaced by pinside

int smooth_contours ( size_t  nfact  )  [protected]

Smooth the contours by adding internal points using cubic interpolation (this doesn't work).

This makes the contours smoother by adding internal points between each contour line segment determined by cubic spline interpolation.

For more accurate contours, it is better to provide the original data on a finer grid, or use regrid_data().


The documentation for this class was generated from the following file:

Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.

Project hosting provided by SourceForge.net Logo, O2scl Sourceforge Project Page