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 # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from functools import partial
from boxes import Boxes, edges, boolarg from boxes import Boxes, edges, boolarg
import math import math
from functools import partial
class DividerTray(Boxes): class DividerTray(Boxes):
"""Divider tray - rows and dividers""" """Divider tray - rows and dividers"""
@ -86,10 +87,7 @@ class DividerTray(Boxes):
help="generate wall on the right side", help="generate wall on the right side",
) )
self.argparser.add_argument( self.argparser.add_argument(
"--bottom", "--bottom", type=boolarg, default=False, help="generate wall on the bottom",
type=boolarg,
default=False,
help="generate wall on the bottom",
) )
def render(self): def render(self):
@ -98,7 +96,15 @@ class DividerTray(Boxes):
if side_walls_number == 0: if side_walls_number == 0:
raise ValueError("You need at least one side wall to generate this tray") 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: if self.outside:
self.sx = self.adjustSize(self.sx, self.left_wall, self.right_wall) self.sx = self.adjustSize(self.sx, self.left_wall, self.right_wall)
@ -119,7 +125,12 @@ class DividerTray(Boxes):
self.rectangularWall( self.rectangularWall(
facing_wall_length, facing_wall_length,
self.h, 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)], callback=[partial(self.generate_finger_holes, self.h)],
move="up", move="up",
) )
@ -144,12 +155,18 @@ class DividerTray(Boxes):
# Bottom piece. # Bottom piece.
if self.bottom: if self.bottom:
self.rectangularWall(facing_wall_length, side_wall_length, self.rectangularWall(
["f", facing_wall_length,
"f" if self.right_wall else "e", side_wall_length,
"f", [
"f" if self.left_wall else "e"], "f",
callback=[partial(self.generate_finger_holes, side_wall_length)], move="up") "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 # Dividers
divider_height = ( divider_height = (
@ -208,61 +225,6 @@ class DividerTray(Boxes):
) )
self.text(str.join("\n", debug_info), x=5, y=5, align="bottom left") 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): def generate_finger_holes(self, length):
posx = -0.5 * self.thickness posx = -0.5 * self.thickness
for x in self.sx[:-1]: for x in self.sx[:-1]:
@ -287,41 +249,42 @@ class DividerTray(Boxes):
# Upper: divider width (with notch if possible) # Upper: divider width (with notch if possible)
if upper_third > 0: if upper_third > 0:
self.edge(upper_third) self.polyline(
self.corner(90, upper_radius) upper_third,
self.edge(self.divider_notch_depth - upper_radius - lower_radius) (90, upper_radius),
self.corner(-90, lower_radius) self.divider_notch_depth - upper_radius - lower_radius,
self.edge(upper_third) (-90, lower_radius),
self.corner(-90, lower_radius) upper_third,
self.edge(self.divider_notch_depth - upper_radius - lower_radius) (-90, lower_radius),
self.corner(90, upper_radius) self.divider_notch_depth - upper_radius - lower_radius,
self.edge(upper_third) (90, upper_radius),
upper_third,
)
else: else:
# if there isn't enough room for the radius, we don't use it # if there isn't enough room for the radius, we don't use it
self.edge(width) self.edge(width)
# Upper: second tab width if needed self.polyline(
self.edge(second_tab_width) # Upper: second tab width if needed
second_tab_width,
# First side, with tab depth only if there is 2 walls # First side, with tab depth only if there is 2 walls
self.corner(90) 90,
self.edge(self.slot_depth) self.slot_depth,
self.corner(90) 90,
self.edge(second_tab_width) second_tab_width,
self.corner(-90) -90,
self.edge(height - self.slot_depth) height - self.slot_depth,
# Lower edge
# Lower edge 90,
self.corner(90) width,
self.edge(width) # Second side, always a tab
90,
# Second side, always a tab height - self.slot_depth,
self.corner(90) -90,
self.edge(height - self.slot_depth) self.thickness,
self.corner(-90) 90,
self.edge(self.thickness) self.slot_depth,
self.corner(90) )
self.edge(self.slot_depth)
# Move for next piece # Move for next piece
self.move(total_width, height, move) 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): class DividerSlotsEdge(edges.BaseEdge):
"""Edge with multiple angled rounded slots for dividers""" """Edge with multiple angled rounded slots for dividers"""
@ -513,13 +526,16 @@ class DividerSlotsEdge(edges.BaseEdge):
def do_slot(self, slot): def do_slot(self, slot):
self.ctx.save() self.ctx.save()
self.corner(90 - slot.angle, slot.start_radius) self.polyline(
self.edge(slot.corrected_start_depth()) 0,
self.corner(-90) (90 - slot.angle, slot.start_radius),
self.edge(slot.width) slot.corrected_start_depth(),
self.corner(-90) -90,
self.edge(slot.corrected_end_depth()) slot.width,
self.corner(90 + slot.angle, slot.end_radius) -90,
slot.corrected_end_depth(),
(90 + slot.angle, slot.end_radius),
)
# rounding errors might accumulates : # rounding errors might accumulates :
# restore context and redo the move straight # restore context and redo the move straight