Libcurvecollection: Difference between revisions
No edit summary |
No edit summary |
||
| Line 47: | Line 47: | ||
'''Copy constructors''' | |||
<code>CurveVertex(CurveVertex const &)</code><br /> | <code>CurveVertex(CurveVertex const &)</code><br /> | ||
<code>CurveVertex(CurveVertex const *)</code> | <code>CurveVertex(CurveVertex const *)</code> | ||
A vertex instantiated using a copy constructor will have the same coordinates as the original, but won't have any properties and will not belong to any Curve (or CurveCollection). Hence, a '''warning''': calling functions like <tt>property</tt> or <tt>getPropertyNames</tt> on a copy-constructed curve will result in a <tt>runtime_error</tt>. | |||
A vertex instantiated using a copy constructor will have the same coordinates as the original, but won't have any properties and will not belong to any Curve (or CurveCollection). Hence, a '''warning''': calling | |||
| Line 58: | Line 58: | ||
<code>double y() const</code><br /> | <code>double y() const</code><br /> | ||
<code>double z() const</code> | <code>double z() const</code> | ||
Access the x, y, or z coordinate of the vertex, respectively. | |||
===Property accessors & mutators=== | ===Property accessors & mutators=== | ||
<code>double & property([http://www.sgi.com/tech/stl/basic_string.html std::string] const & | <code>double & property([http://www.sgi.com/tech/stl/basic_string.html std::string] const &)</code> | ||
<code>double const & property( | <code>double const & property(std::string const &) const</code> | ||
The parameter of this function is the vertex property name. | |||
This function 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 your reference to the object is non-<tt>const</tt>). | |||
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 | 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 function. If you call it before this has happened, the program will exit with a <tt>runtime_error</tt> (''CurveVertex::checkForContainer: ...''). | ||
<ref>libcurvecollection uses exceptions built into the C++ Standard Library ([http://www.cplusplus.com/reference/std/stdexcept/ stdexcept]).</ref> | <ref>libcurvecollection uses exceptions built into the C++ Standard Library ([http://www.cplusplus.com/reference/std/stdexcept/ stdexcept]).</ref> | ||
If the lookup fails (i.e., the given string ''name'' was not found in the CurveCollection), the | If the lookup fails (i.e., the given string ''name'' was not found in the CurveCollection), the function will throw an <tt>invalid_argument</tt> exception. | ||
<code>double const & property(int | <code>double & property(int)</code><br /> | ||
<code>double const & property(int) const</code> | |||
Returns a reference the vertex property identified by the | The parameter of this function is the integer ''Property ID''. | ||
Returns a reference the vertex property identified by the Property ID. Throws an <tt>invalid_argument</tt> exception if the given ID is out of bounds. | |||
<blockquote>''What is a Property ID?'' <br /> | <blockquote>''What is a Property ID?'' <br /> | ||
A Property ID is | A Property ID is the index of the position in the vector where a property is stored. You can look it up using the <tt>CurveCollection::getVertexPropertyID</tt> function. | ||
<br /><br /> | <br /><br /> | ||
''Why use a Property ID?'' <br /> | ''Why use a Property ID?'' <br /> | ||
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 | |||
<tt>[[#Vertex_properties_2|curveCollection::getVertexPropertyID]]</tt>, and pass the resulting int ID | |||
to <tt>property</tt> inside their loop."</blockquote> | |||
===Other property | ===Other property function=== | ||
<code>int propertyCount() const</code> | <code>int propertyCount() const</code> | ||
| Line 94: | Line 99: | ||
<code>[http://www.sgi.com/tech/stl/Vector.html std::vector]< | <code>[http://www.sgi.com/tech/stl/Vector.html std::vector]<std::string> const & getPropertyNames() const</code> | ||
Returns a vector of all the property names of this CurveVertex (in the order in which they were set). Throws a <tt>runtime_error</tt> 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. | Returns a vector of all the property names of this CurveVertex (in the order in which they were set). Throws a <tt>runtime_error</tt> 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. | ||
| Line 145: | Line 150: | ||
<code>void addVertex(CurveVertex const & v)</code> | <code>void addVertex(CurveVertex const & v)</code> | ||
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<ref>Whenever the library wants to check that the properties of two curves match, it calls the (public) <tt>Curve::propertiesMatch</tt> | 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<ref>Whenever the library wants to check that the properties of two curves match, it calls the (public) <tt>Curve::propertiesMatch</tt> function, which checks that the curve and vertex properties are identical in their quantity, names, and ordering.</ref> 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. | '''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 | Note: this function 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 [http://www.sgi.com/tech/stl/Vector.html vector] of vertices and pass them to the [[#Constructors_2|constructor]]. (But remember to store the vertex properties separately, or they will be erased!) | ||
| Line 189: | Line 194: | ||
See the documentation for the [[#Property_accessors_.26_mutators|CurveVertex property accessor | See the documentation for the [[#Property_accessors_.26_mutators|CurveVertex property accessor functions]] — these work just like they do. | ||
===Other curve property | ===Other curve property functions=== | ||
<code>int propertyCount() const</code> | <code>int propertyCount() const</code> | ||
| Line 201: | Line 206: | ||
See the documentation for the [[# | See the documentation for the [[#Other_property_functions|CurveVertex property functions]] — their behavior is identical. | ||
| Line 209: | Line 214: | ||
===Other curve | ===Other curve functions=== | ||
<code>int size() const</code> | <code>int size() const</code> | ||
| Line 251: | Line 256: | ||
==CurveCollection== | ==CurveCollection== | ||
An instance of '''CurveCollection''' holds an arbitrary number of Curve objects and information about the Curve and CurveVertex properties (name/description strings). It also provides | An instance of '''CurveCollection''' holds an arbitrary number of Curve objects and information about the Curve and CurveVertex properties (name/description strings). It also provides functions for the import and export of this data. | ||
===A note on properties=== | ===A note on properties=== | ||
Every CurveVertex stores its own (vertex) properties. Likewise, every Curve stores its own curve properties. However, all curves and vertices in a CurveCollection must have the same properties. In fact, the only way to set properties is through | Every CurveVertex stores its own (vertex) properties. Likewise, every Curve stores its own curve properties. However, all curves and vertices in a CurveCollection must have the same properties. In fact, the only way to set properties is through functions that are located in CurveCollection. | ||
Why is this the case? For metadata such as curve and vertex properties to be meaningful, there must be some string associated with them: a name (or a description). But storing a string with every data point in a collection is cost-prohibitive (in memory consumed). Since data in most collections shares the same properties, we have chosen to store the property names at the top level — in a CurveCollection. Enforcing this invariant is why all properties must be set at the same time and why a Curve and CurveVertex cannot have properties when they are not in a CurveCollection — without it, there simply isn't a way to look up the properties to access them. | Why is this the case? For metadata such as curve and vertex properties to be meaningful, there must be some string associated with them: a name (or a description). But storing a string with every data point in a collection is cost-prohibitive (in memory consumed). Since data in most collections shares the same properties, we have chosen to store the property names at the top level — in a CurveCollection. Enforcing this invariant is why all properties must be set at the same time and why a Curve and CurveVertex cannot have properties when they are not in a CurveCollection — without it, there simply isn't a way to look up the properties to access them. | ||
Revision as of 20:27, 13 September 2010
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:
- DTK/TrackVis
- Tubegen's custom format (.data and .nocr files)
- CCF
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 an object-oriented fashion.
Installation
The Curve Collection library can be found under $G/common/libcurvecollection/. To compile and install it, run make all, then make install.
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:
If you look at the library source code, each component has a header (.h) and a .cpp file associated with it.
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.
Copy constructors
CurveVertex(CurveVertex const &)
CurveVertex(CurveVertex const *)
A vertex instantiated using a copy constructor will have the same coordinates as the original, but won't have any properties and will not belong to any Curve (or CurveCollection). Hence, a warning: calling functions like property or getPropertyNames on a copy-constructed curve will result in a runtime_error.
Accessors
double x() const
double y() const
double z() const
Access the x, y, or z coordinate of the vertex, respectively.
Property accessors & mutators
double & property(std::string const &)
double const & property(std::string const &) const
The parameter of this function is the vertex property name. This function 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 your reference to the object is non-const).
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 function. 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 function will throw an invalid_argument exception.
double & property(int)
double const & property(int) const
The parameter of this function is the integer Property ID. 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 the index of the position in the vector where a property is stored. You can look it up using the CurveCollection::getVertexPropertyID function.
Why use a Property ID?
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 IDto property inside their loop."
Other property function
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.
This behavior (keeping around properties) introduces a bug: when you copy-construct a curve, then add it to a curve collection, then define property "new_property" for it, calling getProperty("new_property") will return one of the old properties — not the newly added one. Possible solution: clear properties in CurveCollection constructors. (That's what the Curve constructor currently does, avoiding the same problem with the CurveVertex copy constructor.)
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 function 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 functions — these work just like they do.
Other curve property functions
int propertyCount() const
std::string const & getPropertyNames() const
bool hasProperty(std::string const & name) const
See the documentation for the CurveVertex property functions — 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 functions
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
An instance of CurveCollection holds an arbitrary number of Curve objects and information about the Curve and CurveVertex properties (name/description strings). It also provides functions for the import and export of this data.
A note on properties
Every CurveVertex stores its own (vertex) properties. Likewise, every Curve stores its own curve properties. However, all curves and vertices in a CurveCollection must have the same properties. In fact, the only way to set properties is through functions that are located in CurveCollection.
Why is this the case? For metadata such as curve and vertex properties to be meaningful, there must be some string associated with them: a name (or a description). But storing a string with every data point in a collection is cost-prohibitive (in memory consumed). Since data in most collections shares the same properties, we have chosen to store the property names at the top level — in a CurveCollection. Enforcing this invariant is why all properties must be set at the same time and why a Curve and CurveVertex cannot have properties when they are not in a CurveCollection — without it, there simply isn't a way to look up the properties to access them.
Constructors
Populating a CurveCollection
Accessors
Setting properties
Curve properties
Vertex properties
Accessing properties and information about them
Curve properties
Vertex properties
Clearing property
Curve properties
Vertex properties
I/O functions
CCF
Notes
- ↑ libcurvecollection uses exceptions built into the C++ Standard Library (stdexcept).
- ↑ Whenever the library wants to check that the properties of two curves match, it calls the (public) Curve::propertiesMatch function, which checks that the curve and vertex properties are identical in their quantity, names, and ordering.