module Gg:`sig`

..`end`

Basic types for computer graphics.

`Gg`

defines types and functions for floats,
vectors, points, matrices,
quaternions, sizes,
axis aligned boxes, colors,
color profiles and raster data.

Consult the basics. Open the module to use it, this defines only modules and types in your scope.

*Release 0.8.0 - Daniel Bünzli <daniel.buenzl i@erratique.ch> *

module Float:`sig`

..`end`

Floating point number utilities.

The following type are defined so that they can be used in vector modules. The matrix modules are here.

`type `

m2

The type for 2x2 matrices.

`type `

m3

The type for 3x3 matrices.

`type `

m4

The type for 4x4 matrices.

An n-dimensional *vector* `v`

is a sequence of n, zero indexed,
floating point *components*. We write `v`

_{i} the ith component
of a vector.

`type `

v2

The type for 2D vectors.

`type `

v3

The type for 3D vectors.

`type `

v4

The type for 4D vectors.

module type V =`sig`

..`end`

Implemented by all vector types.

module V2:`sig`

..`end`

module V3:`sig`

..`end`

module V4:`sig`

..`end`

An n-dimensional *point* `p`

is a vector of the corresponding
dimension. The components of the vector are the point's * coordinates*.

type`p2 =`

`v2`

The type for 2D points.

type`p3 =`

`v3`

The type for 3D points.

module type P =`sig`

..`end`

Implemented by all point types.

module P2:`sig`

..`end`

module P3:`sig`

..`end`

Unit quaternions
represent rotations in 3D space. They allow to smoothly
interpolate between orientations. A quaternion is a 4D vector,
whose components `x`

, `y`

, `z`

, `w`

represents the quaternion
`x`

i+ `y`

j + `z`

k + `w`

.

type`quat =`

`v4`

The type for quaternions.

module Quat:`sig`

..`end`

An *m*x*n* matrix `a`

is an array of *m* rows and *n*
columns of floating point *elements*. We write `a`

_{ij} the
element of `a`

located at the ith row and jth column.

Matrix constructors specify matrix elements in
row-major order
so that matrix definitions look mathematically natural with proper
code indentation. However elements are *stored* and * iterated* over in
column-major
order.

module type M =`sig`

..`end`

Implemented by all (square) matrix types.

module M2:`sig`

..`end`

module M3:`sig`

..`end`

module M4:`sig`

..`end`

An n-dimensional *size* `s`

represents extents in n-dimensional space.

type`size2 =`

`v2`

The type for sizes in 2D space.

type`size3 =`

`v3`

The type for sizes in 3D space.

module type Size =`sig`

..`end`

Implemented by all size types.

module Size2:`sig`

..`end`

module Size3:`sig`

..`end`

An n-dimensional axis-aligned box `b`

is defined by an
n-dimensional point `o`

, its *origin*, and an n-dimensional size
`s`

. Operations on boxes with negative sizes are undefined.

The space S(`b`

) spanned by `b`

is [`o`

_{0};
`o`

_{0} + `s`

_{0}] x ... x [`o`

_{n-1}; `o`

_{n-1} +
`s`

_{n-1}]. The extremum points of this space are the box's * corners*. There is a distinguished n-dimensional `empty`

box such
that S(`empty`

) is empty.

`type `

box2

The type for 2D axis-aligned boxes
(rectangles).

`type `

box3

The type for 3D axis-aligned boxes
(cuboids).

module type Box =`sig`

..`end`

Implemented by all axis-aligned box types.

module Box2:`sig`

..`end`

module Box3:`sig`

..`end`

type`color =`

`v4`

The type for colors, see details.

module Color:`sig`

..`end`

Colors and color profiles.

`type `

raster

The type for raster data.

module Raster:`sig`

..`end`

Raster data.

`Gg`

is designed to be opened in your module. This defines only
types and modules in your scope, no values. Thus to use `Gg`

start
with :

`open Gg`

In the toplevel, if you installed `Gg`

with ocamlfind, requiring
`Gg`

:

`> #require "gg";;`

automatically opens `Gg`

and installs printers for the types.

Most types and their functions are defined with the following
conventions. The type is first defined in `Gg`

, like `Gg.v2`

for 2D
vectors, a module for it follows. The name of the module is
the type name capitalized, e.g. `Gg.V2`

for 2D vectors and it has
the following definitions:

- a type
`t`

equal to the original toplevel type (`Gg.V2.t`

). `dim`

, an`int`

