# 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='') → creates a shape object of a specific type.

Bases: `object`

Depending on the type, the following parameters are allowed:

• 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

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

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.

`contains`(points) → return contour points as a 2xNumPoints float64 dataObject

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

Parameters

points : {seq. of two floats or dataObject}

Pass one point by a seq. of two floats (x,y) or an numpy.array with two elements. A sequence of points is passed by a 2xN dataObject (1st row: x, 2nd row: y) that is internally converted to float64.

Returns

result : {bool or uint8 dataObject}

If one point is passed, True is returned if this point is within the shape’s contour, else False. In the case of multiple points, an 1xN dataObject (uint8) is returned where 255 indicates, that the corresponding point is inside of the shape’s contour (else 0)

`contour`(applyTrafo=True, tol=- 1.0) → return contour points as a 2xNumPoints float64 dataObject

If a transformation matrix is set, the base points can be transformed if ‘applyTrafo’ is True. For point, line and rectangle based shapes, the contour is directly given. For ellipses and circles, a polygon is approximated to the form of the ellipse and returned as contour. The approximation is done by line segments. Use ‘tol’ to set the maximum distance between each line segment and the real shape. If ‘tol’ is -1.0, ‘tol’ is set to 1% of the smallest diameter.

`copy`() → return a deep copy of this shape.
static `createCircle`(center, radius, index=- 1, name='', flags=0) → returns a new shape object of type shape.Circle.
Parameters

center : {array-like object}

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

radius of the circle

index : {int}, optional

index of this shape, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

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

static `createEllipse`(corner1=None, corner2=None, center=None, size=None, index=- 1, name='', flags=0) → 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.

Parameters

corner1 : {array-like object}, 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

corner2 : {array-like object}, 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

center : {array-like object}, optional

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

size : {array-like object}, 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, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

myShape = shape(shape.Ellipse, corner1, corner2, index, name) myShape.flags = flags #optional

static `createLine`(point1, point2, index=- 1, name='', flags=0) → returns a new shape object of type shape.Line.
Parameters

point1 : {array-like object}

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

point2 : {array-like object}

(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, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

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

static `createPoint`(point, index=- 1, name='', flags=0) → returns a new shape object of type shape.Point.
Parameters

point : {array-like object}

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

index : {int}, optional

index of this shape, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

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

static `createPolygon`(points, index=- 1, name='', flags=0) → returns a new shape object of type shape.Polygon.
Parameters

points : {array-like object}

2xM, float64 array with the coordinates of M points (order: x,y)

index : {int}, optional

index of this shape, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

myShape = shape(shape.Polygon, points, index, name) myShape.flags = flags #optional

static `createRectangle`(corner1=None, corner2=None, center=None, size=None, index=- 1, name='', flags=0) → 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.

Parameters

corner1 : {array-like object}, optional

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

corner2 : {array-like object}, optional

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

center : {array-like object}, optional

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

size : {array-like object}, 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, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

myShape = shape(shape.Rectangle, corner1, corner2, index, name) myShape.flags = flags #optional

static `createSquare`(center, sideLength, index=- 1, name='', flags=0) → returns a new shape object of type shape.Square.
Parameters

center : {array-like object}

(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, if -1 (default), an automatic index is assigned

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

This static method is equal to the command:: :

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

`normalized`() -> return a normalized shape (this has only an impact on rectangles, squares, ellipses and circles)

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 rectangle, square, circle or ellipse are not affected by this and are returned as they are.

`region`() → Return 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 coordinates.

`rotateDeg`(angle) → Rotate shape by given angle in degree around the center point of this shape (counterclockwise).
Parameters

angle : {float}

is the rotation angle (in degrees) 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).
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, 2 elements

tuple, np.array or dataObject with two elements, which are the dx and dy components of the translation

`angleDeg`

Get/set angle of optional rotation matrix in degree (counter-clockwise).

`angleRad`

Get/set angle of optional rotation matrix in radians (counter-clockwise).

`area`

Get area of shape (points and lines have an empty area).

`basePoints`

Return base points of this shape: M base points of shape as 2xM float64 dataObject

The 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`

Get/set center point

The center point is the point (type: point), or the center of the line (type: line) or bounding box of a rectangle, square, ellipse or circle.

`color`

Get/set color of the shape (default: invalid color (None). In this case the default color for shapes is used for visualization.)

`flags`

Get/set bitmask with flags for this shape: shape.MoveLock, shape.RotateLock, shape.ResizeLock

`height`

Get/set height of shape.

A height can only be set for a square or for a rectangle and is defined with respect to the base coordinate system.

`index`

Get/set index of 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`

Get/set name (label) of the shape.

`point1`

Get/set first point (of bounding box)

The first point is the first point (type: point or line) or the upper left point of the bounding box (type: rectangle, square, ellipse, circle). The point always considers a possible 2D coordinate transformation matrix.

`point2`

Get/set second point of bounding box

The second point is the bottom right point of the bounding box (type: rectangle, square, ellipse, circle). The point always considers a possible 2D coordinate transformation matrix.

`radius`

Get/set radius of shape.

A radius can only be set for a circle (float value) or for an ellipse (a, b) as half side-length in x- and y-direction of the base coordinate system.

`transform`

Get/set the affine, non scaled 2D transformation matrix (2x3, float64, [2x2 Rot, 2x1 trans])

`type`

Get type of shape, e.g. shape.Line, shape.Point, shape.Rectangle, shape.Ellipse, shape.Circle, shape.Square

`valid`

Return True if shape is a valid geometric shape, else False

`width`

Get/set width of shape.

A width can only be set for a square or for a rectangle and is defined with respect to the base coordinate system.