Libcurvecollection

From VrlWiki
Revision as of 20:35, 21 June 2010 by Nathan Malkin (talk | contribs)
Jump to navigation Jump to search
This page is incomplete and currently under development.

The Curve Collection Library (libcurvecollection) provides a representation of streamlines/curves in memory and an interface to access this information in a convenient but memory-safe manner. It can also read and write to disk, freely converting between several file formats.

Currently, the supported formats are:


Introduction

Tubegen represents streamlines/tubes in several different formats in memory and on disk, which are distinct from the representations used by well-established third parties, for example FSL, Camino, and DTK. The core of any representation, though, is quite simple: a collection of streamlines, in which each streamline is just an ordered list of vertex points in 3-space. The tricky bit is that we want to be able to associate scalars with these datasets at various levels:

  • each individual streamline (ex: the length of the streamline)
  • each vertex point of each streamline (ex: the interpolated FA value at that point)

Some of the data formats also include a description (i.e., a string) for each scalar value.

libcurvecollection provides a unified interface for handling these various formats, while simplifying access to the information in memory by presenting it in a object-oriented fashion.

Installation

The Curve Collection library can be found under $G/common/libcurvecollection/. To install it, run make clean all. Anything else???

To use the library after it has been installed, include the following lines:

#include <brain/curveCollection.h>
#include <brain/curve.h> 
#include <brain/curveVertex.h> 

near the top of your file.

Structure

The library consists of three mutually dependent components, each with a header (.h) and a .cpp file:

  1. CurveVertex
  2. Curve
  3. CurveCollection

CurveVertex

A CurveVertex represents a point in 3D space. It holds the point's coordinates and any metadata (in the form of doubles) that the point may have.

Constructors

CurveVertex(double, double, double)

The main constructor takes three doubles: the x, y, and z coordinates of the point.


CurveVertex(CurveVertex const & v)

A vertex instantiated using a copy constructor will have the same coordinates and properties as the source, but will not belong to any Curve. Thus, the properties can only be accessed by calling property(int) (and not property(string)).

Accessors

double x() const

double y() const

double z() const

Property accessors & mutators

double & property(std::string const & name)

double const & property(std::string const & name) const

Looks up the given property name and returns a reference to the vertex property (in the current CurveVertex) that it identifies. Because the return value is a reference, you can modify the stored property value (assuming you called the non-const version of the function).

Note that the Curve Collection Library stores property names only at the highest level (i.e., in a CurveCollection). Therefore, the CurveVertex in question must be in a Curve, and that Curve must be in a CurveCollection before you can call this method. If you call it before this has happened, the program will exit with a runtime_error (CurveVertex::checkForContainer: ...). [1]

If the lookup fails (i.e., the given string name was not found in the CurveCollection), the method will throw an invalid_argument exception.


double & property(int id)

double const & property(int id) const

Returns a reference the vertex property identified by the Property ID. Throws an invalid_argument exception if the given ID is out of bounds.

What is a Property ID?

A Property ID is essentially the index of the position in the vector where a property is stored. You can look it up using the CurveCollection::getVertexPropertyID method.

Why use a Property ID?
As the library explains, "those wishing to call getProperty from within a loop may want to avoid the efficiency loss associated with looking up the name at each call. Instead, they can perform the lookup once using curveCollection::getVertexPropertyID, and pass the resulting int ID

to getProperty inside their loop."

Other property methods

int propertyCount() const

Returns the number of properties this vertex has.


std::vector<std::string> const & getPropertyNames() const

Returns a vector of all the property names of this CurveVertex (in the order in which they were set). Throws a runtime_error if the CurveVertex is not in a Curve, or if that Curve is not in a CurveCollection. Returns an empty vector if this CurveVertex is in a CurveCollection, but no properties have been set.

TODO: rethink this?


bool hasProperty(std::string const & name) const

Returns true if this vertex has the property identified by the given name. (Specifically, checks that the CurveCollection knows this property name.) Hence, throws a runtime_error if the CurveVertex is not in a Curve, or if that Curve is not in a CurveCollection.


