<a id="e3d-zmap"></a>

# ZMap

ZMaps are another representation for 3D data. They are generated by capturing the orthogonal projection of a point cloud or a mesh onto an arbitrary 3D reference plane.

* They contain an image in which each pixel value represents a positive distance from the reference plane.
* They are grayscale images like depth maps but represent metric and corrected 3D points.
* They are convenient representations for measurement and matching.
* They are compatible with most 2D processing functions.

![image](assets/images/easy3d/zmap_01.webp)

A ZMap also contains the following information:

* The transformation from the World coordinates to the ZMap coordinates.
* The size of a pixel, called the *resolution*.

#### HINT
* Use the method [`AsEImage`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap8.html#a25b614ee5e7b0d37284f93c3e63a4c8f) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap8.html#af2f15296498de96ad74444e9252bc5eb) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap8.html#ad41517753211f3febb2e1e79cce51bac) to obtain a reference to the contained image. This is useful to use all 2D processing features of **eVision** on ZMaps.
* Like in depth maps, a specific pixel value is reserved to represent undefined pixels. To get this pixel value, use the method [`GetUndefinedValue`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap8.html#a0937f7f455c60539eab3ffe38d37f6d9) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap8.html#ad5245d836a858aecb9f4b2584caa8b9c) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap8.html#a6f3016ecd4bf198322956510ef6d7493).
* These methods are not defined for the base class [`EZMap`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html) but are defined for all subclasses [`EZMap8`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap8.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap8.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap8.html), [`EZMap16`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap16.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap16.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap16.html) and [`EZMap32f`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap32f.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap32f.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap32f.html)

<a id="e3d-generating-zmap"></a>

## Generating a ZMap

The [`EPointCloudToZMapConverter`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html) class implements the conversion from a point cloud to a ZMap ([`EMeshToZMapConverter`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EMeshToZMapConverter.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EMeshToZMapConverter.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EMeshToZMapConverter.html) converts a mesh to a ZMap). With all parameters at default value, the [`EPointCloudToZMapConverter::Convert`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a2a77e28bc4f75485b5be186329565c3c) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a657883b067034e5dd2eb0960c19791eb) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a28e10b8c92383314eecaa933a473aa13) method automatically chooses the projection plane, the orientation, the map size and the resolution.

Several methods are available to further control the conversion:

