# 9.16. shape¶

The class shape represents 2D geometric elements with floating (or subpixel) precision. Any shape is given by a set of base points and an optional transformation matrix. The following shapes are currently defined:

• Point

• Line (a direct connection between two points)

• Rectangle (an rectangle that is mainly defined by the top-left and bottom-right corner point)

• Square (similar to a rectangle, however the side lengths are equal. It is defined by the center point and the side lengths)

• Ellipse (an ellipse that is defined by the top-left and bottom-right corner of its outer rectangle)

• Circle (similar to an ellipse, however the side lengths are equal. It is defined by the center point and the side lengths)

• Polygon (polygon with n points)

Examples for the creation of shapes are:

```point = shape(shape.Point, (0,0))
line = shape(shape.Line, (0,0), (100,50))
rect = shape(shape.Rectangle, (20,20), (70,100)) #top-left, bottom-right
square = shape(shape.Square, (30,-50), 20) #center, side-length
ellipse = shape(shape.Ellipse, (-50,-70), (-20, 0)) #top-left, bottom-right
circle = shape(shape.Circle, (-30, 100), 40) #center, side-length
```

If the optional transformation matrix (2x3 float64 matrix) is set, the shape can be translated and/or rotated. Please consider, that any rotation is currently not supported in any plot. Rectangles, squares, ellipses or circles are always defined, such that their main axes are parallel to the x- and y-axis. Use the rotation to choose another principal orientation. The base points of the shape are never affected by any transformation matrix. Only the contour points can be requested with the applied coordinate transformation (if desired).

It is possible to obtain a `region` from any shape with a valid area (points and lines don’t have an area). The region is always a pixel-precise structure. Regions can be combined using union or intersection operators.

Furthermore, a mask `dataObject` can be obtained from any dataObject using the method `createMask()` if one or multiple shapes are given.

The demo script demoShapes.py show further examples about the usage of shape objects.

class `itom.``shape`(type=shape.Invalid, param1=None, param2=None, index=- 1, name='')shape

Bases: `object`

Creates a shape object of a specific type.

A shape object is used to describe a vectorized object, that can for instance be displayed in plots or might also be passed to different methods, e.g. in order to define a masked area etc. A `shape` object can also be converted into a `region` object, however the vector information is then projected onto a raster with a given resolution.

Depending on the `type`, the following arguments are allowed, where the first argument must be given to `param1` and the 2nd one to `param2`:

• `shape.Invalid`: -

• `shape.Point`: point

• `shape.Line`: start-point, end-point

• `shape.Rectangle`: top left point, bottom right point

• `shape.Square`: center point, side-length

• `shape.Ellipse`: top left point, bottom right point of bounding box

• `shape.Circle`: center point, radius

• `shape.Polygon`: 2xM float64 array with M points of polygon

The parameters `point`, `start-point`, … can be all array-like types (e.g. `dataObject`, `list`, `tuple`, `np.ndarray`) that can be mapped to float64 and have two elements.

Another possibility to create a `shape` object for a certain type is to use one of the following static creation functions:

During construction, all shapes are aligned with respect to the x- and y-axis. Set a 2d transformation (attribute `transform`) to rotate and move it.

Parameters
type`int`

Type of the shape (see list above).

param1`list` `of` `float` or `tuple` `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

1st initialization argument. This argument is depending on the `type` (see list above).

param2`list` `of` `float` or `tuple` `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

2nd initialization argument. This argument is depending on the `type` (see list above).

index`int`

index of the shape, or `-1` if not further specified (default).

name`str`

name of the shape, can for instance be displayed next to shapes in plots (depending on the parameterization of the plot).

`contains`(points)Union[bool, dataObject]

Checks if one or multiple `points` are contained in this shape.

Tests if one or multiple `points` lie within the contour of the given shape. If the shape has an empty area (e.g. points, line…) the test will always return `False`.

Parameters
points

The coordinates `(x, y)` of the point to be tested as sequence or an array-like object (shape `2 x N`), where the first row contains the x-coordinates and the 2nd-row the y-coordinates of `N` points to be tested. The array-like object must be convertible to `float64`, which is internally done before testing.

