summaryrefslogtreecommitdiff
path: root/ambiguous-cylinders.scad
diff options
context:
space:
mode:
Diffstat (limited to 'ambiguous-cylinders.scad')
-rw-r--r--ambiguous-cylinders.scad75
1 files changed, 72 insertions, 3 deletions
diff --git a/ambiguous-cylinders.scad b/ambiguous-cylinders.scad
index 9a59522..965942d 100644
--- a/ambiguous-cylinders.scad
+++ b/ambiguous-cylinders.scad
@@ -1,3 +1,25 @@
+/*
+ Recreating Sugihara's impossible objects
+
+ Original work: http://www.isc.meiji.ac.jp/~kokichis/Welcomee.html
+
+ PDF Paper with the maths: https://www.mdpi.com/2073-8994/8/4/21
+
+ Based on Sugihara's work, I've approximated his mathematical model
+ with OpenSCAD.
+ */
+
+/* let's build it in steps:
+
+ given a 2D object, extrude a `thin` "cylinder" with its shape as
+ section; this approximates the set of points that would appear
+ indistinguishable from the given shape to an observer infinitely
+ distant on the Z axis
+
+ (`height` determines how tall the cylinder is, `shift` determines
+ how low it is on Z axis)
+*/
+
module view_cylinder(shift=100/3,height=200,thin=0.1) {
translate([0,0,-shift]) {
difference() {
@@ -11,6 +33,24 @@ module view_cylinder(shift=100/3,height=200,thin=0.1) {
}
}
+/*
+ given two objects:
+
+ * build they view cylinders
+
+ * rotate them so the two "observers" are opposite each other on the
+ Y axis, lookin toward the origin with a downward `angle`
+
+ * intersect them
+
+ the result approximates the set of points that would look like the
+ first object to the first observers, and like the second object to
+ the second observer
+
+ (`size` should be higher than the diameter of the largest child,
+ otherwise the shapes may get cut)
+*/
+
module intersect_view_cylinders(angle=45,size=100,thin=0.1) {
shift=size/3;
height=size*2;
@@ -21,6 +61,21 @@ module intersect_view_cylinders(angle=45,size=100,thin=0.1) {
}
};
+/*
+ `intersect_view_cylinders` produces a slightly ugly shape, with two
+ half-curves for each half-object; to see the problem, render this:
+
+intersect_view_cylinders() {
+ circle(d=14);
+ rotate([0,0,45]) square(size=10,center=true);
+}
+
+ therefore, we render it twice, cutting the "wrong half" out each
+ time. This gives us the curve we want at the top of our ambiguous
+ cylinder
+*/
+
+
module clip_intersect_view(angle=45,size=100,thin=0.1) {
bound=size*2;
skip=0;
@@ -41,17 +96,30 @@ module clip_intersect_view(angle=45,size=100,thin=0.1) {
}
};
+/*
+ finally, we "extrude" the curve; OpenSCAD can't extrude a 3d shape,
+ but we can "paint" it with a vertical cylinder, and that's close
+ enough
+
+ (`thick` determines the thickness of the wall, `height` its height)
+ */
+
module ambiguous_cylinder(angle=45,size=100,thin=0.1,thick=1,height=10) {
minkowski() {
clip_intersect_view(angle,size,thin) {
children(0);
children(1);
}
- cylinder(r=thick,h=height*2,center=true);
+ cylinder(r=thick/2,h=height*2,center=true);
}
}
-/* Arrow that always points right
+/*
+ Some examples:
+ */
+
+/*
+ Arrow that always points right
*/
module arrow(length=10) {
scale([length/10,length/10,length/10])
@@ -64,7 +132,8 @@ ambiguous_cylinder() {
rotate([0,0,-90]) arrow(30);
}
-/* circle / diamond
+/*
+ circle / diamond
*/
translate([0,50,0]) ambiguous_cylinder() {