Skip to content

Drawing

momapy.drawing

Classes and objects for drawing elements (SVG-like)

Classes:

Name Description
ClosePath

Class for close-path path actions

CompositeEffect

Class for composite effects

CompositionOperator

Class for composition operators

CurveTo

Class for curve-to path actions

DrawingElement

Class for drawing elements

DropShadowEffect

Class for drop shadow effects

EdgeMode

Class for edge modes

Ellipse

Class for ellipse drawing elements

EllipticalArc

Class for elliptical-arc path actions

FillRule

Class for fill rules

Filter

Class for filters

FilterEffect

Class for filter effects

FilterEffectInput

Class for filter effect inputs

FilterUnits

Class for filter units

FloodEffect

Class for flood effects

FontStyle

Class for font styles

FontWeight

Class for font weights

GaussianBlurEffect

Class for Gaussian blur effects

Group

Class for group drawing elements

LineTo

Class for line-to path actions

MoveTo

Class for move-to path actions

NoneValueType

Class for none values (as in SVG)

OffsetEffect

Class for offset effects

Path

Class for the path drawing elements

PathAction

Abstract class for path actions

QuadraticCurveTo

Class for quadratic-curve-to paht actions

Rectangle

Class for rectangle drawing elements

Text

Class for text drawing elements

TextAnchor

Class for text anchors

Functions:

Name Description
drawing_elements_to_shapely

Return a geometry collection reproducing the given drawing elements

get_drawing_elements_anchor_point

Return the anchor point of the drawing elements

get_drawing_elements_angle

Compute and return the point at the intersection of the given drawing elements and the line passing through the and the center of the given drawing elements and at the given angle from the horizontal

get_drawing_elements_bbox

Return the bounding box of the given drawing elements

get_drawing_elements_border

Compute and return the point at the intersection of the given drawing elements and the line passing through the given point and the center of the given drawing elements

get_initial_value

Return the initial value of a presentation attribute

Attributes:

Name Type Description
NoneValue

A singleton value for type NoneValueType

ClosePath dataclass

ClosePath()

Bases: PathAction

Class for close-path path actions

Methods:

Name Description
transformed

Return a copy of the close-path path action

transformed

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

Return a copy of the close-path path action

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "ClosePath":
    """Return a copy of the close-path path action"""
    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

Class for composite effects

CompositionOperator

Bases: Enum

Class for composition operators

CurveTo dataclass

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

Bases: PathAction

Class for curve-to path actions

Methods:

Name Description
to_geometry

Return a bezier curve from the curve-to path action and the given current point

to_shapely

Return a line string reproducing the curve-to path action from the given current point

transformed

Compute and return a copy of the curve-to path action transformed with the given transformation and current point

to_geometry

to_geometry(current_point: Point) -> BezierCurve

Return a bezier curve from the curve-to path action and the given current point

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.BezierCurve:
    """Return a bezier curve from the curve-to path action and the given current point"""
    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

Return a line string reproducing the curve-to path action from the given current point

Source code in src/momapy/drawing.py
def to_shapely(
    self, current_point: momapy.geometry.Point, n_segs: int = 50
) -> shapely.GeometryCollection:
    """Return a line string reproducing the curve-to path action from the given current point"""
    bezier_curve = self.to_geometry(current_point)
    return bezier_curve.to_shapely(n_segs)

transformed

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

Compute and return a copy of the curve-to path action transformed with the given transformation and current point

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "CurveTo":
    """Compute and return a copy of the curve-to path action transformed with the given transformation and current point"""
    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),
    )

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: tuple[float, ...] | None = None, stroke_dashoffset: float | None = None, stroke_width: float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None)

Bases: ABC

Class for drawing elements

Methods:

Name Description
bbox

Compute and return the bounding box of the drawing element

get_filter_region

Compute and return the filter region of the drawing element

to_shapely

Compute and return a geometry collection built from the given drawing elements

bbox

bbox() -> Bbox

Compute and return the bounding box of the drawing element

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Compute and return the bounding box of the drawing element"""
    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

Compute and return the filter region of the drawing element

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Compute and return the filter region of the drawing element"""

    if self.filter is None or self.filter is NoneValue:
        return None
    if (
        self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX
    ):  # only percentages or fraction values
        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:  # only absolute values
        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

