Skip to content

Commit

Permalink
merge Barrel and Tube, fix Threads
Browse files Browse the repository at this point in the history
  • Loading branch information
guillp committed Feb 12, 2024
1 parent da5b44a commit dccc9df
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 155 deletions.
2 changes: 1 addition & 1 deletion src/muscad/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .barrel import *
from .fillet import *
from .shapes import *
from .stack import *
from .star import *
from .surface import *
from .tube import *
from .volume import *
124 changes: 0 additions & 124 deletions src/muscad/utils/barrel.py

This file was deleted.

94 changes: 83 additions & 11 deletions src/muscad/utils/tube.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,106 @@
class Tube(Part):
def init( # type: ignore[override]
self,
*args: Misc | Hole | Object,
diameter: float | None = None,
top_diameter: float | None = None,
*args: Misc | Hole | Object,
radius: float | None = None,
top_diameter: float | None = None,
top_radius: float | None = None,
left: float | None = None,
center_x: float | None = None,
right: float | None = None,
width: float | None = None,
back: float | None = None,
center_y: float | None = None,
front: float | None = None,
depth: float | None = None,
bottom: float | None = None,
center_z: float | None = None,
top: float | None = None,
height: float | None = None,
segments: int | None = None,
**kwargs: Misc | Hole | Object,
) -> None:
if diameter is None and radius is not None:
diameter = radius * 2
with contextlib.suppress(ValueError):
# first try to get the cylinder diameter from the x coordinates
left, center_x, right, diameter = calc(left, center_x, right, diameter)
match diameter, radius:
case None, None:
# no explicit diameter or radius, try to deduce it from the other params
with contextlib.suppress(ValueError):
left, center_x, right, width = calc(left, center_x, right, width)
with contextlib.suppress(ValueError):
back, center_y, front, depth = calc(back, center_y, front)
match width, depth:
case None, None:
msg = (
"No sufficient parameter to calculate the barrel diameter."
" Please provide either a diameter `d`, a radius `r`,"
"or at least 2 two parameters on axis X or Y."
)
raise ValueError(msg)
case float() | int(), None:
diameter = width
case None, float() | int():
diameter = depth
case float() | int(), float() | int() if width != depth:
msg = (
f"width ({width}mm) is different from depth ({depth}mm)."
" I don't know which one to use as diameter."
)
raise ValueError(msg)
case float() | int(), None if diameter is not None:
pass
case None, float() if radius is not None:
diameter = radius * 2
case (
float()
| int(),
float()
| int(),
) if radius is not None and diameter is not None and radius * 2 != diameter:
msg = (
"diameter `d` and radius `r` must be consistent." "Please fix, or provide either one or the other."
)
raise ValueError(msg)

# fallback to the y coordinates
back, center_y, front, diameter = calc(back, center_y, front, diameter)
assert diameter is not None

match top_radius, top_diameter:
case None, float() | int():
pass
case float() | int(), None if top_radius is not None:
top_diameter = top_radius * 2
case (
float()
| int(),
float()
| int(),
) if top_diameter is not None and top_radius is not None and top_diameter != top_radius * 2:
msg = (
f"inconsistent top diameter `d2` ({top_diameter}mm) and top radius ({top_radius}mm)."
"Please fix, or provide either one or the other."
)
raise ValueError(msg)

match width, diameter:
case None, float() | int():
width = diameter
case float() | int(), float() | int() if width != diameter:
msg = f"diameter `d` ({diameter}mm) is different from width ({width}mm)."
raise ValueError(msg)

match depth, diameter:
case None, float() | int():
depth = diameter
case float() | int(), None:
assert False
case float() | int(), float() | int() if depth != diameter:
msg = f"diameter `d` ({diameter}mm) is different from depth ({depth}mm)."
raise ValueError(msg)