Returns
result

If one point is passed as sequence, `True` is returned if this point is within the contour of this shape, otherwise `False`. If `points` is given as array-like object, a `1 x N` `dataObject` with dtype `uint8` is returned, where the value `255` indicates, that the corresponding point is inside of the shape’s contour and `0` outside.

`contour`(applyTrafo=True, tol=- 1.0)dataObject

Returns the contour points of this shape as `2 x N`, float64 `dataObject`.

For most shapes, the contour is exactly given by its corner points. However for circles or ellipses, the contour has to be approximated by line segments. Use the argument `tol` to set the maximum distance between each line segment and the real contour of the shape. If `tol` is set to -1.0, `tol` is assumed to be 1 % of the smalles diameter.

Shapes can have a transformation matrix (attribute `transform`). If `applyTrafo` is `True`, the returned contour points correspond to the transformed base shape, else the contour with respect to the base points is returned.

Parameters
applyTrafobool

Define if the transformation matrix (default: unity matrix, attribute `transform`) should be considered for the returned contour points (`True`) or not (`False`).

tol`float`

Maximum tolerance to determine the approximated contour in the case of circular or elliptical shapes. The approximated contour consists of line segments, that can differ from the real contour by a maximum of `tol`. If -1.0, the tolerance is assumed to be one percent of the smallest diameter.

`copy`()shape

Returns a deep copy of this shape.

Returns
copy`shape`

deep copy of this shape.

