DividerTray: refactor, and makes it easier to reuse

This commit is contained in:
Guillaume Collic 2020-09-19 23:47:21 +02:00 committed by Florian Festi
parent eba63d9acb
commit 7495de72f7
1 changed files with 122 additions and 106 deletions

View File

@ -15,9 +15,10 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from functools import partial
from boxes import Boxes, edges, boolarg
import math
from functools import partial
class DividerTray(Boxes):
"""Divider tray - rows and dividers"""
@ -86,10 +87,7 @@ class DividerTray(Boxes):
help="generate wall on the right side",
)
self.argparser.add_argument(
"--bottom",
type=boolarg,
default=False,
help="generate wall on the bottom",
"--bottom", type=boolarg, default=False, help="generate wall on the bottom",
)
def render(self):
@ -98,7 +96,15 @@ class DividerTray(Boxes):
if side_walls_number == 0:
raise ValueError("You need at least one side wall to generate this tray")
slot_descriptions = self.generate_slot_descriptions(self.sy)
slot_descriptions = SlotDescriptionsGenerator().generate_all_same_angles(
self.sy,
self.thickness,
self.slot_extra_slack,
self.slot_depth,
self.h,
self.slot_angle,
self.slot_radius,
)
if self.outside:
self.sx = self.adjustSize(self.sx, self.left_wall, self.right_wall)
@ -119,7 +125,12 @@ class DividerTray(Boxes):
self.rectangularWall(
facing_wall_length,
self.h,
[bottom_edge(self.bottom), side_edge(self.right_wall), "e", side_edge(self.left_wall)],
[
bottom_edge(self.bottom),
side_edge(self.right_wall),
"e",
side_edge(self.left_wall),
],
callback=[partial(self.generate_finger_holes, self.h)],
move="up",
)
@ -144,12 +155,18 @@ class DividerTray(Boxes):
# Bottom piece.
if self.bottom:
self.rectangularWall(facing_wall_length, side_wall_length,
["f",
"f" if self.right_wall else "e",
"f",
"f" if self.left_wall else "e"],
callback=[partial(self.generate_finger_holes, side_wall_length)], move="up")
self.rectangularWall(
facing_wall_length,
side_wall_length,
[
"f",
"f" if self.right_wall else "e",
"f",
"f" if self.left_wall else "e",
],
callback=[partial(self.generate_finger_holes, side_wall_length)],
move="up",
)
# Dividers
divider_height = (
@ -208,61 +225,6 @@ class DividerTray(Boxes):
)
self.text(str.join("\n", debug_info), x=5, y=5, align="bottom left")
def generate_slot_descriptions(self, sections):
slot_width = self.thickness + self.slot_extra_slack
descriptions = SlottedEdgeDescriptions()
# Special case: if first slot start at 0, then radius is 0
first_correction = 0
current_section = 0
if sections[0] == 0:
slot = SlotDescription(
slot_width,
depth=self.slot_depth,
angle=self.slot_angle,
start_radius=0,
end_radius=self.slot_radius,
)
descriptions.add(slot)
first_correction = slot.round_edge_end_correction()
current_section += 1
first_length = sections[current_section]
current_section += 1
descriptions.add(
StraightEdgeDescription(
first_length, round_edge_compensation=first_correction
)
)
for l in sections[current_section:]:
slot = SlotDescription(
slot_width,
depth=self.slot_depth,
angle=self.slot_angle,
radius=self.slot_radius,
)
# Fix previous edge length
previous_edge = descriptions.get_last_edge()
previous_edge.round_edge_compensation += slot.round_edge_start_correction()
# Add this slot
descriptions.add(slot)
# Add the straigth edge after this slot
descriptions.add(
StraightEdgeDescription(l, slot.round_edge_end_correction())
)
# We need to add extra space for the divider (or the actual content)
# to slide all the way down to the bottom of the tray in spite of walls
end_length = self.h * math.tan(math.radians(self.slot_angle))
descriptions.get_last_edge().angle_compensation += end_length
return descriptions
def generate_finger_holes(self, length):
posx = -0.5 * self.thickness
for x in self.sx[:-1]:
@ -287,41 +249,42 @@ class DividerTray(Boxes):
# Upper: divider width (with notch if possible)
if upper_third > 0:
self.edge(upper_third)
self.corner(90, upper_radius)
self.edge(self.divider_notch_depth - upper_radius - lower_radius)
self.corner(-90, lower_radius)
self.edge(upper_third)
self.corner(-90, lower_radius)
self.edge(self.divider_notch_depth - upper_radius - lower_radius)
self.corner(90, upper_radius)
self.edge(upper_third)
self.polyline(
upper_third,
(90, upper_radius),
self.divider_notch_depth - upper_radius - lower_radius,
(-90, lower_radius),
upper_third,
(-90, lower_radius),
self.divider_notch_depth - upper_radius - lower_radius,
(90, upper_radius),
upper_third,
)
else:
# if there isn't enough room for the radius, we don't use it
self.edge(width)
# Upper: second tab width if needed
self.edge(second_tab_width)
# First side, with tab depth only if there is 2 walls
self.corner(90)
self.edge(self.slot_depth)
self.corner(90)
self.edge(second_tab_width)
self.corner(-90)
self.edge(height - self.slot_depth)
# Lower edge
self.corner(90)
self.edge(width)
# Second side, always a tab
self.corner(90)
self.edge(height - self.slot_depth)
self.corner(-90)
self.edge(self.thickness)
self.corner(90)
self.edge(self.slot_depth)
self.polyline(
# Upper: second tab width if needed
second_tab_width,
# First side, with tab depth only if there is 2 walls
90,
self.slot_depth,
90,
second_tab_width,
-90,
height - self.slot_depth,
# Lower edge
90,
width,
# Second side, always a tab
90,
height - self.slot_depth,
-90,
self.thickness,
90,
self.slot_depth,
)
# Move for next piece
self.move(total_width, height, move)
@ -481,6 +444,56 @@ class SlotDescription:
)
class SlotDescriptionsGenerator:
def generate_all_same_angles(
self, sections, thickness, extra_slack, depth, height, angle, radius=2,
):
width = thickness + extra_slack
descriptions = SlottedEdgeDescriptions()
# Special case: if first slot start at 0, then radius is 0
first_correction = 0
current_section = 0
if sections[0] == 0:
slot = SlotDescription(
width, depth=depth, angle=angle, start_radius=0, end_radius=radius,
)
descriptions.add(slot)
first_correction = slot.round_edge_end_correction()
current_section += 1
first_length = sections[current_section]
current_section += 1
descriptions.add(
StraightEdgeDescription(
first_length, round_edge_compensation=first_correction
)
)
for l in sections[current_section:]:
slot = SlotDescription(width, depth=depth, angle=angle, radius=radius,)
# Fix previous edge length
previous_edge = descriptions.get_last_edge()
previous_edge.round_edge_compensation += slot.round_edge_start_correction()
# Add this slot
descriptions.add(slot)
# Add the straigth edge after this slot
descriptions.add(
StraightEdgeDescription(l, slot.round_edge_end_correction())
)
# We need to add extra space for the divider (or the actual content)
# to slide all the way down to the bottom of the tray in spite of walls
end_length = height * math.tan(math.radians(angle))
descriptions.get_last_edge().angle_compensation += end_length
return descriptions
class DividerSlotsEdge(edges.BaseEdge):
"""Edge with multiple angled rounded slots for dividers"""
@ -513,13 +526,16 @@ class DividerSlotsEdge(edges.BaseEdge):
def do_slot(self, slot):
self.ctx.save()
self.corner(90 - slot.angle, slot.start_radius)
self.edge(slot.corrected_start_depth())
self.corner(-90)
self.edge(slot.width)
self.corner(-90)
self.edge(slot.corrected_end_depth())
self.corner(90 + slot.angle, slot.end_radius)
self.polyline(
0,
(90 - slot.angle, slot.start_radius),
slot.corrected_start_depth(),
-90,
slot.width,
-90,
slot.corrected_end_depth(),
(90 + slot.angle, slot.end_radius),
)
# rounding errors might accumulates :
# restore context and redo the move straight