Source code for fibomat.shapes.circle

"""Provides the :class:`Circle` class."""
# pylint: disable=invalid-name
from __future__ import annotations
from typing import Optional

import numpy as np

from fibomat.shapes.shape import Shape
from fibomat.linalg import Vector, VectorLike, BoundingBox
from fibomat.shapes.arc_spline import ArcSpline, ArcSplineCompatible


[docs]class Circle(Shape, ArcSplineCompatible): """2-dim circle."""
[docs] def __init__(self, r: float, center: Optional[VectorLike] = None, description: Optional[str] = None): """ Args: r (float): radius center (:class:`~fibomat.linalg.vectortypes.VectorLike`, optional): center of circle, default to (0, 0) description (str, optional): description Raises: ValueError: Raised if r <= 0. """ super().__init__(description) self._center = Vector(center) if center is not None else Vector() self._r = float(r) if self._r <= 0: raise ValueError('radius <= 0.')
[docs] @classmethod def from_points(cls, p1: VectorLike, p2: VectorLike, p3: VectorLike, description: Optional[str] = None): """Create circumscribed circle (from three points). Args: p1 (VectorLike): first points p2 (VectorLike): second points p3 (VectorLike): third points description (str, optional): description Returns: Circle """ # https://en.wikipedia.org/wiki/Circumscribed_circle#Cartesian_coordinates_2 a = Vector(p1) # A b = Vector(p2) - a # B c = Vector(p3) - a # C inv_d = 1 / (2 * (b.x * c.y - b.y * c.x)) b2 = b.x*b.x + b.y*b.y c2 = c.x*c.x + c.y*c.y u = Vector(inv_d * (c.y * b2 - b.y * c2), inv_d * (b.x * c2 - c.x * b2)) r = np.sqrt(u.x*u.x + u.y*u.y) return cls(r, u + a, description)
def __repr__(self) -> str: return '{}(r={!r}, center={!r})'.format( self.__class__.__name__, self.r, self.center)
[docs] def to_arc_spline(self) -> ArcSpline: return ArcSpline( [(*(self._center + Vector(self._r, 0.)), 1.), (*(self._center - Vector(self._r, 0.)), 1.)], True, self.description )
@property def r(self) -> float: """Radius. Access: get Returns: float """ return self._r @property def center(self) -> Vector: return self._center @property def bounding_box(self) -> BoundingBox: return BoundingBox(self._center-(self._r, self._r), self._center + (self._r, self._r)) @property def is_closed(self) -> bool: return True def _impl_translate(self, trans_vec: VectorLike) -> None: self._center += Vector(trans_vec) def _impl_rotate(self, theta: float) -> None: self._center = self._center.rotated(theta) def _impl_scale(self, fac: float) -> None: self._center *= float(fac) self._r *= float(fac) def _impl_mirror(self, mirror_axis: VectorLike) -> None: self._center = self._center.mirrored(mirror_axis)