Skip to content

Drawing

momapy.drawing

SVG-like drawing elements for momapy.

This module provides classes for creating and manipulating SVG-like drawing elements including paths, shapes, text, filters, and groups. It supports transformations, styling attributes, and conversion to/from shapely geometries.

Examples:

>>> from momapy.drawing import Path, MoveTo, LineTo, Rectangle, Text
>>> from momapy.geometry import Point
>>> from momapy.coloring import red, blue
>>> # Create a simple path
>>> path = Path(
...     actions=(
...         MoveTo(Point(0, 0)),
...         LineTo(Point(10, 10)),
...     ),
...     stroke=red,
...     stroke_width=2.0
... )
>>> # Create a rectangle
>>> rect = Rectangle(
...     point=Point(5, 5),
...     width=10,
...     height=10,
...     fill=blue,
...     stroke=red
... )
>>> # Create text
>>> text = Text(
...     text="Hello",
...     point=Point(10, 10),
...     font_size=14.0
... )

Classes:

Name Description
ClosePath

Close the current path.

CompositeEffect

Composite filter effect.

CompositionOperator

Composition operators for filter effects.

CurveTo

Draw a cubic Bezier curve.

DrawingElement

Abstract base class for drawing elements.

DropShadowEffect

Drop shadow filter effect.

EdgeMode

Edge mode for blur effects.

Ellipse

Ellipse drawing element.

EllipticalArc

Draw an elliptical arc.

FillRule

Fill rule for complex shapes.

Filter

Filter with multiple effects.

FilterEffect

Abstract base class for filter effects.

FilterEffectInput

Filter effect input types.

FilterUnits

Units for filter regions.

FloodEffect

Flood filter effect.

FontStyle

Font style options.

FontWeight

Font weight options.

GaussianBlurEffect

Gaussian blur filter effect.

Group

Group of drawing elements.

LineTo

Draw a line to a point.

MoveTo

Move to a point (start a new subpath).

NoneValueType

Singleton type for None values (as in SVG).

OffsetEffect

Offset filter effect.

Path

Path drawing element composed of path actions.

PathAction

Abstract base class for path actions.

QuadraticCurveTo

Draw a quadratic Bezier curve.

Rectangle

Rectangle drawing element with optional rounded corners.

Text

Text drawing element.

TextAnchor

Text anchor options.

Functions:

Name Description
drawing_elements_to_shapely

Convert drawing elements to shapely geometry.

get_drawing_elements_anchor_point

Get anchor point of drawing elements.

get_drawing_elements_angle

Get border point at an angle from center.

get_drawing_elements_bbox

Get bounding box of drawing elements.

get_drawing_elements_border

Get border point in a direction from center.

get_initial_value

Get the initial value of a presentation attribute.

Attributes:

Name Type Description
NoneValue

A singleton value for type NoneValueType.

ClosePath dataclass

ClosePath()

Bases: PathAction

Close the current path.

Methods:

Name Description
transformed

Apply a transformation.

transformed

transformed(transformation: Transformation, current_point: Point) -> ClosePath

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation (unused).

required
current_point Point

Current point (unused).

required

Returns:

Type Description
ClosePath

A new ClosePath.

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "ClosePath":
    """Apply a transformation.

    Args:
        transformation: The transformation (unused).
        current_point: Current point (unused).

    Returns:
        A new ClosePath.
    """
    return ClosePath()

CompositeEffect dataclass

CompositeEffect(result: str | None = None, *, in_: FilterEffectInput | str | None = None, in2: FilterEffectInput | str | None = None, operator: CompositionOperator | None = OVER)

Bases: FilterEffect

Composite filter effect.

Attributes:

Name Type Description
in_ FilterEffectInput | str | None

First input or filter effect name.

in2 FilterEffectInput | str | None

Second input or filter effect name.

operator CompositionOperator | None

Composition operator.

CompositionOperator

Bases: Enum

Composition operators for filter effects.

CurveTo dataclass

CurveTo(point: Point, control_point1: Point, control_point2: Point)

Bases: PathAction

Draw a cubic Bezier curve.

Attributes:

Name Type Description
point Point

End point.

control_point1 Point

First control point.

control_point2 Point

Second control point.

Methods:

Name Description
to_geometry

Convert to BezierCurve geometry.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation.

to_geometry

to_geometry(current_point: Point) -> BezierCurve

Convert to BezierCurve geometry.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
BezierCurve

A BezierCurve.

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.BezierCurve:
    """Convert to BezierCurve geometry.

    Args:
        current_point: Start point.

    Returns:
        A BezierCurve.
    """
    return momapy.geometry.BezierCurve(
        current_point,
        self.point,
        tuple([self.control_point1, self.control_point2]),
    )

to_shapely

to_shapely(current_point: Point, n_segs: int = 50) -> GeometryCollection

Convert to shapely geometry.

Parameters:

Name Type Description Default
current_point Point

Start point.

required
n_segs int

Number of segments.

50

Returns:

Type Description
GeometryCollection

A LineString approximating the curve.

Source code in src/momapy/drawing.py
def to_shapely(
    self, current_point: momapy.geometry.Point, n_segs: int = 50
) -> shapely.GeometryCollection:
    """Convert to shapely geometry.

    Args:
        current_point: Start point.
        n_segs: Number of segments.

    Returns:
        A LineString approximating the curve.
    """
    bezier_curve = self.to_geometry(current_point)
    return bezier_curve.to_shapely(n_segs)

transformed

transformed(transformation: Transformation, current_point: Point) -> CurveTo

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required
current_point Point

Start point (unused).

required

Returns:

Type Description
CurveTo

A new CurveTo with transformed points.

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "CurveTo":
    """Apply a transformation.

    Args:
        transformation: The transformation.
        current_point: Start point (unused).

    Returns:
        A new CurveTo with transformed points.
    """
    return CurveTo(
        momapy.geometry.transform_point(self.point, transformation),
        momapy.geometry.transform_point(self.control_point1, transformation),
        momapy.geometry.transform_point(self.control_point2, transformation),
    )

x property

x

X coordinate.

y property

y

Y coordinate.

DrawingElement dataclass

DrawingElement(*, class_: str | None = None, fill: NoneValueType | Color | None = None, fill_rule: FillRule | None = None, filter: NoneValueType | Filter | None = None, font_family: str | None = None, font_size: float | None = None, font_style: FontStyle | None = None, font_weight: FontWeight | int | None = None, id_: str | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None)

Bases: ABC

Abstract base class for drawing elements.

Attributes:

Name Type Description
class_ str | None