* [`EPointCloudToZMapConverter::SetReferencePlane`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a3b2ade8437ca90d2a90ff979374cc74a) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a74654fb6913fd7a6df68917691e29af8) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a077f366d45130d962ff9b03d84bf28fc) defines a world space projection plane. The values of the ZMap pixels are the distance of the point cloud to that reference plane. By default, the reference plane crosses the origin and is perpendicular to the world Z axis. The plane is defined as a [`E3DPlane`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1E3DPlane.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1E3DPlane.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1E3DPlane.html) object.
* [`EPointCloudToZMapConverter::SetOrientationVector`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a89af83ed644b544422fdd2533ec10718) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a2da0df31418242995b74925502b2a5d0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a77ec5e9e2b074a6955a958762237bfcd) sets a world space vector representing the expected direction of the X (width) axis of the ZMap. The orientation vector allows you to “rotate” the object around the normal of the reference plane.
* [`EPointCloudToZMapConverter::SetOrigin`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a28d95ac6d0aa9a13b996488ce993e8a8) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a0e2ea51972294d1647f52d2e7d08fb05) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a44390b50971d9fa748dda3d0ec47bf11) specifies the world position that is on the ZMap lower left pixel (0, 0).
* [`EPointCloudToZMapConverter::SetMapSize`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a6abe6e94379a16ff5ef50404ec18bf39) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a5515ba86929a78381a1e357c268df9e3) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a8a5392bfff4872fb7d0aee4c5b4e0c8a) defines the resolution (number of pixels in X and Y axis) of the generated ZMap.
* [`EPointCloudToZMapConverter::SetMapXYResolution`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a12851027fa9895fb4496fd4e3a04baf0) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a08fca9511eb30931432ea46c85dd5baf) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a4961cf2c341ae515ad04aa791f8f622b) adjusts the X and Y resolution of the ZMap pixels, in world space unit per pixel (for example mm/pixel). This value is used to compute the ZMap size (width and height), depending on the projected size of the point cloud on the reference plane.
* [`EPointCloudToZMapConverter::SetMapZResolution`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a484433b3b270a954616af7fcdcda1ba8) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a026c9f71a78fcae5cb1825561a45ce4e) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a687e96f1f0738a5cd9d377e5768e371b) sets the Z resolution, in world space unit per pixel unit (gray value). The Z resolution is used to compute the transformation of the distance to the reference plan to the integer 8, 16 or 32 bits pixel value.
* [`EPointCloudToZMapConverter::EnableFillMode`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a9e55567efc3311806849185b784287df) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a2c649c8d3709c8771de630e7fd2ed28f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a07465d5d11bd51b59f4efc8aa1ef771e) and [`EPointCloudToZMapConverter::SetFillMode`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#ad8fbf5ee484a02baa8fc4f8c2b5120c2) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a57f52432ab30f6a29426481ded5d6304) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a2458b494ef6754fcc43e466d7d9195d3) control the options used to fill the “hole” in the ZMap. A hole exists when no 3D point is projected in the ZMap at a pixel position.

The methods [`EPointCloudToZMapConverter::SetReferencePlane`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a3b2ade8437ca90d2a90ff979374cc74a) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a74654fb6913fd7a6df68917691e29af8) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a077f366d45130d962ff9b03d84bf28fc), [`EPointCloudToZMapConverter::SetOrientationVector`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a89af83ed644b544422fdd2533ec10718) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a2da0df31418242995b74925502b2a5d0) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a77ec5e9e2b074a6955a958762237bfcd) and [`EPointCloudToZMapConverter::SetOrigin`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a28d95ac6d0aa9a13b996488ce993e8a8) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a0e2ea51972294d1647f52d2e7d08fb05) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a44390b50971d9fa748dda3d0ec47bf11) are used to set up the transformation between the world space and the ZMap space. This transformation is rigid (distances are kept).

Alternatively, it is possible to directly set that transformation with the method [`EPointCloudToZMapConverter::SetWorldToZMapTransform`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a92476dab1487b6faf609f2e72fba35be) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#aefe7146e977a49666001e4da45b1b0bb) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a91332640946783782d8342ce45d4a0bc) using a rigid matrix as parameter. In that case, the reference plane, the orientation vector and the origin parameters are ignored.

![image](assets/images/easy3d/zmap_02.webp)

The [`EPointCloudToZMapConverter::Convert`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a2a77e28bc4f75485b5be186329565c3c) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a657883b067034e5dd2eb0960c19791eb) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a28e10b8c92383314eecaa933a473aa13) method performs the effective projection of a point cloud ([`EPointCloud`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloud.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloud.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloud.html)) or a 3D object ([`EMesh`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EMesh.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EMesh.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EMesh.html)) to the 8, 16 or 32 bits ZMap.

When generating a ZMap from a point cloud, only individual points are projected on the ZMap. Depending on the point cloud density and the ZMap resolution, some regions of the ZMap may remain “undefined”. To get around this problem, adjust the resolution of the ZMap ([`EPointCloudToZMapConverter::SetMapXYResolution`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a12851027fa9895fb4496fd4e3a04baf0) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a08fca9511eb30931432ea46c85dd5baf) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloudToZMapConverter.html#a4961cf2c341ae515ad04aa791f8f622b) method) to remove “holes” on the ZMap.

By default, the point cloud to ZMap converter performs a filling algorithm. This process tries to replace undefined pixels with locally interpolated values.

![High-resolution ZMap with the pixel scale exceeding the point cloud density.](assets/images/easy3d/zmap_03.webp)![High-resolution ZMap generated using the same parameters, with filling enabled.](assets/images/easy3d/zmap_04.webp)![A reduced ZMap scale/resolution, without filling.](assets/images/easy3d/zmap_05.webp)

As a mesh defines a surface, its triangles are projected onto the ZMap plane. Thus, the generated image shows better continuity and less undefined pixels. However, the generation of a ZMap from an [`EMesh`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EMesh.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EMesh.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EMesh.html) is slower than from an [`EPointCloud`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloud.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloud.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloud.html).

