# LIBRARY

Octrope library (liboctrope, -loctrope)

# SYNOPSIS

``` typedef struct octrope_vector_type {   /* A point in 3-space. */
double c[3];
} octrope_vector;```
``` typedef struct octrope_color_type {
double r;
double g;
double b;
double alpha;
} octrope_color;```

typedef struct octrope_pline_type { int acyclic; /* True if pline has distinct ends */ int nv; /* Number of vertices */ int cc; /* Color count (number of colors) */ octrope_vector *vt; /* Vertex buffer */ octrope_color *clr; /* Actual colors */ } octrope_pline;>

# DESCRIPTION

The octrope_link library consists of data types and interface functions designed for the efficient representation of polygonal links in 3-space. The fundamental data types, as given above, are the octrope_vector, the octrope_pline, and the octrope_link.

As expected, the octrope_vector is a 3-vector.

## The octrope_pline type

The octrope_pline is a bit more subtle. The data type contains a buffer of nv vertices and the acyclic tag. The value of acyclic is TRUE (nonzero) when the space polygon has two ends, and FALSE (zero) when the space polygon is closed. For example, a line segment has nv == 2 and acyclic == TRUE, while a triangle has nv == 3 and acyclic == FALSE.

However, nv is not the size of the buffer vt allocated by `octrope_link_new()` and freed by octrope_link_free(). The reason for this is that in many geometric functions on polygonal curves, it is convenient to allow at least one step of ``wraparound'' addressing for closed curves. Using this feature often makes code much cleaner, faster, and more stable.

But implementing this efficiently is a problem for the library designer. The obvious solution (allowing access only through special interface functions or macros which encode wraparound addressing via modular arithmetic or branching) turns out to be too slow. For instance, a test implementation of the library with this interface was almost 30% slower than the current version. Therefore, we have chosen to implement one step of wraparound by adding copies of the last and first vertices to the buffer locations vt[-1] and vt[nv] when acyclic == FALSE. As long as the extra memory is correctly allocated (by `octrope_link_new())` and freed (by octrope_link_free()), this should be transparent to users of this code.

Users may read and write freely from the buffer vt as long as their code does not depend on wraparound addressing. To use the wraparound addressing facility, call `octrope_link_fix_wrap(L)` to update the ``hidden'' elements of the array vt from the ``visible'' ones. Since `octrope_link_fix_wrap()` is very fast, it is acceptable to simply insert calls to it whenever one switches from writing to reading data from an octrope_link, or whenever one is unsure whether the hidden elements have been updated since the last write to the data structure. Many internal library functions use this procedure to ensure that wraparound addressing is updated before any other work is done.

The octrope_pline type also contains space for a buffer of colors, to ensure compatibility with the Geomview VECT specification. Currently, no use is made of these colors within the library, but they are read by `octrope_link_read()` and written by octrope_link_write().

An octrope_link is simply an array of nc pointers to octrope_pline. No facility has been provided in this version of Octrope to work with these plines separately, and we discourage taking octrope_pline types out of their octrope_link wrappers: the proper representation for a single polygon in this library is as an octrope_link with one component.

` octrope_link *octrope_link_new(int components, int *nv, int *acyclic);`

creates a pointer to an octrope_link structure containing space for components octrope_pline structures where the ith octrope_pline has space for nv[i] vertices. The octrope_link structure itself is allocated inside octrope_link_new, and must be later freed (the function `octrope_link_free()` handles this automatically). The buffers nv and acyclic are copied into new memory locations inside octrope_link_new. It is hence safe to free them after a call to octrope_link_new if desired.

The acyclic array contains TRUE in acyclic[i] if the ith component of the link has distinct end vertices and FALSE if the ith component is closed.

` void octrope_link_free(octrope_link *L);`

frees all the memory associated with an octrope_link structure. As above, we note that the vertex buffers in the octrope_pline members of the cp array are larger than they appear, so freeing an octrope_link without using this function is likely to cause a memory leak.

` octrope_link *octrope_link_read(FILE *infile);`

creates an octrope_link from the data in infile, which is assumed to be a Geomview VECT file. A VECT file is a text file which stores multi-component polygonal curves in human-readable format, with comments. The file format is documented with Geomview, at http://www.geomview.org, which provides an interactive 3d viewer for such links on X windows/OpenGL capable systems. The VECT format also contains color information, which is recorded by octrope_link_read().

` int octrope_link_write(FILE *outfile, octrope_link *L);`

writes the octrope_link L to the (open) text file outfile in the Geomview VECT format mentioned above. Returns TRUE if the write was successful, FALSE otherwise.

` void octrope_link_fix_wrap(const octrope_link *L);`

updates the vt (vertex) buffers in the members of L's cp array so that if a component L->cp[i] is closed (that is, L->cp[i]->acyclic == FALSE), then

`   L->cp[i]->vt[-1] == L->cp[i]->vt[L->cp[i]->nv-1]`

and

`   L->cp[i]->vt[L->cp[i]->nv] = L->cp[i]->vt[0].`

That is, it provides one element of ``wraparound addressing'' in the buffer L->cp[i]->vt. To implement this, the buffer L->cp[i]->vt actually contains L->cp[i]->nv + 2 elements, and L->cp[i]->vt[0] points to the second element of the buffer. This procedure copies the elements L->cp[i]->vt[0] and L->cp[i]->vt[L->cp[i]->nv-1] to the ``hidden'' locations in the vt buffer.

Call this procedure before any code which depends on wraparound addressing in the vt array.

` int octrope_link_edges(const octrope_link *L);`

returns the number of edges in the octrope_link L.

`  octrope_link *octrope_link_copy(octrope_link *L);`

allocates new memory using `octrope_link_new()` and copies the data from L into that space.

# AUTHORS

Ted Ashton and Jason Cantarella.

the liboctrope manpage

# HISTORY

This library was first released in September 2004. It is described in the paper A Fast Octree-Based Algorithm for Computing Ropelength by Ashton and Cantarella, which is included in the library distribution as octrope-paper.pdf, and published in the World Scientific Press volume.

Reading a link with `octrope_link_read()` and then writing it with `octrope_link_write()` loses information from the initial VECT file, since comments aren't preserved.