Compute and return a geometry collection built from the given drawing elements

Source code in src/momapy/drawing.py
@abc.abstractmethod
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Compute and return a geometry collection built from the given drawing elements"""
    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

Class for drop shadow effects

Methods:

Name Description
to_compat

Return a list of filter effects better supported by software that is equivalent to the given drop-shadow effect

to_compat

to_compat() -> list[FilterEffect]

Return a list of filter effects better supported by software that is equivalent to the given drop-shadow effect

Source code in src/momapy/drawing.py
def to_compat(self) -> list[FilterEffect]:
    """Return a list of filter effects better supported by software that is equivalent to the given drop-shadow effect"""
    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

Class for edge modes

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: tuple[float, ...] | None = None, stroke_dashoffset: float | None = None, stroke_width: float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, point: Point, rx: float, ry: float)

Bases: DrawingElement

Class for ellipse drawing elements

Methods:

Name Description
bbox

Compute and return the bounding box of the drawing element

get_filter_region

Compute and return the filter region of the drawing element

to_path

Return a path element reproducing the ellipse element

to_shapely

Return a geometry collection reproducing the ellipse element

transformed

Compute and return a copy of the ellipse element transformed with the given transformation

bbox

bbox() -> Bbox

Compute and return the bounding box of the drawing element

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Compute and return the bounding box of the drawing element"""
    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

Compute and return the filter region of the drawing element

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Compute and return the filter region of the drawing element"""

    if self.filter is None or self.filter is NoneValue:
        return None
    if (
        self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX
    ):  # only percentages or fraction values
        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:  # only absolute values
        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

Return a path element reproducing the ellipse element

Source code in src/momapy/drawing.py
def to_path(self) -> Path:
    """Return a path element reproducing the ellipse element"""
    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)

Return a geometry collection reproducing the ellipse element

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False):
    """Return a geometry collection reproducing the ellipse element"""
    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

Compute and return a copy of the ellipse element transformed with the given transformation

Source code in src/momapy/drawing.py
def transformed(self, transformation) -> Path:
    """Compute and return a copy of the ellipse element transformed with the given transformation"""
    path = self.to_path()
    return path.transformed(transformation)

EllipticalArc dataclass

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

Bases: PathAction

Class for elliptical-arc path actions

Methods:

Name Description
to_geometry

Return an elliptical arc from the elliptical-arc path action and the given current point

to_shapely

Return a line string reproducing the elliptical-arc path action from the given current point

transformed

Compute and return a copy of the elliptical-arc path action transformed with the given transformation and current point

to_geometry

to_geometry(current_point: Point) -> EllipticalArc

Return an elliptical arc from the elliptical-arc path action and the given current point

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.EllipticalArc:
    """Return an elliptical arc from the elliptical-arc path action and the given current point"""
    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

Return a line string reproducing the elliptical-arc path action from the given current point

Source code in src/momapy/drawing.py
def to_shapely(
    self, current_point: momapy.geometry.Point
) -> shapely.GeometryCollection:
    """Return a line string reproducing the elliptical-arc path action from the given current point"""
    elliptical_arc = self.to_geometry(current_point)
    return elliptical_arc.to_shapely()

transformed

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

Compute and return a copy of the elliptical-arc path action transformed with the given transformation and current point

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "EllipticalArc":
    """Compute and return a copy of the elliptical-arc path action transformed with the given transformation and current point"""
    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,
    )

FillRule

Bases: Enum

Class for fill rules

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

Class for filters

Methods:

Name Description
to_compat

Return a filter equivalent to the given filter with its filter effects replaced by better supported

to_compat

to_compat() -> Self

Return a filter equivalent to the given filter with its filter effects replaced by better supported

Source code in src/momapy/drawing.py
def to_compat(self) -> typing.Self:
    """Return a filter equivalent to the given filter with its filter effects replaced by better supported"""
    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

Class for filter effects

FilterEffectInput

Bases: Enum

Class for filter effect inputs

FilterUnits

Bases: Enum

Class for filter units

FloodEffect dataclass

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

Bases: FilterEffect

Class for flood effects

FontStyle

Bases: Enum

Class for font styles

FontWeight

Bases: Enum

Class for font weights

GaussianBlurEffect dataclass

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

Bases: FilterEffect

Class for Gaussian blur effects

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: tuple[float, ...] | None = None, stroke_dashoffset: float | None = None, stroke_width: float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, elements: tuple[DrawingElement] = tuple())

Bases: DrawingElement

Class for group drawing elements

Methods:

Name Description
bbox

Compute and return the bounding box of the drawing element

get_filter_region

Compute and return the filter region of the drawing element

to_shapely

Return a geometry collection built from the elements of the group

transformed

Compute and return a copy of the group transformed with the given transformation

bbox

bbox() -> Bbox

Compute and return the bounding box of the drawing element

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Compute and return the bounding box of the drawing element"""
    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

