New .polygonWall() part

Similar to .polyline() but with (f) edges on the outside
.polygonWalls draws the surrounding walls
This commit is contained in:
Florian Festi 2019-03-08 17:52:52 +01:00
parent 4f4d947253
commit 7aec26e893
2 changed files with 157 additions and 0 deletions

View File

@ -29,6 +29,7 @@ import re
from functools import wraps
from xml.sax.saxutils import quoteattr
from contextlib import contextmanager
import copy
from boxes import edges
from boxes import formats
@ -1805,6 +1806,158 @@ class Boxes:
self.move(overallwidth, overallheight, move)
### polygonWall and friends
def _polygonWallExtend(self, borders, edge, close=False):
posx, posy = 0, 0
ext = [ 0.0 ] * 4
angle = 0
def checkpoint(ext, x, y):
ext[0] = min(ext[0], x)
ext[1] = min(ext[1], y)
ext[2] = max(ext[2], x)
ext[3] = max(ext[3], y)
for i in range(len(borders)):
if i % 2:
try:
a, r = borders[i]
except TypeError:
angle = (angle + borders[i]) % 360
continue
centerx = posx + r * math.cos(math.radians(angle+90))
centery = posy + r * math.sin(math.radians(angle+90))
for direction in (0, 90, 180, 270):
if ((a > 0 and
angle <= direction and angle + a >= direction) or
(a < 0 and
angle >= direction and angle + a <= direction)):
checkpoint(ext, centerx + r * math.cos(math.radians(direction)), centery + r * math.sin(math.radians(direction)))
angle = (angle + a) % 360
posx = centerx + r * math.cos(math.radians(angle-90))
posy = centery + r * math.sin(math.radians(angle-90))
else:
posx += borders[i] * math.cos(math.radians(angle))
posy += borders[i] * math.sin(math.radians(angle))
checkpoint(ext, posx, posy)
ext[0] -= edge.margin()
ext[1] -= edge.margin()
ext[2] += edge.margin()
ext[3] += edge.margin()
return ext
def polygonWall(self, borders, edge="f", callback=None, move=None):
e = self.edges.get(edge, edge)
t = self.thickness # XXX edge.margin()
minx, miny, maxx, maxy = self._polygonWallExtend(borders, e)
tw, th = maxx - minx, maxy - miny
if self.move(tw, th, move, True):
return
self.moveTo(-minx, -miny)
length_correction = 0.
for i in range(0, len(borders), 2):
self.cc(callback, i)
self.edge(length_correction)
l = borders[i] - length_correction
next_angle = borders[i+1]
if isinstance(next_angle, (int, float)) and next_angle < 0:
length_correction = t * math.tan(math.radians((-next_angle / 2)))
else:
length_correction = 0.0
l -= length_correction
e(l)
self.edge(length_correction)
self.corner(next_angle, tabs=1)
self.move(tw, th, move)
@restore
def polygonWalls(self, borders, h, bottom="F", top="F", symetrical=True):
bottom = self.edges.get(bottom, bottom)
top = self.edges.get(top, top)
t = self.thickness # XXX edge.margin()
leftsettings = copy.deepcopy(self.edges["f"].settings)
lf, lF, lh = leftsettings.edgeObjects(self, add=False)
rightsettings = copy.deepcopy(self.edges["f"].settings)
rf, rF, rh = rightsettings.edgeObjects(self, add=False)
length_correction = 0.
angle = borders[-1]
i = 0
part_cnt = 0
self.moveTo(0, bottom.margin())
while i < len(borders):
if symetrical:
if part_cnt % 2:
left, right = lf, rf
else:
left, right = lF, rF
else:
left, right = lf, rF
top_lengths = []
top_edges = []
self.moveTo(left.spacing() + self.spacing, 0)
l = borders[i] - length_correction
leftsettings.setValues(self.thickness, angle=angle)
angle = borders[i+1]
while isinstance(angle, (tuple, list)):
bottom(l)
angle, radius = angle
lr = math.radians(angle) * radius
self.edges["X"](lr, h + 2*t) # XXX
top_lengths.append(l)
top_lengths.append(lr)
top_edges.append(top)
top_edges.append("E")
i += 2
l = borders[i]
angle = borders[i+1]
rightsettings.setValues(self.thickness, angle=angle)
if angle < 0:
length_correction = t * math.tan(math.radians((-angle / 2)))
else:
length_correction = 0.0
l -= length_correction
bottom(l)
top_lengths.append(l)
top_edges.append(top)
with self.saved_context():
self.edgeCorner(bottom, right, 90)
right(h)
self.edgeCorner(right, top, 90)
top_edges.reverse()
top_lengths.reverse()
edges.CompoundEdge(self, top_edges, top_lengths)(sum(top_lengths))
self.edgeCorner(top, left, 90)
left(h)
self.edgeCorner(left, bottom, 90)
self.moveTo(right.spacing() + self.spacing)
part_cnt += 1
i += 2
##################################################
### Place Parts
##################################################

View File

@ -584,6 +584,10 @@ class FingerJointBase:
if angle >=90:
return self.settings.thickness, 0
if angle < 0:
return math.sin(math.radians(-angle)) * self.settings.thickness, 0
# 0 to 90
a = 90 - (180-angle) / 2.0
fingerlength = self.settings.thickness * math.tan(math.radians(a))
b = 90-2*a