value that indicates the dimensionality of the type (`Gg.V2.dim`

).`v`

, a constructor for the type (`Gg.V2.v`

).`to_string`

and`pp`

to convert values to a textual representation for debugging purposes and toplevel interaction (`Gg.V2.to_string`

,`Gg.V2.pp`

).`equal`

and`compare`

the standard functions that make a module a good functor argument (`Gg.V2.equal`

,`Gg.V2.compare`

).`equal_f`

and`compare_f`

which compare like`equal`

and`compare`

but allow to use a client provided function to compare floats (`Gg.V2.equal_f`

,`Gg.V2.compare_f`

).`ltr`

and`tr`

to apply linear and affine transforms on the type (`Gg.V2.ltr`

,`Gg.V2.tr`

).- Other accessors (e.g.
`Gg.V2.x`

), constants (e.g.`Gg.V2.zero`

), functions (e.g.`Gg.V2.dot`

) and predicates (e.g.`Gg.V2.exists`

) specific to the type. - Modules that represent the same object but for different
dimensions, like
`Gg.V2`

,`Gg.V3`

,`Gg.V4`

for vectors, usually share a common signature. This common signature is collected in a module type defined in`Gg`

, this signature is`Gg.V`

for vectors.

Some types are defined as simple abreviations. For example the
type `Gg.p2`

for 2D points is equal to `Gg.v2`

. These types also have
a module whose name is the type name capitalized, `Gg.P2`

in our
example. However this module only provides alternate constructors,
constants and accessors and the extended functionality specific to the
type. You should fallback on the module of the abreviated type
(`Gg.V2`

in our example) for other operations. The aim of these
types is to make your code and signatures semantically clearer
without the burden of explicit conversions.

Finally there are some types and modules like `Gg.Color`

whose structure
is different because they provide specific functionality.

Here are a few other conventions :

- Numbers in names indicate dimensionality when ambiguity can arise.
For example
`Gg.M4.scale3`

indicates scale in 3D space wihle`Gg.M4.scale`

scale in 4D space. - Most functions take the value they act upon first.
But exceptions abound, to match OCaml conventions, to have your
curry or to match mathematical notation (e.g.
`Gg.V2.tr`

). - Conversion functions follow the
`of_`

conventions. Thus to convert a value of type`t'`

to a value of type`t`

look for the function named`T.of_t'`

.

To conclude note that it is sometimes hard to find the right place for a function. If you cannot find a function look into each of the modules of the types you want to act upon.

- In 3D space we assume a right-handed coordinate system.
- Angles are always given in radians (except in this function...).
- In 2D space positive angles determine counter clockwise rotations.
- In 3D space positive angles determine rotations directed according to the right hand rule.

Values of type `Gg.color`

are in a *linear* sRGB space as this is
the space to work in if you want to process colors correctly (e.g.
for blending). The constructor `Gg.Color.v_srgb`

takes its parameters
from a *non-linear* sRGB space and converts them to *linear*
sRGB.

`# let c = Color.v_srgb 0.5 0.5 0.5 1.0;;`

- : Gg.color = (0.214041 0.214041 0.214041 1)

This is the constructor you are likely to use when you specify color
constants (e.g. to specify a color value matching a CSS color).
If you need an sRGB color back from a `Gg.color`

value use `Gg.Color.to_srgb`

:
`# Color.to_srgba c;;`

- : Gg.Color.srgba = (0.5 0.5 0.5 1)

- Everything is tail-recursive.
`to_string`

functions are not thread-safe. Thread-safety can be achieved with`pp`

functions.- Do not rely on the output of printer functions, they are
subject to change. The only exception is
`Gg.Float`

's module printers that output a lossless textual representation of floats. While the actual format is subject to change it will remain compatible with`float_of_string`

. - All modules can be directly given as arguments to
`Set.Make`

and`Map.Make`

. However this will use`Pervasives.compare`

and thus binary comparison between floats. Depending on the intended use this may be sensible or not. Comparisons with alternate functions to compare floats can be defined by using the functions named`compare_f`

(e.g.`Gg.V2.compare_f`

). An alternate float comparison function is`Gg.Float.compare_tol`

that combines relative and absolute float comparison in a single test, see`Gg.Float.equal_tol`

for the details. - For performance reasons some functions of the
`Gg.Float`

module are undefined on certain arguments but do not raise`Invalid_argument`

on those. As usual do not rely on the behaviour of functions on undefined arguments, these are subject to change.