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 functools import wraps
from xml.sax.saxutils import quoteattr from xml.sax.saxutils import quoteattr
from contextlib import contextmanager from contextlib import contextmanager
import copy
from boxes import edges from boxes import edges
from boxes import formats from boxes import formats
@ -1805,6 +1806,158 @@ class Boxes:
self.move(overallwidth, overallheight, move) 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 ### Place Parts
################################################## ##################################################

View File

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