diff --git a/CHANGELOG.md b/CHANGELOG.md index e190e7c..dd74472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,13 @@ +# GFLabel 0.3.dev + +- Added `square_nut` fragment. Thanks to [@MinchinWeb](https://github.com/MinchinWeb). +- Added `wafer` bold head profile. Thanks to [@MinchinWeb](https://github.com/MinchinWeb). + # GFLabel 0.2.0 (2025-01-03) - Label base type must now always be specified. You can pass `pred` to get the old default kind. You can also specify partial/incomplete - names, as long as it is unambuguous (e.g. `gflabel cull` will select + names, as long as it is unambiguous (e.g. `gflabel cull` will select `cullenect` labels). - Added new base: `modern`, to generate labels for [Modern Gridfinity Base][modern]. - The "webb" base type has been renamed to "cullenect", to reflect the @@ -25,11 +30,13 @@ standards version. - Added alias "Robertson" for square-drive, as it is generally used in Canada. Thanks to [@MinchinWeb](https://github.com/MinchinWeb). -- Added `{circle} {nut_profile} {locknut_profile}` fragments. Thanks to [@MinchinWeb](https://github.com/MinchinWeb). +- Added `{circle}`, `{nut_profile}`, and `{locknut_profile}` fragments. Thanks + to [@MinchinWeb](https://github.com/MinchinWeb). - Bugfix: Specifying output filename will no longer break generation when written before the label contents. -- Bugfix: Countersunk screws were incorrectly treating the head of the - screw separately from the body length. Thanks to [@MinchinWeb](https://github.com/MinchinWeb). +- Bugfix: Countersunk screws were incorrectly treating the head of the screw + separately from the body length. Thanks to + [@MinchinWeb](https://github.com/MinchinWeb). [modern]: https://www.printables.com/model/894202-modern-gridfinity-case diff --git a/README.md b/README.md index 36f7c9f..c6ec6e8 100644 --- a/README.md +++ b/README.md @@ -255,6 +255,7 @@ A list of all the fragments currently recognised: | head | Screw head with specifiable head-shape. | | hexhead | Hexagonal screw head. Will accept drives, but not compulsory. | | hexnut, nut | Hexagonal outer profile nut with circular cutout. | +| square_nut | A square with a center hole. | | nut_profile | Rectangle with two horizontal lines, as the side view of a hex nut. | | locknut_profile | Rectangle with two horizontal lines, as the side view of a hex nut, with an added "top bump". | | lockwasher | Circular washer with a locking cutout. | @@ -300,8 +301,8 @@ There are two classes of bolt/screw representation: [cullenect]: https://makerworld.com/en/models/446624 Both types of bolts will accept a head style, one of `pan`, `socket`, `round`, -or `countersunk`. Both can be marked as `tapping` to have a pointed tip, and -both can be pointed backwards by adding the `flipped` feature. +`countersunk` or `wafer`. Both can be marked as `tapping` to have a pointed +tip, and both can be pointed backwards by adding the `flipped` feature. Examples showing some differences between the two bolts: diff --git a/src/gflabel/fragments.py b/src/gflabel/fragments.py index f65c817..82e0381 100644 --- a/src/gflabel/fragments.py +++ b/src/gflabel/fragments.py @@ -455,12 +455,21 @@ def _fragment_circle(height: float, _maxsize: float) -> Sketch: Circle(height / 2) return sketch.sketch +@fragment("square_nut", examples=["{square_nut}"]) +def _fragment_square_nut(height: float, _maxsize: float) -> Sketch: + """Square with a circular hole.""" + with BuildSketch(mode=Mode.PRIVATE) as sketch: + inner_radius = 0.55 + Rectangle(height, height) + Circle(height / 2 * inner_radius, mode=Mode.SUBTRACT) + return sketch.sketch + class BoltBase(Fragment): """Base class for handling common bolt/screw configuration""" # The options for head shape - HEAD_SHAPES = {"countersunk", "pan", "round", "socket"} + HEAD_SHAPES = {"countersunk", "pan", "round", "socket", "wafer"} # Other, non-drive features MODIFIERS = {"tapping", "flip", "partial"} # Other names that features can be known as, and what they map to @@ -589,6 +598,19 @@ def render(self, height: float, maxsize: float, options: RenderOptions) -> Sketc ) head_connector_bottom = _head @ 0 head_connector_top = _head @ 1 + elif self.headshape == "wafer": + # for the wafer head, use a "socket head", but the head + # being only 1/3 the linewidth thick + _head = Polyline( + [ + (-hw + lw, -head_h), + (-hw + lw * 2 / 3, -head_h), + (-hw + lw * 2 / 3, head_h), + (-hw + lw, head_h), + ] + ) + head_connector_bottom = _head @ 0 + head_connector_top = _head @ 1 elif self.headshape == "countersunk": head_connector_bottom = Vector(-hw, -head_h) head_connector_top = Vector(-hw, head_h)