# -*- coding: utf-8 -*-
# Copyright (C) 2018 Michael Matthews
#
# This file is part of CutCraft.
#
# CutCraft is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# CutCraft is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with CutCraft. If not, see .
from .point import Point
from .line import Line
from .trace import Trace
from ..util import isclose
from math import pi, sin, cos, asin
class Circle(Trace):
def __init__(self, radius, segments, cuts, cutdepth=0.0, start=0.0, end=pi*2.0, rotation=0.0,
origin=Point(0.0, 0.0), thickness=0.0, kerf=0.0):
super(Circle, self).__init__()
self.thickness = thickness
self.kerf = kerf
partial = True if start != 0.0 or end != pi*2.0 else False
if cuts==0:
c = 0.0
else:
if self.thickness <= 0.0:
raise ValueError("cutcraft.circle: parameter 'thickness' not set when 'cuts' greater than zero.")
if cutdepth <= 0.0:
raise ValueError("cutcraft.circle: parameter 'cutdepth' not set when 'cuts' greater than zero.")
c = asin(self.thickness/2/radius)
if partial:
angles = [[rotation+start+(end-start)/segments*seg, 'SEG'] for seg in range(segments+1)] + \
[[rotation+start+(end-start)/(cuts+1)*cut-c, ''] for cut in range(1, cuts+1)]
else:
angles = [[rotation+end/segments*seg, 'SEG'] for seg in range(segments)] + \
[[rotation+end/cuts*cut-c, ''] for cut in range(cuts)]
angles = sorted(angles)
if angles[0][1] == 'CUT>':
angles = angles[1:] + [angles[0]]
for i, angle in enumerate(angles):
angle.append(self._cnext(angles, i, 'SEG'))
angle.append(self._cprev(angles, i, 'SEG'))
angle.append(self._cnext(angles, i, 'CUT>') if angle[1]=='' else None)
for i, angle in enumerate(angles):
if angle[1] == 'SEG':
angle.append([self._pos(angle[0], radius)])
for i, angle in enumerate(angles):
if angle[1] != 'SEG':
mult = -1 if angle[1] == '':
incut = False
if atype != 'SEG' or (atype == 'SEG' and not incut):
for pos in angle[6]:
x = origin.x + pos.x
y = origin.y + pos.y
if len(self.x)==0 or not (isclose(x, self.x[-1]) and isclose(y, self.y[-1])):
self.x.append(x)
self.y.append(y)
return
def _cnext(self, angles, i, item):
if i>=len(angles):
i=-1
for j, angle in enumerate(angles[i+1:]):
if angle[1] == item:
return i+1+j
for j, angle in enumerate(angles):
if angle[1] == item:
return j
return None
def _cprev(self, angles, i, item):
if i<=0:
i=len(angles)
for j, angle in enumerate(angles[:i][::-1]):
if angle[1] == item:
return i-j-1
for j, angle in enumerate(angles[::-1]):
if angle[1] == item:
return j
return None
def _pos(self, angle, radius):
return Point(sin(angle)*radius, cos(angle)*radius)