CSS class name.

fill NoneValueType | Color | None

Fill color.

fill_rule FillRule | None

Fill rule for complex shapes.

filter NoneValueType | Filter | None

Filter to apply.

font_family str | None

Font family.

font_size float | None

Font size.

font_style FontStyle | None

Font style.

font_weight FontWeight | int | None

Font weight.

id_ str | None

Element ID.

stroke NoneValueType | Color | None

Stroke color.

stroke_dasharray NoneValueType | tuple[float, ...] | None

Stroke dash pattern.

stroke_dashoffset NoneValueType | float | None

Stroke dash offset.

stroke_width NoneValueType | float | None

Stroke width.

text_anchor TextAnchor | None

Text anchor.

transform NoneValueType | tuple[Transformation] | None

Transformation tuple.

Methods:

Name Description
bbox

Get the bounding box.

get_filter_region

Get the filter region.

to_shapely

Convert to a shapely geometry collection.

bbox

bbox() -> Bbox

Get the bounding box.

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Get the bounding box.

    Returns:
        The bounding box.
    """
    bounds = self.to_shapely().bounds
    return momapy.geometry.Bbox(
        momapy.geometry.Point(
            (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2
        ),
        bounds[2] - bounds[0],
        bounds[3] - bounds[1],
    )

get_filter_region

get_filter_region() -> Bbox

Get the filter region.

Returns:

Type Description
Bbox

The filter region bbox.

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Get the filter region.

    Returns:
        The filter region bbox.
    """
    if self.filter is None or self.filter is NoneValue:
        return None
    if self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX:
        bbox = self.bbox()
        north_west = bbox.north_west()
        if isinstance(self.filter.x, float):
            sx = self.filter.x
        else:
            sx = float(self.filter.x.rstrip("%")) / 100
        px = north_west.x + bbox.width * sx
        if isinstance(self.filter.y, float):
            sy = self.filter.y
        else:
            sy = float(self.filter.y.rstrip("%")) / 100
        py = north_west.y + bbox.height * sy
        if isinstance(self.filter.width, float):
            swidth = self.filter.width
        else:
            swidth = float(self.filter.width.rstrip("%")) / 100
        width = bbox.width * swidth
        if isinstance(self.filter.height, float):
            sheight = self.filter.height
        else:
            sheight = float(self.filter.height.rstrip("%")) / 100
        height = bbox.height * sheight
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(px + width / 2, py + height / 2),
            width,
            height,
        )
    else:
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(
                self.filter.x + self.filter.width / 2,
                self.filter.y + self.filter.height / 2,
            ),
            self.filter.width,
            self.filter.height,
        )
    return filter_region

to_shapely abstractmethod

to_shapely(to_polygons=False) -> GeometryCollection

Convert to a shapely geometry collection.

Parameters:

Name Type Description Default
to_polygons

Whether to convert to polygons.

False

Returns:

Type Description
GeometryCollection

A shapely GeometryCollection.

