Path Segments

class geometry.Direction(vector: Optional[geometry.point.Point], is_horizontal: bool, start: str, end: str)

Represents a direction along one of the coordinate axes.

Fields are:

  • vector: the direction as a point object

  • is_horizontal: True if the direction is horizontal

  • start_point: handle name of the start of this direction

  • end_point: handle name of the end of this direction

>>> Direction.up.vector
(0, 1)
>>> Direction.up.is_horizontal
False
>>> Direction.left.is_horizontal
True
>>> Direction.up.start_point
'bottom_center'
>>> Direction.up.end_point
'top_center'
__mul__(other: Union[int, float]) → geometry.point.Point

Multiply the actual vector that represents this direction by a factor

>>> Direction.up * 3
(0, 3)
up = ((0, 1), False, 'bottom_center', 'top_center')
down = ((0, -1), False, 'top_center', 'bottom_center')
left = ((-1, 0), True, 'center_right', 'center_left')
right = ((1, 0), True, 'center_left', 'center_right')
class geometry.Segment(x: Union[int, float], y: Union[int, float], width: Union[int, float], height: Union[int, float], direction: geometry.path.Direction, user_data: Any = None)

An oriented path segment. This is basically a rectangle plus a direction.

>>> Segment(0, 0, 10, 20, Direction.up)
[-5:5, -10:10] (up)
classmethod from_rect(rect: geometry.rect.Rect, direction: geometry.path.Direction) → geometry.path.Segment

Create a segment from a rect and a direction

>>> Segment.from_rect(Rect[0:2, 0:4], Direction.up)
[0:2, 0:4] (up)
property bottom

The bottom edge of the rect.

>>> from geometry import Rect
>>> r = Rect[1:2, 3:4]
>>> r.bottom
3.0

Assigning the edge translates the whole rect.

>>> r.bottom = 10
>>> r
[1:2, 10:11]
copy(user_data: Any = <object object>) → Self

Copy the rect or any other shape. You can specify the copy behaviour for the user data object.

The default is a shallow copy

>>> from geometry import Rect
>>> r = Rect[0:1, 0:1, ['my', 'user', 'data']]
>>> r.copy(Rect.shallow_copy)
[0:1, 0:1] ['my', 'user', 'data']

You can force a deep copy

>>> r = Rect[0:1, 0:1, [...]]
>>> r.copy(Rect.deep_copy)
[0:1, 0:1] [...]

You can pass the user data without copying

>>> r = Rect[0:1, 0:1, [...]]
>>> r.copy(Rect.keep)
[0:1, 0:1] [...]

And you can supply a completely new user data object

>>> r = Rect[0:1, 0:1, [...]]
>>> r.copy('completely new')
[0:1, 0:1] 'completely new'
property end

The start point of the Segment. E.g. for Segments with direction “up” this is identical to the top center point of the corresponding Rect.

>>> p = Segment.from_rect(Rect[2, 10], Direction.up)
>>> p.end == p.top_center
True

Assigning to start is identical to assigning to the corresponding point of the underlying Rect.

>>> p.end = Point(0, 0)
>>> p
[-1:1, -10:0] (up)
classmethod from_start_end(start: geometry.point.Point, end: geometry.point.Point, thickness: Union[int, float], user_data: Any = None) → geometry.path.Segment

Create a segment from start point, end point and thickness

>>> Segment.from_start_end(Point(0, 0), Point(0, 10), 2)
[-1:1, 0:10] (up)
>>> Segment.from_start_end(Point(0, 0), Point(10, 0), 4)
[0:10, -2:2] (right)
>>> Segment.from_start_end(Point(0, 0), Point(10, 10), 2)
Traceback (most recent call last):
 ...
ValueError: Segment must be parallel to one of the coordinate axes
intersection(rect: geometry.rect.Rect) → Optional[geometry.rect.Rect]

Calculate the intersecting rectangle between this and the given rectangle.

If the rectangles don’t intersect, None is returned

+---------+
|         |
|    +----+----+
|    |    |    |
+----+----+    |
     |         |
     +---------+
>>> Rect[0:2, 0:4].intersection(Rect[1:3, 2:6])
[1:2, 2:4]
>>> Rect[0:1, 0:1].intersection(Rect[1:2, 1:2]) is None
True
>>> Rect[0:1, 0:1].intersection(Rect[2:3, 2:3]) is None
True
is_inside_of(rect: geometry.rect.BaseRect) → bool

Check if this rectangle is inside the other rectangle.

>>> Rect[1, 1].is_inside_of(Rect[2, 2])
True
>>> Rect[2, 2].is_inside_of(Rect[2, 2])
True
>>> Rect[1, 2].is_inside_of(Rect[2, 1])
False

You can also use the in operator

>>> Rect[1, 1] in Rect[2, 2]
True
>>> Rect[1, 1] not in Rect[2, 2]
False
property left

The left edge of the rect.

>>> from geometry import Rect
>>> r = Rect[1:2, 3:4]
>>> r.left
1.0