left, center_x, right, width = calc(left, center_x, right, width)
back, center_y, front, depth = calc(back, center_y, front, depth)
bottom, center_z, top, height = calc(bottom, center_z, top, height)
self.cylinder = Cylinder(d=diameter, d2=top_diameter, h=height).align(
center_x=center_x, center_y=center_y, bottom=bottom
self.cylinder = Cylinder(d=diameter, d2=top_diameter, h=height, segments=segments).align(
center_x=center_x, center_y=center_y, center_z=center_z
)
super().init(*args, **kwargs)

Expand Down
50 changes: 31 additions & 19 deletions src/muscad/vitamins/threads.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
from math import floor, pi

from muscad import (
Barrel,
Cylinder,
Object,
Part,
Polygon,
Polyhedron,
Tube,
Union,
cos,
sin,
Expand All @@ -29,41 +29,53 @@ def init( # type: ignore[override]
bottom_countersink: bool = False,
) -> None:
if not top_countersink and not bottom_countersink:
self.shape = Barrel(height=length, d=outer_diameter, segments=segments)
self.shape = Tube(height=length, diameter=outer_diameter, bottom=0, segments=segments)
else:
self.shape = Barrel(bottom=step / 2, height=length - step + 0.005, d=outer_diameter, segments=segments)
self.shape = Tube(bottom=step / 2, height=length - step + 0.005, diameter=outer_diameter, segments=segments)
self.top_countersink = (
Barrel(bottom=self.shape.top, height=step / 2, d=outer_diameter, d2=inner_diameter, segments=segments)
Tube(
bottom=self.shape.top,
height=step / 2,
diameter=outer_diameter,
top_diameter=inner_diameter,
segments=segments,
)
if top_countersink
else Barrel(bottom=self.shape.top, height=step / 2, d=outer_diameter, segments=segments)
else Tube(bottom=self.shape.top, height=step / 2, diameter=outer_diameter, segments=segments)
)
self.bottom_countersink = (
Barrel(height=step / 2, top=self.shape.bottom, d=outer_diameter, d2=inner_diameter, segments=segments)
Tube(
height=step / 2,
top=self.shape.bottom,
diameter=inner_diameter,
top_diameter=outer_diameter,
segments=segments,
)
if bottom_countersink
else Barrel(height=step / 2, top=self.shape.bottom, d=outer_diameter, segments=segments)
else Tube(height=step / 2, top=self.shape.bottom, diameter=outer_diameter, segments=segments)
)


class ScrewThread(Part):
def init( # type: ignore[override]
self,
*,
outer_diameter: float,
diameter: float,
length: float,
step: int,
top_countersink: bool = False,
bottom_countersink: bool = False,
shape_degrees: float = 45,
resolution: float = 0.5,
) -> None:
inner_diameter = outer_diameter - step * cos(shape_degrees) / sin(shape_degrees)
segments = floor(pi * outer_diameter / resolution)
inner_diameter = diameter - step * cos(shape_degrees) / sin(shape_degrees)
segments = floor(pi * diameter / resolution)
ttn = round(length / step + 1)
lfxy = 360 / segments
zt = step / segments
self.thread = ThreadShape(
length=length,
outer_diameter=outer_diameter,
outer_diameter=diameter,
inner_diameter=inner_diameter,
segments=segments,
step=step,
Expand All @@ -85,13 +97,13 @@ def init( # type: ignore[override]
],
[0, 0, i * step],
[
outer_diameter / 2 * cos(j * lfxy),
outer_diameter / 2 * sin(j * lfxy),
diameter / 2 * cos(j * lfxy),
diameter / 2 * sin(j * lfxy),
i * step + j * zt - step / 2,
],
[
outer_diameter / 2 * cos((j + 1) * lfxy),
outer_diameter / 2 * sin((j + 1) * lfxy),
diameter / 2 * cos((j + 1) * lfxy),
diameter / 2 * sin((j + 1) * lfxy),
i * step + (j + 1) * zt - step / 2,
],
[
Expand Down Expand Up @@ -182,7 +194,7 @@ def init(self, height: float, diameter: float) -> None: # type: ignore[override
y1 = height / 2
y2 = height

self.head = Barrel(bottom=0, height=height, d=d0, segments=6) & Polygon(
self.head = Tube(bottom=0, height=height, d=d0, segments=6) & Polygon(
(x0, y0), (x1, y0), (x2, y1), (x1, y2), (x0, y2)
).z_rotational_extrude(bottom=0)

Expand All @@ -199,15 +211,15 @@ def init( # type: ignore[override]
resolution: float = 0.5,
) -> None:
self.nut = HexHead(height, diameter)
self.countersinks = ~Barrel(
self.countersinks = ~Tube(
bottom=self.nut.bottom - 0.1,
height=thread_step / 2,
d=thread_outer_diameter,
d2=thread_outer_diameter - (diameter / 2 + 0.1) * cos(step_shape_degrees) / sin(step_shape_degrees),
).z_mirror(center=self.nut.center_z)
self.bore = ~ScrewThread(
outer_diameter=thread_outer_diameter, length=height, step=thread_step, shape_degrees=step_shape_degrees
diameter=thread_outer_diameter, length=height, step=thread_step, shape_degrees=step_shape_degrees
).align(center_z=self.nut.center_z)


HexNut(diameter=9, height=4, thread_outer_diameter=6.2).render_to_file()
# HexNut(diameter=9, height=4, thread_outer_diameter=6.2).render_to_file()

0 comments on commit dccc9df

Please sign in to comment.