DividerTray: refactor, and makes it easier to reuse
This commit is contained in:
parent
eba63d9acb
commit
7495de72f7
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue