BRL-CAD Boundary-Representation Primitive
-----------------------------------------

-- Introduction --

This document describes the new Boundary-representation (BREP)
primitive that has been implemented in BRL-CAD for use with external
geometry import and improved visualisation.


-- BREP Description --

A boundary-representation is a method of representing solid geometry
by describing its topology and corresponding geometry. In other words,
the vertexes, edges, and faces as well as the points, curves, and
surfaces belonging to those topological elements.

For example, a cube has 8 vertexes each mapping to 1 point in space, 6
faces each mapping to 1 surface, and 8 edges each shared by two faces
and sharing its two vertexes with two other faces and owning 1 real
curve.

Actually creating/using a BREP requires keeping track of a lot of details,
including everything mentioned above, plus curve / face orientations
(a CCW edge/vertex ordering is usually used for determining front/back
designations.)

BRL-CAD has/had an existing BREP structure: the NMG (non-manifold
geometry) primitive/library.  We don't use the NMG library for
BREP/NURBS because it's already a very complex library and NURBS would
introduce exceptional additional complexity.


-- Primitive Implementation --

openNURBS was chosen to represent the geometry within BRL-CAD. This
turned out to be a good but incomplete choice:

* contains a lot of solid functionality
* missing a lot of useful and important functionality

In other words, the openNURBS API provided methods of functions for
several pieces of functionality that had implementations removed when
McNeil and Associates released openNURBS as an open source code to be
used by others.  This meant requisite functionality had to be
reimplemented, whose code can be predominantly found in libbrep.

OpenNURBS API is relatively straightforward C++, and it is used to
represent/store BREPs in the BRL-CAD geometry file.  Entities are
stored using the built-in serialization facility (i.e., NURBS are
serialized as 3DM data in the G file).


-- Raytracing BREPs --

See Abert et al. (raytracing 06 paper: Direct and Fast Ray Tracing of
NURBS Surfaces).

We use a two-dimensional root-finding technique: we represent the ray
as two orthogonal planes (the intersection of the planes includes the
ray), and then find the root of an equation that represents the
gradient of the distance from the point to the intersection of the ray
planes. When this gradient becomes zero (we found a root), we've also
found the uv parameters for the intersection point.

Newton iteration is used, mostly since it is simple, displays
quadratic convergence when using good guesses, and is amenable to
acceleration using SIMD instructions.

Evaluation of the surface and its derivatives is done by the openNURBS
library at this point. The Abert paper gives some information on how
to do the evaluation using SIMD instructions (needed for speeding
things up).

After intersection, we need to trim the surface. Every edge of a BREP
is part of a loop "within" a face. Loops define boundaries on
faces. In our cube example above, the four edges of a each face
comprise a single loop (in this case an outer boundary). The surface
may be defined as an infinite plane, but this outer boundary loop
limits it to the area enclosed within those edges. As you may imagine,
a face may have more than one loop and these additional loops will
always be internal. All loops can also be considered trims, although
this term seems to be reserved for actual geometric curves that are
parameterized within the domain of an individual surface.

Properly ray tracing a BREP is quite difficult.  BREPs are not like
implicit solid geometry: there is no nice equation to simply solve.  A
lot of numerical techniques are used.  Moreover, surfaces, curves and
point geometry may not be aligned. There can be gaps between two mated
surfaces... and the list goes on.

Since it's possible to miss a surface but *need* a hit (i.e. it hit an
edge but passed between surfaces that did not mate up or overlap), we
need to do edge checks: at some point, we find out how far an
intersection point or a ray is from some set of edges


-- IGES converter --

A significant bit of time was spent writing the skeleton for a new
IGES converter in order to get non-trivial BREP geometry from an
external package into BRL-CAD for testing purposes.  These are the
"n_" files in src/conv/iges (e.g., n_iges.cpp).  Outstanding work:

* handle assemblies and proper mapping to BRL-CAD
* handle names better
* handle units properly
* more iges test cases

Moreover, continuation may require reivew on how tolerancing is
applied.  Tolerances cause BREP validity problems. Trims endpoint are
sometimes not within zero tolerance (e.g., 1e-12), so they "don't
match" but they are very very close (e.g., 1e-11)... so need to go
through and call ON_Brep::CloseTrimGap() on each pair of trims in a
loop.
