Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
},
"editor.formatOnSave": true,
"mypy.runUsingActiveInterpreter": true,
"restructuredtext.preview.name": "docutils",
"restructuredtext.preview.name": "docutils"
}
Binary file modified docs/assets/base_feature_rich_bot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/base_feature_rich_top.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/base_plate.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/base_plate_equal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/base_plate_full.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/baseplate.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
117 changes: 101 additions & 16 deletions docs/assets/image_gen.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations

import logging
import shutil
from enum import Enum, auto
from pathlib import Path
from subprocess import check_call
Expand All @@ -16,13 +17,15 @@
BasePlate,
BasePlateBlockFull,
BasePlateBlockSkeleton,
BasePlateBottomSideRound,
BasePlateEqual,
Bin,
BottomCorners,
BottomMiddle,
BottomSides,
Compartment,
CompartmentsEqual,
Direction,
GridfinityRefinedConnectionCutout,
GridfinityRefinedMagnetHolePressfit,
GridfinityRefinedMagnetHoleSide,
Expand All @@ -44,6 +47,41 @@
logger = logging.getLogger(__name__)


OPENSCAD_DEFAULT_PATH = "/usr/bin/openscad"
IMAGEMAGICK_DEFAULT_PATH = "/usr/bin/convert"


def resolve_openscad_cmd() -> str:
"""Resolve OpenSCAD executable path for the current developer environment."""
if Path(OPENSCAD_DEFAULT_PATH).exists():
return OPENSCAD_DEFAULT_PATH

# Check if "openscad" is in PATH
openscad_in_path = shutil.which("openscad")
if openscad_in_path:
return openscad_in_path

msg = "OpenSCAD executable not found. Install 'openscad' in PATH."
raise FileNotFoundError(msg)


def resolve_imagemagick_cmd() -> str:
"""Resolve ImageMagick executable for GIF generation."""
if Path(IMAGEMAGICK_DEFAULT_PATH).exists():
return IMAGEMAGICK_DEFAULT_PATH

convert_in_path = shutil.which("convert")
if convert_in_path:
return convert_in_path

magick_in_path = shutil.which("magick")
if magick_in_path:
return magick_in_path

msg = "ImageMagick executable not found. Install 'convert'/'magick' in PATH."
raise FileNotFoundError(msg)