Source code in src/momapy/drawing.py
@abc.abstractmethod
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Convert to a shapely geometry collection.

    Args:
        to_polygons: Whether to convert to polygons.

    Returns:
        A shapely GeometryCollection.
    """
    pass

DropShadowEffect dataclass

DropShadowEffect(result: str | None = None, *, dx: float = 0.0, dy: float = 0.0, std_deviation: float = 0.0, flood_opacity: float = 1.0, flood_color: Color = black)

Bases: FilterEffect

Drop shadow filter effect.

Attributes:

Name Type Description
dx float

Horizontal offset of the shadow.

dy float

Vertical offset of the shadow.

std_deviation float

Standard deviation for blur.

flood_opacity float

Opacity of the shadow.

flood_color Color

Color of the shadow.

Methods:

Name Description
to_compat

Convert to more compatible filter effects.

to_compat

to_compat() -> list[FilterEffect]

Convert to more compatible filter effects.

Returns:

Type Description
list[FilterEffect]

List of equivalent filter effects.

Source code in src/momapy/drawing.py
def to_compat(self) -> list[FilterEffect]:
    """Convert to more compatible filter effects.

    Returns:
        List of equivalent filter effects.
    """
    flood_effect = FloodEffect(
        result=momapy.utils.make_uuid4_as_str(),
        flood_opacity=self.flood_opacity,
        flood_color=self.flood_color,
    )
    composite_effect1 = CompositeEffect(
        in_=flood_effect.result,
        in2=FilterEffectInput.SOURCE_GRAPHIC,
        operator=CompositionOperator.IN,
        result=momapy.utils.make_uuid4_as_str(),
    )
    gaussian_blur_effect = GaussianBlurEffect(
        in_=composite_effect1.result,
        std_deviation=self.std_deviation,
        result=momapy.utils.make_uuid4_as_str(),
    )
    offset_effect = OffsetEffect(
        in_=gaussian_blur_effect.result,
        dx=self.dx,
        dy=self.dy,
        result=momapy.utils.make_uuid4_as_str(),
    )
    composite_effect2 = CompositeEffect(
        in_=FilterEffectInput.SOURCE_GRAPHIC,
        in2=offset_effect.result,
        operator=CompositionOperator.OVER,
        result=self.result,
    )
    effects = [
        flood_effect,
        composite_effect1,
        gaussian_blur_effect,
        offset_effect,
        composite_effect2,
    ]
    return effects

EdgeMode

Bases: Enum

Edge mode for blur effects.

Ellipse dataclass

Ellipse(*, class_: str | None = None, fill: NoneValueType | Color | None = None, fill_rule: FillRule | None = None, filter: NoneValueType | Filter | None = None, font_family: str | None = None, font_size: float | None = None, font_style: FontStyle | None = None, font_weight: FontWeight | int | None = None, id_: str | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, point: Point, rx: float, ry: float)

Bases: DrawingElement

Ellipse drawing element.

Attributes:

Name Type Description
point Point

Center point.

rx float

X-radius.

ry float

Y-radius.

Methods:

Name Description
bbox

Get the bounding box.

get_filter_region

Get the filter region.

to_path

Convert to a Path.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation.

bbox

bbox() -> Bbox

Get the bounding box.

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Get the bounding box.

    Returns:
        The bounding box.
    """
    bounds = self.to_shapely().bounds
    return momapy.geometry.Bbox(
        momapy.geometry.Point(
            (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2
        ),
        bounds[2] - bounds[0],
        bounds[3] - bounds[1],
    )

get_filter_region

get_filter_region() -> Bbox

Get the filter region.

Returns:

Type Description
Bbox

The filter region bbox.

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Get the filter region.

    Returns:
        The filter region bbox.
    """
    if self.filter is None or self.filter is NoneValue:
        return None
    if self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX:
        bbox = self.bbox()
        north_west = bbox.north_west()
        if isinstance(self.filter.x, float):
            sx = self.filter.x
        else:
            sx = float(self.filter.x.rstrip("%")) / 100
        px = north_west.x + bbox.width * sx
        if isinstance(self.filter.y, float):
            sy = self.filter.y
        else:
            sy = float(self.filter.y.rstrip("%")) / 100
        py = north_west.y + bbox.height * sy
        if isinstance(self.filter.width, float):
            swidth = self.filter.width
        else:
            swidth = float(self.filter.width.rstrip("%")) / 100
        width = bbox.width * swidth
        if isinstance(self.filter.height, float):
            sheight = self.filter.height
        else:
            sheight = float(self.filter.height.rstrip("%")) / 100
        height = bbox.height * sheight
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(px + width / 2, py + height / 2),
            width,
            height,
        )
    else:
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(
                self.filter.x + self.filter.width / 2,
                self.filter.y + self.filter.height / 2,
            ),
            self.filter.width,
            self.filter.height,
        )
    return filter_region

to_path

to_path() -> Path

Convert to a Path.

Returns:

Type Description
Path

A Path approximating the ellipse.

Source code in src/momapy/drawing.py
def to_path(self) -> Path:
    """Convert to a Path.

    Returns:
        A Path approximating the ellipse.
    """
    north = self.point + (0, -self.ry)
    east = self.point + (self.rx, 0)
    south = self.point + (0, self.ry)
    west = self.point - (self.rx, 0)
    actions = [
        MoveTo(north),
        EllipticalArc(east, self.rx, self.ry, 0, 0, 1),
        EllipticalArc(south, self.rx, self.ry, 0, 0, 1),
        EllipticalArc(west, self.rx, self.ry, 0, 0, 1),
        EllipticalArc(north, self.rx, self.ry, 0, 0, 1),
        ClosePath(),
    ]
    path = Path(
        stroke_width=self.stroke_width,
        stroke=self.stroke,
        fill=self.fill,
        transform=self.transform,
        filter=self.filter,
        actions=actions,
    )
    return path

to_shapely

to_shapely(to_polygons=False)

Convert to shapely geometry.

Parameters:

Name Type Description Default
to_polygons

Whether to return polygons.

False

Returns:

Type Description

A GeometryCollection containing the ellipse.

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False):
    """Convert to shapely geometry.

    Args:
        to_polygons: Whether to return polygons.

    Returns:
        A GeometryCollection containing the ellipse.
    """
    point = self.point.to_shapely()
    circle = point.buffer(1)
    ellipse = shapely.affinity.scale(circle, self.rx, self.ry)
    if not to_polygons:
        ellipse = ellipse.boundary
    return shapely.geometry.GeometryCollection([ellipse])

transformed

transformed(transformation) -> Path

Apply a transformation.

Parameters:

Name Type Description Default
transformation

The transformation.

required

Returns:

Type Description
Path

A transformed Path.

Source code in src/momapy/drawing.py
def transformed(self, transformation) -> Path:
    """Apply a transformation.

    Args:
        transformation: The transformation.

    Returns:
        A transformed Path.
    """
    path = self.to_path()
    return path.transformed(transformation)

x property

x

X coordinate of center.

y property

y

Y coordinate of center.

EllipticalArc dataclass

EllipticalArc(point: Point, rx: float, ry: float, x_axis_rotation: float, arc_flag: int, sweep_flag: int)

Bases: PathAction

Draw an elliptical arc.

Attributes:

Name Type Description
point Point

End point.

rx float

X-radius.

ry float

Y-radius.

x_axis_rotation float

Rotation of x-axis.

arc_flag int

Large arc flag.

sweep_flag int

Sweep flag.

Methods:

Name Description
to_geometry

Convert to geometry.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation.

to_geometry

to_geometry(current_point: Point) -> EllipticalArc

Convert to geometry.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
EllipticalArc

An EllipticalArc geometry.

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.EllipticalArc:
    """Convert to geometry.

    Args:
        current_point: Start point.

    Returns:
        An EllipticalArc geometry.
    """
    return momapy.geometry.EllipticalArc(
        current_point,
        self.point,
        self.rx,
        self.ry,
        self.x_axis_rotation,
        self.arc_flag,
        self.sweep_flag,
    )

to_shapely

to_shapely(current_point: Point) -> GeometryCollection

Convert to shapely geometry.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
GeometryCollection

A LineString approximating the arc.

Source code in src/momapy/drawing.py
def to_shapely(
    self, current_point: momapy.geometry.Point
) -> shapely.GeometryCollection:
    """Convert to shapely geometry.

    Args:
        current_point: Start point.

    Returns:
        A LineString approximating the arc.
    """
    elliptical_arc = self.to_geometry(current_point)
    return elliptical_arc.to_shapely()

transformed

transformed(transformation: Transformation, current_point: Point) -> EllipticalArc

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required
current_point Point

Start point.

required

Returns:

Type Description
EllipticalArc

A new EllipticalArc with transformed parameters.

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "EllipticalArc":
    """Apply a transformation.

    Args:
        transformation: The transformation.
        current_point: Start point.

    Returns:
        A new EllipticalArc with transformed parameters.
    """
    east = momapy.geometry.Point(
        math.cos(self.x_axis_rotation) * self.rx,
        math.sin(self.x_axis_rotation) * self.rx,
    )
    north = momapy.geometry.Point(
        math.cos(self.x_axis_rotation) * self.ry,
        math.sin(self.x_axis_rotation) * self.ry,
    )
    new_center = momapy.geometry.transform_point(
        momapy.geometry.Point(0, 0), transformation
    )
    new_east = momapy.geometry.transform_point(east, transformation)
    new_north = momapy.geometry.transform_point(north, transformation)
    new_rx = momapy.geometry.Segment(new_center, new_east).length()
    new_ry = momapy.geometry.Segment(new_center, new_north).length()
    new_end_point = momapy.geometry.transform_point(self.point, transformation)
    new_x_axis_rotation = math.degrees(
        momapy.geometry.get_angle_to_horizontal_of_line(
            momapy.geometry.Line(new_center, new_east)
        )
    )
    return EllipticalArc(
        new_end_point,
        new_rx,
        new_ry,
        new_x_axis_rotation,
        self.arc_flag,
        self.sweep_flag,
    )

x property

x

X coordinate.

y property

y

Y coordinate.

FillRule

Bases: Enum

Fill rule for complex shapes.

Filter dataclass

Filter(*, id_: str = make_uuid4_as_str(), filter_units: FilterUnits = OBJECT_BOUNDING_BOX, effects: tuple[FilterEffect] = tuple(), width: float | str = '120%', height: float | str = '120%', x: float | str = '-10%', y: float | str = '-10%')

Bases: object

Filter with multiple effects.

Attributes:

Name Type Description
id_ str

Unique identifier.

filter_units FilterUnits

Units for filter region.

effects tuple[FilterEffect]

Tuple of filter effects.

width float | str

Width of filter region.

height float | str

Height of filter region.

x float | str

X position of filter region.

y float | str

Y position of filter region.

Methods:

Name Description
to_compat

Convert to compatible filter with simpler effects.

to_compat

to_compat() -> Self

Convert to compatible filter with simpler effects.

Returns:

Type Description
Self

A filter with effects replaced by simpler equivalents.

Source code in src/momapy/drawing.py
def to_compat(self) -> typing_extensions.Self:
    """Convert to compatible filter with simpler effects.

    Returns:
        A filter with effects replaced by simpler equivalents.
    """
    effects = []
    for effect in self.effects:
        if hasattr(effect, "to_compat"):
            effects += effect.to_compat()
        else:
            effects.append(effect)
    return dataclasses.replace(self, effects=tuple(effects))

FilterEffect dataclass

FilterEffect(result: str | None = None)

Bases: ABC

Abstract base class for filter effects.

FilterEffectInput

Bases: Enum

Filter effect input types.

FilterUnits

Bases: Enum

Units for filter regions.

FloodEffect dataclass

FloodEffect(result: str | None = None, *, flood_color: Color = black, flood_opacity: float = 1.0)

Bases: FilterEffect

Flood filter effect.

Attributes:

Name Type Description
flood_color Color

Color of the flood.

flood_opacity float

Opacity of the flood.

FontStyle

Bases: Enum

Font style options.

FontWeight

Bases: Enum

Font weight options.

GaussianBlurEffect dataclass

GaussianBlurEffect(result: str | None = None, *, in_: FilterEffectInput | str | None = None, std_deviation: float = 0.0, edge_mode: NoneValueType | EdgeMode = NoneValue)

Bases: FilterEffect

Gaussian blur filter effect.

Attributes:

Name Type Description
in_ FilterEffectInput | str | None

Input or filter effect name.

std_deviation float

Standard deviation for blur.

edge_mode NoneValueType | EdgeMode

Edge handling mode.

Group dataclass

Group(*, class_: str | None = None, fill: NoneValueType | Color | None = None, fill_rule: FillRule | None = None, filter: NoneValueType | Filter | None = None, font_family: str | None = None, font_size: float | None = None, font_style: FontStyle | None = None, font_weight: FontWeight | int | None = None, id_: str | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, elements: tuple[DrawingElement] = tuple())

Bases: DrawingElement

Group of drawing elements.

Attributes:

Name Type Description
elements tuple[DrawingElement]

Tuple of child elements.

Methods:

Name Description
bbox

Get the bounding box.

get_filter_region

Get the filter region.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation to all elements.

bbox

bbox() -> Bbox

Get the bounding box.

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Get the bounding box.

    Returns:
        The bounding box.
    """
    bounds = self.to_shapely().bounds
    return momapy.geometry.Bbox(
        momapy.geometry.Point(
            (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2
        ),
        bounds[2] - bounds[0],
        bounds[3] - bounds[1],
    )

get_filter_region

get_filter_region() -> Bbox

Get the filter region.

Returns:

Type Description
Bbox

The filter region bbox.

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Get the filter region.

    Returns:
        The filter region bbox.
    """
    if self.filter is None or self.filter is NoneValue:
        return None
    if self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX:
        bbox = self.bbox()
        north_west = bbox.north_west()
        if isinstance(self.filter.x, float):
            sx = self.filter.x
        else:
            sx = float(self.filter.x.rstrip("%")) / 100
        px = north_west.x + bbox.width * sx
        if isinstance(self.filter.y, float):
            sy = self.filter.y
        else:
            sy = float(self.filter.y.rstrip("%")) / 100
        py = north_west.y + bbox.height * sy
        if isinstance(self.filter.width, float):
            swidth = self.filter.width
        else:
            swidth = float(self.filter.width.rstrip("%")) / 100
        width = bbox.width * swidth
        if isinstance(self.filter.height, float):
            sheight = self.filter.height
        else:
            sheight = float(self.filter.height.rstrip("%")) / 100
        height = bbox.height * sheight
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(px + width / 2, py + height / 2),
            width,
            height,
        )
    else:
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(
                self.filter.x + self.filter.width / 2,
                self.filter.y + self.filter.height / 2,
            ),
            self.filter.width,
            self.filter.height,
        )
    return filter_region

to_shapely

to_shapely(to_polygons=False) -> GeometryCollection

Convert to shapely geometry.

Parameters:

Name Type Description Default
to_polygons

Whether to convert to polygons.

False

Returns:

Type Description
GeometryCollection

A GeometryCollection of all elements.

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Convert to shapely geometry.

    Args:
        to_polygons: Whether to convert to polygons.

    Returns:
        A GeometryCollection of all elements.
    """
    return drawing_elements_to_shapely(self.elements)

transformed

transformed(transformation: Transformation) -> Self

Apply a transformation to all elements.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required

Returns:

Type Description
Self

A new Group with transformed elements.

Source code in src/momapy/drawing.py
def transformed(
    self, transformation: momapy.geometry.Transformation
) -> typing_extensions.Self:
    """Apply a transformation to all elements.

    Args:
        transformation: The transformation.

    Returns:
        A new Group with transformed elements.
    """
    elements = []
    for element in self.elements:
        elements.append(element.transformed(transformation))
    return dataclasses.replace(self, elements=tuple(elements))

LineTo dataclass

LineTo(point: Point)

Bases: PathAction

Draw a line to a point.

Attributes:

Name Type Description
point Point

The end point.

Methods:

Name Description
to_geometry

Convert to a segment.

to_shapely

Convert to shapely LineString.

transformed

Apply a transformation.

to_geometry

to_geometry(current_point: Point) -> Segment

Convert to a segment.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
Segment

A Segment from current_point to self.point.

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.Segment:
    """Convert to a segment.

    Args:
        current_point: Start point.

    Returns:
        A Segment from current_point to self.point.
    """
    return momapy.geometry.Segment(current_point, self.point)

to_shapely

to_shapely(current_point: Point) -> LineString

Convert to shapely LineString.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
LineString

A LineString.

Source code in src/momapy/drawing.py
def to_shapely(self, current_point: momapy.geometry.Point) -> shapely.LineString:
    """Convert to shapely LineString.

    Args:
        current_point: Start point.

    Returns:
        A LineString.
    """
    return self.to_geometry(current_point).to_shapely()

transformed

transformed(transformation: Transformation, current_point: Point)

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required
current_point Point

Current point (unused).

required

Returns:

Type Description

A new LineTo with transformed point.

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
):
    """Apply a transformation.

    Args:
        transformation: The transformation.
        current_point: Current point (unused).

    Returns:
        A new LineTo with transformed point.
    """
    return LineTo(momapy.geometry.transform_point(self.point, transformation))

x property

x

X coordinate.

y property

y

Y coordinate.

MoveTo dataclass

MoveTo(point: Point)

Bases: PathAction

Move to a point (start a new subpath).

Attributes:

Name Type Description
point Point

The point to move to.

Methods:

Name Description
transformed

Apply a transformation.

transformed

transformed(transformation: Transformation, current_point: Point) -> MoveTo

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required
current_point Point

Current point (unused).

required

Returns:

Type Description
MoveTo

A new MoveTo with transformed point.

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "MoveTo":
    """Apply a transformation.

    Args:
        transformation: The transformation.
        current_point: Current point (unused).

    Returns:
        A new MoveTo with transformed point.
    """
    return MoveTo(momapy.geometry.transform_point(self.point, transformation))

x property

x

X coordinate.

y property

y

Y coordinate.

NoneValue module-attribute

NoneValue = NoneValueType()

A singleton value for type NoneValueType.

NoneValueType

Bases: object

Singleton type for None values (as in SVG).

OffsetEffect dataclass

OffsetEffect(result: str | None = None, *, in_: FilterEffectInput | str | None = None, dx: float = 0.0, dy: float = 0.0)

Bases: FilterEffect

Offset filter effect.

Attributes:

Name Type Description
in_ FilterEffectInput | str | None

Input or filter effect name.

dx float

Horizontal offset.

dy float

Vertical offset.

Path dataclass

Path(*, class_: str | None = None, fill: NoneValueType | Color | None = None, fill_rule: FillRule | None = None, filter: NoneValueType | Filter | None = None, font_family: str | None = None, font_size: float | None = None, font_style: FontStyle | None = None, font_weight: FontWeight | int | None = None, id_: str | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, actions: tuple[PathAction] = tuple())

Bases: DrawingElement

Path drawing element composed of path actions.

Attributes:

Name Type Description
actions tuple[PathAction]

Tuple of path actions.

Methods:

Name Description
bbox

Get the bounding box.

get_filter_region

Get the filter region.

to_path_with_bezier_curves

Convert to path with only Bezier curves.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation to all actions.

bbox

bbox() -> Bbox

Get the bounding box.

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Get the bounding box.

    Returns:
        The bounding box.
    """
    bounds = self.to_shapely().bounds
    return momapy.geometry.Bbox(
        momapy.geometry.Point(
            (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2
        ),
        bounds[2] - bounds[0],
        bounds[3] - bounds[1],
    )

get_filter_region

get_filter_region() -> Bbox

Get the filter region.

Returns:

Type Description
Bbox

The filter region bbox.

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Get the filter region.

    Returns:
        The filter region bbox.
    """
    if self.filter is None or self.filter is NoneValue:
        return None
    if self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX:
        bbox = self.bbox()
        north_west = bbox.north_west()
        if isinstance(self.filter.x, float):
            sx = self.filter.x
        else:
            sx = float(self.filter.x.rstrip("%")) / 100
        px = north_west.x + bbox.width * sx
        if isinstance(self.filter.y, float):
            sy = self.filter.y
        else:
            sy = float(self.filter.y.rstrip("%")) / 100
        py = north_west.y + bbox.height * sy
        if isinstance(self.filter.width, float):
            swidth = self.filter.width
        else:
            swidth = float(self.filter.width.rstrip("%")) / 100
        width = bbox.width * swidth
        if isinstance(self.filter.height, float):
            sheight = self.filter.height
        else:
            sheight = float(self.filter.height.rstrip("%")) / 100
        height = bbox.height * sheight
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(px + width / 2, py + height / 2),
            width,
            height,
        )
    else:
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(
                self.filter.x + self.filter.width / 2,
                self.filter.y + self.filter.height / 2,
            ),
            self.filter.width,
            self.filter.height,
        )
    return filter_region

