# -*- coding: utf-8 -*-
from __future__ import annotations
from math import cos, degrees, radians, sin, tau
from pygerber.mathclasses import Vector2D, angle_from_zero
from pygerber.renderer.spec import ArcSpec
[docs]class ArcUtilMixin:
@property
def isCCW(self):
return self.renderer.isCCW()
[docs] def get_begin_end_angles(self, spec: ArcSpec):
begin_relative = spec.begin - spec.center
end_relative = spec.end - spec.center
begin_angle = degrees(angle_from_zero(begin_relative))
end_angle = degrees(angle_from_zero(end_relative))
if begin_angle >= end_angle:
end_angle += 360
return begin_angle, end_angle
[docs] def get_arc_points(self, spec: ArcSpec, is_ccw: bool) -> Vector2D:
begin_angle, end_angle = self.get_begin_end_angles(spec)
radius = spec.get_radius()
x, y = self.get_arc_co_functions(radius)
delta = self.get_arc_traverse_step_angle(begin_angle, end_angle, radius)
if is_ccw:
return self.__get_arc_points_ccw(end_angle, begin_angle, x, spec, y, delta)
else:
return self.__get_arc_points_cw(end_angle, begin_angle, x, spec, y, delta)
[docs] def get_arc_traverse_step_angle(self, begin_angle, end_angle, radius):
raise NotImplementedError(
"get_arc_traverse_step_angle() have to be implemented in subclass."
)
def __get_arc_points_ccw(self, end_angle, begin_angle, x, spec, y, delta):
end_relative_angle = end_angle - begin_angle
angle_offset = begin_angle
current_angle = 0
while current_angle <= end_relative_angle:
yield Vector2D(
x(current_angle + angle_offset) + spec.center.x,
y(current_angle + angle_offset) + spec.center.y,
)
current_angle += delta
def __get_arc_points_cw(self, end_angle, begin_angle, x, spec, y, delta):
end_relative_angle = end_angle - begin_angle
angle_offset = begin_angle
current_angle = 360
while current_angle >= end_relative_angle:
yield Vector2D(
x(current_angle + angle_offset) + spec.center.x,
y(current_angle + angle_offset) + spec.center.y,
)
current_angle -= delta
[docs] @staticmethod
def get_arc_co_functions(radius):
def x(alpha):
return radius * cos(radians(alpha))
def y(alpha):
return radius * sin(radians(alpha))
return x, y
[docs] @staticmethod
def get_arc_length(radius) -> float:
return tau * radius
[docs] @staticmethod
def get_arc_ratio(relative_angle):
return relative_angle / 360
[docs] @staticmethod
def get_relative_angle(begin_angle, end_angle):
return end_angle - begin_angle