Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minkowski complements #65

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
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
10 changes: 6 additions & 4 deletions src/main/python/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

# Get config from user dir

config_file = os.path.expanduser("~/.puzzlecad")
config_file = os.path.expanduser("~/.puzzlecad/config.ini")
config = configparser.ConfigParser()
config.read(config_file)

Expand Down Expand Up @@ -79,9 +79,11 @@ def process_command(args):

elif args.command == 'open-printables-session':

driver = webdriver.Chrome()
print('Looking for ~/.puzzlecad/chromedriver ...')
driver = webdriver.Chrome(os.path.expanduser("~/.puzzlecad/chromedriver"))
driver.get("https://www.printables.com/model/171148/edit")
print(driver.session_id + " " + driver.command_executor._url)
print('Session created; now you can update models with:')
print('admin.py update-printables-model ' + driver.session_id + ' ' + driver.command_executor._url + ' model-name [options]')
return driver

elif args.command == "update-printables-model":
Expand Down Expand Up @@ -113,7 +115,7 @@ def get_access_token():

access_token = params['access_token']

print('Put this line in ~/.puzzlecad:')
print('Put this line in ~/.puzzlecad/config.ini:')
print(f'AccessToken = {access_token}')

def print_thing_description(thing_name):
Expand Down
5 changes: 5 additions & 0 deletions src/main/scad/globals.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ alfons-eyckmans-bio: |-

Alfons Eyckmans specializes in highly complex burr puzzles with intricate interlocking solutions. His designs range from moderately challenging to truly gargantuan, often requiring dozens of moves to remove the first piece. Many of his designs incorporate unusual geometric shapes or figurative elements, such as his "Burr Zoo" series of puzzles featuring animal shapes. Eyckmans's puzzles are for experienced puzzle solvers (you have been warned!), but patience will be rewarded as they reveal their creative and fascinating structure.

gregory-benedetti-bio: |-
### About the Designer

French designer Gregory Benedetti has created some of the world's most inventive interlocking puzzles, often employing rotational moves, coordinate motions, or unusual combinations of geometries. They range from moderately challenging to "brutally difficult," in the words of Eric Fuller, and many of them are absolutely unique in the puzzle repertoire. Benedetti's designs are well-regarded in the puzzle community, and in 2011 and 2012 he was recognized with back-to-back Top 10 awards at the International Puzzle Party.

osanori-yamamoto-bio: |-
### About the Designer

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
176 changes: 176 additions & 0 deletions src/main/scad/gregory-benedetti/nos/benedetti.nos.scad
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/* ====================================================================

This is a 3D model of a mechanical puzzle. It is released under
the following license:

Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported
https://creativecommons.org/licenses/by-nc-nd/3.0/

This means the model is licensed for personal, noncommercial use
only. Anyone may print a copy for their own use, but selling or
otherwise monetizing the model or print (or any derivatives) is
prohibited. For details, refer to the summary at the above URL.

Puzzle design (c) Gregory Benedetti
3D model (c) Aaron Siegel

==================================================================== */

include <puzzlecad.scad>

require_puzzlecad_version("2.4");

$burr_scale = 11.15;

// $burr_inset value for each of the 7 puzzles:
insets = [0.07, 0.08, 0.07, 0.07, 0.07, 0.07, 0.07];

// This can be used to uniformly adjust the insets up or down:
inset_delta = 0;

// Use a very slight interior bevel; intersect with a hull later to get a larger exterior bevel
$burr_bevel = 0.1;

// OpenSCAD is fussy about some of these shapes. If you get GCAL errors rendering them, try flushing
// the cache ("Flush Caches" in the Design menu) and re-render directly in render mode (F6).

*nos1_compressed();
*nos2_transfer();
*nos3_round_trip();
*nos4_go_back();
*nos5_crenel();
*nos6_dodge();
*nos7_seizaine();

module nos1_compressed() {

$burr_inset = insets[0] + inset_delta;
$plate_width = $burr_scale * 7;
burr_plate([
["xxx{components=sy-z+}.x{connect=mz+y+,clabel=A}x|xxxxxx", "x....x|x...x{components=sx-z-}x"],
["xxx{components=sy+z+}x{components=sy+z+}xx|xx..xx",
"xx{components=sx-z-}...x|xx{components=sx-z-}..x{components=sx+z+}x"],
["x{components=sx+y-}x{connect=fz-y+,clabel=A}"]
]);

}