to_path_with_bezier_curves

to_path_with_bezier_curves() -> Self

Convert to path with only Bezier curves.

Converts elliptical arcs to Bezier curves.

Returns:

Type Description
Self

A new Path with Bezier curves only.

Source code in src/momapy/drawing.py
def to_path_with_bezier_curves(self) -> typing_extensions.Self:
    """Convert to path with only Bezier curves.

    Converts elliptical arcs to Bezier curves.

    Returns:
        A new Path with Bezier curves only.
    """
    new_actions = []
    current_point = momapy.geometry.Point(0, 0)
    initial_point = current_point
    for action in self.actions:
        if isinstance(action, MoveTo):
            current_point = action.point
            initial_point = current_point
            new_actions.append(action)
        elif isinstance(action, ClosePath):
            current_point = initial_point
            new_actions.append(action)
        elif isinstance(
            action,
            (
                LineTo,
                CurveTo,
                QuadraticCurveTo,
            ),
        ):
            current_point = action.point
            new_actions.append(action)
        elif isinstance(action, EllipticalArc):
            geom_object = action.to_geometry(current_point)
            bezier_curves = geom_object.to_bezier_curves()
            for bezier_curve in bezier_curves:
                new_action = CurveTo(
                    point=bezier_curve.p2,
                    control_point1=bezier_curve.control_points[0],
                    control_point2=bezier_curve.control_points[1],
                )
                new_actions.append(new_action)
    new_path = dataclasses.replace(self, actions=new_actions)
    return new_path

