mapteksdk.data.primitives.point_properties module

Support for point primitives.

A point is a 3D location in space. In Python, they are represented as a numpy array containing three 64-bit floating point numbers, representing the location relative to the origin. For example, the point [X, Y, Z] is X metres away from the origin in the x direction (typically east), Y metres away from the origin in the y direction (typically north) and Z metres away from the origin in the z direction (typically up).

Points are typically used to define other primitives, such as edges, facets and cells.

class PointProperties

Bases: object

Mixin class which provides spatial objects support for point primitives.

A point is represented as a numpy array of length 3 of the form [x, y, z] where x, y and z are floating point numbers. For example, the point [1, 2, 3.5] is 1 metre away from the origin in the X direction (East in a standard view), 2 units away from the origin in the Y direction (North in a standard view) and 3.5 units away from the origin in the z direction. If one of the elements of a point is negative, this indicates its distance from the origin is in the opposite direction. For example, the point [-1, 0, 0] is 1 unit away from the origin in the direction opposite to the East arrow.

Functions and properties defined on this class are available on all classes which support points.

is_read_only: bool
property points: PointArray

The three dimensional points in the object.

This is a numpy array of shape (N, 3) where N is the point count. This is of the form: [[x1, y1, z1], [x2, y2, z2], …, [xN, yN, zN]]

To get the ith point:

>>> point_i = point_set.points[i]

Similarly, to get the x, y and z coordinates of the ith point:

>>> x, y, z = point_set.points[i]
Raises:

AttributeError – If attempting to set the points on an object which does not support setting points.

Examples

Create a new point set and set the points:

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> project = Project()
... with project.new("cad/test_points", PointSet) as new_points:
...     new_points.points = [[0, 0, 0], [1, 0, 0], [1, 1, 0],
...                          [0, 1, 0], [0, 2, 2], [0, -1, 3]]

Print the second point from the point set defined above.

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> project = Project()
>>> with project.read("cad/test_points") as read_points:
...     print(read_points.points[2])
[1., 1., 0.]

Then set the 2nd point to [1, 2, 3]:

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> project = Project()
>>> with project.edit("cad/test_points") as edit_points:
...     edit_points.points[2] = [1, 2, 3]

Iterate over all of the points and print them.

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> project = Project()
>>> with project.read("cad/test_points") as read_points:
>>>     for point in read_points.points:
>>>         print(point)
[0., 0., 0.]
[1., 0., 0.]
[1., 2., 3.]
[0., 1., 0.]
[0., 2., 2.]
[0., -1., 3.]

Print all points with y > 0 using numpy. Note that index has one element for each point which will be true if that point has y > 0 and false otherwise. This is then used to retrieve the points with y > 0.

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> project = Project()
>>> with project.read("cad/test_points") as read_points:
...     index = read_points.points[:, 1] > 0
...     print(read_points.points[index])
[[1. 2. 3.]
 [0. 1. 0.]
 [0. 2. 2.]]

To add a new point to a PointSet, the numpy row_stack function can be used. This is demonstrated by the following example which creates a point set and then opens it for editing and adds an extra point. The original points are coloured blue and the new point is coloured red.

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> import numpy as np
>>> if __name__ == "__main__":
...   with Project() as project:
...     with project.new("cad/append_single_example", PointSet
...         ) as point_set:
...       point_set.points = [
...         [-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0]
...       ]
...       point_set.point_colours = [0, 0, 255, 255]
...     with project.edit(point_set.id) as edit_set:
...       edit_set.points = np.row_stack((edit_set.points, [0, 0, 1]))
...       edit_set.point_colours[-1] = [255, 0, 0, 255]

