diff --git a/Arches/arches.scad b/Arches/arches.scad new file mode 100755 index 0000000..c21addc --- /dev/null +++ b/Arches/arches.scad @@ -0,0 +1,54 @@ +// file arches.scad +// Creates Gothic or circular arches, made up of smaller "stones +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +size = 80; //diameter of the arch opening at the base, mm +w = 10; //width of the bricks that make the arch, mm +thick = w; //height of the print, set to 0 for 2D printing on paper +segments = 11; // Number of stones; use 10.01 for a small keystone (the stone on top of a Gothic arch) +gap = 0.1; //Gap between stones (to leave space for mortar, for example), mm +separate = 0; //Extra spacing between the stones for printing (to ensure that they don't stick together). + +gothic = false; //Make this true to print a Gothic arch, false for a circular one + +$fs = .2; +$fa = 2; + + +if(thick) linear_extrude(thick) { + arch(); +} else { + arch(); +} + + +module arch() { + if(gothic) for(i = [0:segments / 2 - .0001], j = [0, 1]) mirror([j, 0, 0]) translate([separate * (floor((segments / 2 - .0001)) - i), separate * i, 0]) intersection() { + difference() { + translate([-size / 2, 0, 0]) circle(size + w); + translate([-size / 2, 0, 0]) circle(size); + } + square(size + w); + if(segments > 1) offset(-gap / 2) translate([-size / 2, 0, 0]) rotate(120 / segments * i) intersection() { + square(size + w * 2); + if((segments % 2) || (i < (segments / 2 - 1))) rotate(-90 + 120 / segments) square(size + w * 2); + else rotate(-120 / segments * i) translate([size / 2, 0, 0]) square(size + w); + } + } else for(i = [0:segments / 2 - .0001], j = [0, 1]) mirror([j, 0, 0]) translate([separate * (floor((segments / 2 - .0001)) - i), separate * i, 0])intersection() { + difference() { + circle(size / 2 + w); + circle(size / 2); + } + square(size + w); + if(segments > 1) offset(-gap / 2) rotate(180 / segments * i) intersection() { + square(size + w); + rotate(-90 + 180 / segments) square(size + w); + } + } + + translate([0, -2 - separate, 0]) difference() { + translate([-size / 2 - w * 2, -w, 0]) square([size + w * 4, w + 2]); + translate([-size / 2 - w * 1, 0, 0]) square([size + w * 2, w + 2]); + } +} \ No newline at end of file diff --git a/Arches/castle.scad b/Arches/castle.scad new file mode 100755 index 0000000..dcd21de --- /dev/null +++ b/Arches/castle.scad @@ -0,0 +1,31 @@ +// file castle.scad +// Creates a simple castle wall with towers and crenellation +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +wall = 100; //length of a castle wall, mm +height = 40; //height of a castle wall, mm +thick = 4; //thickness of the wall, mm + + +for(side = [0:1:3]) { + rotate(90 * side) { + translate([-wall / 2, wall / 2, 0]) { + translate([0, -thick / 2, 0]) { + cube([wall, thick, height - thick]); + for(crenellation = [0:thick * 2:wall - thick]) { + translate([crenellation, 0, 0]) { + cube([thick, thick, height]); + } //end translate + } //end for + } //end translate + + cylinder(h = height, r = 1.5 * thick); + translate([0, 0, height]) { + cylinder(h = 3 * thick, r1 = 1.5 * thick, r2 = 0); + } //end translate + } //end translate + } //end rotate +} //end for + + diff --git a/Arches/castle_advanced.scad b/Arches/castle_advanced.scad new file mode 100755 index 0000000..4c8f066 --- /dev/null +++ b/Arches/castle_advanced.scad @@ -0,0 +1,53 @@ +// file castle_advanced.scad +// Creates a castle with Gothic or circular arched windows +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +wall = 100; //length of a castle wall, mm +height = 40; //height of a castle wall, mm +thick = 4; //thickness of the wall, mm + +$fs = .2; +$fa = 2; +//make the basic castle and then subtract off the windows/door +difference() { + for(side = [0:1:3]) { + rotate(90 * side) { + translate([-wall / 2, wall / 2, 0]) { + translate([0, -thick / 2, 0]) { + cube([wall, thick, height]); + for(crenellation = [0:thick * 2:wall - thick]) { + translate([crenellation, 0, 0]) { + cube([thick, thick, height + thick]); + } //end translate + } //end for + } //end translate + + cylinder(h = height + thick, r = 1.5 * thick); + translate([0, 0, height + thick]) { + cylinder(h = 3 * thick, r1 = 1.5 * thick, r2 = 0); + } //end translate + } //end translate + } //end rotate + } //end for + for(a = [1:1:3]) rotate([90, 0, a * 90]) for(i = [-2:1:2]) translate([i * wall / 6, 20, 0]) arch([5, 10, wall], true); + rotate([90, 0, 0]) { + for(i = [-2, 2]) translate([i * wall / 6, 20, 0]) arch([5, 10, wall], true); + translate([0, 20, 0]) arch([25, 25, wall], false); + } +} +//module which creates arched door on one side and windows on all + +module arch(size, gothic = true) { + if(size[2]) { + linear_extrude(size[2]) arch([size[0], size[1], 0], gothic); + } + else intersection() { + union() { + if(gothic) intersection_for(i = [-1, 1]) translate([size[0] / 2 * i, 0, 0]) circle(size[0]); + else circle(size[0] / 2); + if(height > 0) translate([-size[0] / 2, -size[1], 0]) square([size[0], size[1]]); + } + translate([-size[0] / 2, -size[1], 0]) square([size[0], size[0] + size[1]]); + } +} \ No newline at end of file diff --git a/Arches/tracery.scad b/Arches/tracery.scad new file mode 100755 index 0000000..843164e --- /dev/null +++ b/Arches/tracery.scad @@ -0,0 +1,31 @@ +// file tracery.scad +// Creates a Gothic window with tracery +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +size = 60; //Overall height of the piece, mm +wall = 1; //Thickness of the walls, mm +depth = 5; //Depth of the tracery walls, mm +backing = .5; //Thickness of a solid backing plate; 0 creates open tracery + +$fs = .2; +$fa = 2; + +module shape() { + translate([0, -size / 2, 0]) square(size, center = true); + intersection_for(i = [1, -1]) translate([i * size / 2, 0, 0]) circle(size); +} + +if(backing) #linear_extrude(backing) shape(); + +for(i = [0:4]) linear_extrude(backing + depth / (i + 1)) for(j = [0:pow(2, i) - 1]) translate([-size * (-.5 + pow(2, -i - 1) + j / pow(2, i)), 0, 0]) difference() { + offset(wall / 2) intersection_for(k = [-1, 1]) translate([k * size * (.5 - 1 / pow(2, i + 1)), 0, 0]) shape(); + offset(-wall / 2) intersection_for(k = [-1, 1]) translate([k * size * (.5 - 1 / pow(2, i + 1)), 0, 0]) shape(); +} + +linear_extrude(backing + depth / 4) translate([0, size * .6, 0]) rotate(180) difference() { + offset(wall / 2) trefoil(size * .1125); + offset(-wall / 2) trefoil(size * .1125); +} + +module trefoil(r) for(a = [0:120:359]) rotate(a) translate([0, r, 0]) circle(r); \ No newline at end of file diff --git a/gnomon.scad b/Gnomon/gnomon.scad similarity index 100% rename from gnomon.scad rename to Gnomon/gnomon.scad diff --git a/Gnomon/sun_dial_gnomon.scad b/Gnomon/sun_dial_gnomon.scad new file mode 100755 index 0000000..ac4c110 --- /dev/null +++ b/Gnomon/sun_dial_gnomon.scad @@ -0,0 +1,13 @@ +// file sun_dial_gnomon.scad +// Creates a gnomon for a sundial to be used at the given latitude +// +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +length = 100; //length of the base of the triangle, mm +base = 30; //width of the base of the triangle, mm +latitude = 34.1; //latitude of user, degrees +thickness = 2.2; //thickness of the piece, mm + +rotate([90, 0, 90]) linear_extrude(thickness, center = true) polygon([[0, 0], [0, length], [length * tan(abs(latitude)), 0]]); +translate([-base / 2, -thickness, 0]) cube([base, thickness, length]); diff --git a/Polygons+Polyhedrons/edge_platonic_solids.scad b/Polygons+Polyhedrons/edge_platonic_solids.scad new file mode 100755 index 0000000..5491372 --- /dev/null +++ b/Polygons+Polyhedrons/edge_platonic_solids.scad @@ -0,0 +1,27 @@ +// file edge_platonic_solids.scad +// creates platonic solids specified by length of an edge in mm +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +edge = 50 / sqrt(2); //length of the edge of each solid +// to get just one solid, comment out the others + +%rotate([45, 35, 0]) cube(48.8, center = true); + +//translate(edge * [.75, -.75, 0]) tetrahedron(edge); +//translate(edge * [1.5, 1.5, 0]) cube(edge); +octahedron(edge, true); +//translate(edge * [2, 0, 0]) dodecahedron(edge); +//translate(edge * [.5, 1.6, 0]) icosahedron(edge); + +//%cube(1, center = true); + +phi = (1 + sqrt(5)) / 2; + +module tetrahedron(edge = 1, center = false) translate([0, 0, center ? 0 : edge * sqrt(2) / sqrt(3) / 2]) cylinder(r1 = edge / sqrt(3), r2 = 0, h = edge * sqrt(2) / sqrt(3), center = true, $fn = 3); + +module octahedron(edge = 1, center = false) translate([0, 0, center ? 0 : edge * sqrt(2) / sqrt(3) / 2]) hull() for(i = [0, 1]) mirror([0, 0, i]) mirror([i, 0, 0]) tetrahedron(edge, true); + +module dodecahedron(edge = 1, center = false) scale(pow(phi, 5 / 2) / pow(5, 1 / 4)) translate([0, 0, center ? 0 : edge / 2]) intersection_for(a = [0:72:360]) rotate([0, a ? atan(2) : 0, a]) cylinder(r = edge, h = edge, center = true, $fn = 10); + +module icosahedron(edge = 1, center = false) scale(pow(phi, 2) / sqrt(3)) translate([0, 0, center ? 0 : edge / 2]) intersection_for(a = [0:120:360], b = [-60, 0, 60]) rotate([0, a ? acos(sqrt(5) / 3) : 0, a]) rotate([0, b ? acos(sqrt(5) / 3) : 0, a ? b : 0]) cylinder(r = edge, h = edge, $fn = 6, center = true); \ No newline at end of file diff --git a/Reuleaux/meissner.scad b/Reuleaux/meissner.scad new file mode 100755 index 0000000..ba84caf --- /dev/null +++ b/Reuleaux/meissner.scad @@ -0,0 +1,23 @@ +// file meissner.scad +// Creates miessner tetrahedrons +// +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +size = 50; // radius of the spheres, and also the constant width +meissner = 1; // Meissner tetrahedron (1 or 2) or 0 for Reuleaux tetrahedron + +$fs = .2; +$fa = 2; + +difference() { + intersection_for(i = [0:3]) translate(size / sqrt(2) / 2 * [(i % 2) ? 1 : -1, (i == 1 || i == 2) ? -1 : 1, (i > 1) ? 1 : -1]) sphere(size); + if(meissner) for(i = [0:2]) rotate(90 * [i ? 1 : 0, (i == 2) ? 1 : 0, i]) rotate([0, (meissner - 1) * 180, 0]) translate(size * 3/4 * sqrt(2) * [0, 0, 1]) rotate([90, 0, -45]) + difference() { + scale([1 / sqrt(2), 1, 1]) rotate(45) cube(size, center = true); + translate(size / sqrt(2) * [0, -1, 0]) rotate_extrude() intersection() { + translate(size * [-cos(30), 0, 0]) circle(size); + translate([0, -size / 2, 0]) square(size); + } + } +} \ No newline at end of file diff --git a/Reuleaux/revolved_reuleaux.scad b/Reuleaux/revolved_reuleaux.scad new file mode 100755 index 0000000..2a99279 --- /dev/null +++ b/Reuleaux/revolved_reuleaux.scad @@ -0,0 +1,20 @@ +// file revolved_reuleaux.scad +// Creates Reuleaux constant-width figures of revolultion +// +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + +width = 50; //constant width +reuleaux = 3; // number of sides, odd numbers 3 thru 13 + +$fs = .2; +$fa = 2; + +if((reuleaux % 2) != 1 || reuleaux < 3) { + echo("Reuleaux polygons must have an odd number of sides."); +} else { + rotate_extrude() intersection() { + intersection_for(a = [0:360 / reuleaux:359]) rotate(a) translate([0, width / (sin(180 / reuleaux) / sin(90 / reuleaux)), 0]) circle(width); + translate([0, -width, 0]) square(width * 2); + } +} \ No newline at end of file diff --git a/Slices+Sections/centerfinders.scad b/Slices+Sections/centerfinders.scad new file mode 100755 index 0000000..a9b20f7 --- /dev/null +++ b/Slices+Sections/centerfinders.scad @@ -0,0 +1,43 @@ +// file centerfinders.scad +// Creates nested "D" shapes to construct parabolas and hyperbolas +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License + + +w = 2; //width of the D lines, mm +h = 2; //thickness of the D lines, mm +hole = 1; //size of notch to mark parabola, mm +enclosed = false; //if true makes a circle around the marking hole + +radii = [10:6:60]; //radii of the "D" shapes + +$fs = .2; +$fa = 2; + +echo(len([for(i = radii) i]) - 1); + +for(i = [0:len([for(i = radii) i]) - 1], radius = [for(i = radii) i][i]) translate([0, -i * (enclosed ? 2 : 1) * (w + hole / 2 + .5), 0]) difference() { + if(h) { + linear_extrude(h, convexity = 2) shape(radius, hole, w, enclosed); + if(enclosed) cylinder(r1 = 0, r2 = h * 2, h = h * 2); + } else shape(radius, hole, w, enclosed); +} + +module shape(radius, hole, w, enclosed = false) difference() { + intersection() { + circle(radius); + translate([-radius, enclosed ? -w / 2 : 0, 0]) square(radius * 2); + } + circle(hole / 2); + offset(-w) difference() { + intersection() { + circle(radius); + translate([-radius, enclosed ? -w / 2 : 0, 0]) square(radius * 2); + } + circle(hole / 2); + } + } + if(enclosed) difference() { + offset(w) circle(hole / 2); + circle(hole / 2); + } \ No newline at end of file diff --git a/ellipse.scad b/Slices+Sections/ellipse.scad similarity index 100% rename from ellipse.scad rename to Slices+Sections/ellipse.scad diff --git a/sphere_cone_volume.scad b/Slices+Sections/sphere_cone_volume.scad similarity index 100% rename from sphere_cone_volume.scad rename to Slices+Sections/sphere_cone_volume.scad diff --git a/Triangles/theodorus.scad b/Triangles/theodorus.scad old mode 100644 new mode 100755 index 79ebe89..4c117bf --- a/Triangles/theodorus.scad +++ b/Triangles/theodorus.scad @@ -2,8 +2,10 @@ // makes a spiral of theodorus // (c) 2020, Rich Cameron, licensed Creative Commons CC-BY4.0 -max = 53; // number of triangles to be made -// the last triangle's sides will be sqrt(max), 1 and sqrt(max + 1) +max = 53; // number of triangles to be made -1 +// if max = 16, 17 triangles will be made +// triangles are right triangles with sides 1 : sqrt(n-1) :sqrt(n) +// 1 <= n <= max +1 xyscale = 10; wall = 1; diff --git a/golden_ratio.scad b/golden_ratio.scad new file mode 100755 index 0000000..08a8f12 --- /dev/null +++ b/golden_ratio.scad @@ -0,0 +1,8 @@ +// file golden_ratio.scad +// Creates successive rectangles whose smallest side is the large side of +// the next rectangle. Rectangle sides in ratio of phi to each other +// (c) 2020 Rich Cameron +// released under a Creative Commons CC-BY 4.0 International License +phi = (1 + sqrt(5)) / 2; + +for(i = [0:10]) rotate(i * 0) mirror((i % 2) * [1, -1, 0]) linear_extrude(12 - i) square(pow(phi, i) * [1, phi]); \ No newline at end of file diff --git a/theodorus.scad b/theodorus.scad deleted file mode 100755 index 4c117bf..0000000 --- a/theodorus.scad +++ /dev/null @@ -1,31 +0,0 @@ -// theodorus.scad -// makes a spiral of theodorus -// (c) 2020, Rich Cameron, licensed Creative Commons CC-BY4.0 - -max = 53; // number of triangles to be made -1 -// if max = 16, 17 triangles will be made -// triangles are right triangles with sides 1 : sqrt(n-1) :sqrt(n) -// 1 <= n <= max +1 - -xyscale = 10; -wall = 1; -base = 1; - -zstep = .2; //should be a multiple of layer height - -$fs = .2; -$fa = 2; - - -function angle(n) = (n > 1) ? asin(1 / sqrt(n)) + angle(n - 1) : 0; - -for(i = [1:max]) rotate(angle(i)) linear_extrude(base + (max + 1 - i) * zstep) difference() { - offset(wall / 2) polygon(xyscale * [[0, 0], [sqrt(i), 0], [sqrt(i), 1]]); - offset(-wall / 2) polygon(xyscale * [[0, 0], [sqrt(i), 0], [sqrt(i), 1]]); -} - -for(i = [1:max]) rotate(angle(i)) linear_extrude(base) difference() { - polygon(xyscale * [[0, 0], [sqrt(i), 0], [sqrt(i), 1]]); -} - -echo(angle(max + 1) % 360); \ No newline at end of file diff --git a/tracery.scad b/tracery.scad deleted file mode 100644 index 2160eec..0000000 --- a/tracery.scad +++ /dev/null @@ -1,24 +0,0 @@ -size = 60; -wall = 1; - - -$fs = .2; -$fa = 2; - - - -module shape() { - translate([0, -size / 2, 0]) square(size, center = true); - intersection_for(i = [1, -1]) translate([i * size / 2, 0, 0]) circle(size); -} - -#linear_extrude(.5) shape(); - -for(i = [0:4]) linear_extrude(.5 + 10 / (i + 1)) for(j = [0:pow(2, i) - 1]) translate([-size * (-.5 + pow(2, -i - 1) + j / pow(2, i)), 0, 0]) difference() { - offset(wall / 2) intersection_for(k = [-1, 1]) translate([k * size * (.5 - 1 / pow(2, i + 1)), 0, 0]) shape(); - offset(-wall / 2) intersection_for(k = [-1, 1]) translate([k * size * (.5 - 1 / pow(2, i + 1)), 0, 0]) shape(); -} - - - -