to_shapely

to_shapely(to_polygons=False) -> GeometryCollection

Convert to shapely geometry.

Parameters:

Name Type Description Default
to_polygons

Whether to convert closed paths to polygons.

False

Returns:

Type Description
GeometryCollection

A GeometryCollection.

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Convert to shapely geometry.

    Args:
        to_polygons: Whether to convert closed paths to polygons.

    Returns:
        A GeometryCollection.
    """
    current_point = momapy.geometry.Point(0, 0)
    initial_point = current_point
    geom_collection = []
    line_strings = []
    previous_action = None
    for current_action in self.actions:
        if isinstance(current_action, MoveTo):
            current_point = current_action.point
            initial_point = current_point
            if (
                not isinstance(previous_action, ClosePath)
                and previous_action is not None
            ):
                multi_linestring = shapely.geometry.MultiLineString(line_strings)
                line_string = shapely.ops.linemerge(multi_linestring)
                geom_collection.append(line_string)
            line_strings = []
        elif isinstance(current_action, ClosePath):
            if (
                current_point.x != initial_point.x
                or current_point.y != initial_point.y
            ):
                line_string = shapely.geometry.LineString(
                    [current_point.to_tuple(), initial_point.to_tuple()]
                )
                line_strings.append(line_string)
            if not to_polygons:
                multi_line = shapely.MultiLineString(line_strings)
                line_string = shapely.ops.linemerge(multi_line)
                geom_collection.append(line_string)
            else:
                polygons = shapely.ops.polygonize(line_strings)
                for polygon in polygons:
                    geom_collection.append(polygon)
            current_point = initial_point
        else:
            line_string = current_action.to_shapely(current_point)
            line_strings.append(line_string)
            current_point = current_action.point
        previous_action = current_action
    if not isinstance(current_action, (MoveTo, ClosePath)):
        multi_linestring = shapely.geometry.MultiLineString(line_strings)
        line_string = shapely.ops.linemerge(multi_linestring)
        geom_collection.append(line_string)
    return shapely.geometry.GeometryCollection(geom_collection)

transformed

transformed(transformation: Transformation) -> Self

Apply a transformation to all actions.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required

Returns:

Type Description
Self

A new Path with transformed actions.

Source code in src/momapy/drawing.py
def transformed(
    self, transformation: momapy.geometry.Transformation
) -> typing_extensions.Self:
    """Apply a transformation to all actions.

    Args:
        transformation: The transformation.

    Returns:
        A new Path with transformed actions.
    """
    actions = []
    current_point = None
    for action in self.actions:
        new_action = action.transformed(transformation, current_point)
        actions.append(new_action)
        if hasattr(action, "point"):
            current_point = action.point
        else:
            current_point = None
    return dataclasses.replace(self, actions=tuple(actions))

PathAction dataclass

PathAction()

Bases: ABC

Abstract base class for path actions.

QuadraticCurveTo dataclass

QuadraticCurveTo(point: Point, control_point: Point)

Bases: PathAction

Draw a quadratic Bezier curve.

Attributes:

Name Type Description
point Point

End point.

control_point Point

Control point.

Methods:

Name Description
to_curve_to

Convert to cubic CurveTo.

to_geometry

Convert to BezierCurve geometry.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation.

to_curve_to

to_curve_to(current_point: Point) -> CurveTo

Convert to cubic CurveTo.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
CurveTo

An equivalent CurveTo.

Source code in src/momapy/drawing.py
def to_curve_to(self, current_point: momapy.geometry.Point) -> CurveTo:
    """Convert to cubic CurveTo.

    Args:
        current_point: Start point.

    Returns:
        An equivalent CurveTo.
    """
    p1 = current_point
    p2 = self.point
    control_point1 = p1 + (self.control_point - p1) * (2 / 3)
    control_point2 = p2 + (self.control_point - p2) * (2 / 3)
    return CurveTo(p2, control_point1, control_point2)

to_geometry

to_geometry(current_point: Point) -> BezierCurve

Convert to BezierCurve geometry.

Parameters:

Name Type Description Default
current_point Point

Start point.

required

Returns:

Type Description
BezierCurve

A BezierCurve.

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.BezierCurve:
    """Convert to BezierCurve geometry.

    Args:
        current_point: Start point.

    Returns:
        A BezierCurve.
    """
    return momapy.geometry.BezierCurve(
        current_point,
        self.point,
        tuple([self.control_point]),
    )

to_shapely

to_shapely(current_point, n_segs=50)

Convert to shapely geometry.

Parameters:

Name Type Description Default
current_point

Start point.

required
n_segs

Number of segments.

50

Returns:

Type Description

A LineString approximating the curve.

Source code in src/momapy/drawing.py
def to_shapely(self, current_point, n_segs=50):
    """Convert to shapely geometry.

    Args:
        current_point: Start point.
        n_segs: Number of segments.

    Returns:
        A LineString approximating the curve.
    """
    bezier_curve = self.to_geometry(current_point)
    return bezier_curve.to_shapely()

transformed

transformed(transformation: Transformation, current_point: Point) -> QuadraticCurveTo

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required
current_point Point

Start point (unused).

required

Returns:

Type Description
QuadraticCurveTo

A new QuadraticCurveTo with transformed points.

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "QuadraticCurveTo":
    """Apply a transformation.

    Args:
        transformation: The transformation.
        current_point: Start point (unused).

    Returns:
        A new QuadraticCurveTo with transformed points.
    """
    return QuadraticCurveTo(
        momapy.geometry.transform_point(self.point, transformation),
        momapy.geometry.transform_point(self.control_point, transformation),
    )

x property

x

X coordinate.

y property

y

Y coordinate.

Rectangle dataclass

Rectangle(*, class_: str | None = None, fill: NoneValueType | Color | None = None, fill_rule: FillRule | None = None, filter: NoneValueType | Filter | None = None, font_family: str | None = None, font_size: float | None = None, font_style: FontStyle | None = None, font_weight: FontWeight | int | None = None, id_: str | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, point: Point, width: float, height: float, rx: float, ry: float)

Bases: DrawingElement

Rectangle drawing element with optional rounded corners.

Attributes:

Name Type Description
point Point

Top-left corner.

width float

Width.

height float

Height.

rx float

X-radius for rounded corners.

ry float

Y-radius for rounded corners.

Methods:

Name Description
bbox

Get the bounding box.

get_filter_region

Get the filter region.

to_path

Convert to a Path.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation.

bbox

bbox() -> Bbox

Get the bounding box.

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Get the bounding box.

    Returns:
        The bounding box.
    """
    bounds = self.to_shapely().bounds
    return momapy.geometry.Bbox(
        momapy.geometry.Point(
            (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2
        ),
        bounds[2] - bounds[0],
        bounds[3] - bounds[1],
    )

get_filter_region

get_filter_region() -> Bbox

Get the filter region.

Returns:

Type Description
Bbox

The filter region bbox.

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Get the filter region.

    Returns:
        The filter region bbox.
    """
    if self.filter is None or self.filter is NoneValue:
        return None
    if self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX:
        bbox = self.bbox()
        north_west = bbox.north_west()
        if isinstance(self.filter.x, float):
            sx = self.filter.x
        else:
            sx = float(self.filter.x.rstrip("%")) / 100
        px = north_west.x + bbox.width * sx
        if isinstance(self.filter.y, float):
            sy = self.filter.y
        else:
            sy = float(self.filter.y.rstrip("%")) / 100
        py = north_west.y + bbox.height * sy
        if isinstance(self.filter.width, float):
            swidth = self.filter.width
        else:
            swidth = float(self.filter.width.rstrip("%")) / 100
        width = bbox.width * swidth
        if isinstance(self.filter.height, float):
            sheight = self.filter.height
        else:
            sheight = float(self.filter.height.rstrip("%")) / 100
        height = bbox.height * sheight
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(px + width / 2, py + height / 2),
            width,
            height,
        )
    else:
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(
                self.filter.x + self.filter.width / 2,
                self.filter.y + self.filter.height / 2,
            ),
            self.filter.width,
            self.filter.height,
        )
    return filter_region

to_path

to_path() -> Path

Convert to a Path.

Returns:

Type Description
Path

A Path representing the rectangle.

Source code in src/momapy/drawing.py
def to_path(self) -> Path:
    """Convert to a Path.

    Returns:
        A Path representing the rectangle.
    """
    x = self.point.x
    y = self.point.y
    rx = self.rx
    ry = self.ry
    width = self.width
    height = self.height
    actions = [
        MoveTo(momapy.geometry.Point(x + rx, y)),
        LineTo(momapy.geometry.Point(x + width - rx, y)),
    ]
    if rx > 0 and ry > 0:
        actions.append(
            EllipticalArc(momapy.geometry.Point(x + width, y + ry), rx, ry, 0, 0, 1)
        )
    actions.append(LineTo(momapy.geometry.Point(x + width, y + height - ry)))
    if rx > 0 and ry > 0:
        actions.append(
            EllipticalArc(
                momapy.geometry.Point(x + width - rx, y + height),
                rx,
                ry,
                0,
                0,
                1,
            )
        )
    actions.append(LineTo(momapy.geometry.Point(x + rx, y + height)))
    if rx > 0 and ry > 0:
        actions.append(
            EllipticalArc(
                momapy.geometry.Point(x, y + height - ry), rx, ry, 0, 0, 1
            )
        )
    actions.append(LineTo(momapy.geometry.Point(x, y + ry)))
    if rx > 0 and ry > 0:
        actions.append(
            EllipticalArc(momapy.geometry.Point(x + rx, y), rx, ry, 0, 0, 1)
        )
    actions.append(ClosePath())
    path = Path(
        stroke_width=self.stroke_width,
        stroke=self.stroke,
        fill=self.fill,
        transform=self.transform,
        filter=self.filter,
        actions=actions,
    )
    return path

to_shapely

to_shapely(to_polygons=False) -> GeometryCollection

Convert to shapely geometry.

Parameters:

Name Type Description Default
to_polygons

Whether to return polygons.

False

Returns:

Type Description
GeometryCollection

A GeometryCollection.

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Convert to shapely geometry.

    Args:
        to_polygons: Whether to return polygons.

    Returns:
        A GeometryCollection.
    """
    return self.to_path().to_shapely(to_polygons=to_polygons)

transformed

transformed(transformation: Transformation) -> Path

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required

Returns:

Type Description
Path

A transformed Path.

Source code in src/momapy/drawing.py
def transformed(self, transformation: momapy.geometry.Transformation) -> Path:
    """Apply a transformation.

    Args:
        transformation: The transformation.

    Returns:
        A transformed Path.
    """
    path = self.to_path()
    return path.transformed(transformation)

x property

x

X coordinate of top-left.

y property

y

Y coordinate of top-left.

Text dataclass

Text(*, class_: str | None = None, fill: NoneValueType | Color | None = None, fill_rule: FillRule | None = None, filter: NoneValueType | Filter | None = None, font_family: str | None = None, font_size: float | None = None, font_style: FontStyle | None = None, font_weight: FontWeight | int | None = None, id_: str | None = None, stroke: NoneValueType | Color | None = None, stroke_dasharray: NoneValueType | tuple[float, ...] | None = None, stroke_dashoffset: NoneValueType | float | None = None, stroke_width: NoneValueType | float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, text: str, point: Point)

Bases: DrawingElement

Text drawing element.

Attributes:

Name Type Description
text str

The text content.

point Point

Position of the text.

Methods:

Name Description
bbox

Get the bounding box.

get_filter_region

Get the filter region.

to_shapely

Convert to shapely geometry.

transformed

Apply a transformation.

bbox

bbox() -> Bbox

Get the bounding box.

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Get the bounding box.

    Returns:
        The bounding box.
    """
    bounds = self.to_shapely().bounds
    return momapy.geometry.Bbox(
        momapy.geometry.Point(
            (bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2
        ),
        bounds[2] - bounds[0],
        bounds[3] - bounds[1],
    )

get_filter_region

get_filter_region() -> Bbox

Get the filter region.

Returns:

Type Description
Bbox

The filter region bbox.

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Get the filter region.

    Returns:
        The filter region bbox.
    """
    if self.filter is None or self.filter is NoneValue:
        return None
    if self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX:
        bbox = self.bbox()
        north_west = bbox.north_west()
        if isinstance(self.filter.x, float):
            sx = self.filter.x
        else:
            sx = float(self.filter.x.rstrip("%")) / 100
        px = north_west.x + bbox.width * sx
        if isinstance(self.filter.y, float):
            sy = self.filter.y
        else:
            sy = float(self.filter.y.rstrip("%")) / 100
        py = north_west.y + bbox.height * sy
        if isinstance(self.filter.width, float):
            swidth = self.filter.width
        else:
            swidth = float(self.filter.width.rstrip("%")) / 100
        width = bbox.width * swidth
        if isinstance(self.filter.height, float):
            sheight = self.filter.height
        else:
            sheight = float(self.filter.height.rstrip("%")) / 100
        height = bbox.height * sheight
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(px + width / 2, py + height / 2),
            width,
            height,
        )
    else:
        filter_region = momapy.geometry.Bbox(
            momapy.geometry.Point(
                self.filter.x + self.filter.width / 2,
                self.filter.y + self.filter.height / 2,
            ),
            self.filter.width,
            self.filter.height,
        )
    return filter_region