The row stack function can also be used to add multiple points to an object at once, as demonstrated in the following example:

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> import numpy as np
>>> if __name__ == "__main__":
...   original_points = [[-1, -1, 1], [1, -1, 1], [-1, 1, 1], [1, 1, 1]]
...   new_points = [[-1, -1, 2], [1, -1, 2], [-1, 1, 2], [1, 1, 2]]
...       with Project() as project:
...     with project.new("cad/append_multiple_example", PointSet
...         ) as point_set:
...       point_set.points = original_points
...       point_set.point_colours = [0, 0, 255, 255]
...     with project.edit(point_set.id) as edit_set:
...       original_point_count = edit_set.point_count
...       edit_set.points = np.row_stack((edit_set.points, new_points))
...       new_point_count = edit_set.point_count
...       edit_set.point_colours[
...         original_point_count:new_point_count] = [255, 0, 0, 255]

The row stack function can combine more than two point arrays if required by adding additional arrays to the tuple passed to the function. This is demonstrated by the following example, which creates a new point set containing the points from the point sets in the previous two examples plus a third set of points defined in the script. Make sure to run the previous two examples before running this one.

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> import numpy as np
>>> if __name__ == "__main__":
...   extra_points = [[-2, -2, 3], [2, -2, 3], [-2, 2, 3], [2, 2, 3]]
...   with Project() as project:
...     with project.new("cad/triple_point_stack", PointSet) as new_set, \
...         project.read("cad/append_single_example") as single_set, \
...         project.read("cad/append_multiple_example") as multiple_set:
...       new_set.points = np.row_stack((
...         extra_points,
...         single_set.points,
...         multiple_set.points
...       ))
property point_z: FloatArray

The Z coordinates of the points.

Raises:
  • ValueError – If set using a string which cannot be converted to a float.

  • ValueError – If set to a value which cannot be broadcast to the right shape.

  • TypeError – If set using a value which cannot be converted to a float.

append_points(*points)

Append points to the object.

Using this function is preferable to assigning to the points array directly because it allows points to be added to the object without any risk of changing existing points by accident. The return value can also be used to assign point properties for the new points.

Parameters:

points (Point) – Points to append to the object.

Returns:

Boolean array which can be used to assign properties for the newly added points.

Return type:

BooleanArray

Raises:

AppendPointsNotSupportedError – If the object does not support appending points. This is raised for GridSurfaces, and non-new Scans.

Examples

This function can be used to add a single point to an object:

>>> point_set: PointSet
>>> point_set.append_points([1.5, -1.5, 2.25])

Passing multiple points can be used to append multiple points at once:

>>> point_set: PointSet
>>> point_set.append_points([3.1, 1.1, 4.1], [2.2, 7.2, 1.2])

This function also accepts iterables of points, so the following is functionally identical to the previous example:

>>> point_set: PointSet
>>> point_set.append_points([[3.1, 1.1, 4.1], [2.2, 7.2, 1.2]])

The return value of this function can be used to assign point properties to the newly added points:

>>> point_set: PointSet
>>> new_point_indices = point_set.append_points(
...     [3.1, 1.1, 4.1], [2.2, 7.2, 1.2])
>>> # Colour the two new points blue and magenta.
>>> point_set.point_colours[new_point_indices] = [
...     [0, 0, 255, 255], [255, 0, 255, 255]]
property point_colours: ColourArray

The colour of each point in RGBA.

This is a numpy array of shape (N, 4) where N is the point count.

Examples

To get the colour of the ith point:

>>> point_i_colour = point_set.point_colours[i]

To get the red, green, blue and alpha components of the ith point:

>>> red, green, blue, alpha = point_set.point_colours[i]
property point_visibility: BooleanArray

An array which indicates which points are visible.

This is an array of booleans of shape (N,) where N is the point count. If the ith element in this array is True, then the ith point is visible. If the ith element in this array is False, then the ith point is invisible.

Examples

To get if the ith point is visible:

>>> point_i_visible = point_set.point_visibility[i]

The point visibility can be used to filter the arrays of other per-point properties down to only include the values of visible points. The following snippet demonstrates getting the colours of only the visible points in an object:

>>> visible_colours = point_set.point_colours[point_set.point_visibility]
property point_selection: BooleanArray

An array which indicates which points have been selected.