Assigning the edge translates the whole rect.

>>> r.left = 10
>>> r
[10:11, 3:4]
property length

The side in the direction of the segment. I.e. the height for vertical Segments and the width for horizontal Segments.

>>> p = Segment.from_rect(Rect[2, 10], Direction.up)
>>> p.length == p.height
True
property long_side

Return the longer side of the rectangle

>>> Rect[0:3, 0:2].long_side
3
>>> Rect[0:2, 0:3].long_side
3
property right

The right edge of the rect.

>>> from geometry import Rect
>>> r = Rect[1:2, 3:4]
>>> r.right
2.0

Assigning the edge translates the whole rect.

>>> r.right = 10
>>> r
[9:10, 3:4]
property short_side

Return the shorter side of the rectangle

>>> Rect[0:3, 0:2].short_side
2
>>> Rect[0:2, 0:3].short_side
2
property start

The start point of the Segment. E.g. for Segments with direction “up” this is identical to the bottom center point of the corresponding Rect.

>>> p = Segment.from_rect(Rect[2, 10], Direction.up)
>>> p.start == p.bottom_center
True

Assigning to start is identical to assigning to the corresponding point of the underlying Rect.

>>> p.start = Point(0, 0)
>>> p
[-1:1, 0:10] (up)
stretch(*relative: Union[geometry.handles.EdgeHandle, geometry.handles.PointHandle, geometry.handles.MultiHandle], **absolute: Union[int, float, geometry.point.Point]) → Self

Stretch the given edges or corners of the rectangle. I.e. move the given edge or corner while leaving the opposite edge or corner intact.

You can stretch the edges to an absolute coordinate.

>>> Rect[2:4, 4:6].stretch(left=0)
[0:4, ...]
>>> Rect[2:4, 4:6].stretch(right=6)
[2:6, ...]
>>> r = Rect[2:4, 4:6]; r2 = r.copy()
>>> r.stretch(left=0, right=6) == r2.stretch(left=0).stretch(right=6)
True
>>> Rect[2:4, 4:6].stretch(bottom=0)
[2:4, 0:6]
>>> Rect[2:4, 4:6].stretch(top=8)
[2:4, 4:8]

You can stretch the edges relatively. Here, positive numbers will always stretch away from the center.

>>> from geometry import left
>>> Rect[2:4, 4:6].stretch(left + 1)
[1:4, 4:6]
>>> from geometry import right, bottom, top
>>> Rect[2:5, 4:7].stretch(left - 1, right - 1, bottom - 1, top - 1)
[3:4, 5:6]

It is also possible to stretch the corners like this:

>>> Rect[2:4, 4:6].stretch(bottom_left=Point(0, 0))
[0:4, 0:6]
>>> from geometry import bottom_left
>>> Rect[2:4, 4:6].stretch(bottom_left + Point(1, 2))
[1:4, 2:6]

As a shortcut you can also pass a scalar instead of a vector in the relative case.

>>> Rect[2:4, 4:6].stretch(bottom_left + 2)
[0:4, 2:6]

Here is another shortcut for stretching every edge out

>>> from geometry import out
>>> Rect[2:4, 4:6].stretch(out + 1)
[1:5, 3:7]

And inwards:

>>> from geometry import in_
>>> Rect[2:5, 4:7].stretch(in_ + 1)
[3:4, 5:6]
property thickness

The side perpendicular to the direction of the segment. I.e. the width for vertical Segments and the height for horizontal Segments.

>>> p = Segment.from_rect(Rect[2, 10], Direction.up)
>>> p.thickness == p.width
True
property top

The top edge of the rect.

>>> from geometry import Rect
>>> r = Rect[1:2, 3:4]
>>> r.top
4.0

Assigning the edge translates the whole rect.

>>> r.top = 10
>>> r
[1:2, 9:10]
translate(**absolute: Union[int, float, geometry.point.Point, geometry.handles.EdgeHandle, geometry.handles.PointHandle]) → geometry.translate.CanTranslate

Translates the whole shape.

>>> from geometry import Rect, right
>>> r = Rect[2, 4]
>>> r.translate(bottom_left=Point(0, 0))  # move the bottom left to the origin
[0:2, 0:4]
>>> r.translate(center=Point(0, 0))  # move the center to the origin
[-1:1, -2:2]
>>> r.translate(left=right)  # move by 2 (width) to the right
[1:3, -2:2]
>>> r.translate(left=right + 1)  # move by 3 (width + 1) to the right
[4:6, -2:2]
union(rect: geometry.rect.Rect) → Optional[geometry.rect.Rect]

Calculate the union rectangle of this and the given rectangle.

+----+-------+
|    |       |
+----+       |
|       +----+
|       |    |
+-------+----+
>>> Rect[0:1, 0:1].union(Rect[2:3, 2:3])
[0:3, 0:3]
property rect

Create a new rectangle from a segment by removing the direction information

>>> Segment.from_start_end(Point(0, 0), Point(0, 10), 2).rect
[-1:1, 0:10]