Compute and return the filter region of the drawing element

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Compute and return the filter region of the drawing element"""

    if self.filter is None or self.filter is NoneValue:
        return None
    if (
        self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX
    ):  # only percentages or fraction values
        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:  # only absolute values
        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

Return a geometry collection built from the elements of the group

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Return a geometry collection built from the elements of the group"""
    return drawing_elements_to_shapely(self.elements)

transformed

transformed(transformation: Transformation) -> Self

Compute and return a copy of the group transformed with the given transformation

Source code in src/momapy/drawing.py
def transformed(
    self, transformation: momapy.geometry.Transformation
) -> typing.Self:
    """Compute and return a copy of the group transformed with the given transformation"""
    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

Class for line-to path actions

Methods:

Name Description
to_geometry

Return a segment from the line-to path action and the given current point

to_shapely

Return a line string from the line-to path action and the given current point

transformed

Compute and return a copy of the line-to path action transformed with the given transformation and current point

to_geometry

to_geometry(current_point: Point) -> Segment

Return a segment from the line-to path action and the given current point

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.Segment:
    """Return a segment from the line-to path action and the given current point"""
    return momapy.geometry.Segment(current_point, self.point)

to_shapely

to_shapely(current_point: Point) -> LineString

Return a line string from the line-to path action and the given current point

Source code in src/momapy/drawing.py
def to_shapely(self, current_point: momapy.geometry.Point) -> shapely.LineString:
    """Return a line string from the line-to path action and the given current point"""
    return self.to_geometry(current_point).to_shapely()

transformed

transformed(transformation: Transformation, current_point: Point)

Compute and return a copy of the line-to path action transformed with the given transformation and current point

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
):
    """Compute and return a copy of the line-to path action transformed with the given transformation and current point"""
    return LineTo(momapy.geometry.transform_point(self.point, transformation))

MoveTo dataclass

MoveTo(point: Point)

Bases: PathAction

Class for move-to path actions

Methods:

Name Description
transformed

Compute and return a copy of the move-to path action transformed with the given transformation and current point

transformed

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

Compute and return a copy of the move-to path action transformed with the given transformation and current point

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "MoveTo":
    """Compute and return a copy of the move-to path action transformed with the given transformation and current point"""
    return MoveTo(momapy.geometry.transform_point(self.point, transformation))

NoneValue module-attribute

NoneValue = NoneValueType()

A singleton value for type NoneValueType

NoneValueType

Bases: object

Class 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

Class for offset effects

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: tuple[float, ...] | None = None, stroke_dashoffset: float | None = None, stroke_width: float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, actions: tuple[PathAction] = tuple())

Bases: DrawingElement

Class for the path drawing elements

Methods:

Name Description
bbox

Compute and return the bounding box of the drawing element

get_filter_region

Compute and return the filter region of the drawing element

to_path_with_bezier_curves

Compute and return a path element reproducing the path element with curves and ellipses transformed to bezier curves

to_shapely

Compute and return a geometry collection reproducing the path element

transformed

Compute and return a copy of the path element transformed with the given transformation

bbox

bbox() -> Bbox

Compute and return the bounding box of the drawing element

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Compute and return the bounding box of the drawing element"""
    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

Compute and return the filter region of the drawing element

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Compute and return the filter region of the drawing element"""

    if self.filter is None or self.filter is NoneValue:
        return None
    if (
        self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX
    ):  # only percentages or fraction values
        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:  # only absolute values
        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