<a id="e3d-zmap-to-point-cloud"></a>

## Creating a Point Cloud from a ZMap

To generate a point cloud from a ZMap, use the [`EZMapToPointCloudConverter`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapToPointCloudConverter.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapToPointCloudConverter.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapToPointCloudConverter.html) class.

The [`EZMapToPointCloudConverter::Convert`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapToPointCloudConverter.html#aa01c1d208bdc1477e82abdf8b6fab959) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapToPointCloudConverter.html#a9bf741914ff31e043bf21c76b50f2897) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapToPointCloudConverter.html#a7b21798aba0acd6953d5653a1c86985c)method takes:

* A ZMap source
* A [`EPointCloud`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPointCloud.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPointCloud.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPointCloud.html) destination.
* 4 optional parameters:
  * An [`ERegion`](../../../doxygen_cpp/classeVision_1_1ERegion.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1ERegion.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1ERegion.html) that defines the domain of the ZMap to convert. By default, uses all the defined pixels of the ZMap generate the point cloud.
  * A parameter to select the world space (by default) or the ZMap space to store the resulting positions in the point cloud.
  * Whether to compute the normals of the points of the point cloud during the conversion. This is not done by default.
  * A black and white or color image (with the same size as the ZMap) that is used to generate the intensity or color attribute of the point cloud.

<a id="e3d-zmap-coordinates"></a>

## Managing Coordinates

<a id="e3d-zmap-coordinate-systems"></a>

### Coordinate Systems on a ZMap

A ZMap has multiple coordinate systems:

* The **world space** system is the original, metric space from which the ZMap has been generated. Point clouds and meshes are expressed in the world coordinate system.
* The **ZMap space** is defined by a rigid transformation of the **world space**. The basis linked to this transformation is attached to the lower left corner of the ZMap.
* The **image space** is the system attached to the image representation of the ZMap. Its origin is the upper left corner of the ZMap and its unit length is one pixel along the X and Y axis.

The transformations between:

* The **image space** and the **ZMap space** include a scale factor.
* The **ZMap space** and the **world space** are solid transformations.

![image](assets/images/easy3d/coordinates_1.webp)

#### NOTE
To perform 2D processing in metric units on a ZMap, for example measurements with **EasyGauge**, you can retrieve an [`EFrame`](../../../doxygen_cpp/classeVision_1_1EFrame.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1EFrame.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1EFrame.html) converting image coordinates to ZMap coordinates using the method [`EZMap::GetZMapPositionFrame`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#a677de39202e5cc3f0af59fed08254aa6) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#a03449bbd8ed12dc95796a5f442a00200) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#a7880fe74edb066b2711de37e97bd0c30).

<a id="e3d-ezmap"></a>

### EZMap

The [`EZMap`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html) object exposes a set of methods to convert coordinates between world, ZMap and image spaces:

* [`EZMap::ImageToZMap`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#af7c76c56932fd5ef183fb4a05a72d35b) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#ada593bc73339de7c4803ec7c8715a95f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#aba69dc0c17cb35ae396633e85b9d1cda) converts a 2D position in the image to ZMap coordinates.
* [`EZMap::ZMapToImage`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#a253176ed121030e0f22e9c52a63bb48e) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#ad8a3c90e82990f2eacdf0612fcec5cdd) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#ad4d7d86677f3e9ae772257704401a5cd) is the reciprocal operation and converts a ZMap position to an image position.
* [`EZMap::ZMapToWorld`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#ad42ec051220e44c4649a05b251604151) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#afd1291c4d086d6c1e8d7e831cbc18810) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#ae592b61407ae165c7a99a6c93572fd52) is a method to transform positions from the 3D ZMap space to the 3D world space. The world space is the original point cloud or mesh space.
* [`EZMap::WorldToZMap`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#a55f695d84fe06378c7e8cfb17b203d59) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#a7e3009b5b6226f8d76d8c17c5c343025) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#a45393c1151b3d7882874d6566555a277) is the reciprocal operation, converting from world space to ZMap.
* [`EZMap::ImageToWorld`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#a5f14037bc6c3100c527f8f104c91a6fd) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#a1795ba812b6df8d40527cd9d69516642) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#a37d78daf9503dd9603f17346845a3700) and [`EZMap::WorldToImage`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#a19e3012335b75636bb064167ca9c09a0) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#a84c2d5f54212b0f08409e2a0f7138c2e) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#ab3b0961b9ba2da8ab5e82d8f565ad092) combine the functions above to transform directly from image space to world space (or the other way). These methods only perform geometric transformations between the various coordinate systems and do not access the actual ZMap gray scale values.

An overload of [`EZMap::ImageToWorld`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#a5f14037bc6c3100c527f8f104c91a6fd) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#a1795ba812b6df8d40527cd9d69516642) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#a37d78daf9503dd9603f17346845a3700) computes the world point corresponding to a 2D image point without specifying its $z$ coordinate.

* The $z$ coordinate is taken as the median or mean of the $z$ coordinates of the pixels in the vicinity of the 2D image point. This is useful to align an object based on features found on the ZMap with 2D operators.
* The $z$ coordinate is computed on the vicinity because the feature itself may not have a defined $z$ coordinate, for example if it is the center of a hole.

The functions that access the pixel values are:

* [`EZMap::GetWorldPositionFromPixelPosition`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#aebdc018880d751a7ef9165be8f4de96c) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#ac9e73278aff6c6cfa4a7cc716f0d9391) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#a5b04364930518f763794658a4158b968) is a method transforming the actual pixel value at integer position (u, v) to the original world space. This method queries the ZMap internal representation to get the pixel value w and transform the pixel space (u, v, w) coordinates to a world space position.
* [`EZMap16::GetPixelPositionFromWorldPosition`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap16.html#a996137f622569b3de261b18d5e42e3aa) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap16.html#aeaa82cdb375f8daef7090956841a4000) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap16.html#a082c84748048a3c7ea25cba1d85c8243) is a method to get a pixel value from a world position. The world position is projected on the ZMap and the pixel value is returned. If the world position is outside the ZMap domain, the method returns `FALSE`.
* [`EZMap::GetWorldPositionFromMapPosition`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMap.html#afec7c5cd954aa1249a3b794f65ae30f7) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMap.html#abbce08cd336efdef7e62e329787dd5c8) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMap.html#aa67a88d6d382211db49e73e4c079ad74) is a method to get a 3D world position corresponding to a ZMap 2D coordinate. The world position is in the original point cloud space. If the 2D coordinate is undefined, an exception is thrown.

<a id="e3d-zmap-leveling"></a>

## Leveling a ZMap

Sometimes, the reference plane of the ZMap is not set correctly.

To solve this problem, use the method [`EZMapLeveler::Level`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a60554efdb488e8fd97d43f9a824d78f4) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a79dc7fc7c875da99d704e9940442b5d1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a272c8cc00c35bef1bf9d63defe4c1219) of the class [`EZMapLeveler`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html) to reproject the ZMap on a new reference plane.

To specify the new reference plane, you can either:

* Give an `ERegion` of points contained in the plane to the method [`EZMapLeveler::Level`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a60554efdb488e8fd97d43f9a824d78f4) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a79dc7fc7c875da99d704e9940442b5d1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a272c8cc00c35bef1bf9d63defe4c1219). The plane might be shifted so that the leveled ZMap contains all the points of the original one.

![image](assets/images/easy3d/zmap_leveler_2.webp)
* Give the normal of the new plane to the ZMap (with argument `projectionDirection`). The ZMap plane is computed from the normal and shifted so that the new ZMap contains all the points of the old one.

#### HINT
A typical way to find the `projectionDirection` is to use an [`EPlaneFinder`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EPlaneFinder.html) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EPlaneFinder.html) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPlaneFinder.html) to find the biggest plane in the ZMap.

#### NOTE
See code snippet: [“Performing ZMap Leveling”](../../../resources/code_snippets/3d_processing/easy3d/zmapleveling.html.md).

* To set the angle of the X and Y axes of the leveled ZMap, use the argument `rotationAngle`.

![image](assets/images/easy3d/zmap_leveler_1.webp)

<a id="e3d-zmap-size-resolution"></a>

### Size and XYZ Resolution Settings

There are several options to handle the size and X, Y or Z resolution of the leveled ZMap:

* [`EPreservationMode`](../../../doxygen_cpp/namespaceeVision_1_1Easy3D.html#acf8683b87b8b1c412a6fcc963431f565) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision_1_1Easy3D.html#af6774944b3a6c3e0a1634889b10c2bf1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPreservationMode.html) (through methods [`EZMapLeveler::GetPreservationModes`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#aaba0c8b11cb44d6e4cc0d5f18134f652) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a0034a08af8494305078d45bc271b3f4f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a13fb021ddc7c9c0358fe501461ef3c23) and [`EZMapLeveler::SetPreservationModes`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a0ba4cb9160cb467c08ebbd3f29b72d26) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a0034a08af8494305078d45bc271b3f4f) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a13fb021ddc7c9c0358fe501461ef3c23)) determines whether the XY resolution, size and/or Z resolution of the input ZMap are preserved.
  * When the XY resolution is preserved, the size of the leveled ZMap is adjusted.
  * When the size of the ZMap is preserved, the resolution is adjusted.

  #### NOTE
  Note that this may introduce holes in the leveled ZMap.

  * When both are preserved, the visible contents of the ZMap are adjusted, meaning that some undefined pixels may appear on the edges of the ZMap or the extremities of the object may be cropped.
  * When the Z resolution is preserved, some data may be impossible to represent if the Z range of the leveled ZMap is bigger than the one of the source ZMap (see next point). Otherwise, the Z resolution is recomputed to use the whole range of the ZMap.
  * To avoid undesired side-effects, only the XY resolution is preserved by default.
* Use [`EZMapLeveler::SetPreserveZResolutionFailureHandler`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a41bebc7ddb20f179c9cd02524ef6e233) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a8902b27a7c83531397680c7b43d82e7c) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#acaa88f5e6c8c64b363a31e419b4bef9a) to choose how to handle data falling outside of the representable range of the ZMap when [`EPreservationMode`](../../../doxygen_cpp/namespaceeVision_1_1Easy3D.html#acf8683b87b8b1c412a6fcc963431f565) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision_1_1Easy3D.html#af6774944b3a6c3e0a1634889b10c2bf1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPreservationMode.html) is set to [`EPreservationMode_ZResolution`](../../../doxygen_cpp/namespaceeVision_1_1Easy3D.html#acf8683b87b8b1c412a6fcc963431f565) [<sub>.NET</sub>](../../../doxygen_cs/namespaceeVision_1_1Easy3D.html#af6774944b3a6c3e0a1634889b10c2bf1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EPreservationMode.html). The data may be cropped (the corresponding pixel is undefined), Saturated (the corresponding pixel is white) or an exception is thrown when the problem occurs.

<a id="e3d-zmap-3d-position"></a>

### 3D Position Settings

* By default, the leveling does not change the underlying 3D data of the ZMap. The goal is to use the leveling to ease some 2D processing while maintaining the link with the real-world positions of the data.
* Alternatively, you can use the method [`EZMapLeveler::SetPreserve3DPosition`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#aabb593a010b977a88d2098345e1970a2) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#aef14f1245ead1b01a266e79a826e2f36) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a9cb3158eebe337b8b2908ec8c8e6e976) to alter that behavior and modify the 3D data of the leveled ZMap. In this mode, the `z = 0` plane is either:
  * The plane defined by the `ERegion` when the method [`EZMapLeveler::Level`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a60554efdb488e8fd97d43f9a824d78f4) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a79dc7fc7c875da99d704e9940442b5d1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a272c8cc00c35bef1bf9d63defe4c1219) takes a region as argument.
  * The plane used for the leveling when the method [`EZMapLeveler::Level`](../../../doxygen_cpp/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a60554efdb488e8fd97d43f9a824d78f4) [<sub>.NET</sub>](../../../doxygen_cs/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a79dc7fc7c875da99d704e9940442b5d1) [<sub>Python</sub>](../../../doxygen_python/classeVision_1_1Easy3D_1_1EZMapLeveler.html#a272c8cc00c35bef1bf9d63defe4c1219) takes a projection direction as argument.
