# Surface

### Description

The Surface data type represents a cloud of points in a three-dimensional space. The represented point cloud is organized in a precisely defined way. The X coordinate values of the points create an arithmetic progression, and the same goes for the Y coordinate values. Therefore the whole Surface object has a grid structure, which enables to spare a lot of memory in the point cloud representation. It also allows to define regions of interest for a Surface object.

## Memory Representation

The aforementioned grid structure is described by four values: offsets and scales on X and Y axes, named: XOffset, XScale, YOffset, YScale. The values denotes that the cloud points in the first row of the grid have the Y coordinate equal to YOffset, in the second row the Y coordinate is: YOffset + YScale, in the third row it is: YOffset + 2 * YScale and so on. Similarly, the points in the consecutive columns of the grid have the X coordinate equal to XOffset, XOffset + XScale, XOffset + 2 * XScale and so on.

The Z coordinate values are stored in the same way as the values in an Image object.
Just as in there, the Surface values are represented in a one of 6 possible primitive
types: **sint8**, **uint8**, **sint16**, **uint16**, **sint32** and **real**.
To obtain the resulting value of the Z coordinate, the value stored has to be multiplied
by ZScale and ZOffset has to be added. For every point in the cloud however it is possible that it does not exist.
In this case a special value of Z is stored to mark that the point is missing.

## Invalid points

Some surface generation and transformation filters can introduce **invalid points**, that is, points
that have an infinite value in the Z coordinate. An example of such filter could be **ArrangePoint3DArray**
which will insert an invalid point in all locations for which the Z coordinate could not be computed (e.g. due to
lack of nearby points in the input array).

Invalid points can be localized using **SurfaceValidPointsRegion** or replaced with a constant value with a filter
called **ReplaceInvalidSurfacePoints**.

## Remarks

- Single Surface object can allocate no more than 2GB of memory.
- Maximum Surface single dimension should not exceed 65535 (because regions use 16-bit integers for performance reasons).