Compute and return a path element reproducing the path element with curves and ellipses transformed to bezier curves

Source code in src/momapy/drawing.py
def to_path_with_bezier_curves(self) -> typing.Self:
    """Compute and return a path element reproducing the path element with curves and ellipses transformed to bezier curves"""
    new_actions = []
    current_point = momapy.geometry.Point(
        0, 0
    )  # in case the path does not start with a move_to command;
    # this is not possible in svg but not enforced here
    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

Compute and return a geometry collection reproducing the path element

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Compute and return a geometry collection reproducing the path element"""
    current_point = momapy.geometry.Point(
        0, 0
    )  # in case the path does not start with a move_to command;
    # this is not possible in svg but not enforced here
    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

Compute and return a copy of the path element transformed with the given transformation

Source code in src/momapy/drawing.py
def transformed(
    self, transformation: momapy.geometry.Transformation
) -> typing.Self:
    """Compute and return a copy of the path element transformed with the given transformation"""
    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 class for path actions

QuadraticCurveTo dataclass

QuadraticCurveTo(point: Point, control_point: Point)

Bases: PathAction

Class for quadratic-curve-to paht actions

Methods:

Name Description
to_curve_to

Return a curve-to path action repdroducing the quadratic-curve-to path action from the given current point

to_geometry

Return a bezier curve from the quadratic-curve-to path action and the given current point

to_shapely

Return a line string reproducing the quadratic-curve-to from the given current point

transformed

Compute and return a copy of the quadratic-curve-to transformed with the given transformation and current point

to_curve_to

to_curve_to(current_point: Point) -> CurveTo

Return a curve-to path action repdroducing the quadratic-curve-to path action from the given current point

Source code in src/momapy/drawing.py
def to_curve_to(self, current_point: momapy.geometry.Point) -> CurveTo:
    """Return a curve-to path action repdroducing the quadratic-curve-to path action from the given current point"""
    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

Return a bezier curve from the quadratic-curve-to path action and the given current point

Source code in src/momapy/drawing.py
def to_geometry(
    self, current_point: momapy.geometry.Point
) -> momapy.geometry.BezierCurve:
    """Return a bezier curve from the quadratic-curve-to path action and the given current point"""
    return momapy.geometry.BezierCurve(
        current_point,
        self.point,
        tuple([self.control_point]),
    )

to_shapely

to_shapely(current_point, n_segs=50)

Return a line string reproducing the quadratic-curve-to from the given current point

Source code in src/momapy/drawing.py
def to_shapely(self, current_point, n_segs=50):
    """Return a line string reproducing the quadratic-curve-to from the given current point"""
    bezier_curve = self.to_geometry(current_point)
    return bezier_curve.to_shapely()

transformed

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

Compute and return a copy of the quadratic-curve-to transformed with the given transformation and current point

Source code in src/momapy/drawing.py
def transformed(
    self,
    transformation: momapy.geometry.Transformation,
    current_point: momapy.geometry.Point,
) -> "QuadraticCurveTo":
    """Compute and return a copy of the quadratic-curve-to transformed with the given transformation and current point"""
    return QuadraticCurveTo(
        momapy.geometry.transform_point(self.point, transformation),
        momapy.geometry.transform_point(self.control_point, transformation),
    )

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: tuple[float, ...] | None = None, stroke_dashoffset: float | None = None, stroke_width: 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

Class for rectangle drawing elements

Methods:

Name Description
bbox

Compute and return the bounding box of the drawing element

get_filter_region

Compute and return the filter region of the drawing element

to_path

Return a path element reproducing the rectangle element

to_shapely

Return a geometry collection reproducing the rectangle element

transformed

Compute and return a copy of the rectangle element transformed with the given transformation

bbox

bbox() -> Bbox

Compute and return the bounding box of the drawing element

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Compute and return the bounding box of the drawing element"""
    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

