Skip to content

init

shape_segments

shape_segments module contains classes representing shape segments.

Arc

Bases: ShapeSegment

Arc segment which can be used to define Shape contents.

Arc resolution is determined at rendering time and dynamically adjusted to provide the best image quality. This gives Arc class great advantage over creating arcs with multiple manually defined Line segments.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
class Arc(ShapeSegment):
    """Arc segment which can be used to define Shape contents.

    Arc resolution is determined at rendering time and dynamically adjusted to provide
    the best image quality. This gives Arc class great advantage over creating arcs
    with multiple manually defined Line segments.
    """

    start: Vector
    end: Vector
    center: Vector
    clockwise: bool

    @classmethod
    def from_tuples(
        cls,
        start: tuple[float, float],
        end: tuple[float, float],
        center: tuple[float, float],
        *,
        clockwise: bool,
    ) -> Self:
        """Create a new arc from two tuples."""
        return cls(
            start=Vector.from_tuple(start),
            end=Vector.from_tuple(end),
            center=Vector.from_tuple(center),
            clockwise=clockwise,
        )

    def get_relative_start_point(self) -> Vector:
        """Get starting point relative to arc center."""
        return self.start - self.center

    def get_relative_end_point(self) -> Vector:
        """Get ending point relative to arc center."""
        return self.end - self.center

    def get_radius(self) -> float:
        """Get radius of circle arc."""
        return self.get_relative_start_point().length()

    def is_valid_arc(self) -> bool:
        """Check if arc is valid."""
        return (
            self.get_relative_start_point().length()
            == self.get_relative_end_point().length()
        )

    @pp.cached_property
    def outer_box(self) -> Box:
        """Get outer box of shape segment."""
        radius = self.get_radius()
        relative_start = self.get_relative_start_point()

        total_angle = relative_start.angle_between(
            self.get_relative_end_point(),
        )

        angle_x_plus = relative_start.angle_between(Vector.unit.x) % 360
        angle_y_minus = relative_start.angle_between(-Vector.unit.y) % 360
        angle_x_minus = relative_start.angle_between(-Vector.unit.x) % 360
        angle_y_plus = relative_start.angle_between(Vector.unit.y) % 360

        vectors = [
            Vector(x=0, y=0),
            relative_start,
            self.get_relative_end_point(),
        ]
        if not self.clockwise:
            total_angle = 360 - total_angle
            angle_x_plus = 360 - angle_x_plus
            angle_y_minus = 360 - angle_y_minus
            angle_x_minus = 360 - angle_x_minus
            angle_y_plus = 360 - angle_y_plus

        if angle_x_plus < total_angle:
            vectors.append(Vector(x=radius, y=0))
        if angle_y_minus < total_angle:
            vectors.append(Vector(x=0, y=-radius))
        if angle_x_minus < total_angle:
            vectors.append(Vector(x=-radius, y=0))
        if angle_y_plus < total_angle:
            vectors.append(Vector(x=0, y=radius))

        return Box.from_vectors(*(v + self.center for v in vectors))

    def transform(self, transform: Matrix3x3) -> Self:
        """Transform points defining this line."""
        return self.__class__(
            start=self.start.transform(transform),
            end=self.end.transform(transform),
            center=self.center.transform(transform),
            clockwise=(
                self.clockwise
                if transform[0][0] * transform[1][1] > 0
                else not self.clockwise
            ),
        )

from_tuples classmethod

from_tuples(
    start: tuple[float, float],
    end: tuple[float, float],
    center: tuple[float, float],
    *,
    clockwise: bool
) -> Self

Create a new arc from two tuples.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
@classmethod
def from_tuples(
    cls,
    start: tuple[float, float],
    end: tuple[float, float],
    center: tuple[float, float],
    *,
    clockwise: bool,
) -> Self:
    """Create a new arc from two tuples."""
    return cls(
        start=Vector.from_tuple(start),
        end=Vector.from_tuple(end),
        center=Vector.from_tuple(center),
        clockwise=clockwise,
    )

get_relative_start_point

get_relative_start_point() -> Vector

Get starting point relative to arc center.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
def get_relative_start_point(self) -> Vector:
    """Get starting point relative to arc center."""
    return self.start - self.center

get_relative_end_point

get_relative_end_point() -> Vector

Get ending point relative to arc center.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
def get_relative_end_point(self) -> Vector:
    """Get ending point relative to arc center."""
    return self.end - self.center

get_radius

get_radius() -> float

Get radius of circle arc.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
def get_radius(self) -> float:
    """Get radius of circle arc."""
    return self.get_relative_start_point().length()

is_valid_arc

is_valid_arc() -> bool

Check if arc is valid.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
def is_valid_arc(self) -> bool:
    """Check if arc is valid."""
    return (
        self.get_relative_start_point().length()
        == self.get_relative_end_point().length()
    )

outer_box

