Converting 2D points to 3D points

The mapteksdk package usually uses three dimensional points (x, y and z). However when reading data from files or other packages, the points may be provided with only two dimensions (x and y). The following script demonstrates how to efficiently convert an array of two dimensional points to an array of three dimensional points.

from __future__ import annotations

import typing

from mapteksdk.project import Project
from mapteksdk.data import PointSet

import numpy as np

def convert_2d_points_to_3d(points_2d, z_coordinate):
    """Convert 2D coordinates to 3D coordinates.

    Parameters
    ----------
    points_2d
        Array like containing two dimensional (x, y) coordinates.
    z_coordinate
        Z coordinate to add to the 2D coordinates.

    Returns
    -------
    npt.ArrayLike
        An array of points containing the 2D points in points_2d
        with z_coordinate added to make the coordinates three
        dimensional.
    """
    points_3d = np.empty(
        (len(points_2d), 3), dtype=np.float64
    )
    points_3d[:, :2] = points_2d
    points_3d[:, 2] = z_coordinate
    return points_3d

if __name__ == "__main__":
    points = [
        (-1, -1), (2, -1), (-1, 2), (2, 2)
    ]
    with Project() as project:
        with project.new("cad/2d_point_set", PointSet) as point_set:
            point_set.points = convert_2d_points_to_3d(points, 0.0)
            print(point_set.points)

    # Expected output:
    # [[-1. -1.  0.]
    #  [ 2. -1.  0.]
    #  [-1.  2.  0.]
    #  [ 2.  2.  0.]]

An alternative approach to the above would be using the following code snippets.

If you have a list of tuples (or lists) with two elements in each tuple, such as [(x0, y0), (x1, y1), … xN, yN)], then the following snippet can convert it into a 3D array with of triples (x, y, z) where z is always zero.

import numpy as np
points_2d = [(-1, -1), (2, -1), (-1, 2), (2, 2)]
points_3d = np.hstack((points_2d, np.zeros((len(points_2d), 1))))

If you have a NumPy array of shape (N, 2), then the following snippet can convert it into a 3D array with (x, y, z) where z is always zero.

import numpy as np
points_3d = np.hstack((points_2d, np.zeros((points_2d.shape[0], 1))))

The resulting points_3d in both cases will be:

array([[-1., -1.,  0.],
       [ 2., -1.,  0.],
       [-1.,  2.,  0.],
       [ 2.,  2.,  0.]])