Compute and return the filter region of the drawing element

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Compute and return the filter region of the drawing element"""

    if self.filter is None or self.filter is NoneValue:
        return None
    if (
        self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX
    ):  # only percentages or fraction values
        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:  # only absolute values
        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

Return a path element reproducing the rectangle element

Source code in src/momapy/drawing.py
def to_path(self) -> Path:
    """Return a path element reproducing the rectangle element"""
    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

Return a geometry collection reproducing the rectangle element

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Return a geometry collection reproducing the rectangle element"""
    return self.to_path().to_shapely(to_polygons=to_polygons)

transformed

transformed(transformation: Transformation) -> Path

Compute and return a copy of the rectangle element transformed with the given transformation

Source code in src/momapy/drawing.py
def transformed(self, transformation: momapy.geometry.Transformation) -> Path:
    """Compute and return a copy of the rectangle element transformed with the given transformation"""
    path = self.to_path()
    return path.transformed(transformation)

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: tuple[float, ...] | None = None, stroke_dashoffset: float | None = None, stroke_width: float | None = None, text_anchor: TextAnchor | None = None, transform: NoneValueType | tuple[Transformation] | None = None, text: str, point: Point)

Bases: DrawingElement

Class for text drawing elements

Methods:

Name Description
bbox

Compute and return the bounding box of the drawing element

get_filter_region

Compute and return the filter region of the drawing element

to_shapely

Return a geometry collection built from the point of the text element

transformed

Return a copy of the text element

bbox

bbox() -> Bbox

Compute and return the bounding box of the drawing element

Source code in src/momapy/drawing.py
def bbox(self) -> momapy.geometry.Bbox:
    """Compute and return the bounding box of the drawing element"""
    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

Compute and return the filter region of the drawing element

Source code in src/momapy/drawing.py
def get_filter_region(self) -> momapy.geometry.Bbox:
    """Compute and return the filter region of the drawing element"""

    if self.filter is None or self.filter is NoneValue:
        return None
    if (
        self.filter.filter_units == FilterUnits.OBJECT_BOUNDING_BOX
    ):  # only percentages or fraction values
        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:  # only absolute values
        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

Return a geometry collection built from the point of the text element

Source code in src/momapy/drawing.py
def to_shapely(self, to_polygons=False) -> shapely.GeometryCollection:
    """Return a geometry collection built from the point of the text element"""
    return shapely.geometry.GeometryCollection([self.point.to_shapely()])

transformed

transformed(transformation: Transformation) -> Self

Return a copy of the text element

Source code in src/momapy/drawing.py
def transformed(
    self, transformation: momapy.geometry.Transformation
) -> typing.Self:
    """Return a copy of the text element"""
    return copy.deepcopy(self)

TextAnchor

Bases: Enum

Class for text anchors

drawing_elements_to_shapely

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

Return a geometry collection reproducing the given drawing elements

Source code in src/momapy/drawing.py
def drawing_elements_to_shapely(
    drawing_elements: collections.abc.Sequence[DrawingElement],
) -> shapely.GeometryCollection:
    """Return a geometry collection reproducing the given drawing elements"""
    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

Return the anchor point of the drawing elements

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:
    """Return the anchor point of the drawing elements"""
    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

Compute and return the point at the intersection of the given drawing elements and the line passing through the and the center of the given drawing elements and at the given angle from the horizontal

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:
    """Compute and return the point at the intersection of the given drawing elements and the line passing through the and the center of the given drawing elements and at the given angle from the horizontal"""
    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

Return the bounding box of the given drawing elements

Source code in src/momapy/drawing.py
def get_drawing_elements_bbox(
    drawing_elements: collections.abc.Sequence[DrawingElement],
) -> momapy.geometry.Bbox:
    """Return the bounding box of the given drawing elements"""
    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

Compute and return the point at the intersection of the given drawing elements and the line passing through the given point and the center of the given drawing elements

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:
    """Compute and return the point at the intersection of the given drawing elements and the line passing through the given point and the center of the given drawing elements"""
    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)

Return the initial value of a presentation attribute

Source code in src/momapy/drawing.py
def get_initial_value(attr_name: str):
    """Return the initial value of a presentation attribute"""
    attr_value = PRESENTATION_ATTRIBUTES[attr_name]["initial"]
    if attr_value is None:
        attr_value = INITIAL_VALUES[attr_name]
    return attr_value