\documentstyle{report}

\title{Programmer's Reference for the
BIC Programming Library}

\author{David MacDonald}

\newcommand{\name}[1]{{\bf\tt #1}}

\newcommand{\desc}[1]{\begin{itemize}
\item[] #1
\end{itemize}}

\newcommand{\bicpl}{BIC Programming Library}

\begin{document}

\maketitle

\newpage

\tableofcontents

\newpage

\chapter{Introduction}

This document is still under construction, so beware.

This document describes a library of routines available at the
McConnell Brain Imaging Centre (BIC) at the Montreal Neurological Institute.
It was developed as part of a medical imaging software testbed by
David MacDonald, with source code and considerable input from Peter
Neelin, Louis Collins, and others at the Centre.
The library comprises a set of functions for manipulating volumes,
objects such as polygons and lines, some basic geometry, and some general
programming utilities.  It is
based on top of the MNI Volume IO library, which is described in a
separate document.

This document describes where to find the \bicpl,
what functionality is provided, and
how to integrate it into a user's programs.
The library is written in C source code, and is designed
to be linked with C source.

\chapter{Compiling and Linking}

The library is \name{libbicpl.a} and is available in the directory
\name{/usr/local/lib}.  The relevant include files are in the
directory \name{/usr/local/include}.  Both of these directories are
usually already in the compiler and loader search paths, so the
command line need not specify the paths:
{\bf\begin{verbatim}
        cc -prototypes test_bicpl.c -c
\end{verbatim}}

Source files which make calls to \bicpl\ functions must include
the corresponding header file:
{\bf\begin{verbatim}
        #include  <bicpl.h>
\end{verbatim}}

In order to link with the \bicpl\ , the relevant libraries must be
specified:
{\bf\begin{verbatim}
        cc test_bicpl.o  -o test_bicpl \
           -lbicpl -lvolume_io -lminc -lnetcdf -lm -lsun -lmalloc
\end{verbatim}}
See the documentation for the BIC Volume IO Library for more
information on the list of libraries on the link line.

\chapter{Types and Macros}

There are several types and macros defined for use with the \bicpl.

\chapter{Programming Utilities}

A set of functions which are useful for general purpose, portable
programming is provided.  At present this comprises only argument
processing, global variable manipulation, and random number
generation.

\section{Argument Processing}

Simple command line argument processing is provided.  Note that more
sophisticated and extensive argument processing can be provided by
other existing packages around the lab.  Nevertheless, command line
argument lists can be scanned in command line order as follows:

{\bf\begin{verbatim}
public  void  initialize_argument_processing(
    int     argc,
    char    *argv[] )
\end{verbatim}}

\desc{called once to let the argument processor know what the command line
arguments are.  Initializes the current argument to the first
argument, in preparation for sequential processing of the command line
arguments.}

{\bf\begin{verbatim}
public  BOOLEAN  get_int_argument(
    int   default_value,
    int   *value )
public  BOOLEAN  get_real_argument(
    Real  default_value,
    Real  *value )
public  BOOLEAN  get_string_argument(
    char   default_value[],
    char   *value[] )
\end{verbatim}}

\desc{checks if there is a current argument and that it
is of the desired type.  If so,
then it assigns the appropriate \name{value}, advances to the next
argument, and returns \name{TRUE}.  Otherwise, the default value is assigned
to the \name{value} and the current argument is not advanced.}

{\bf\begin{verbatim}
public  BOOLEAN  get_prefix_argument(
    char  prefix[] )
\end{verbatim}}

\desc{checks if the next argument starts with the given prefix and if so,
advances to the point in the argument just after the end of the prefix, or
to the next argument if there are no characters after the prefix.
Returns \name{TRUE} if the command line argument starts with the prefix.}

\section{Global Variables}

This module provides support for defining global variables in such a
way that there is a lookup table of global variable names.  This table
can be used to provide reading of global variables from files at
runtime, or to allow the user to query and modify global variable
values during program execution.  In order to use this facility, the
programmer must have (either directly or indirectly)
{\bf\begin{verbatim}
#include  <globals.h>
\end{verbatim}}
in every program file that refers to a global variable.  The
global variables must be defined in a file called
\name{global\_variables.h} which has the following form:
{\bf\begin{verbatim}
START_GLOBALS
    DEF_GLOBAL(        Mine_1, BOOLEAN,  TRUE )
    DEF_GLOBAL(        Mine_2, int,      3 )
    DEF_GLOBAL(        Mine_3, Real,     2.5 )
    DEF_GLOBAL(        Mine_4, Colour,   RED )
    DEF_GLOBAL5(       Mine_5, Surfprop,
                       0.3, 0.6, 0.6, 40.0, 1.0 )
    DEF_GLOBAL3(       Mine_6, Vector,   1.0, 0.0, 0.0 )
    DEF_GLOBAL3(       Mine_7, Point,    2.0, 2.0, 2.0 )
    DEF_GLOBAL_STRING( Mine_8, "Initial value" )
END_GLOBALS
\end{verbatim}}
The first argument of each of these macros is the name of the global
variable.  The second argument is the type of the global variable.
Note that only the types in the previous example are supported.  The
final argument or arguments are the initial values of the global
variable.

Finally, one needs to create the lookup table in one program file,
usually the main program file, as follows:
{\bf\begin{verbatim}
#define  GLOBALS_LOOKUP_NAME  my_globals
#include  <globals.h>
\end{verbatim}}
which creates a global variable lookup table called
\name{my\_globals} (any name may be chosen for this table).
Relevant functions for global variables are:


{\bf\begin{verbatim}
public  Status  input_globals_file(
    int             n_globals_lookup,
    global_struct   globals_lookup[],
    char            filename[] )
\end{verbatim}}

\desc{Inputs global variable assignments from the specified file.
Assignments are of the form \name{variable = value ;}.  The lookup
table and its size are passed to this function.  An example
follows: }
{\bf\begin{verbatim}
    if( input_globals_file( SIZEOF_STATIC_ARRAY(my_globals),
           my_globals, filename ) != OK )
    {
        print( "Error reading globals file.\n" );
    }
\end{verbatim}}

{\bf\begin{verbatim}
public  Status  get_global_variable(
    int              n_globals_lookup,
    global_struct    globals_lookup[],
    char             variable_name[],
    char             value[] )
\end{verbatim}}

\desc{Creates a string containing the value of the global variable
matching the specified name, \name{variable\_name}.  For example, if
the global variable \name{my\_variable} is of type integer,}
{\bf\begin{verbatim}
    if( get_global_variable( SIZEOF_STATIC_ARRAY(my_globals),
            my_globals, "my_variable", value_string ) == OK )
    {
        print( "Value is: %s\n", value_string );
    }
\end{verbatim}}
is equivalent to:
{\bf\begin{verbatim}
    print( "Value is: %d\n", my_variable );
\end{verbatim}}

{\bf\begin{verbatim}
public  Status  set_global_variable(
    int              n_globals_lookup,
    global_struct    globals_lookup[],
    char             variable_name[],
    char             value_to_set[] )
\end{verbatim}}

\desc{Sets the value of the global variable matching the specified name,
\name{vari\-able\_name}, to the value specified by the ascii string
\name{value\_to\_set}.  For ex\-ample, if the global variable
\name{my\_variable} is of type integer,}
{\bf\begin{verbatim}
    if( set_global_variable( SIZEOF_STATIC_ARRAY(my_globals),
            my_globals, "my_variable", "45" ) != OK )
    {
        print( "Error setting variable.\n" );
    }
\end{verbatim}}
is equivalent to
{\bf\begin{verbatim}
    my_variable = 45;
\end{verbatim}}

{\bf\begin{verbatim}
public  Status  set_or_get_global_variable(
    int              n_globals_lookup,
    global_struct    globals_lookup[],
    char             input_str[],
    char             variable_name[],
    char             value_string[] )
\end{verbatim}}

\desc{If the \name{input\_str} is of the form
``\name{variable = value}'', then the corresponding global variable is
set to the value, and the value is passed back in ascii form in the
\name{value\_string} argument.  Otherwise, the form of
\name{input\_str} is simply ``\name{variable}'' and the corresponding
global variable is not changed, but its current value is passed back
in the \name{value\_string} argument.  This routine is useful in many
programs to read input lines from the user, allowing the user to query
and set global variable values during program execution.}

\section{Numerical Utilities}

A small set of useful numerical functions are provided:

{\bf\begin{verbatim}
public  BOOLEAN  numerically_close(
    Real  n1,
    Real  n2,
    Real  threshold_ratio )
\end{verbatim}}

\desc{Checks if the two numbers are within the given threshold ratio.
For instance, \name{numerically\_close( 4113.0, 4112.0, 0.001 )}
returns \name{TRUE}, since the two numbers are with 0.1 percent of
each other.}

{\bf\begin{verbatim}
public  Real  get_good_round_value(
    Real    value )
\end{verbatim}}

\desc{Returns the largest power of 10 or five times a power of 10
which is less then the specified value.  Useful for determining graph
axis positions.}

{\bf\begin{verbatim}
public  int  solve_quadratic(
    Real   a,
    Real   b,
    Real   c,
    Real   *root1,
    Real   *root2 )
\end{verbatim}}

\desc{Finds the real roots of the equation $a * x^2 + b * x + c$.
Returns either 0, 1, or 2, indicating the number of unique real roots,
which are passed back either in the argument \name{root1}, or in both
arguments, \name{root1} and \name{root2}.}

{\bf\begin{verbatim}
public  int solve_cubic(
    Real   a,
    Real   b,
    Real   c,
    Real   d,
    Real   roots[ 3 ] )
\end{verbatim}}

\desc{Finds the real roots of the equation $a * x^3 + b * x^2 + c * x
+ d$.  Returns the number of unique real solutions, and passes them
back in the array \name{roots}.}

{\bf\begin{verbatim}
public  Real  evaluate_polynomial(
    int     n,
    Real    poly[],
    Real    u )
\end{verbatim}}

\desc{Efficiently evaluates a polynomial of the form $poly[0] +
poly[1] * u + poly[2] * u^2 ...$, using Horner's rule.}

\section{Random Numbers}

A simple random number package is provided, which produces a sequence
of pseudo-random numbers based on a seed value, which totally
determines the entire sequence of numbers.  If the user does not set a
seed, a seed is automatically created from the current time and date.

{\bf\begin{verbatim}
public  void  set_random_seed(
    int seed )
\end{verbatim}}

\desc{Sets the seed which determines the sequence of pseudo-random numbers.}

{\bf\begin{verbatim}
public  int  get_random_int(
    int n )
\end{verbatim}}

\desc{Returns a random integer in the range zero to \name{n-1}.}

{\bf\begin{verbatim}
public  Real  get_random_0_to_1( void )
\end{verbatim}}

\desc{Returns a random number greater than or equal to zero and
strictly less than one.}

\chapter{Data Structures}

\chapter{Geometry}

\chapter{Numerical}

\chapter{Objects}

\section{Colour Manipulation}

Colours are generally represented as triples of coordinates,
representing red, green, and blue components.  Sometimes, an opacity
is included as a fourth component, to determine how much the colour
will let other objects show through.  Sometimes it is useful
to work with colours in a different space, Hue-Saturation-Light, which
is also a triple of coordinates.  Each colour component is usually either a
real value in the range zero to one, or an integral value in the range
zero to 255.  A colour type is defined (\name{Colour}) which uses a
single long integer to store colours as four eight-bit integers.
Various macros and functions exist to manipulate these colours:

{\bf\begin{verbatim}
make_Colour( r, g, b )
\end{verbatim}}

\desc{Returns a value of type
\name{Colour} which contains the specified red, green, and blue
components, each of which must be within the range zero to 255.}

{\bf\begin{verbatim}
make_rgba_Colour( r, g, b, a )
\end{verbatim}}

\desc{Returns a value of type
\name{Colour} which contains the specified red, green, blue, and alpha
(opacity) components, each of which must be within the range zero to 255.}

{\bf\begin{verbatim}
get_Colour_r( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the red component, in the range
zero to 255.}

{\bf\begin{verbatim}
get_Colour_g( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the green component, in the range
zero to 255.}

{\bf\begin{verbatim}
get_Colour_b( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the blue component, in the range
zero to 255.}

{\bf\begin{verbatim}
get_Colour_a( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the alpha component, in the range
zero to 255.}

{\bf\begin{verbatim}
make_Colour_0_1( r, g, b )
\end{verbatim}}

\desc{Returns a value of type
\name{Colour} which contains the specified red, green, and blue
components, each of which must be within the range zero to 1.0.}

{\bf\begin{verbatim}
make_rgba_Colour_0_1( r, g, b )
\end{verbatim}}

\desc{Returns a value of type
\name{Colour} which contains the specified red, green, blue, and
alpha components, each of which must be within the range zero to 1.0.}

{\bf\begin{verbatim}
get_Colour_r_0_1( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the red component, in the range
zero to 1.0.}

{\bf\begin{verbatim}
get_Colour_g_0_1( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the green component, in the range
zero to 1.0.}

{\bf\begin{verbatim}
get_Colour_b_0_1( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the blue component, in the range
zero to 1.0.}

{\bf\begin{verbatim}
get_Colour_a_0_1( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the value of the alpha component, in the range
zero to 1.0.}

{\bf\begin{verbatim}
get_Colour_luminance( col )
\end{verbatim}}

\desc{Given an argument of type
\name{Colour}, returns the brightness of the colour, in the range zero
to 255.  This is used to convert colour to gray-scale.}

A surface property type is also defined, to provide descriptions of
surface lighting characteristics:

{\bf\begin{verbatim}
fill_Surfprop( spr, a, d, s, e, o )
\end{verbatim}}

\desc{Fills in the
\name{spr} structure, which is of type \name{Surfprop}, with the five
parameters:  ambient coefficient, diffuse coefficient, specular
coefficient, specular exponent, and opacity.}

{\bf\begin{verbatim}
Surfprop_a( spr )
\end{verbatim}}

\desc{Returns the ambient coefficient, a
number in the range of zero to one.}

{\bf\begin{verbatim}
Surfprop_d( spr )
\end{verbatim}}

\desc{Returns the diffuse coefficient, a
number in the range of zero to one.}

{\bf\begin{verbatim}
Surfprop_s( spr )
\end{verbatim}}

\desc{Returns the specular coefficient, a
number in the range of zero to one.}

{\bf\begin{verbatim}
Surfprop_se( spr )
\end{verbatim}}

\desc{Returns the specular exponent, a
number in the range of zero to infinity, typically less than 100.}

{\bf\begin{verbatim}
Surfprop_t( spr )
\end{verbatim}}

\desc{Returns the opacity (inverse of
transparency), a number in the range of zero to one.}

Several functions are available which deal with colours and surface
properties:

{\bf\begin{verbatim}
public  void  rgb_to_hsl(
    Real    r,
    Real    g,
    Real    b,
    Real    *h,
    Real    *s,
    Real    *l )
public  void  hsl_to_rgb(
    Real   h,
    Real   s,
    Real   l,
    Real   *r,
    Real   *g,
    Real   *b )
public  void  convert_colour_to_hsl(
    Colour   rgb,
    Colour   *hsl )
public  void  convert_colour_to_rgb(
    Colour   hsl,
    Colour   *rgb )
\end{verbatim}}

\desc{Converts between red-green-blue and hue-saturation-light space.}

{\bf\begin{verbatim}
public  BOOLEAN  equal_colours(
    Colour  col1,
    Colour  col2 )
\end{verbatim}}

\desc{returns \name{TRUE} if the two colours are equal.}

{\bf\begin{verbatim}
public  int  get_colour_distance(
    int      r,
    int      g,
    int      b,
    Colour   c2 )
\end{verbatim}}

\desc{finds the squared Euclidean distance between the first colour,
specified by its components, and the second colour, \name{c2}.}

{\bf\begin{verbatim}
public  int   find_closest_colour(
    int     r,
    int     g,
    int     b,
    int     n_colours,
    Colour  colours[] )
\end{verbatim}}

\desc{Given the three components of a target colour, and a list of
\name{n\_colours} colours, returns the index in the list of the
closest colour to the target colour.}

{\bf\begin{verbatim}
public  BOOLEAN  lookup_colour(
    char    colour_name[],
    Colour  *col )
\end{verbatim}}

\desc{Given a colour name, such as ``\name{red}'' or ``\name{dark\_blue}''
looks up the name in a list of colours and passes back the
corresponding colour, returning \name{TRUE} if successful.  The
supported colours are from the list of about 300 named X colours.}

{\bf\begin{verbatim}
public  BOOLEAN  lookup_colour_name(
    Colour  col,
    char    colour_name[] )
\end{verbatim}}

\desc{This performs the inverse of the \name{lookup\_colour()}
function, taking a colour and seeing if it matches one of the known
named colours.  If so, the colour name is copied into the argument
\name{colour\_name}, and \name{TRUE} is returned.}

\chapter{Transforms}

{\bf\begin{verbatim}
public  void  make_scale_transform(
    Real        sx,
    Real        sy,
    Real        sz,
    Transform   *transform )
\end{verbatim}}

\desc{Creates a scaling transform with separate scaling in each
dimension.  If the point (1.0, 1.0, 1.0) is transformed by the resulting
transform, the result will be (\name{sx}, \name{sy}, \name{sz}).}

{\bf\begin{verbatim}
public  void  make_translation_transform(
    Real        x_trans,
    Real        y_trans,
    Real        z_trans,
    Transform   *transform )
\end{verbatim}}

\desc{Creates a translation transform with separate translation in each
dimension.  Transforming the point ( 0.0, 0.0, 0.0 ) by the resulting
transform will result in the point (\name{x\_trans}, \name{y\_trans},
\name{z\_trans}).}

{\bf\begin{verbatim}
public  void  make_rotation_transform(
    Real       radians,
    int        axis,
    Transform  *transform )
\end{verbatim}}

\desc{Creates a transform which achieves a rotation about one of the
three axes, (\name{X}, \name{Y}, or \name{Z}).}

{\bf\begin{verbatim}
public void  get_nonlinear_warp(
    float **transformed_points,
    float **original_points,
    float **displacements,
    int   n_points,
    int   n_dimensions )
\end{verbatim}}

\desc{Fills in the \name{displacements} array with the appropriate
values to achieve a thin-plate spline transformation.  The mapping
will provide a smooth transformation of space such that each point in
the \name{original\_points} array maps exactly to the corresponding point in
the \name{transformed\_points} array.  These displacements are then
fed into the function \name{create\-\_thin\-\_plane\-\_transform} to create
the general transform.}

\end{document}