module nos2_transfer() {

$burr_inset = insets[1] + inset_delta;
$joint_style = "flush";
$plate_width = $burr_scale * 7;
burr_plate([
["xxx{components=sy+z+}x{components=sy+z+}xx|xx.x{components=sy+z-}xx",
"xx{components=sy-z-}..x{components=sx+z-}x|x...x{components=sx+z-}x"],
["xx.x{components=sx+y+}xx|xxx{components=sy-z+,connect=mz+y-,clabel=B}x{components=sy-z+}xx",
"x...x{components=sx+z-}x|x...x{components=sx+z-}x"],
[".x{components=sx-y+}..|.x{connect=fz+y-,clabel=B}x{components=sx-z-}."]
]);

}

module nos3_round_trip() {

$burr_inset = insets[2] + inset_delta;
burr_plate([
["xxxxxx|xxxxxx", "xx{components=sx-z-}x.x{components=sx+z-}x|xx{components=sx-z-}x.x{components=sx+z-}x"],
["xx..xx|xxxxxx", "xx{components=sx-z-}..x{components=sx+z-}x|xx{components=sx-z-}..x{components=sx+z-}x"],
["xxx{components=sy-z+}x{components=sy-z+}xx|xxxxxx", "x....x|x....x"],
["xxx{components=sy-z+}x{components=sy-z+}xx|xxx{components=sy+z+}x{components=sy+z+}xx", "x....x|x....x"],
["xxx{components=sy+z+}.xx|xxx{components=sy-z+}x{components=sy-z+}xx", "x....x|x...x{components=sx+z+}x"],
["xx..xx|xxx{components=sy-z+}x{components=sy-z+}xx", "x....x|xx{components=sx-z+}..x{components=sx+z+}x"]
]);

}

module nos4_go_back() {

$burr_inset = insets[3] + inset_delta;
$use_diag_voxel_expand_hack = true;
burr_plate([
["xxx{components=sx+y+}x{components=sx-y+}xx|xxx{components=sy-z+}xxx",
"x...x{components=sx+y+}x|xxx{components=sx-y-}x{components=sx+y+}x{components=sx-y-}x"],
["xxx{components=sx+y+}x{components=sx-y+}xx|xxx{components=sx-z+}x{components=sx+z-}xx",
"xx{components=sy+z-}...x|xx{components=sy-z+}x{components=sx+z-}..x"],
["xx..xx|xxxxxx", "x....x|xx{components=sx-z-}...x"],
["xx..xx|xxx{components=sy+z+}x{components=sy+z+}xx", "xx{components=sy+z-}...x|x....x"],
["xxx{components=sy+z-}x{components=sy+z-}x{components=sy-z-}x|xxx{components=sx+z+}x{components=sx-z+}x{components=sy+z-}x",
"x....x|xx{components=sx-z+}...x"],
["xx{components=sy-z-}..xx|xx{components=sy+z-}x{components=sx-y+}x{components=sx+y-}xx",
"x....x{components=sx+y-}|x.x{components=sy-z-}x{components=sy-z-}.x{components=sx+y+}"]
]);

}

module nos5_crenel() {

$burr_inset = insets[4] + inset_delta;
burr_plate([
["xxxxxx|xxxxxx", "x....x|xx{components=sx-z+}x{components=sx+z-}x{components=sx-z+}x{components=sx+z-}x"],
["xxxxxx|xxxxxx", "x.x{components=sy+z-}..x|x.x{components=sx+z-}x{components=sx-z-}x{components=sx+z+}x"],
["xx..xx|xxxx{components=sy+z+}xx", "x....x|xx{components=sy-z+}..x{components=sx+z+}x"],
["xx..xx|xxx{components=sy-z+}x{components=sy-z+}xx", "x....x|xx{components=sx-z+}.x{components=sy+z-}x{components=sy-z+}x"],
["xx.x{components=sx+y-}xx|xxx{components=sy+z+}x{components=sy+z+}xx", "x....x|x.x{components=sy-z-}x{components=sx-z-}.x"],
["xxx{components=sx-y-}.xx|xxx{components=sy+z+}x{components=sy+z+}xx", "x....x|x....x"]
]);

}