This is an array of booleans of shape (N,) where N is the point count. If the ith element in this array is True, then the ith point is selected. If the ith element in this array is False, then the ith point is not selected.

Examples

To get if the ith point is selected:

>>> point_i_selected = point_set.point_selection[i]

The point selection can be used to filter the arrays of other per-point properties down to only include the values of selected points. The following snippet demonstrates getting the colours of only the selected points in an object:

>>> selected_colours = point_set.point_colours[point_set.point_selection]
property point_count: int

The number of points in this object.

property point_attributes: PrimitiveAttributes

Access the custom point attributes.

These are arrays of values of the same type, with one value for each point.

Use Object.point_attributes[attribute_name] to access the point attribute called attribute_name. See PrimitiveAttributes for valid operations on point attributes.

Returns:

Access to the point attributes.

Return type:

PrimitiveAttributes

Raises:

ValueError – If the type of the attribute is not supported.

save_point_attribute(attribute_name, data)

Create and/or edit the values of the point attribute attribute_name.

This is equivalent to Object.point_attributes[attribute_name] = data.

Saving a point attribute using an AttributeKey allows for additional metadata to be specified.

Parameters:
  • attribute_name (str | AttributeKey) – The name or key of the attribute.

  • data (npt.ArrayLike) – An array_like of length point_count containing the values for attribute_name.

Raises:
  • ValueError – If the type of the attribute is not supported.

  • AmbiguousNameError – If there is already an attribute with the same name, but with different metadata.

delete_point_attribute(attribute_name)

Delete a point attribute by name.

This is equivalent to: point_attributes.delete_attribute(attribute_name)

Parameters:

attribute_name (str | AttributeKey) – The name or key of the attribute.

class PointDeletionProperties

Bases: object

Mixin class which adds functionality for removing points.

This is intended to be used in addition to PointProperties. It is a separate class because not all objects which have points support remove_points.

remove_points(point_indices)

Remove one or more points from the object.

Calling this function is preferable to altering the points array because this function also removes the point properties associated with the removed points (e.g. point colours, point visibility, etc).

This operation is performed directly on the Project and will not be undone if an error occurs.

Parameters:

point_indices (int | Sequence[int]) – The index of the point to remove or a list of indices of points to remove. Indices should only contain 32-bit unsigned integer (They should be greater than or equal to 0 and less than 2**32). Any index greater than or equal to the point count is ignored. Passing an index less than zero is not supported. It will not delete the last point.

Returns:

If passed a single point index, True if the point was removed and False if it was not removed. If passed an iterable of point indices, True if the object supports removing points and False otherwise.

Return type:

bool

Raises:

ReadOnlyError – If called on an object not open for editing. This error indicates an issue with the script and should not be caught.

Warning

Any unsaved changes to the object when this function is called are discarded before any points are deleted. If you wish to keep these changes, call save() before calling this function.

Examples

Deleting a point through this function is preferable over removing the point from the points array because this function also deletes the properties associated with the deleted points. For example, all points will remain the same colour after the deletion operation, which points are visible will remain the same, etc. This is shown in the following script:

>>> from mapteksdk.project import Project
>>> from mapteksdk.data import PointSet
>>> project = Project()
>>> red = [255, 0, 0, 255]
>>> blue = [0, 0, 255, 255]
>>> with project.new("cad/deletion_example", PointSet) as point_set:
...     point_set.points = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [1, 1, 0]]
...     point_set.point_colours = [red, red, blue, blue]
...     point_set.point_attributes["attribute"] = [0, 1, 2, 3]
>>> with project.edit(point_set.id) as edit_set:
...     edit_set.remove_points((1, 2))
...     print("points\n", edit_set.points)
...     print("colours\n", edit_set.point_colours)
...     print("attribute\n", edit_set.point_attributes["attribute"])
points
 [[0. 0. 0.]
 [1. 1. 0.]]
colours
 [[255   0   0 255]
 [  0   0 255 255]]
attribute
 [0 3]