Other functions

bool equals(CurveVertex const & v, double EPSILON = 1e-6) const

Compares the positions of two vertices in 3D space, returning true if each pair of coordinates (x, y, z) is within EPSILON of each other. Does not check for equality of properties.


double distance(CurveVertex const & v) const

Computes the distance between two vertices in 3D space.


Curve

A Curve represents a track or streamline in 3D space, and consists of an ordered sequence of vertices and any metadata (in the form of doubles) that is common to them.

Constructors

Curve(std::vector<CurveVertex> const & p_vertices);

Initializes Curve with given vertices and no curve properties. Warning: if the given vertices have any properties, they will be cleared.


Curve(Curve const & c)

Copy constructor. The new Curve will not be in any CurveCollection. Thus while any curve and vertex properties will be copied over, they may only be accessed using the property(int) accessor.


Curve()

Empty constructor


Populating a curve

void addVertex(CurveVertex const & v)

Appends the given CurveVertex to the end of the current Curve. Since you are adding to an already-existing curve, the properties of the new vertex must match[2] the properties of the vertices that are already in the curve. In the event of a mismatch, an invalid_argument exception is thrown.

There is one exception: if you are adding a vertex with no properties to a curve that does have properties, the vertex will be added to the curve (and no exception will be thrown), but the vertex will get zeros (0.0) for each of the properties.

Note: this method checks for matching properties on every call, so — depending on your situation — a more efficient way to populate a curve may be to store a vector of vertices and pass them to the constructor. (But remember to store the vertex properties separately, or they will be erased!)


Accessors

std::vector<CurveVertex> const & getVertices() const

Returns a vector with all of the vertices this Curve contains.


CurveVertex const & operator[](int index) const

CurveVertex & operator[](int index)

Returns the CurveVertex at the given index in the curve. Throws a invalid_argument exception if the index is out of bounds.

Usage example: CurveVertex& firstVertex = someCurve[0];


Accessing vertex properties

std::vector<double> getVertexProperty(std::string const & name) const

Returns a vector with the identified property value from each of this Curve's vertices. Throws runtime_error if the Curve is not in any CurveCollection. Throws invalid_argument exception if the given string was not found among the vertex property names.

Usage example:
If Curve someCurve consists of three vertices aVertex, anotherVertex, and aThirdVertex, each of which has a property propertyX with values 10, 20, and 30, respectively, someCurve.getVertexProperty("propertyX") will return the vector [10, 20, 30].


Curve property accessors & mutators

double & property(std::string const & name)

double const & property(std::string const & name) const

double & property(int id)

double const & property(int id) const


See the documentation for the CurveVertex property accessor methods — these work just like they do.


Other curve property methods

int propertyCount() const

std::string const & getPropertyNames() const

bool hasProperty(std::string const & name) const


See the documentation for the CurveVertex property methods — their behavior is identical.


bool propertiesMatch(Curve const & other) const

Returns true when the curve and vertex properties in the two curves are identical in quantity, name, and order.


Other curve methods

int size() const

Returns the number of vertices in this curve.


double length() const

The actual length of the curve (sum of vertex-to-vertex distances).


Curve & operator=(Curve const & c)

Assignment operator: replaces this curve's vertices and properties with those of the given curve. The properties of the current curve and new curves must match; otherwise, a domain_error is thrown.


Iterator

const_iterator begin() const

const_iterator end() const

Works like your typical iterator.

Usage example:

Curve myCurve; // already populated
for(Curve::const_iterator vertexIterator = myCurve.begin(); 
    vertexIterator != myCurve.end(); 
    ++vertexIterator) 
{
    CurveVertex const & currentVertex = *cc_it;

    // do something with currentVertex
}


CurveCollection

  1. libcurvecollection uses exceptions built into the C++ Standard Library (stdexcept).
  2. Whenever the library wants to check that the properties of two curves match, it calls the (public) Curve::propertiesMatch method, which checks that the curve and vertex properties are identical in their quantity, names, and ordering.