to_shapely

to_shapely(to_polygons=False) -> GeometryCollection

Convert to shapely geometry.

Parameters:

Name Type Description Default
to_polygons

Whether to convert to polygons.

False

Returns:

Type Description
GeometryCollection

A GeometryCollection containing the point.

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Convert to shapely geometry.

    Args:
        to_polygons: Whether to convert to polygons.

    Returns:
        A GeometryCollection containing the point.
    """
    return shapely.geometry.GeometryCollection([self.point.to_shapely()])

transformed

transformed(transformation: Transformation) -> Self

Apply a transformation.

Parameters:

Name Type Description Default
transformation Transformation

The transformation.

required

Returns:

Type Description
Self

A copy of the text element.

Source code in src/momapy/drawing.py
def transformed(
    self, transformation: momapy.geometry.Transformation
) -> typing_extensions.Self:
    """Apply a transformation.

    Args:
        transformation: The transformation.

    Returns:
        A copy of the text element.
    """
    return copy.deepcopy(self)

x property

x

X coordinate of the text position.

y property

y

Y coordinate of the text position.

TextAnchor

Bases: Enum

Text anchor options.

drawing_elements_to_shapely

drawing_elements_to_shapely(drawing_elements: Sequence[DrawingElement]) -> GeometryCollection

Convert drawing elements to shapely geometry.

Parameters:

Name Type Description Default
drawing_elements Sequence[DrawingElement]

Sequence of drawing elements.

required

Returns:

Type Description
GeometryCollection

A GeometryCollection.

Source code in src/momapy/drawing.py
def drawing_elements_to_shapely(
    drawing_elements: collections.abc.Sequence[DrawingElement],
) -> shapely.GeometryCollection:
    """Convert drawing elements to shapely geometry.

    Args:
        drawing_elements: Sequence of drawing elements.

    Returns:
        A GeometryCollection.
    """
    geom_collection = []
    for drawing_element in drawing_elements:
        geom_collection += drawing_element.to_shapely(to_polygons=False).geoms
    return shapely.GeometryCollection(geom_collection)

get_drawing_elements_anchor_point

get_drawing_elements_anchor_point(drawing_elements, anchor_point: str, center: Point | None = None) -> Point

Get anchor point of drawing elements.

Parameters:

Name Type Description Default
drawing_elements

Drawing elements.

required
anchor_point str

Name of anchor point.

required
center Point | None

Optional center point.

None

Returns:

Type Description
Point

The anchor point.

Source code in src/momapy/drawing.py
def get_drawing_elements_anchor_point(
    drawing_elements,
    anchor_point: str,
    center: momapy.geometry.Point | None = None,
) -> momapy.geometry.Point:
    """Get anchor point of drawing elements.

    Args:
        drawing_elements: Drawing elements.
        anchor_point: Name of anchor point.
        center: Optional center point.

    Returns:
        The anchor point.
    """
    shapely_object = drawing_elements_to_shapely(drawing_elements)
    return momapy.geometry.get_shapely_object_anchor_point(
        shapely_object=shapely_object, anchor_point=anchor_point, center=center
    )

get_drawing_elements_angle

get_drawing_elements_angle(drawing_elements: Sequence[DrawingElement], angle: float, unit='degrees', center: Point | None = None) -> Point

Get border point at an angle from center.

Parameters:

Name Type Description Default
drawing_elements Sequence[DrawingElement]

Drawing elements.

required
angle float

The angle.

required
unit

Unit ('degrees' or 'radians').

'degrees'
center Point | None

Optional center point.

None

Returns:

Type Description
Point

The border point.

Source code in src/momapy/drawing.py
def get_drawing_elements_angle(
    drawing_elements: collections.abc.Sequence[DrawingElement],
    angle: float,
    unit="degrees",
    center: momapy.geometry.Point | None = None,
) -> momapy.geometry.Point:
    """Get border point at an angle from center.

    Args:
        drawing_elements: Drawing elements.
        angle: The angle.
        unit: Unit ('degrees' or 'radians').
        center: Optional center point.

    Returns:
        The border point.
    """
    shapely_object = drawing_elements_to_shapely(drawing_elements)
    return momapy.geometry.get_shapely_object_angle(
        shapely_object=shapely_object, angle=angle, unit=unit, center=center
    )

get_drawing_elements_bbox

get_drawing_elements_bbox(drawing_elements: Sequence[DrawingElement]) -> Bbox

Get bounding box of drawing elements.

Parameters:

Name Type Description Default
drawing_elements Sequence[DrawingElement]

Drawing elements.

required

Returns:

Type Description
Bbox

The bounding box.

Source code in src/momapy/drawing.py
def get_drawing_elements_bbox(
    drawing_elements: collections.abc.Sequence[DrawingElement],
) -> momapy.geometry.Bbox:
    """Get bounding box of drawing elements.

    Args:
        drawing_elements: Drawing elements.

    Returns:
        The bounding box.
    """
    shapely_object = drawing_elements_to_shapely(drawing_elements)
    return momapy.geometry.Bbox.from_bounds(shapely_object.bounds)

get_drawing_elements_border

get_drawing_elements_border(drawing_elements: Sequence[DrawingElement], point: Point, center: Point | None = None) -> Point

Get border point in a direction from center.

Parameters:

Name Type Description Default
drawing_elements Sequence[DrawingElement]

Drawing elements.

required
point Point

Direction point.

required
center Point | None

Optional center point.

None

Returns:

Type Description
Point

The border point.

Source code in src/momapy/drawing.py
def get_drawing_elements_border(
    drawing_elements: collections.abc.Sequence[DrawingElement],
    point: momapy.geometry.Point,
    center: momapy.geometry.Point | None = None,
) -> momapy.geometry.Point:
    """Get border point in a direction from center.

    Args:
        drawing_elements: Drawing elements.
        point: Direction point.
        center: Optional center point.

    Returns:
        The border point.
    """
    shapely_object = drawing_elements_to_shapely(drawing_elements)
    return momapy.geometry.get_shapely_object_border(
        shapely_object=shapely_object, point=point, center=center
    )

get_initial_value

get_initial_value(attr_name: str)

Get the initial value of a presentation attribute.

Parameters:

Name Type Description Default
attr_name str

Name of the attribute.

required

Returns:

Type Description

The initial value.

Source code in src/momapy/drawing.py
def get_initial_value(attr_name: str):
    """Get the initial value of a presentation attribute.

    Args:
        attr_name: Name of the attribute.

    Returns:
        The initial value.
    """
    attr_value = PRESENTATION_ATTRIBUTES[attr_name]["initial"]
    if attr_value is None:
        attr_value = INITIAL_VALUES[attr_name]
    return attr_value