This repository has been archived on 2023-03-25. You can view files and clone it, but cannot push or open issues or pull requests.
mightyscape-1.1-deprecated/extensions/cutcraft/platforms/rollerframe.py
2020-07-31 13:46:07 +02:00

380 lines
18 KiB
Python

# -*- 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 <http://www.gnu.org/licenses/>.
from ..core.point import Point
from ..core.part import Part
from ..core.trace import Trace
from ..core.circle import Circle
from ..core.fingerjoint import FingerJoint
from ..core.neopixel import NeoPixel
from .platform import Platform
from ..util import intersection
from math import pi, sqrt, asin, atan
#import inkex
class RollerFrame(Platform):
""" RollerBot Platform. """
def __init__(self, supwidth, wheelradius, upperradius, lowerradius,
facesize, barsize, primarygapwidth, secondarygapwidth,
scale, part_id, thickness=0.0):
super(RollerFrame, self).__init__(thickness)
self.supwidth = supwidth
self.barsize = barsize
cutdepth = supwidth / 3.0
barradius = sqrt(2.0*(barsize/2.0)**2)
facewidth = primarygapwidth*2.0 + thickness*3.0
faceheight = facesize + thickness
fjoint = FingerJoint(faceheight, thickness*2.0, 'height', thickness=thickness) # Face
bjoint = FingerJoint(faceheight, thickness*2.0, 'depth', thickness=thickness) # Base
wjoint = FingerJoint(facewidth, thickness*2.0, 'width', thickness=thickness) # Length
if part_id<5:
# The circular segments for the main body structure.
# Outer section.
x = barsize/2.0
y = sqrt(lowerradius**2 - x**2)
a = atan(x/y)
outer = Circle(upperradius, 72, 5, cutdepth=cutdepth, start=0.0, end=pi, thickness=thickness) + \
Point(0.0, -upperradius + cutdepth) + \
Point(-thickness, -upperradius + cutdepth) + \
Point(-thickness, -upperradius) + \
Point(-barsize/2.0, -upperradius) + \
Circle(lowerradius, 72, 4, cutdepth=cutdepth, start=pi+a, end=pi*2-a, thickness=thickness) + \
Point(-barsize/2.0, upperradius) + \
Point(-thickness, upperradius) + \
Point(-thickness, upperradius - cutdepth) + \
Point(0.0, upperradius - cutdepth)
outer.close()
self.traces.append(outer)
if part_id in (0,4):
# Central Motor Position.
inner = Trace() + \
Point(-barsize/2.0, -barsize/2.0) + \
Point(-barsize/2.0, barsize/2.0) + \
Point(-barsize/6.0, barsize/2.0) + \
Point(-barsize/6.0, barsize/2.0-thickness/2.0) + \
Point(barsize/6.0, barsize/2.0-thickness/2.0) + \
Point(barsize/6.0, barsize/2.0) + \
Point(barsize/2.0, barsize/2.0) + \
Point(barsize/2.0, -barsize/2.0) + \
Point(barsize/6.0, -barsize/2.0) + \
Point(barsize/6.0, -barsize/2.0+thickness/2.0) + \
Point(-barsize/6.0, -barsize/2.0+thickness/2.0) + \
Point(-barsize/6.0, -barsize/2.0)
inner.close()
self.traces.append(reversed(inner))
# Outer parts are complete, inner parts have cutouts.
if part_id in (1,2,3):
# Central Motor Position and Bar.
inner = Trace() + \
Point(-barsize/2.0*1.3, -barsize/2.0) + \
Point(-barsize/2.0*1.3, -barsize/2.0*0.55) + \
Point(-barsize/2.0, -barsize/2.0*0.55) + \
Point(-barsize/2.0, barsize/2.0*0.55) + \
Point(-barsize/2.0*1.3, barsize/2.0*0.55) + \
Point(-barsize/2.0*1.3, barsize/2.0) + \
Point(barsize/2.0, barsize/2.0) + \
Point(barsize/2.0, barsize/10.0) + \
Point(barsize/2.0*1.2, barsize/20.0) + \
Point(barsize/2.0*1.2, -barsize/20.0) + \
Point(barsize/2.0, -barsize/10.0) + \
Point(barsize/2.0, -barsize/2.0)
inner.close()
self.traces.append(reversed(inner))
# Upper segment cut-outs.
x = supwidth/2.0
y = sqrt((upperradius-supwidth)**2 - x**2)
a_outer = atan(x/y)
y = sqrt((barradius+supwidth)**2 - x**2)
a_inner = atan(x/y)
inner = self._segment(upperradius-supwidth, barradius+supwidth,
0, 1, cutdepth, 0.0, a_outer, a_inner)
self.traces.append(reversed(inner))
fa = (pi/2.0 - self._faceangle(facesize, upperradius)) / 2.0
(fx, fy) = intersection(upperradius, angle=fa)
if 0:
inner = Trace() + \
Point(fx, -fy) + \
Point(fy, -fy) + \
Point(fy, -fx)
inner.close()
self.traces.append(reversed(inner))
oy = fy-thickness*2.0
(ox, oa) = intersection(upperradius, y=oy)
if 0:
inner = Trace() + \
Point(ox, -oy) + \
Point(oy, -oy) + \
Point(oy, -ox)
inner.close()
self.traces.append(reversed(inner))
iy = oy
(ix, ia) = intersection(upperradius-supwidth, y=iy)
if part_id==2:
inner = Circle(upperradius-supwidth, 18, 0, cutdepth=cutdepth,
start=pi/3+a_outer, end=pi-a_outer,
thickness=self.thickness) + \
reversed(Circle(barradius+supwidth, 18, 0, cutdepth=cutdepth,
start=pi/3+a_inner, end=pi-a_inner,
thickness=self.thickness))
inner.close()
self.traces.append(reversed(inner))
# Temporary cut to remove where the face will be installed.
oy = fy-thickness
(ox, oa) = intersection(upperradius, y=oy)
inner = Trace() + \
Point(ox, -ox) + \
Point(oy, -ox) + \
Point(oy, -oy) + \
Point(ox, -oy)
inner.close()
self.traces.append(reversed(inner))
else:
inner = Circle(upperradius-supwidth, 18, 0, cutdepth=cutdepth,
start=pi/3*1+a_outer, end=pi/2+ia,
thickness=self.thickness) + \
reversed(Circle(barradius+supwidth, 18, 0, cutdepth=cutdepth,
start=pi/3*1+a_inner, end=pi/3*2-a_inner,
thickness=self.thickness))
inner.close()
self.traces.append(reversed(inner))
ia = pi/2 - ia
(ix, iy) = intersection(upperradius-supwidth, angle=ia)
inner = Circle(upperradius-supwidth, 18, 0, cutdepth=cutdepth,
start=pi/2+ia, end=pi/3*3-a_outer,
thickness=self.thickness) + \
reversed(Circle(barradius+supwidth, 18, 0, cutdepth=cutdepth,
start=pi/3*2+a_inner, end=pi/3*3-a_inner,
thickness=self.thickness)) + \
Point(ix, -ix)
inner.close()
self.traces.append(reversed(inner))
# Face and base cutout slots.
cy = fy-thickness
for (x1, x2) in zip(fjoint.fingers[1::2],fjoint.fingers[2::2]):
inner = Trace() + \
Point(cy+x1, -cy) + \
Point(cy+x2, -cy) + \
Point(cy+x2, -cy-thickness) + \
Point(cy+x1, -cy-thickness)
inner.close()
self.traces.append(reversed(inner))
for (y1, y2) in zip(bjoint.fingers[1::2],bjoint.fingers[2::2]):
inner = Trace() + \
Point(cy, -cy-y2) + \
Point(cy, -cy-y1) + \
Point(cy+thickness, -cy-y1) + \
Point(cy+thickness, -cy-y2)
inner.close()
self.traces.append(reversed(inner))
if 0:
if part_id==2:
for seg in range(2):
segnext = seg*2+1
inner = self._segment(upperradius-supwidth, barradius+supwidth,
seg, segnext, cutdepth, 0.0, a_outer, a_inner)
self.traces.append(reversed(inner))
else:
for seg in range(3):
segnext = seg+1
inner = self._segment(upperradius-supwidth, barradius+supwidth,
seg, segnext, cutdepth, 0.0, a_outer, a_inner)
self.traces.append(reversed(inner))
# Lower segment cut-outs.
x = supwidth/2.0
y = sqrt((lowerradius-supwidth)**2 - x**2)
a_outer = atan(x/y)
y = sqrt((barradius+supwidth)**2 - x**2)
a_inner = atan(x/y)
for seg in range(3):
segnext = seg+1
inner = self._segment(lowerradius-supwidth, barradius+supwidth,
seg, segnext, cutdepth, pi, a_outer, a_inner)
self.traces.append(reversed(inner))
if part_id in (1,2,3):
r_mid = barradius+supwidth + ((upperradius-supwidth) - (barradius+supwidth))/2.0
self._slot(barsize/2.0 + supwidth/2.0, cutdepth*1.5, cutdepth)
self._slot(barsize/2.0 + supwidth/2.0, -cutdepth*1.5, cutdepth)
self._slot(barsize/2.0 + supwidth/2.0, r_mid+cutdepth*1.5, cutdepth)
self._slot(barsize/2.0 + supwidth/2.0, r_mid-cutdepth*1.5, cutdepth)
elif part_id in (5,6):
# The board supports.
x = primarygapwidth
y = ((upperradius-supwidth) + (barradius+supwidth))/2.0 + supwidth*2.0
t = Trace() + \
Point(0.0, 0.0) + \
Point(0.0, supwidth-cutdepth*2.0) + \
Point(-cutdepth, supwidth-cutdepth*2.0) + \
Point(-cutdepth, supwidth-cutdepth*1.0) + \
Point(0.0, supwidth-cutdepth*1.0) + \
Point(0.0, supwidth*2.0-cutdepth*2.0) + \
Point(-cutdepth, supwidth*2.0-cutdepth*2.0) + \
Point(-cutdepth, supwidth*2.0-cutdepth*1.0) + \
Point(0.0, supwidth*2.0-cutdepth*1.0) + \
Point(0.0, y-supwidth*2.0+cutdepth*1.0) + \
Point(-cutdepth, y-supwidth*2.0+cutdepth*1.0) + \
Point(-cutdepth, y-supwidth*2.0+cutdepth*2.0) + \
Point(0.0, y-supwidth*2.0+cutdepth*2.0) + \
Point(0.0, y-supwidth+cutdepth*1.0) + \
Point(-cutdepth, y-supwidth+cutdepth*1.0) + \
Point(-cutdepth, y-supwidth+cutdepth*2.0) + \
Point(0.0, y-supwidth+cutdepth*2.0) + \
Point(0.0, y) + \
Point(x, y) + \
Point(x, y-supwidth-cutdepth*1.0) + \
Point(x+cutdepth, y-supwidth-cutdepth*1.0) + \
Point(x+cutdepth, y-supwidth-cutdepth*2.0) + \
Point(x, y-supwidth-cutdepth*2.0) + \
Point(x, supwidth-cutdepth*1.0) + \
Point(x+cutdepth, supwidth-cutdepth*1.0) + \
Point(x+cutdepth, supwidth-cutdepth*2.0) + \
Point(x, supwidth-cutdepth*2.0) + \
Point(x, 0.0)
t.close()
self.traces.append(t)
elif part_id==7:
# The face components.
t = Trace(x=[thickness], y=[thickness])
for i, pos in enumerate(fjoint.fingers[1:-1]):
if i%2==0:
t += Point(pos, thickness)
t += Point(pos, 0.0)
else:
t += Point(pos, 0.0)
t += Point(pos, thickness)
t += Point(faceheight, thickness)
t += Point(faceheight, facewidth-thickness)
for i, pos in enumerate(reversed(fjoint.fingers[1:-1])):
if i%2==0:
t += Point(pos, facewidth-thickness)
t += Point(pos, facewidth)
else:
t += Point(pos, facewidth)
t += Point(pos, facewidth-thickness)
t += Point(thickness, facewidth-thickness)
for i, pos in enumerate(reversed(wjoint.fingers[1:-1])):
if i%2==0:
t += Point(thickness, pos)
t += Point(0.0, pos)
else:
t += Point(0.0, pos)
t += Point(thickness, pos)
t.close()
self.traces.append(t)
elif part_id==8:
t = Trace(x=[thickness], y=[0.0])
t += Point(facewidth-thickness, 0.0)
for i, pos in enumerate(bjoint.fingers[1:-1]):
if i%2==0:
t += Point(facewidth-thickness, pos)
t += Point(facewidth, pos)
else:
t += Point(facewidth, pos)
t += Point(facewidth-thickness, pos)
t += Point(facewidth-thickness, faceheight)
for i, pos in enumerate(reversed(wjoint.fingers[1:-1])):
if i%2==0:
t += Point(pos, faceheight)
t += Point(pos, faceheight-thickness)
else:
t += Point(pos, faceheight-thickness)
t += Point(pos, faceheight)
t += Point(thickness, faceheight)
for i, pos in enumerate(reversed(bjoint.fingers[1:-1])):
if i%2==0:
t += Point(thickness, pos)
t += Point(0.0, pos)
else:
t += Point(0.0, pos)
t += Point(thickness, pos)
t.close()
self.traces.append(t)
for eye in range(2):
np = NeoPixel(style='rings', origin=Point(facewidth/4.0*(1+eye*2), faceheight/2.5), scale=scale, rotate=pi/2)
self.traces.extend(np.traces)
np = NeoPixel(style='strip', origin=Point(facewidth/2.0, faceheight*0.80), scale=scale)
self.traces.extend(np.traces)
# Camera
csize = 8.5*scale
t = Trace() + \
Point(facewidth/2.0 - csize/2.0, faceheight/2.5 - csize/2.0) + \
Point(facewidth/2.0 + csize/2.0, faceheight/2.5 - csize/2.0) + \
Point(facewidth/2.0 + csize/2.0, faceheight/2.5 + csize/2.0) + \
Point(facewidth/2.0 - csize/2.0, faceheight/2.5 + csize/2.0)
t.close()
self.traces.append(t)
def _faceangle(self, size, radius):
# Returns total angle required for a face.
o = sqrt(2.0*(size**2))*0.5
h = radius
return 2.0*asin(o/h)
def _segment(self, r_outer, r_inner, seg, segnext, cutdepth, a_offset, a_outer, a_inner):
# Create an inner segment cutout.
t = Circle(r_outer, 18, 0, cutdepth=cutdepth,
start=a_offset+pi/3*seg+a_outer, end=a_offset+pi/3*segnext-a_outer,
thickness=self.thickness) + \
reversed(Circle(r_inner, 18, 0, cutdepth=cutdepth,
start=a_offset+pi/3*seg+a_inner, end=a_offset+pi/3*segnext-a_inner,
thickness=self.thickness))
if a_offset == 0.0 and seg == 0:
r_mid = r_inner + (r_outer - r_inner)/2.0
t += Trace() + \
Point(self.supwidth / 2.0, r_mid - self.supwidth) + \
Point(self.barsize/2.0 + self.supwidth, r_mid - self.supwidth) + \
Point(self.barsize/2.0 + self.supwidth, r_mid + self.supwidth) + \
Point(self.supwidth / 2.0, r_mid + self.supwidth)
t.close()
return t
def _slot(self, x, y, cutdepth):
slot = Trace() + \
Point(x-self.thickness/2.0, y+cutdepth/2.0) + \
Point(x+self.thickness/2.0, y+cutdepth/2.0) + \
Point(x+self.thickness/2.0, y-cutdepth/2.0) + \
Point(x-self.thickness/2.0, y-cutdepth/2.0)
slot.close()
self.traces.append(reversed(slot))