outer_box() -> Box

Get outer box of shape segment.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
@pp.cached_property
def outer_box(self) -> Box:
    """Get outer box of shape segment."""
    radius = self.get_radius()
    relative_start = self.get_relative_start_point()

    total_angle = relative_start.angle_between(
        self.get_relative_end_point(),
    )

    angle_x_plus = relative_start.angle_between(Vector.unit.x) % 360
    angle_y_minus = relative_start.angle_between(-Vector.unit.y) % 360
    angle_x_minus = relative_start.angle_between(-Vector.unit.x) % 360
    angle_y_plus = relative_start.angle_between(Vector.unit.y) % 360

    vectors = [
        Vector(x=0, y=0),
        relative_start,
        self.get_relative_end_point(),
    ]
    if not self.clockwise:
        total_angle = 360 - total_angle
        angle_x_plus = 360 - angle_x_plus
        angle_y_minus = 360 - angle_y_minus
        angle_x_minus = 360 - angle_x_minus
        angle_y_plus = 360 - angle_y_plus

    if angle_x_plus < total_angle:
        vectors.append(Vector(x=radius, y=0))
    if angle_y_minus < total_angle:
        vectors.append(Vector(x=0, y=-radius))
    if angle_x_minus < total_angle:
        vectors.append(Vector(x=-radius, y=0))
    if angle_y_plus < total_angle:
        vectors.append(Vector(x=0, y=radius))

    return Box.from_vectors(*(v + self.center for v in vectors))

transform

transform(transform: Matrix3x3) -> Self

Transform points defining this line.

Source code in src/pygerber/vm/commands/shape_segments/arc.py
def transform(self, transform: Matrix3x3) -> Self:
    """Transform points defining this line."""
    return self.__class__(
        start=self.start.transform(transform),
        end=self.end.transform(transform),
        center=self.center.transform(transform),
        clockwise=(
            self.clockwise
            if transform[0][0] * transform[1][1] > 0
            else not self.clockwise
        ),
    )

Line

Bases: ShapeSegment

Line segment which can be used to define Shape contents.

Source code in src/pygerber/vm/commands/shape_segments/line.py
class Line(ShapeSegment):
    """Line segment which can be used to define Shape contents."""

    start: Vector
    end: Vector

    @classmethod
    def from_tuples(cls, start: tuple[float, float], end: tuple[float, float]) -> Self:
        """Create a new line from two tuples."""
        return cls(start=Vector.from_tuple(start), end=Vector.from_tuple(end))

    @pp.cached_property
    def outer_box(self) -> Box:
        """Get outer box of shape segment."""
        return Box.from_vectors(self.start, self.end)

    def transform(self, transform: Matrix3x3) -> Self:
        """Transform points defining this line."""
        return self.__class__(
            start=self.start.transform(transform),
            end=self.end.transform(transform),
        )

from_tuples classmethod

from_tuples(
    start: tuple[float, float], end: tuple[float, float]
) -> Self

Create a new line from two tuples.

Source code in src/pygerber/vm/commands/shape_segments/line.py
@classmethod
def from_tuples(cls, start: tuple[float, float], end: tuple[float, float]) -> Self:
    """Create a new line from two tuples."""
    return cls(start=Vector.from_tuple(start), end=Vector.from_tuple(end))

outer_box

outer_box() -> Box

Get outer box of shape segment.

Source code in src/pygerber/vm/commands/shape_segments/line.py
@pp.cached_property
def outer_box(self) -> Box:
    """Get outer box of shape segment."""
    return Box.from_vectors(self.start, self.end)

transform

transform(transform: Matrix3x3) -> Self

Transform points defining this line.

Source code in src/pygerber/vm/commands/shape_segments/line.py
def transform(self, transform: Matrix3x3) -> Self:
    """Transform points defining this line."""
    return self.__class__(
        start=self.start.transform(transform),
        end=self.end.transform(transform),
    )

ShapeSegment

Bases: ModelType

Base class for shape segment types.

Source code in src/pygerber/vm/commands/shape_segments/shape_segment.py
class ShapeSegment(ModelType):
    """Base class for shape segment types."""

    @pp.cached_property
    def outer_box(self) -> Box:
        """Get outer box of shape segment."""
        raise NotImplementedError

    def transform(self, transform: Matrix3x3) -> Self:
        """Transform line."""
        raise NotImplementedError

outer_box

outer_box() -> Box

Get outer box of shape segment.

Source code in src/pygerber/vm/commands/shape_segments/shape_segment.py
@pp.cached_property
def outer_box(self) -> Box:
    """Get outer box of shape segment."""
    raise NotImplementedError

transform

transform(transform: Matrix3x3) -> Self

Transform line.

Source code in src/pygerber/vm/commands/shape_segments/shape_segment.py
def transform(self, transform: Matrix3x3) -> Self:
    """Transform line."""
    raise NotImplementedError