module nos6_dodge() {

$burr_inset = insets[5] + inset_delta;
burr_plate([
["xx{components=sx-y+}x{components=sx+y-}x{components=sx-y+}x{components=sy-z+}x|xxxx{components=sy-z-}xx", "x...x{components=sy+z-}x|xx..xx"],
["xxx{components={x+y-,y-x+,x+z+,z+x+,y-z+,z+y-,z+x-,z+y+}}x{components=sy-z+}xx|xxx{components=sy+z+}x{components=sy+z+}xx", "xx{components=sx+z+}x{components=sx-y+}..x|x...x{components=sx+z-}x"],
["xxx{components=sy-z+}.xx|xxxxxx", "x...x{components=sx+z+}x|x....x"],
["xx..xx|xxx{components=sy-z+}x{components=sy-z+}xx", "x....x|xx{components={x-y-,y-x-,x-z+,z+x-,y-z+,z+y-,x-z-,x-y+}}x{components=sy+z-}x{components=sy+z-}x{components=sx+z+}x"],
["xx..xx|xxx{components=sx-y+}x{components=sx+y-}xx", "x....x|x.x{components=sy-z-}x{components={x-y-,y-x-,x-z-,z-x-,y-z-,z-y-,z-x+,z-y+}}x{components=sx+z+}x"],
["xx{components=sy-z-}x{components=sy-z-}.x{components=sy-z-}x|xxx{components=sy+z+}x{components=sy+z+}xx", "x....x|x...x{components=sy-z-}x"]
]);

}

module nos7_seizaine() {

$burr_inset = insets[6] + inset_delta;
$use_diag_voxel_expand_hack = true;
burr_plate([
["xxx{components=sx-y+}x{components=sx-y+}xx|xxxxxx", "x....x|x.x{components=sx-z-}.xx"],
["xxx{components=sy+z+}x{components=sy+z+}xx|xxx{components=sx+y-}x{components=sx-y-}xx", "x.x{components=sy+z+}x{components=sy-z-}.x|x.x{components=sy-z-}..x"],
["xx.x{components=sy+z+}xx|xxxxxx", "xx{components=sx-z-}...x|x....x"],
["xx..xx|xxx{components=sy-z+}x{components=sy-z+}xx", "xx{components=sx-z-}...x|xx{components=sx-z-}x{components=sx+z+}x{components=sy-z-}.x"],
["xxx{components=sx-y-}.x{components=sy-z-}x|xxxxx{components=sy+z-}x", "x....x|x..x{components=sx-z-}.x"],
["xx..xx|xxx{components=sy+z+}xxx", "xx{components=sy+z+}...x|xx{components=sx-y-}...x{components=sx+y+}"]
]);

}

module nos2_transfer_alternate() {

$burr_inset = insets[1] + inset_delta;
burr_piece(["xx.x{components=sx+y+}xx|xxx{components=sy-z+}x{components=sy-z+}xx",
"x.x{components=sx+y+}x{components=sx-z-}x{components=sx+z-}x|xx{components=sx+z+}x{components=sy-z-}.x{components=sx+z-}x"]);

}

module minkowski_inset_shape(inset) {

cube(2 * inset, center = true);

}

module minkowski_bevel_cutout_shape(bevel) {

cube(2 * bevel, center = true);

}

module post_process_burr_piece() {

intersection() {
children(0);
burr_piece_base(1, $burr_bevel = 0.5, $burr_outer_x_bevel = 1.75);
}

}
36 changes: 36 additions & 0 deletions src/main/scad/gregory-benedetti/nos/benedetti.nos.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
thing-id: 5793804
printables-model-id: 371748
name: "NOS Burr Series - Interlocking puzzles by Gregory Benedetti"
tags: [puzzle, 3D_puzzle]
images: [cover.jpeg, assembled.jpg, pieces.jpg, partially-assembled.jpg]
targets: [nos1_compressed, nos2_transfer, nos3_round_trip, nos4_go_back, nos5_crenel, nos6_dodge, nos7_seizaine]
configurations:
- {name: '', code: '', targets: ''}
- {name: 'tighter', code: 'inset_delta = -0.01;', targets: ''}
- {name: 'looser', code: 'inset_delta = 0.01;', targets: ''}
description: |
The NOS Burr Series is a set of seven highly unusual interlocking puzzles by Gregory Benedetti. The goal of each puzzle is the same: assemble six pieces into the familiar shape of an ordinary six-piece burr.