static `createCircle`(center, radius, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Circle`.

This static method is equal to the command:

```myShape = shape(shape.Circle, center, radius, index, name)
myShape.flags = flags #optional
```
Parameters
center

(x,y) coordinate of the center point, given as any type that can be interpreted as array with two values

radius`float`

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

static `createEllipse`(corner1=None, corner2=None, center=None, size=None, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Ellipse`.

Basically, there are two different ways to construct the ellipse: Either by the top left and bottom right corner points of the outer bounding box (`corner1` and `corner2`), or by the `center` point (x,y) and the `size`, as array of (width, height).

Furthermore, you can indicate a `size` together with `corner1` OR `corner2`, where corner1.x + width = corner2.x and corner1.y + height = corner2.y.

This static method is equal to the command:

```myShape = shape(shape.Ellipse, corner1, corner2, index, name)
myShape.flags = flags #optional
```
Parameters
corner1sequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(x,y) coordinate of the top, left corner point of the bounding box, given as any type that can be interpreted as array with two values

corner2sequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(x,y) coordinate of the bottom, right corner point of the bounding box, given as any type that can be interpreted as array with two values

centersequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(x,y) coordinate of the center point, given as any type that can be interpreted as array with two values

sizesequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(width, height) of the rectangle, given as any type that can be interpreted as array with two values

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

static `createLine`(point1, point2, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Line`.

This static method is equal to the command:

```myShape = shape(shape.Line, point1, point2, index, name)
myShape.flags = flags #optional
```
Parameters
point1

(x,y) coordinate of the first point, given as any type that can be interpreted as array with two values

point2

(x,y) coordinate of the 2nd point, given as any type that can be interpreted as array with two values

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

static `createPoint`(point, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Point`.

This static method is equal to the command:

```myShape = shape(shape.Point, point, index, name)
myShape.flags = flags  # optional
```
Parameters
point

(x,y) coordinate of the point, given as any type that can be interpreted as array with two float64 values.

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

static `createPolygon`(points, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Polygon`.

This static method is equal to the command:

```myShape = shape(shape.Polygon, points, index, name)
myShape.flags = flags #optional
```
Parameters
pointssequence `of` sequence `of` `float` or `dataObject` or `numpy.ndarray`

An array-like object of shape `2 x M` (with M > 2), that can be converted to float64. This object defines `M` points for the polygon (order: x, y). If a sequence is given, it must look like this:

```points = ((1, 2, 3), (4, 5, 6))
```

where the first inner tuple defines the x-coordinates, and the 2nd tuple the y-coordinates.

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

static `createRectangle`(corner1=None, corner2=None, center=None, size=None, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Rectangle`.

Basically, there are two different ways to construct a rectangle: Either by the top left and bottom right corner points (`corner1` and `corner2`), or by the `center` point (x, y) and the `size`, as array of (width, height).

Furthermore, you can indicate a `size` together with `corner1` OR `corner2`, where corner1.x + width = corner2.x and corner1.y + height = corner2.y.

This static method is equal to the command:

```myShape = shape(shape.Rectangle, corner1, corner2, index, name)
myShape.flags = flags #optional
```
Parameters
corner1sequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(x,y) coordinate of the top, left corner point, given as any type that can be interpreted as array with two values

corner2sequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(x,y) coordinate of the bottom, right corner point, given as any type that can be interpreted as array with two values

centersequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(x,y) coordinate of the center point, given as any type that can be interpreted as array with two values

sizesequence `of` `float` or `dataObject` or `numpy.ndarray`, `optional`

(width, height) of the rectangle, given as any type that can be interpreted as array with two values

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

static `createSquare`(center, sideLength, index=- 1, name='', flags=0)shape

Returns a new shape object of type `shape.Square`.

This static method is equal to the command:

```myShape = shape(shape.Square, center, sideLength, index, name)
myShape.flags = flags #optional
```
Parameters
center

(x,y) coordinate of the center point, given as any type that can be interpreted as array with two values

sideLength`float`

side length of the square

index`int`, `optional`

index of this shape or -1 (default) if not further specified.

name`str`, `optional`

optional name of this shape (default: “”). This name can for instance be displayed in a plot.

flags`int`, `optional`

if the user should not be able to rotate, resize and / or move this shape in any plot canvas, then pass an or-combination of the restricitive flag values `shape.ResizeLock`, `shape.RotateLock` or `shape.MoveLock`.

Returns
`shape`

The new shape object.

`normalized`()shape

Returns the normalized version of this shape.

The normalized shape guarantees that the bounding box of the shape never has a non-negative width or height. Therefore, the order or position of the two corner points (base points) is switched or changed, if necessary. Shapes different than rectangles, squares, circles or ellipses are not affected by this such that the original shape object is returned as it is.

Returns
normalized`shape`

The normalized shape of this object (for types `shape.Rectange`, `shape.Square` `shape.Circle` or `shape.Ellipse`) or this object (for all other types).

`region`()region

Returns a region object from this shape.

The `region` object only contains valid regions if the shape has an area > 0. A region object is an integer based object (pixel raster), therefore the shapes are rounded to the nearest fixed-point coordinate.

Returns
`region`

The region, whose contour approximates this shape. The inner of this shaped is part of the region.

`rotateDeg`(angle)

Rotate shape by given angle in radians around the center point of this shape (counterclockwise). This method only affects the `transform` matrix, not the base points themselfs.

Parameters
angle`float`

is the rotation angle (in radians) by which the shape is rotated by its center.

`rotateRad`(angle)

Rotate shape by given angle in radians around the center point of this shape (counterclockwise). This method only affects the `transform` matrix, not the base points themselfs.

Parameters
angle`float`

is the rotation angle (in radians) by which the shape is rotated by its center.

`translate`(dxy)

Translate shape by given (dx, dy) value.

Moves the shape by dx and dy along the x- and y-axis of the base coordinate system. This means, that dx and dy are added to the existing tx and ty values of the current transformation matrix.

Parameters
dxy

array-like object with two elements, that define the desired `dx` and `dy` component.

`angleDeg`

`float` : Gets or sets the current angle of rotation of the transformation matrix in degree.

A rotation is always defined counter-clockwise.

`angleRad`

`float` : Gets or sets the current angle of rotation of the transformation matrix in Radians.

A rotation is always defined counter-clockwise.

`area`

`float` : Get area of this shape

Shapes of type `shape.Line` and `shape.Point` will always return 0.0.

`basePoints`

`dataObject` : base points of this shape, given as `2 x M`, float64 dataObject.

The `M` base points are untransformed points that describe the shape dependent on its type:

• `shape.Point`: one point

• `shape.Line` : start point, end point

• `shape.Rectangle`, `shape.Square` : top left point, bottom right point

• `shape.Ellipse`, `shape.Circle` : top left point, bottom right point of bounding box

• `shape.Polygon` : points of polygon, the last and first point are connected, too.

`center`

tuple of `float` : Gets or sets the center point of this shape.

The center point is defined for all types of shapes, beside `shape.Polygon`. Changing the center point will directly influence the base points of the shape.

If the value is set, it is also possible to pass any other array-like object with two values that can be converted to float64.

Raises
`TypeError`

if this attribute is read or assigned for a type, that has no center defined.

`color`

None or `rgba` : Gets or sets color of this shape.

The default color is an invalid color, given by the `None` value. The color of shapes is for instance be used for visualization purposes in plots.

`flags`

`int` : Gets or sets a flag (bitmask) that define denied manipulation of this shape.

It is possible to deny the following manipulations:

• `shape.MoveLock`

• `` shape.RotateLock``

• `` shape.ResizeLock``

`height`

`float` : Gets or sets the height of this shape.

A height can only be set or read for shapes of type `shape.Square` and `shape.Rectangle`.

Raises
`TypeError`

if this attribute is read or assigned for a type, that has no height defined.

`index`

`int` : Gets or sets the index of this shape.

The default is -1, however if the shape is a geometric shape of a plot, an auto-incremented index is assigned once the shape is drawn or set. If >= 0 it is possible to modify an existing shape with the same index.

`name`

`str` : Gets or sets the name (label) of this shape.

`point1`

tuple of `float` : Gets or sets the 1st point of the bounding box of this shape.

The first point is the first point of a `shape.Point` or `shape.Line` or the upper left point of the bounding box of a `shape.Rectangle`, `shape.Square` `shape.Ellipse` or `shape.Circle`. The point always considers a possible 2D coordinate transformation matrix.

For setting this value, it is also possible to pass any other array-like object with two elements, that can be converted to float64.

Raises
`TypeError`

if this attribute is read or assigned for a type, that has no 2nd point defined.

`point2`

tuple of `float` : Gets or sets the second point of the bounding box of this shape.

The second point is the 2nd point of a `shape.Line` or the bottom right point of the bounding box (types: `shape.Rectangle`, `shape.Square`, `shape.Ellipse` or `shape.Circle`). The point always considers a possible 2D coordinate transformation matrix.

For setting this value, it is also possible to pass any other array-like object with two elements, that can be converted to float64.

Raises
`TypeError`

if this attribute is read or assigned for a type, that has no 2nd point defined.

`radius`

`float` or tuple of `float` : Gets or sets the radius of this shape.

A radius can only be set for shapes of type `shape.Circle` or `shape.Ellipse`. For a circle, the radius is a scalar float value. For an ellipse, a tuple of two values `(a, b)` define the half side-length in x- and y-direction of the base coordinate system.

Raises
`TypeError`

if this attribute is read or assigned for a type, that has no radius defined.

`transform`

`dataObject` : gets or sets the affine, non scaled 2D transformation matrix as dataObject.

The returned matrix is a `2 x 3`, float64 `dataObject`, where the left `2 x 2` matrix describes a rotation matrix, and the right `2 x 1` part is the translation vector.

`type`

`int` : Get the type of this shape.

Possible types are:

• `shape.Line`

• `shape.Point`

• `shape.Rectangle`

• `shape.Ellipse`

• `shape.Circle`

• `shape.Square`

`valid`

`bool` : Returns True if this shape is valid, otherwise False.

An invalid shape is the one constructed with the type `shape.Invalid`. All other shapes are valid.

`width`

`float` : Gets or sets the width of this shape.

A width can only be set or read for shapes of type `shape.Square` and `shape.Rectangle`.

Raises
`TypeError`

if this attribute is read or assigned for a type, that has no width defined.