Developers Reference Guide
--------------------------

   Adding a new display method or projection to Magellan is relatively
simple. The main thing to understand is the rendering pathways.

Projections
-----------

   A projection must inherit XfMap (defined in xfmap.h), and supply
three functions: f(), g(), and f_edge().

bool f(dvec2& result, const dvec3& pos) const

   Is the "forward map". pos is the coordinates of a point on the
sphere, in 3-space (so pos has indices [0], [1] and [2]). result is
the coordinates on the projection plane. The function returns true if
the map is possible, false if the point lies outside the valid range
of the map.

bool g(dvec3& result, const dvec2& pos) const

   Is the "backward map". pos is the coordinates of a point on the
projection plane, in 2-space. result is the 3-space coordinates of the
point on the sphere that maps backwards.

bool f_edge(dvec& result, const dvec& vis, const dvec& inv)

   Takes a point which is known to be visible (vis), and a point known
to be invisible (inv), and returns (if possible) a point between the
two on the edge of the visible region. If it is not possible to
calculate one, then it returns false.

Displays
--------

   A display inherits the MDisplay class, and needs to provide a
plot() function. The MDisplay class takes a chain of transformations
to use, from lat/long to the coordinates on the viewport. The display
may use either the f() of the projection (to map points to their
positions in the viewport), or the g() (to map points in the viewport
to the underlying lat/long coordinates).

   f() transformations are useful for non-covering things like the
lat/long marks, where they may be gaps between the points being
plotted. g() transformations are more useful for space-covering things
like the bitmap displays.

Content
-------

   A content class provides methods for rendering things on the
screen. The basic interface for content is:

void plot(Output*, XfView*, XfMap*, XfOrbit*, XfSphere*)

This method does almost all of the hard work on rendering the output.
It should use the four transform functions to determine what to
display where in the provided Output canvas. Typically, this will
involve either:

 - starting with a known set of canvas points, and following the "g"
   transformations in order for each to reach the appropriate value in
   the underlying x,y data, (e.g. for bitmap data) or

 - starting with a known set of surface locations, and following the
   "f" transformations in reverse order to reach the location on the
   canvas to plot (e.g. for point-based location data)

   There is a second base class for content, ContentFilled, where the
plot() method iterates over all of the pixels in the output canvas,
and maps them to points within a rectangular map. It then calls the
member function:

bool getpixel(ivec& result, const dvec& location)

which takes a location and returns an RGB triple (normalised to the
range [0,255]) for that location.