These are no ordinary six-piece burrs, however. Instead of the usual rectilinear cuts found in traditional burr puzzles, the NOS ("New Old School") burrs feature unusual diagonal cuts, yielding an astonishing variety of solving experiences that will continually surprise you. Each one is unique; among them you will find triple and quadruple coordinate motion, multiple consecutive coordinate motions, surprising reversals, and an unusual rotation thrown in for good measure. These are some of the most delightful puzzle designs that I have ever encountered.

Be advised that these are quite difficult puzzles, and they are likely to challenge even experienced puzzle solvers. If you are unfamiliar with burr puzzles, I strongly advise starting with simpler designs such as those in the ${link:starter-burr-set}. However, if you feel up to the challenge, you will not regret embarking on this journey. They are all solvable without hints or computer aids, and if you get desperate, Kevin Sadler has created solution videos for all seven; search for them on YouTube.

These puzzles are quite sensitive to tolerances. If printed too tight, they have a tendency to lock up and become frustrating to use. Therefore, I have modeled them all to be slightly on the loose side (each puzzle had to be individually tested due to differences in fit). If you want to try printing them tighter, you can print the "`tighter`" variants instead (`${name}.nos1-compressed-tighter.stl`, etc). Similarly, if you find they are too tight for comfort, try the "`looser`" variants.

You can find more information about these fascinating designs in an article published by Frans de Vreugd: [New Old School (NOS) Burrs](https://www.gathering4gardner.org/g4g13gift/puzzles/DeVreugdFrans-GiftExchange-NewOldSchoolBurrs-G4G13.pdf)

### Printing Instructions

For puzzle #1 and #2, print three copies of `${name}.nos1-compressed.stl` and `${name}.nos2-transfer.stl`, respectively. For each of the others, print just one copy of the appropriate `stl` file (`${name}.nos3-round-trip.stl` through `${name}.nos7-seizaine.stl`).

Most of the puzzles can be printed without supports, though you will probably want supports for the pieces in #1 and #4 that have unbridged edges near the build plate, and definitely for the piece in #7 with an unbridged overhang.

However, I specifically recommend _not_ using supports for the pieces in #4 and #6 with a bridged overhang; I'd expect better results from the printer's natural bridging feature.

Puzzles #1 and #2 use "snap joints" to model pieces with non-bridgeable overhang. ${snap-joints-boilerplate}

${ppp-boilerplate}

${gregory-benedetti-bio}

Happy puzzling!
Binary file added src/main/scad/gregory-benedetti/nos/cover.jpeg
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 added src/main/scad/gregory-benedetti/nos/pieces.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 21 additions & 2 deletions src/main/scad/puzzlecad.scad
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@ $joint_inset = 0.015;
$joint_cutout = 0.5;
$diag_joint_scale = 0.4;
$diag_joint_position = 0.1;
$short_joints = false;

$unit_beveled = false;
$auto_layout = false;
$detached_joints = false;
$detached_joints = undef; // Deprecated
$short_joints = undef; // Deprecated
$post_rotate = [0, 0, 0];
$joint_style = $detached_joints ? "detached" : $short_joints ? "flush" : "standard";

// Optional parameters that can be used to increase
// the amount of beveling on outer edges of burr pieces:
Expand All @@ -92,6 +93,24 @@ $use_alternate_diag_inset_hack = false;
iota = 0.00001;
iota_vec = [iota, iota, iota];

// Parameter validation.

assert(
list_contains(["standard", "flush", "detached"], $joint_style),
"$joint_style must be one of the following: standard, flush, detached"
)

// Beta version notice.

if (list_contains(puzzlecad_version, "b")) {
echo(str("NOTE: You are using a beta version of puzzlecad (version ", puzzlecad_version, ")."));
}

// Deprecation warnings.

if (!is_undef($detached_joints)) {
echo(str("WARNING: $detached_joints is deprecated. Use $joint_style = \"detached\" instead."));
}
if (!is_undef($short_joints)) {
echo(str("WARNING: $short_joints is deprecated. Use $joint_style = \"flush\" instead."));
}
Loading