class CameraPosition(Enum):
CAMERA_TOP = auto()
CAMERA_BOT = auto()
Expand All @@ -69,6 +107,7 @@ def parts_to_gif(
file_name: str,
camera_pos: CameraPosition,
) -> None:
imagemagick_cmd = resolve_imagemagick_cmd()
with TemporaryDirectory() as tmp_dir:
for idx, part in enumerate(part_list):
Convert._part_to_png(
Expand All @@ -79,7 +118,7 @@ def parts_to_gif(
)
_ = check_call(
[
"/usr/bin/convert",
imagemagick_cmd,
"-delay",
"75",
"-loop",
Expand All @@ -98,6 +137,7 @@ def _part_to_png(
file_name: str,
camera_pos: CameraPosition,
) -> None:
openscad_cmd = resolve_openscad_cmd()
tmp_stl = work_dir.joinpath("tmp.stl")
tmp_scad = work_dir.joinpath("tmp.scad")
_ = build123d.export_stl(part, str(tmp_stl)) # pyright: ignore[reportUnknownMemberType]
Expand All @@ -106,7 +146,7 @@ def _part_to_png(

_ = check_call(
[
"/usr/bin/openscad",
openscad_cmd,
"--autocenter",
"--viewall",
"--camera",
Expand All @@ -133,20 +173,43 @@ def _part_to_png(

# Bases

Convert.part_to_png(Base([[True, True], [True]]), "base", CameraPosition.CAMERA_BOT)
Convert.part_to_png(BaseEqual(2, 2), "base_equal", CameraPosition.CAMERA_BOT)
Convert.part_to_png(
Base(
grid=[[True, True], [True]],
),
"base",
CameraPosition.CAMERA_BOT,
)
Convert.part_to_png(
BaseEqual(
grid_x=2,
grid_y=2,
),
"base_equal",
CameraPosition.CAMERA_BOT,
)
Convert.part_to_png(
BaseEqual(
2,
2,
[MagnetHole(BottomCorners()), ScrewHole(BottomCorners())],
grid_x=2,
grid_y=2,
features=[
MagnetHole(BottomCorners()),
ScrewHole(BottomCorners()),
],
),
"base_holes",
CameraPosition.CAMERA_BOT,
)

# Bins
Convert.part_to_png(Bin(Base(), height_in_units=4), "bin", CameraPosition.CAMERA_TOP)
Convert.part_to_png(
Bin(
Base(),
height_in_units=4,
),
"bin",
CameraPosition.CAMERA_TOP,
)

Convert.part_to_png(
Bin(
Expand Down Expand Up @@ -177,28 +240,50 @@ def _part_to_png(

# Baseplates
Convert.part_to_png(
BasePlate([[True, True], [True]]),
BasePlate(
grid=[[True, True], [True]],
),
"base_plate",
CameraPosition.CAMERA_TOP,
)
Convert.part_to_png(BasePlateEqual(2, 2), "base_plate_equal", CameraPosition.CAMERA_TOP)
Convert.part_to_png(
BasePlateEqual(2, 2, BasePlateBlockFull()),
BasePlateEqual(
size_x=2,
size_y=2,
),
"base_plate_equal",
CameraPosition.CAMERA_TOP,
)
Convert.part_to_png(
BasePlateEqual(
size_x=2,
size_y=2,
baseplate_block=BasePlateBlockFull(),
),
"base_plate_full",
CameraPosition.CAMERA_TOP,
)
Convert.part_to_png(
BasePlateEqual(
2,
2,
BasePlateBlockFull(
size_x=2,
size_y=2,
baseplate_block=BasePlateBlockFull(
features=[
ScrewHoleCountersink(BottomCorners()),
Weighted(BottomMiddle()),
],
),
),
"base_plate_weigthed",
"base_plate_weighted",
CameraPosition.CAMERA_BOT,
)
Convert.part_to_png(
BasePlateEqual(
size_x=2,
size_y=2,
features=BasePlateBottomSideRound(radius=1, direction=Direction.FRONT),
),
"base_plate_bottom_side_round_single",
CameraPosition.CAMERA_BOT,
)

Expand Down Expand Up @@ -240,7 +325,7 @@ def _part_to_png(

Convert.part_to_png(
Weighted(f_loc_mock).create_obj(),
"weigthed",
"weighted",
CameraPosition.CAMERA_TOP,
)

Expand Down
File renamed without changes
12 changes: 10 additions & 2 deletions docs/source/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ Features List
+++
Counterbore hole.

.. grid-item-card:: :class:`gridfinity_build123d.Weigthed`
.. grid-item-card:: :class:`gridfinity_build123d.Weighted`

.. image:: ../assets/weigthed.png
.. image:: ../assets/weighted.png

+++
Cutout for weighted baseplates.
Expand All @@ -83,3 +83,11 @@ Features List

+++
Label for bin compartments.

.. grid-item-card:: :class:`gridfinity_build123d.BasePlateBottomSideRound`

.. image:: ../assets/base_plate_bottom_side_round_single.png

+++
Round the underside perimeter edges of a baseplate so it fits in drawers
with internal rounding between the bottom and sides.
58 changes: 48 additions & 10 deletions docs/source/objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Bins
.. testcode::

Bin(
Base(), height_in_units=4,
Base(),
height_in_units=4,
)

.. raw:: html
Expand Down Expand Up @@ -74,7 +75,7 @@ Bins
compartment_list=Compartment(Label()),
),
lip=StackingLip(),
),
)

.. raw:: html

Expand Down Expand Up @@ -121,7 +122,9 @@ BasePlates

.. testcode::

BasePlate([[True,True],[True]])
BasePlate(
grid=[[True, True], [True]],
)

.. raw:: html

Expand Down Expand Up @@ -162,14 +165,43 @@ BasePlates
BasePlateEqual(
size_x=2,
size_y=2,
baseplate_block=BasePlateBlockFull(),
baseplate_block=BasePlateBlockFull(
features=[
ScrewHoleCountersink(BottomCorners()),
Weighted(BottomMiddle()),
],
),
)

.. raw:: html

</details>

.. image:: ../assets/base_plate_weighted.png

.. grid-item-card:: :class:`BasePlateBottomSideRound` — one side

.. raw:: html

<details>
<summary>source</summary>

.. testcode::

BasePlateEqual(
size_x=2,
size_y=2,
features=BasePlateBottomSideRound(
radius=1,
direction=Direction.FRONT,
),
)

.. raw:: html

</details>

.. image:: ../assets/base_plate_weigthed.png
.. image:: ../assets/base_plate_bottom_side_round_single.png


Bases
Expand Down Expand Up @@ -207,7 +239,9 @@ Bases

.. testcode::

Base([[True,True],[True]])
Base(
grid=[[True, True], [True]],
)

.. raw:: html

Expand All @@ -225,10 +259,14 @@ Bases

.. testcode::

BaseEqual(2, 2, [MagnetHole(
BottomCorners()),
ScrewHole(BottomCorners(),
)])
BaseEqual(
grid_x=2,
grid_y=2,
features=[
MagnetHole(BottomCorners()),
ScrewHole(BottomCorners()),
],
)

.. raw:: html

Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dev = [
"ocp_vscode",
"parameterized",
"ruff",
"mypy",
"pytest-markdown-docs",
"Sphinx",
"sphinx-rtd-theme",
Expand Down
2 changes: 2 additions & 0 deletions src/gridfinity_build123d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"BasePlateBlockFrame",
"BasePlateBlockFull",
"BasePlateBlockSkeleton",
"BasePlateBottomSideRound",
"BasePlateEqual",
"Bin",
"BottomCorners",
Expand Down Expand Up @@ -59,6 +60,7 @@
TopMiddle,
)
from .features import (
BasePlateBottomSideRound,
GridfinityRefinedConnectionCutout,
GridfinityRefinedMagnetHolePressfit,
GridfinityRefinedMagnetHoleSide,
Expand Down
Loading
Loading