mirror of
https://github.com/JustinSDK/dotSCAD.git
synced 2025-09-02 03:02:34 +02:00
move
This commit is contained in:
102
examples/spiral/L_puzzle.scad
Normal file
102
examples/spiral/L_puzzle.scad
Normal file
@@ -0,0 +1,102 @@
|
||||
use <util/fibseq.scad>;
|
||||
|
||||
model = "ALL"; // [ALL, PIECE1, PIECE2]
|
||||
|
||||
level = 10;
|
||||
thickness = 1;
|
||||
thickness_step = true;
|
||||
p = 1.272;
|
||||
spacing = 0;
|
||||
|
||||
// The idea is from: https://www.facebook.com/permalink.php?story_fbid=381947752968951&id=100034611874448
|
||||
|
||||
// n: 1 or 2
|
||||
module L_piece(n, thickness, p = 1.272, spacing = 0) {
|
||||
sides = [for(i = [0:5]) pow(p, n + i) - spacing];
|
||||
|
||||
linear_extrude(thickness)
|
||||
polygon([
|
||||
[0, 0],
|
||||
[sides[5], 0],
|
||||
[sides[5], sides[2]],
|
||||
[sides[3], sides[2]],
|
||||
[sides[3], sides[4]],
|
||||
[0, sides[4]],
|
||||
]);
|
||||
}
|
||||
|
||||
module L_puzzle(level, thickness, thickness_step = true, p = 1.272) {
|
||||
s4 = pow(p, 4);
|
||||
s5 = pow(p, 5);
|
||||
s6 = pow(p, 6);
|
||||
s7 = pow(p, 7);
|
||||
|
||||
module p1() {
|
||||
color(rands(0, 1, 3))
|
||||
L_piece(2, thickness);
|
||||
}
|
||||
|
||||
module p2() {
|
||||
offset1 = s7;
|
||||
offset2 = s4 + s6;
|
||||
|
||||
translate([0, offset1])
|
||||
rotate(-90) {
|
||||
p1();
|
||||
|
||||
translate([offset1, offset2])
|
||||
mirror([1, 0, 0])
|
||||
rotate(-90)
|
||||
color(rands(0, 1, 3))
|
||||
L_piece(1, thickness_step ? thickness * 2 : thickness);
|
||||
}
|
||||
}
|
||||
|
||||
fibs = fibseq(1, round(level / 2) + 1);
|
||||
|
||||
module _L_puzzle(level) {
|
||||
if(level == 1) {
|
||||
p1();
|
||||
}
|
||||
else if(level == 2) {
|
||||
p2();
|
||||
}
|
||||
else {
|
||||
nth = round(level / 2 - 1);
|
||||
|
||||
is_even = level % 2 == 0;
|
||||
|
||||
offset1 = is_even ?
|
||||
s5 * fibs[nth - 1] + s7 * fibs[nth] :
|
||||
s4 * fibs[nth - 1] + s6 * fibs[nth];
|
||||
|
||||
offset2 = is_even ?
|
||||
s4 * fibs[nth] + s6 * fibs[nth + 1] :
|
||||
s5 * fibs[nth - 1] + s7 * fibs[nth];
|
||||
|
||||
translate([0, offset1])
|
||||
rotate(-90) {
|
||||
scale([1, 1, thickness_step ? 1 + level * 0.05 : 1])
|
||||
_L_puzzle(level - 1);
|
||||
|
||||
translate([offset1, offset2])
|
||||
mirror([1, 0, 0])
|
||||
rotate(-90)
|
||||
scale([1, 1, thickness_step ? 1 + (level - 1) * 0.05 : 1])
|
||||
_L_puzzle(level - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_L_puzzle(level);
|
||||
}
|
||||
|
||||
if(model == "ALL") {
|
||||
L_puzzle(level, thickness, thickness_step, p);
|
||||
}
|
||||
else if(model == "PIECE1") {
|
||||
L_piece(1, thickness, p, spacing);
|
||||
}
|
||||
else if(model == "PIECE2") {
|
||||
L_piece(2, thickness, p, spacing);
|
||||
}
|
43
examples/spiral/bauer_text_sphere.scad
Normal file
43
examples/spiral/bauer_text_sphere.scad
Normal file
@@ -0,0 +1,43 @@
|
||||
use <bauer_spiral.scad>;
|
||||
|
||||
txt = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051";
|
||||
|
||||
radius = 20;
|
||||
font_name = "Liberation Sans:style=Bold";
|
||||
font_size = 2.5;
|
||||
txt_extrude = radius * 0.125;
|
||||
txt_scale = 1.15;
|
||||
ball = true;
|
||||
$fn = 48;
|
||||
|
||||
bauer_text_sphere(radius, font_name, font_size, txt_extrude, txt_scale, ball);
|
||||
|
||||
module bauer_text_sphere(radius, font_name, font_size, txt_extrude, txt_scale, ball) {
|
||||
n = len(txt);
|
||||
pts = bauer_spiral(n, radius);
|
||||
|
||||
if(ball) {
|
||||
render()
|
||||
sphere(radius * 0.9);
|
||||
}
|
||||
/*
|
||||
Based on Bauer's spiral:
|
||||
Bauer R. Distribution of points on a sphere with application to star catalogs. Journal of Guidance, Control, and Dynamics. 2000;23(1):130–137
|
||||
*/
|
||||
for(i = [0:n - 1]) {
|
||||
x = pts[i][0];
|
||||
y = pts[i][1];
|
||||
z = pts[i][2];
|
||||
ya = atan2(z, sqrt(x * x + y * y));
|
||||
za = atan2(y, x);
|
||||
|
||||
render()
|
||||
translate(pts[i])
|
||||
rotate([0, -ya, za])
|
||||
rotate([90, 0, -90])
|
||||
linear_extrude(txt_extrude, scale = txt_scale)
|
||||
mirror([-1, 0, 0])
|
||||
text(txt[i], size = font_size, font = font_name, valign = "center", halign = "center");
|
||||
}
|
||||
}
|
||||
|
206
examples/spiral/dragon.scad
Normal file
206
examples/spiral/dragon.scad
Normal file
@@ -0,0 +1,206 @@
|
||||
use <helix.scad>;
|
||||
use <along_with.scad>;
|
||||
use <shape_trapezium.scad>;
|
||||
use <ellipse_extrude.scad>;
|
||||
use <shear.scad>;
|
||||
|
||||
r1 = 25;
|
||||
r2 = 15;
|
||||
levels = 3;
|
||||
level_dist = 20;
|
||||
|
||||
module scales(ang, leng, radius, height, thickness) {
|
||||
module one_scale() {
|
||||
rotate([0, ang, 0])
|
||||
shear(sx = [0, -1.5])
|
||||
linear_extrude(thickness, center = true)
|
||||
scale([leng, 1])
|
||||
circle(1, $fn = 4);
|
||||
}
|
||||
|
||||
for(a = [0:30:330]) {
|
||||
hull() {
|
||||
rotate(a)
|
||||
translate([radius, 0, height])
|
||||
one_scale();
|
||||
|
||||
rotate(a + 15)
|
||||
translate([radius, 0, height + 1.75])
|
||||
one_scale();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module one_segment() {
|
||||
// scales
|
||||
scale([1,0.85,1]) union() {
|
||||
scales(60, 4, 5, 0, 1.5);
|
||||
scales(75, 2.5, 5, -4, 1.25);
|
||||
scales(100, 1.25, 4.5, -7, 1);
|
||||
scales(110, 1.25, 3, -9, 1);
|
||||
scales(120, 2.5, 2, -9, 1);
|
||||
}
|
||||
|
||||
// dorsal fin
|
||||
translate([0, 3, -3])
|
||||
rotate([-75, 0, 0])
|
||||
shear(sy = [0, 3.5])
|
||||
linear_extrude(2.25, scale = 0.2)
|
||||
square([2, 12], center = true);
|
||||
|
||||
// belly
|
||||
translate([0, -2.5, 1])
|
||||
rotate([-10, 0, 0])
|
||||
scale([1.1, 0.8, 1.25])
|
||||
sphere(5.8, $fn = 8);
|
||||
|
||||
translate([0, 0, -1.65])
|
||||
rotate([-5, 0, 0])
|
||||
scale([1, 0.8, 1.6])
|
||||
sphere(5.5, $fn = 8);
|
||||
|
||||
}
|
||||
|
||||
module head(angy_angz) {
|
||||
module hair() {
|
||||
for(i = [18:35]) {
|
||||
rotate(i * 10)
|
||||
translate([0, -14, 0])
|
||||
rotate([9, 0, 0])
|
||||
linear_extrude(15, scale = 0.05, twist = 30)
|
||||
translate([0, 10, 0])
|
||||
circle(3, $fn = 4);
|
||||
}
|
||||
|
||||
for(i = [0:35]) {
|
||||
rotate(i * 10)
|
||||
translate([0, -12, 0])
|
||||
rotate([5, 0, 0])
|
||||
linear_extrude(20, scale = 0.05, twist = 30)
|
||||
translate([0, 10, 0])
|
||||
circle(2, $fn = 4);
|
||||
}
|
||||
|
||||
for(i = [0:35]) {
|
||||
rotate(i * 10)
|
||||
translate([0, -10, 0])
|
||||
rotate([2, 0, 0])
|
||||
linear_extrude(22, scale = 0.05, twist = -30)
|
||||
translate([0, 10, 0])
|
||||
circle(3, $fn = 4);
|
||||
}
|
||||
}
|
||||
|
||||
module one_horn() {
|
||||
translate([-10, -4, -1])
|
||||
rotate([40, -25, 0])
|
||||
linear_extrude(30, scale = 0.1, twist = -90)
|
||||
translate([7.5, 0, 0])
|
||||
circle(3, $fn = 4);
|
||||
}
|
||||
|
||||
module mouth() {
|
||||
translate([0, 0, -2])
|
||||
rotate([90, 0, -90])
|
||||
ellipse_extrude(8, slices = 2)
|
||||
polygon(
|
||||
shape_trapezium([4, 15],
|
||||
h = 22,
|
||||
corner_r = 0)
|
||||
);
|
||||
|
||||
translate([0, 0, -3])
|
||||
rotate([90, 0, -90])
|
||||
ellipse_extrude(6, slices = 4)
|
||||
polygon(
|
||||
shape_trapezium([6, 20],
|
||||
h = 20,
|
||||
corner_r = 0)
|
||||
);
|
||||
|
||||
mirror([1, 0, 0])
|
||||
translate([0, 0, -3])
|
||||
rotate([85, 0, -90])
|
||||
ellipse_extrude(4, slices = 2)
|
||||
polygon(
|
||||
shape_trapezium([6, 19],
|
||||
h = 20,
|
||||
corner_r = 0)
|
||||
);
|
||||
}
|
||||
|
||||
module one_eye() {
|
||||
translate([-5, 3, -2])
|
||||
rotate([-15, 0, 75])
|
||||
scale([1, 1, 1.5])
|
||||
sphere(1.5, $fn = 5);
|
||||
|
||||
translate([-5.5, 3.5, -2.5])
|
||||
rotate([-15, 0, 75])
|
||||
sphere(0.5, $fn = 8);
|
||||
}
|
||||
|
||||
module one_beard() {
|
||||
translate([-11, -12, -11])
|
||||
rotate(180)
|
||||
linear_extrude(8, scale = 0.2, twist = 90)
|
||||
translate([-10, -10, 0])
|
||||
circle(1.25, $fn = 6);
|
||||
}
|
||||
|
||||
rotate([0, angy_angz[0] + 15, angy_angz[1]])
|
||||
translate([0, 0, -25 / 2])
|
||||
scale(1.15) {
|
||||
scale([0.8, 0.9, 1]) hair();
|
||||
|
||||
translate([0, 0, 2]) {
|
||||
rotate(-90) {
|
||||
one_horn();
|
||||
mirror([-1, 0, 0]) one_horn();
|
||||
}
|
||||
|
||||
mouth();
|
||||
|
||||
one_eye();
|
||||
mirror([0, 1, 0]) one_eye();
|
||||
|
||||
one_beard();
|
||||
mirror([0, 1, 0]) one_beard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module dragon() {
|
||||
path_pts = helix(
|
||||
radius = [r1, r2],
|
||||
levels = levels,
|
||||
level_dist = level_dist,
|
||||
vt_dir = "SPI_DOWN",
|
||||
rt_dir = "CLK",
|
||||
$fn = 36
|
||||
);
|
||||
|
||||
function __angy_angz(p1, p2) =
|
||||
let(
|
||||
dx = p2[0] - p1[0],
|
||||
dy = p2[1] - p1[1],
|
||||
dz = p2[2] - p1[2],
|
||||
ya = atan2(dz, sqrt(dx * dx + dy * dy)),
|
||||
za = atan2(dy, dx)
|
||||
) [ya, za];
|
||||
|
||||
angy_angz = __angy_angz(path_pts[0], path_pts[1]);
|
||||
|
||||
scale(1.1)
|
||||
along_with(path_pts, scale = 0.85, method = "EULER_ANGLE")
|
||||
one_segment();
|
||||
|
||||
translate([19, 0, 65])
|
||||
rotate([95, 0, 0])
|
||||
head(angy_angz);
|
||||
}
|
||||
|
||||
translate([0, 0, 7]) dragon($fn = 12);
|
||||
linear_extrude(65, scale = 0.4) circle(30);
|
||||
translate([0, 0, 65]) linear_extrude(15, scale = 0.01) circle(30 * 0.4);
|
||||
|
65
examples/spiral/lotus_like_flower.scad
Normal file
65
examples/spiral/lotus_like_flower.scad
Normal file
@@ -0,0 +1,65 @@
|
||||
use <crystal_ball.scad>;
|
||||
use <util/fibseq.scad>;
|
||||
|
||||
spirals = 10;
|
||||
petals_per_spiral = 4;
|
||||
|
||||
module petal(radius, thickness) {
|
||||
translate([-radius * 1.5, 0, radius * 2])
|
||||
rotate([90, 120, 90])
|
||||
intersection() {
|
||||
crystal_ball(
|
||||
radius = radius * 2,
|
||||
theta = 360,
|
||||
phi = 90,
|
||||
thickness = thickness
|
||||
);
|
||||
|
||||
linear_extrude(radius * 5) hull() {
|
||||
translate([radius * 1.25, 0, 0]) circle(radius / 3);
|
||||
translate([-1.1 * radius, 0, 0]) circle(radius / 3);
|
||||
circle(radius * 0.85);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module petals(fibseq, i = 0) {
|
||||
if(i < len(fibseq) - 1) {
|
||||
f1 = fibseq[i];
|
||||
f2 = fibseq[i + 1];
|
||||
offset = f1 - f2;
|
||||
translate([0, 0, offset * 1.8])
|
||||
rotate([-5, 40, 10])
|
||||
petal(-offset, -offset / 6);
|
||||
|
||||
translate([0, offset, 0])
|
||||
rotate(90)
|
||||
petals(fibseq, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
module lotus_like_flower(spirals, petals_per_spiral) {
|
||||
step_angle = 360 / spirals;
|
||||
|
||||
fibseq = fibseq(1, petals_per_spiral + 1);
|
||||
|
||||
for(i = [0:spirals - 1]) {
|
||||
rotate(i * step_angle)
|
||||
petals(fibseq);
|
||||
}
|
||||
|
||||
fib_diff = fibseq[petals_per_spiral - 1] - fibseq[petals_per_spiral - 2];
|
||||
|
||||
translate([0, 0, -fib_diff])
|
||||
scale([1, 1, fib_diff])
|
||||
sphere(1);
|
||||
|
||||
translate([0, 0, -fib_diff * 2.25])
|
||||
crystal_ball(
|
||||
radius = fib_diff,
|
||||
theta = 360,
|
||||
phi = 90
|
||||
);
|
||||
}
|
||||
|
||||
lotus_like_flower(spirals, petals_per_spiral + 1, $fn = 24);
|
193
examples/spiral/moving_fish.scad
Normal file
193
examples/spiral/moving_fish.scad
Normal file
@@ -0,0 +1,193 @@
|
||||
use <hollow_out.scad>;
|
||||
use <archimedean_spiral.scad>;
|
||||
|
||||
head_size = 26;
|
||||
segments = 99;
|
||||
thickness = 3;
|
||||
spacing = 0.65;
|
||||
|
||||
module joint_Y(leng, width, height, ring_offset, thickness) {
|
||||
half_h = height / 2;
|
||||
half_thickness = thickness / 2;
|
||||
|
||||
inner_leng = leng - thickness * 2;
|
||||
inner_width = width - thickness * 2;
|
||||
|
||||
// U
|
||||
linear_extrude(height, center = true)
|
||||
difference() {
|
||||
hollow_out(thickness)
|
||||
offset(delta = thickness, chamfer = true)
|
||||
square([inner_leng, inner_width], center = true);
|
||||
|
||||
translate([-half_thickness - inner_leng / 2, 0, 0])
|
||||
square([thickness, inner_width], center = true);
|
||||
}
|
||||
|
||||
// ring
|
||||
r = half_h;
|
||||
offset_x = ring_offset - r / 4;
|
||||
translate([half_h + inner_leng / 2 + half_thickness, 0, 0])
|
||||
rotate([90, 0, 0])
|
||||
linear_extrude(thickness, center = true)
|
||||
difference() {
|
||||
hull() {
|
||||
translate([offset_x, 0])
|
||||
circle(r);
|
||||
translate([-r / 2, 0, 0])
|
||||
square([r, height], center = true);
|
||||
}
|
||||
translate([offset_x, 0])
|
||||
circle(r - thickness);
|
||||
}
|
||||
}
|
||||
|
||||
module moving_fish(head_size, segments, thickness, spacing) {
|
||||
joint_leng = thickness * 2;
|
||||
joint_height = thickness * 2 + spacing * 2;
|
||||
joint_thickness = joint_leng / 3;
|
||||
joint_width = joint_thickness + (spacing + joint_thickness) * 2;
|
||||
ring_offset = joint_thickness / 2;
|
||||
|
||||
module tri_bone(tri_side_leng) {
|
||||
double_spacing = spacing * 2;
|
||||
|
||||
tri_r = tri_side_leng * 0.5773502;
|
||||
tri_r_m1 = tri_r - 1;
|
||||
half_tri_r_m1 = tri_r_m1 / 2;
|
||||
|
||||
slot_leng = joint_thickness + double_spacing;
|
||||
|
||||
translate([0, 0, half_tri_r_m1 + 1]) {
|
||||
translate([slot_leng, 0, joint_height / 2 - half_tri_r_m1 - 1])
|
||||
rotate([90, 0, 0])
|
||||
joint_Y(
|
||||
joint_leng,
|
||||
joint_width,
|
||||
joint_height,
|
||||
joint_thickness/ 2 ,
|
||||
joint_thickness
|
||||
);
|
||||
|
||||
|
||||
offset_x = (-tri_r - 1 + joint_width) / 2;
|
||||
rotate([0, -90, 0]) {
|
||||
// triangle
|
||||
linear_extrude(thickness, center = true)
|
||||
difference() {
|
||||
offset(r = 1)
|
||||
circle(tri_r_m1, $fn = 3);
|
||||
|
||||
// slot
|
||||
translate([offset_x, 0, 0])
|
||||
square(
|
||||
[
|
||||
slot_leng,
|
||||
joint_height + double_spacing
|
||||
],
|
||||
center = true
|
||||
);
|
||||
}
|
||||
|
||||
// stick
|
||||
translate([offset_x, 0, 0])
|
||||
rotate([90, 0, 0])
|
||||
rotate([0, 90, 0])
|
||||
linear_extrude(slot_leng, center = true)
|
||||
circle(joint_height / 2 - joint_thickness - spacing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module head(tri_leng) {
|
||||
tri_leng_d2 = tri_leng / 2;
|
||||
tri_leng_d4 = tri_leng / 4;
|
||||
tri_leng_d5 = tri_leng / 5;
|
||||
|
||||
module eye() {
|
||||
translate([tri_leng_d4, tri_leng_d5, tri_leng_d5])
|
||||
sphere(tri_leng / 10);
|
||||
}
|
||||
|
||||
tri_r_m1 = tri_leng * 0.5773502 - 1;
|
||||
mr = tri_leng_d4 * 0.8660254;
|
||||
|
||||
translate([0, 0, tri_r_m1 / 2 + 1])
|
||||
rotate([0, -90, 0]) {
|
||||
difference() {
|
||||
hull() {
|
||||
linear_extrude(thickness, center = true)
|
||||
offset(r = 1)
|
||||
circle(tri_r_m1, $fn = 3);
|
||||
|
||||
translate([tri_leng / 14 * 3, 0, tri_leng_d2])
|
||||
sphere(mr);
|
||||
|
||||
translate([-tri_leng_d4, 0, tri_leng_d2])
|
||||
sphere(mr);
|
||||
}
|
||||
|
||||
linear_extrude(tri_leng * 1.5, center = true)
|
||||
translate([-tri_leng / 2 - tri_r_m1 / 2 - 1, 0, 0])
|
||||
square([tri_leng, tri_leng], center = true);
|
||||
|
||||
translate([0, 0, tri_leng / 1.25])
|
||||
rotate([90, 0, 0])
|
||||
scale([0.75, 1, 1])
|
||||
linear_extrude(tri_leng, center = true)
|
||||
circle(tri_leng / 1.5, $fn = 3);
|
||||
}
|
||||
|
||||
// eyes
|
||||
eye();
|
||||
mirror([0, 1, 0]) eye();
|
||||
}
|
||||
}
|
||||
|
||||
point_distance = joint_leng + ring_offset + spacing * 3;
|
||||
arm_distance = head_size;
|
||||
init_angle = 540;
|
||||
num_of_points = segments + 2;
|
||||
|
||||
points_angles = archimedean_spiral(
|
||||
arm_distance = arm_distance,
|
||||
init_angle = init_angle,
|
||||
point_distance = point_distance,
|
||||
num_of_points = num_of_points
|
||||
);
|
||||
|
||||
side_leng_step = 0.45 * head_size / segments;
|
||||
|
||||
// head
|
||||
rotate(init_angle)
|
||||
translate(-points_angles[0][0])
|
||||
rotate(90) {
|
||||
tri_bone(head_size);
|
||||
head(head_size);
|
||||
}
|
||||
|
||||
// body
|
||||
leng_pts = len(points_angles);
|
||||
for(i = [1: leng_pts - 2]) {
|
||||
translate(points_angles[i][0])
|
||||
rotate(points_angles[i][1] + 90)
|
||||
tri_bone(head_size - side_leng_step * i);
|
||||
}
|
||||
|
||||
tail_r = head_size / 3;
|
||||
// tail
|
||||
translate(points_angles[leng_pts - 1][0])
|
||||
linear_extrude(joint_height)
|
||||
rotate(90 + points_angles[leng_pts - 2][1])
|
||||
translate([tail_r / 2, 0, 0]) {
|
||||
difference() {
|
||||
circle(tail_r);
|
||||
translate([tail_r * 0.75, 0, 0])
|
||||
circle(tail_r);
|
||||
}
|
||||
hollow_out(thickness / 2.4)
|
||||
circle(3 * thickness / 2.4);
|
||||
}
|
||||
}
|
||||
|
||||
moving_fish(head_size, segments, thickness, spacing, $fn = 24);
|
45
examples/spiral/nautilus_shell.scad
Normal file
45
examples/spiral/nautilus_shell.scad
Normal file
@@ -0,0 +1,45 @@
|
||||
use <ptf/ptf_rotate.scad>;
|
||||
use <hull_polyline2d.scad>;
|
||||
use <bezier_curve.scad>;
|
||||
use <ellipse_extrude.scad>;
|
||||
|
||||
chambered_section_max_angle = 300;
|
||||
steps = 25;
|
||||
thickness = 1;
|
||||
slices = 5;
|
||||
semi_minor_axis = 10;
|
||||
height = 5;
|
||||
|
||||
module nautilus_shell(chambered_section_max_angle, steps, thickness) {
|
||||
function r(a) = pow(2.71828, 0.0053468 * a);
|
||||
|
||||
a_step = chambered_section_max_angle / steps;
|
||||
spiral = [
|
||||
for(a = [a_step:a_step:chambered_section_max_angle + 450])
|
||||
ptf_rotate([r(a), 0], a)
|
||||
];
|
||||
|
||||
render() {
|
||||
hull_polyline2d(spiral, thickness);
|
||||
|
||||
for(a = [a_step:a_step * 2:chambered_section_max_angle]) {
|
||||
a2 = a + 360;
|
||||
a3 = a + 420;
|
||||
p1 = ptf_rotate([r(a), 0], a);
|
||||
p2 = ptf_rotate((p1 + ptf_rotate([r(a2), 0], a2)) * .6, -5);
|
||||
p3 = ptf_rotate([r(a3), 0], a3);
|
||||
|
||||
hull_polyline2d(bezier_curve(0.1,
|
||||
[p1, p2, p3]
|
||||
), thickness);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ellipse_extrude(semi_minor_axis, height = height, slices = slices)
|
||||
nautilus_shell(chambered_section_max_angle, steps, thickness);
|
||||
|
||||
mirror([0, 0, 1])
|
||||
ellipse_extrude(semi_minor_axis, height = height, slices = slices)
|
||||
nautilus_shell(chambered_section_max_angle, steps, thickness);
|
57
examples/spiral/rose.scad
Normal file
57
examples/spiral/rose.scad
Normal file
@@ -0,0 +1,57 @@
|
||||
use <sweep.scad>;
|
||||
use <util/reverse.scad>;
|
||||
|
||||
thickness = 0.05;
|
||||
|
||||
theta_from = PI * 1.75;
|
||||
theta_to = PI * 15;
|
||||
theta_step = 0.05;
|
||||
|
||||
rf_to = 1;
|
||||
rf_step = 0.025;
|
||||
|
||||
color("red") rose();
|
||||
|
||||
module rose() {
|
||||
function phi(theta) =
|
||||
(PI / 2) * exp(-theta / (8 * PI));
|
||||
|
||||
function wave(theta) =
|
||||
1 - 0.5 * pow(1.25 * pow(1- ((3.6 * theta) % (2 * PI)) / PI - (theta > 0 ? 0 : 2), 2) - 0.25, 2);
|
||||
|
||||
function g(rf, theta) =
|
||||
let(angle = phi(theta) * 57.2958)
|
||||
1.95653 * pow(rf, 2) * pow(1.27689 * rf - 1, 2) * sin(angle);
|
||||
|
||||
function r(rf,theta) =
|
||||
let(angle = phi(theta) * 180 / PI)
|
||||
wave(theta) * (rf * sin(angle) + g(rf, theta) * cos(angle));
|
||||
|
||||
sf = 1 + thickness;
|
||||
sections = [
|
||||
for(theta = [theta_from:theta_step:theta_to])
|
||||
let(
|
||||
path = [
|
||||
for(rf = [0:rf_step:rf_to])
|
||||
let(
|
||||
r = r(rf,theta),
|
||||
angle = theta * 57.2958,
|
||||
angle2 = phi(theta)* 57.2958,
|
||||
x = r*sin(angle),
|
||||
y = r*cos(angle),
|
||||
z = wave(theta)*(rf*cos(angle2)-g(rf,theta)*sin(angle2))
|
||||
)
|
||||
[x, y, z]
|
||||
]
|
||||
)
|
||||
concat(
|
||||
[
|
||||
for(p = path)
|
||||
[p[0] * sf, p[1] * sf, p[2]] - [0, 0, thickness]
|
||||
],
|
||||
reverse(path)
|
||||
)
|
||||
];
|
||||
|
||||
sweep(reverse(sections));
|
||||
}
|
35
examples/spiral/simple_seashell.scad
Normal file
35
examples/spiral/simple_seashell.scad
Normal file
@@ -0,0 +1,35 @@
|
||||
use <shape_circle.scad>;
|
||||
use <ptf/ptf_rotate.scad>;
|
||||
use <sweep.scad>;
|
||||
|
||||
r1 = 0.1;
|
||||
r2 = 50;
|
||||
|
||||
a1 = 1;
|
||||
a2 = 450;
|
||||
|
||||
steps = 40;
|
||||
|
||||
$fn = 48;
|
||||
|
||||
module simple_seashell(r1, r2, a1, a2, steps) {
|
||||
rd = (r2 - r1) / steps;
|
||||
ad = (a2 - a1) / steps;
|
||||
|
||||
sections = [
|
||||
for (i = [0:steps])
|
||||
let(
|
||||
r = r1 + rd * i,
|
||||
a = a1 + i * ad
|
||||
)
|
||||
[
|
||||
for(p = concat(shape_circle(r), shape_circle(r * 0.9)))
|
||||
ptf_rotate([p[0], p[1], 0] + [r, 0, 0], [0, a, 0])
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
rotate([90, 0, 0]) sweep(sections, "HOLLOW");
|
||||
}
|
||||
|
||||
simple_seashell(r1, r2, a1, a2, steps);
|
129
examples/spiral/spiral_city.scad
Normal file
129
examples/spiral/spiral_city.scad
Normal file
@@ -0,0 +1,129 @@
|
||||
use <archimedean_spiral.scad>;
|
||||
use <arc.scad>;
|
||||
use <rounded_cube.scad>;
|
||||
use <util/reverse.scad>;
|
||||
|
||||
num_of_buildings = 10;
|
||||
seed_value = 15;
|
||||
|
||||
spiral_city(num_of_buildings, seed_value);
|
||||
|
||||
module spiral_city(num_of_buildings, seed_value) {
|
||||
$fn = 48;
|
||||
arm_distance = 30;
|
||||
|
||||
points_angles = archimedean_spiral(
|
||||
arm_distance = arm_distance,
|
||||
init_angle = 270,
|
||||
point_distance = 30,
|
||||
num_of_points = num_of_buildings + 1
|
||||
);
|
||||
|
||||
pts = reverse([for(pa = points_angles) pa[0]]);
|
||||
leng_pts = len(pts);
|
||||
|
||||
floor_h = 30;
|
||||
roof_h = 7;
|
||||
w_size = floor_h / 6;
|
||||
|
||||
for(i = [0:leng_pts - 2]) {
|
||||
mid_pt = (pts[i] + pts[i + 1]) / 2;
|
||||
arc_r = norm(mid_pt);
|
||||
d_pts = norm(pts[i] - pts[i + 1]);
|
||||
arc_a = angle(arc_r, d_pts) * (i > leng_pts - 4 ? 0.85 : 0.95);
|
||||
|
||||
is_even = i % 2 == 0;
|
||||
half_a = arc_a / 2;
|
||||
|
||||
building_h = floor_h * (floor(i / 5 + 1) + (is_even ? floor_h / 65: 0));
|
||||
ra_arc = atan2(mid_pt[1], mid_pt[0]) - (i > leng_pts - 4 ? arc_a / 4.5 : arc_a / 5);
|
||||
|
||||
translate(mid_pt)
|
||||
rotate(ra_arc)
|
||||
union() {
|
||||
difference() {
|
||||
union() {
|
||||
linear_extrude(building_h)
|
||||
translate([-arc_r, 0])
|
||||
minkowski() {
|
||||
arc(radius = arc_r, angle = [-half_a, half_a], width = arm_distance / (is_even ? 2.5 : 1.7));
|
||||
circle(1, $fn = 12);
|
||||
}
|
||||
}
|
||||
|
||||
// windows
|
||||
cubes(i, arm_distance, building_h, w_size, arc_a, arc_r, seed_value);
|
||||
}
|
||||
|
||||
|
||||
roof(i, arm_distance, building_h, roof_h, arc_a, arc_r);
|
||||
}
|
||||
}
|
||||
|
||||
function angle(arc_r, d_pts) = 180 * d_pts / (arc_r * PI);
|
||||
|
||||
module cubes(i, arm_distance, building_h, w_size, arc_a, arc_r, seed_value) {
|
||||
half_a = arc_a / 2;
|
||||
is_even = i % 2 == 0;
|
||||
arc_w = arm_distance / (is_even ? 2.5 : 1.7);
|
||||
union() {
|
||||
rs = is_undef(seed_value) ?
|
||||
rands(-1, 1, 4) :
|
||||
rands(-1, 1, 4, seed_value = seed_value + i);
|
||||
|
||||
outer_cube_size = [w_size / 2, w_size + rs[0] , w_size + rs[1]];
|
||||
inter_cube_size = [w_size / 2, (w_size + rs[0]) * 0.85, w_size + rs[1]];
|
||||
|
||||
h_step = w_size * 1.5;
|
||||
h_to = building_h - w_size * 1.5;
|
||||
|
||||
a_from = -half_a + (rs[3] > 0 ? arc_a / 8 : arc_a / 6);
|
||||
a_step = rs[3] > 0 ? arc_a / 4 : arc_a / 3;
|
||||
|
||||
outer_cube_p = [arc_r + arc_w / 2, 0, w_size * 0.75];
|
||||
inner_cube_p = [arc_r - arc_w / 2, 0, w_size * 0.75];
|
||||
|
||||
for(h = [0:h_step: h_to]) {
|
||||
translate([-arc_r, 0, h + rs[2] + 1])
|
||||
for(a = [a_from:a_step:half_a]) {
|
||||
r = is_undef(seed_value) ?
|
||||
rands(0, 1, 1)[0] :
|
||||
rands(0, 1, 1, seed_value = seed_value)[0];
|
||||
s = [r > 0.5 ? 2.75 : 1, 1, 1];
|
||||
rotate(a) {
|
||||
translate(outer_cube_p)
|
||||
scale(s)
|
||||
rounded_cube(outer_cube_size, 1, center = true, $fn = 7);
|
||||
|
||||
translate(inner_cube_p)
|
||||
scale(s)
|
||||
rounded_cube(inter_cube_size, 1, center = true, $fn = 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module roof(i, arm_distance, building_h, roof_h, arc_a, arc_r) {
|
||||
is_even = i % 2 == 0;
|
||||
half_a = arc_a / 2;
|
||||
if(is_even) {
|
||||
translate([0, 0, building_h])
|
||||
linear_extrude(roof_h, scale = [0.1, 0.65], slices = 10)
|
||||
translate([-arc_r, 0])
|
||||
minkowski() {
|
||||
arc(radius = arc_r, angle = [-half_a * 1.075, half_a * 1.075], width = arm_distance * 0.5);
|
||||
circle(1, $fn = 12);
|
||||
}
|
||||
}
|
||||
else {
|
||||
translate([0, 0, building_h])
|
||||
linear_extrude(roof_h * 0.8, scale = [0.1, 0.65], slices = 10)
|
||||
translate([-arc_r, 0])
|
||||
minkowski() {
|
||||
arc(radius = arc_r, angle = [-half_a, half_a], width = arm_distance * 0.65);
|
||||
circle(1, $fn = 12);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
examples/spiral/spiral_math_constans.scad
Normal file
56
examples/spiral/spiral_math_constans.scad
Normal file
@@ -0,0 +1,56 @@
|
||||
use <fibonacci_lattice.scad>;
|
||||
use <hull_polyline3d.scad>;
|
||||
use <polyhedron_hull.scad>;
|
||||
|
||||
n = 150;
|
||||
radius = 12;
|
||||
constants = [
|
||||
"π3.141592653589793238462643383279502884197169399375105820974944592307816406286",
|
||||
"τ6.2831853071795864769252867665590057683943387987502116419498891846156328",
|
||||
"φ1.6180339887498948482045868343656381177203091798057628621354486227052604",
|
||||
"e2.7182818284590452353602874713526624977572470936999595749669676277240766303535"
|
||||
];
|
||||
|
||||
font_name = "Arial Black";
|
||||
font_size = 2.5;
|
||||
txt_extrude = radius * 0.5;
|
||||
txt_scale = 1.5;
|
||||
|
||||
spiral_math_constants(n, radius, constants, font_name, font_size, txt_extrude, txt_scale);
|
||||
|
||||
module spiral_math_constants(n, radius, constants, font_name, font_size, txt_extrude, txt_scale) {
|
||||
|
||||
pts = fibonacci_lattice(n, radius);
|
||||
|
||||
polyhedron_hull(pts * 0.9);
|
||||
|
||||
spirals = [for(j = [0:7])
|
||||
[for(i = j; i < len(pts); i = i + 8) pts[i]]
|
||||
];
|
||||
|
||||
module constant_on_spiral(constant, spiral) {
|
||||
for(i = [0:len(spiral) - 1]) {
|
||||
x = spiral[i][0];
|
||||
y = spiral[i][1];
|
||||
z = spiral[i][2];
|
||||
ya = atan2(z, sqrt(x * x + y * y));
|
||||
za = atan2(y, x);
|
||||
|
||||
render()
|
||||
translate(spiral[i])
|
||||
rotate([0, -ya, za])
|
||||
rotate([90, 0, -90])
|
||||
linear_extrude(txt_extrude, scale = txt_scale)
|
||||
mirror([-1, 0, 0])
|
||||
text(constant[i], size = font_size, font = font_name, valign = "center", halign = "center");
|
||||
}
|
||||
}
|
||||
|
||||
for(i = [0:2:6]) {
|
||||
constant_on_spiral(constants[i / 2], spirals[i + 1]);
|
||||
}
|
||||
|
||||
for(i = [0:2:6]) {
|
||||
hull_polyline3d(spirals[i] * 0.9, 1, $fn = 4);
|
||||
}
|
||||
}
|
329
examples/spiral/spring_dog.scad
Normal file
329
examples/spiral/spring_dog.scad
Normal file
@@ -0,0 +1,329 @@
|
||||
use <rounded_cylinder.scad>;
|
||||
use <helix_extrude.scad>;
|
||||
use <shape_circle.scad>;
|
||||
use <arc.scad>;
|
||||
use <ellipse_extrude.scad>;
|
||||
use <shape_ellipse.scad>;
|
||||
use <shape_glued2circles.scad>;
|
||||
use <part/connector_peg.scad>;
|
||||
|
||||
part = "PREVIEW"; // [FRONT, SPRING, BACK, PREVIEW]
|
||||
|
||||
head_radius = 15;
|
||||
spring_levels = 20;
|
||||
line_thickness = 4;
|
||||
line_distance = 1.5;
|
||||
|
||||
peg_radius = 2.5;
|
||||
plate_h = 6;
|
||||
spacing = 0.4;
|
||||
|
||||
module toy_spring(radius, levels, sides, line_thickness, line_distance) {
|
||||
$fn = 4;
|
||||
|
||||
spring = shape_circle(radius = line_thickness / 2);
|
||||
|
||||
helix_extrude(spring,
|
||||
radius = radius,
|
||||
levels = levels,
|
||||
level_dist = line_thickness + line_distance,
|
||||
$fn = sides
|
||||
);
|
||||
|
||||
if(line_distance != 0) {
|
||||
spring_gap = shape_circle(radius = line_distance / 2);
|
||||
|
||||
#translate([0, 0, line_thickness / 2 + line_distance / 2])
|
||||
helix_extrude(spring_gap,
|
||||
radius = radius,
|
||||
levels = levels,
|
||||
level_dist = line_thickness + line_distance,
|
||||
$fn = sides
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module dog_back(head_r, peg_radius) {
|
||||
$fn = 36;
|
||||
|
||||
module foot() {
|
||||
translate([head_r, 0, 0])
|
||||
union() {
|
||||
color("PapayaWhip")
|
||||
ellipse_extrude(head_r / 3)
|
||||
polygon(shape_ellipse([head_r / 3, head_r / 2]));
|
||||
|
||||
color("Maroon")
|
||||
linear_extrude(head_r)
|
||||
circle(head_r / 8);
|
||||
|
||||
color("Goldenrod")
|
||||
translate([head_r / 45, 0, head_r / 2])
|
||||
rotate([0, -15, 0])
|
||||
rounded_cylinder(
|
||||
radius = [head_r / 5, head_r / 3.5],
|
||||
h = head_r * 1.25,
|
||||
round_r = 2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module feet() {
|
||||
foot();
|
||||
mirror([1, 0, 0]) foot();
|
||||
}
|
||||
|
||||
module body_feet() {
|
||||
translate([0, -head_r / 5, -head_r * 1.65])
|
||||
feet();
|
||||
|
||||
|
||||
color("Goldenrod") scale([1, 1.25, 1])
|
||||
difference() {
|
||||
sphere(head_r);
|
||||
translate([-head_r, head_r / 6, -head_r])
|
||||
cube(head_r * 2);
|
||||
}
|
||||
}
|
||||
|
||||
module back() {
|
||||
mirror([0, 1, 0])
|
||||
body_feet();
|
||||
|
||||
rotate([-36.5, 0, 0])
|
||||
color("Goldenrod")
|
||||
linear_extrude(head_r * 2, scale = 0.5)
|
||||
circle(head_r / 6);
|
||||
}
|
||||
|
||||
back();
|
||||
|
||||
color("Goldenrod")
|
||||
translate([0, -head_r * 0.2, 0])
|
||||
rotate([90, 0, 0])
|
||||
connector_peg(peg_radius, spacing = spacing);
|
||||
}
|
||||
|
||||
module spring_dog_spring(head_r, spring_levels, line_thickness, line_distance, peg_radius, plate_h, spacing) {
|
||||
spring_sides = 36;
|
||||
h = spring_levels * line_thickness;
|
||||
|
||||
module plate_back() {
|
||||
difference() {
|
||||
linear_extrude(plate_h + spacing)
|
||||
circle(head_r);
|
||||
connector_peg(peg_radius, spacing = spacing, void = true, $fn = spring_sides);
|
||||
}
|
||||
}
|
||||
|
||||
module plate_front() {
|
||||
linear_extrude(plate_h + spacing)
|
||||
circle(head_r);
|
||||
|
||||
translate([0, 0, plate_h + spacing])
|
||||
connector_peg(peg_radius, spacing = spacing, $fn = spring_sides);
|
||||
}
|
||||
|
||||
color("yellow") {
|
||||
plate_back();
|
||||
|
||||
translate([0, 0, line_thickness / 2]) toy_spring(
|
||||
head_r - line_thickness / 1.5,
|
||||
spring_levels,
|
||||
spring_sides,
|
||||
line_thickness,
|
||||
line_distance
|
||||
);
|
||||
|
||||
translate([0, 0, h + line_distance * spring_levels])
|
||||
plate_front();
|
||||
}
|
||||
}
|
||||
|
||||
module dog_front(head_r, peg_radius, spacing) {
|
||||
$fn = 36;
|
||||
|
||||
module head() {
|
||||
module head_nose() {
|
||||
color("Goldenrod")
|
||||
rotate([-15, 0, 0])
|
||||
scale([1, 0.9, 0.9])
|
||||
sphere(head_r);
|
||||
|
||||
// nose
|
||||
color("PapayaWhip")
|
||||
translate([0, -head_r * 0.45, -head_r / 5])
|
||||
rotate([85, 0, 0])
|
||||
scale([1.25, 0.8, 1])
|
||||
rounded_cylinder(
|
||||
radius = [head_r / 2, head_r / 6],
|
||||
h = head_r * 1.25,
|
||||
round_r = 4
|
||||
);
|
||||
|
||||
color("black")
|
||||
translate([0, -head_r * 1.6, 0])
|
||||
rotate([15, 0, 0])
|
||||
scale([1.25, 1, 1])
|
||||
sphere(head_r / 7);
|
||||
}
|
||||
|
||||
module eye() {
|
||||
translate([head_r / 2, -head_r / 1.75, head_r / 3])
|
||||
rotate([-20, 5, 30])
|
||||
scale([1.2, 0.5, 1]) {
|
||||
color("Goldenrod") sphere(head_r / 3);
|
||||
|
||||
color("white")
|
||||
translate([0, 0, -head_r / 15])
|
||||
rotate([-25, -10, 0])
|
||||
scale([1.1, 1.25, 1.2])
|
||||
sphere(head_r / 3.5);
|
||||
|
||||
color("black")
|
||||
translate([-head_r / 15, -head_r / 4, -head_r / 12])
|
||||
sphere(head_r / 7);
|
||||
}
|
||||
}
|
||||
|
||||
module eyes() {
|
||||
eye();
|
||||
mirror([1, 0, 0]) eye();
|
||||
}
|
||||
|
||||
module eyebrow() {
|
||||
color("black")
|
||||
translate([head_r / 2.5, -head_r / 2.5, head_r / 3])
|
||||
rotate([60, 15, 30])
|
||||
linear_extrude(head_r / 2, center = true) scale([1.5, 1, 1])
|
||||
arc(radius = head_r / 3, angle = 120, width = head_r / 20);
|
||||
|
||||
}
|
||||
|
||||
module eyebrows() {
|
||||
eyebrow();
|
||||
mirror([1, 0, 0]) eyebrow();
|
||||
}
|
||||
|
||||
shape_pts = shape_glued2circles(head_r / 2, head_r * 2.5, tangent_angle = 35);
|
||||
|
||||
module ear() {
|
||||
color("Maroon")
|
||||
rotate([-15, 0, -10])
|
||||
translate([-head_r / 2.75, head_r / 15, -head_r / 2.75])
|
||||
rotate([0, -60, 0])
|
||||
scale([1.25, 1, 1]) intersection() {
|
||||
translate([head_r, 0, 0])
|
||||
linear_extrude(head_r)
|
||||
polygon(shape_pts);
|
||||
|
||||
difference() {
|
||||
sphere(head_r);
|
||||
sphere(head_r - head_r / 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ears() {
|
||||
ear();
|
||||
mirror([1, 0, 0]) ear();
|
||||
}
|
||||
|
||||
head_nose();
|
||||
eyes();
|
||||
eyebrows();
|
||||
ears();
|
||||
}
|
||||
|
||||
|
||||
module foot() {
|
||||
translate([head_r, -head_r / 11, 0]) {
|
||||
color("PapayaWhip")
|
||||
ellipse_extrude(head_r / 3)
|
||||
polygon(
|
||||
shape_ellipse([head_r / 3, head_r / 2])
|
||||
);
|
||||
|
||||
color("Maroon")
|
||||
linear_extrude(head_r)
|
||||
circle(head_r / 8);
|
||||
|
||||
color("Goldenrod")
|
||||
translate([head_r / 45, 0, head_r / 2])
|
||||
rotate([0, -15, 0])
|
||||
rounded_cylinder(
|
||||
radius = [head_r / 5, head_r / 3.5],
|
||||
h = head_r * 1.25,
|
||||
round_r = 2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module feet() {
|
||||
foot();
|
||||
mirror([1, 0, 0]) foot();
|
||||
}
|
||||
|
||||
module body_feet() {
|
||||
translate([0, -head_r / 5, -head_r * 1.65])
|
||||
feet();
|
||||
|
||||
color("Goldenrod")
|
||||
scale([1, 1.25, 1])
|
||||
difference() {
|
||||
sphere(head_r);
|
||||
|
||||
translate([-head_r, head_r / 6, -head_r])
|
||||
cube(head_r * 2);
|
||||
}
|
||||
}
|
||||
|
||||
module front() {
|
||||
body_feet();
|
||||
|
||||
// neck
|
||||
rotate([60, 0, 0]) {
|
||||
color("Goldenrod")
|
||||
linear_extrude(head_r * 2)
|
||||
circle(head_r / 4);
|
||||
|
||||
color("green")
|
||||
translate([0, 0, head_r * 1.1])
|
||||
rotate([-10, 0, 0])
|
||||
rotate_extrude()
|
||||
translate([head_r / 4, 0, 0])
|
||||
circle(head_r / 10);
|
||||
}
|
||||
}
|
||||
|
||||
translate([0, -head_r * 1.75 , head_r * 1.3])
|
||||
head();
|
||||
|
||||
difference() {
|
||||
front();
|
||||
translate([0, head_r * 0.209, 0]) rotate([90, 0, 0])
|
||||
connector_peg(peg_radius, spacing = spacing, void = true, $fn = 36);
|
||||
}
|
||||
}
|
||||
|
||||
if(part == "FRONT") {
|
||||
dog_front(head_radius, peg_radius, spacing);
|
||||
} else if(part == "SPRING") {
|
||||
spring_dog_spring(head_radius, spring_levels, line_thickness, line_distance, peg_radius, plate_h, spacing);
|
||||
} else if(part == "BACK") {
|
||||
dog_back(head_radius, peg_radius);
|
||||
}
|
||||
else {
|
||||
dog_front(head_radius, peg_radius, spacing);
|
||||
translate([0, spring_levels * (line_thickness + line_distance) + plate_h + spacing, 0]) {
|
||||
rotate([90, 0, 0])
|
||||
spring_dog_spring(head_radius, spring_levels, line_thickness, line_distance, peg_radius, plate_h, spacing);
|
||||
|
||||
translate([0, 3.25, 0]) dog_back(head_radius, peg_radius);
|
||||
}
|
||||
}
|
||||
|
||||
|
97
examples/spiral/string_tetrahedron.scad
Normal file
97
examples/spiral/string_tetrahedron.scad
Normal file
@@ -0,0 +1,97 @@
|
||||
use <hull_polyline3d.scad>;
|
||||
|
||||
leng = 50;
|
||||
diameter = 5;
|
||||
segs_per_side = 20;
|
||||
line_fn = 5;
|
||||
model = "Tetrahedron"; // [Tetrahedron, Base, Both]
|
||||
|
||||
|
||||
module string_tetrahedron(leng, diameter, segs_per_side, line_fn) {
|
||||
module lines_between(side1, side2, diameter, segs) {
|
||||
function pts(p1, p2, segs) =
|
||||
let(
|
||||
p = p2 - p1,
|
||||
dx = p[0] / segs,
|
||||
dy = p[1] / segs,
|
||||
dz = p[2] / segs
|
||||
) [for(i = [0:segs]) p1 + [dx, dy, dz] * i];
|
||||
|
||||
pts1 = pts(side1[0], side1[1], segs);
|
||||
pts2 = pts(side2[0], side2[1], segs);
|
||||
|
||||
for(i = [0:len(pts1) - 1]) {
|
||||
hull_polyline3d(points = [pts1[i], pts2[i]], diameter = diameter);
|
||||
}
|
||||
}
|
||||
|
||||
function height(leng) =
|
||||
leng * sqrt(1 - 4 / 9 * pow(sin(60), 2));
|
||||
|
||||
function vts(leng) =
|
||||
let(
|
||||
half_leng = leng / 2,
|
||||
center_y = half_leng * tan(30),
|
||||
vt1 = [half_leng, - center_y, 0],
|
||||
vt2 = [0, leng * sin(60) - center_y, 0],
|
||||
vt3 = [-half_leng, -center_y, 0],
|
||||
vt4 = [0, 0, height(leng)]
|
||||
) [vt1, vt2, vt3, vt4];
|
||||
|
||||
$fn = line_fn;
|
||||
|
||||
half_leng = leng / 2;
|
||||
|
||||
vts = vts(leng);
|
||||
|
||||
vt1 = vts[0];
|
||||
vt2 = vts[1];
|
||||
vt3 = vts[2];
|
||||
vt4 = vts[3];
|
||||
|
||||
lines_between([vt1, vt2], [vt3, vt4], diameter, segs_per_side);
|
||||
lines_between([vt2, vt3], [vt1, vt4], diameter, segs_per_side);
|
||||
lines_between([vt3, vt1], [vt2, vt4], diameter, segs_per_side);
|
||||
}
|
||||
|
||||
module base(leng, diameter, line_fn) {
|
||||
vts = vts(leng);
|
||||
r = leng / 4;
|
||||
half_th = diameter / 2;
|
||||
|
||||
difference() {
|
||||
sphere(r, $fn = 48);
|
||||
|
||||
translate([0, 0, -r])
|
||||
linear_extrude(r)
|
||||
square(r * 2, center = true);
|
||||
|
||||
translate([0, 0, height(leng) + half_th])
|
||||
rotate([0, 180, 0])
|
||||
translate([0, -leng / 2 * tan(30), 0])
|
||||
hull() {
|
||||
translate(vts[0])
|
||||
sphere(half_th, $fn = line_fn);
|
||||
translate(vts[1])
|
||||
sphere(half_th, $fn = line_fn);
|
||||
translate(vts[2])
|
||||
sphere(half_th, $fn = line_fn);
|
||||
translate(vts[3])
|
||||
sphere(half_th, $fn = line_fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(model == "Tetrahedron") {
|
||||
string_tetrahedron(leng, diameter, segs_per_side, line_fn);
|
||||
} else if(model == "Base") {
|
||||
base(leng, diameter, line_fn);
|
||||
} else {
|
||||
translate([0, 0, height(leng) + half_th])
|
||||
rotate([0, 180, 0])
|
||||
translate([0, -leng / 2 * tan(30), 0])
|
||||
string_tetrahedron(leng, diameter, segs_per_side, line_fn);
|
||||
|
||||
base(leng, diameter, line_fn);
|
||||
}
|
||||
|
108
examples/spiral/string_tetrahedrons.scad
Normal file
108
examples/spiral/string_tetrahedrons.scad
Normal file
@@ -0,0 +1,108 @@
|
||||
use <hull_polyline3d.scad>;
|
||||
|
||||
level = 1;
|
||||
leng = 50;
|
||||
diameter = 5;
|
||||
segs_per_side = 10;
|
||||
center = false;
|
||||
|
||||
module string_tetrahedron(leng, diameter, segs_per_side, line_fn) {
|
||||
module lines_between(side1, side2, diameter, segs) {
|
||||
function pts(p1, p2, segs) =
|
||||
let(
|
||||
p = p2 - p1,
|
||||
dx = p[0] / segs,
|
||||
dy = p[1] / segs,
|
||||
dz = p[2] / segs
|
||||
) [for(i = [0:segs]) p1 + [dx, dy, dz] * i];
|
||||
|
||||
pts1 = pts(side1[0], side1[1], segs);
|
||||
pts2 = pts(side2[0], side2[1], segs);
|
||||
|
||||
leng = len(pts1);
|
||||
hull_polyline3d(points = [pts1[0], pts2[0]], diameter = diameter);
|
||||
for(i = [1:leng - 2]) {
|
||||
hull_polyline3d(points = [pts1[i], pts2[i]], diameter = diameter);
|
||||
}
|
||||
end = leng - 1;
|
||||
hull_polyline3d(points = [pts1[end], pts2[end]], diameter = diameter);
|
||||
}
|
||||
|
||||
function height(leng) =
|
||||
leng * sqrt(1 - 4 / 9 * pow(sin(60), 2));
|
||||
|
||||
function vts(leng) =
|
||||
let(
|
||||
half_leng = leng / 2,
|
||||
center_y = half_leng * tan(30),
|
||||
vt1 = [half_leng, - center_y, 0],
|
||||
vt2 = [0, leng * sin(60) - center_y, 0],
|
||||
vt3 = [-half_leng, -center_y, 0],
|
||||
vt4 = [0, 0, height(leng)]
|
||||
) [vt1, vt2, vt3, vt4];
|
||||
|
||||
$fn = line_fn;
|
||||
|
||||
half_leng = leng / 2;
|
||||
|
||||
vts = vts(leng);
|
||||
|
||||
vt1 = vts[0];
|
||||
vt2 = vts[1];
|
||||
vt3 = vts[2];
|
||||
vt4 = vts[3];
|
||||
|
||||
lines_between([vt1, vt2], [vt3, vt4], diameter, segs_per_side);
|
||||
lines_between([vt2, vt3], [vt1, vt4], diameter, segs_per_side);
|
||||
lines_between([vt3, vt1], [vt2, vt4], diameter, segs_per_side);
|
||||
}
|
||||
|
||||
module string_tetrahedrons(level, leng, diameter, segs_per_side, center) {
|
||||
|
||||
function height(leng) =
|
||||
leng * sqrt(1 - 4 / 9 * pow(sin(60), 2));
|
||||
|
||||
if(level == 0) {
|
||||
string_tetrahedron(leng * 2, diameter, segs_per_side, 6);
|
||||
}
|
||||
else {
|
||||
|
||||
half_leng = leng / 2;
|
||||
center_y = half_leng * tan(30);
|
||||
|
||||
translate([0, center_y * 2])
|
||||
string_tetrahedrons(level - 1, half_leng, diameter, segs_per_side, center);
|
||||
|
||||
translate([half_leng, -center_y])
|
||||
string_tetrahedrons(level - 1, half_leng, diameter, segs_per_side, center);
|
||||
|
||||
translate([-half_leng, -center_y])
|
||||
string_tetrahedrons(level - 1, half_leng, diameter, segs_per_side, center);
|
||||
|
||||
translate([0, 0, height(leng)])
|
||||
string_tetrahedrons(level - 1, half_leng, diameter, segs_per_side, center);
|
||||
|
||||
|
||||
if(center) {
|
||||
rotate(60)
|
||||
string_tetrahedrons(level - 1, half_leng, diameter, segs_per_side, center);
|
||||
|
||||
a = atan(height(leng * 2) / (2 * center_y));
|
||||
|
||||
for(i = [0:120:240]) {
|
||||
rotate(i)
|
||||
|
||||
translate([0, -center_y * 2])
|
||||
rotate([a, 0, 0])
|
||||
translate([0, center_y * 2])
|
||||
rotate([180, 0, 0])
|
||||
scale(0.9427)
|
||||
string_tetrahedrons(level - 1, half_leng, diameter, segs_per_side, center);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string_tetrahedrons(level, leng, diameter, segs_per_side, center);
|
||||
|
||||
|
57
examples/spiral/text_sphere.scad
Normal file
57
examples/spiral/text_sphere.scad
Normal file
@@ -0,0 +1,57 @@
|
||||
use <sphere_spiral.scad>;
|
||||
use <sphere_spiral_extrude.scad>;
|
||||
|
||||
tx = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989";
|
||||
font_name = "Liberation Sans:style=Bold Italic";
|
||||
thickness = 2;
|
||||
|
||||
module text_sphere(tx, font_name, thickness) {
|
||||
$fn = 24;
|
||||
radius = 40;
|
||||
za_step = 360 / $fn;
|
||||
z_circles = 48;
|
||||
begin_angle = 720;
|
||||
end_angle = 630;
|
||||
|
||||
half_thickness = thickness / 2;
|
||||
|
||||
points_angles = sphere_spiral(
|
||||
radius = radius,
|
||||
za_step = za_step,
|
||||
z_circles = z_circles,
|
||||
begin_angle = begin_angle,
|
||||
end_angle = end_angle
|
||||
);
|
||||
|
||||
rotate(-180 / $fn)
|
||||
sphere_spiral_extrude(
|
||||
[
|
||||
[thickness, half_thickness],
|
||||
[-half_thickness, half_thickness],
|
||||
[-half_thickness, -half_thickness],
|
||||
[thickness, -half_thickness]
|
||||
],
|
||||
radius = radius,
|
||||
za_step = za_step,
|
||||
z_circles = z_circles,
|
||||
begin_angle = begin_angle,
|
||||
end_angle = end_angle
|
||||
);
|
||||
|
||||
|
||||
for(i = [0:len(points_angles) - 1]) {
|
||||
pa = points_angles[i];
|
||||
translate(pa[0])
|
||||
rotate(pa[1] + [0, 8, 0])
|
||||
rotate([90, 0, 90])
|
||||
linear_extrude(half_thickness)
|
||||
translate([0, -10, 0])
|
||||
text(tx[i], font = font_name, halign = "center");
|
||||
}
|
||||
|
||||
translate([0, 0, -radius])
|
||||
linear_extrude(thickness * 2.5)
|
||||
circle(radius / 2);
|
||||
}
|
||||
|
||||
text_sphere(tx, font_name, thickness);
|
59
examples/spiral/text_tower.scad
Normal file
59
examples/spiral/text_tower.scad
Normal file
@@ -0,0 +1,59 @@
|
||||
use <helix.scad>;
|
||||
use <helix_extrude.scad>;
|
||||
|
||||
tx = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989";
|
||||
font_name = "Liberation Sans:style=Bold Italic";
|
||||
radius = 60;
|
||||
height = 150;
|
||||
thickness = 2;
|
||||
|
||||
module text_tower(tx, font_name, radius, height, thickness) {
|
||||
|
||||
font_size = 2 * PI * radius / $fn;
|
||||
angle_step = 360 / $fn;
|
||||
half_angle_step = angle_step / 2;
|
||||
half_thickness = thickness / 2;
|
||||
|
||||
module body() {
|
||||
points = helix(
|
||||
radius = radius,
|
||||
levels = height / font_size,
|
||||
level_dist = font_size,
|
||||
vt_dir = "SPI_DOWN"
|
||||
);
|
||||
for(i = [0:len(points) - 1]) {
|
||||
translate(points[i])
|
||||
rotate([90, 0, 90 + angle_step * i])
|
||||
linear_extrude(thickness, center = true)
|
||||
text(
|
||||
tx[i],
|
||||
font = font_name,
|
||||
size = font_size,
|
||||
halign = "center"
|
||||
);
|
||||
}
|
||||
|
||||
rotate(-half_angle_step)
|
||||
helix_extrude(
|
||||
[
|
||||
[thickness, half_thickness],
|
||||
[-thickness, half_thickness],
|
||||
[-thickness, -half_thickness],
|
||||
[thickness, -half_thickness]
|
||||
],
|
||||
radius = radius,
|
||||
levels = height / font_size + 1,
|
||||
level_dist = font_size,
|
||||
vt_dir = "SPI_DOWN"
|
||||
);
|
||||
}
|
||||
|
||||
translate([0, 0, -font_size - half_thickness])
|
||||
body();
|
||||
|
||||
rotate(-half_angle_step)
|
||||
translate([0, 0, -font_size - thickness])
|
||||
cylinder(h = font_size, r = radius + thickness);
|
||||
}
|
||||
|
||||
text_tower(tx, font_name, radius, height, thickness, $fn = 24);
|
60
examples/spiral/vx_spiral_text.scad
Normal file
60
examples/spiral/vx_spiral_text.scad
Normal file
@@ -0,0 +1,60 @@
|
||||
use <hull_polyline2d.scad>;
|
||||
use <voxel/vx_ascii.scad>;
|
||||
|
||||
tx = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172";
|
||||
|
||||
pts = [for(p = px_spiral(1, floor(sqrt(len(tx))) + 1)) p * 8];
|
||||
linear_extrude(2)
|
||||
for(i = [0:len(tx) - 1]) {
|
||||
translate(pts[i])
|
||||
difference() {
|
||||
square(7, center = true);
|
||||
render() for(p = vx_ascii(tx[i], center = true)) {
|
||||
translate(p) square(.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
linear_extrude(1) {
|
||||
for(i = [0:len(tx) - 1]) {
|
||||
translate(pts[i])
|
||||
square(7, center = true);
|
||||
}
|
||||
hull_polyline2d([for(i = [0:len(tx) - 1]) pts[i]], width = 2);
|
||||
}
|
||||
|
||||
function _px_spiral_forward(pt, leng, dir, clockwise) =
|
||||
let(
|
||||
DIRS = clockwise ? [
|
||||
[1, 0],
|
||||
[0, -1],
|
||||
[-1, 0],
|
||||
[0, 1]
|
||||
]
|
||||
: [
|
||||
[1, 0],
|
||||
[0, 1],
|
||||
[-1, 0],
|
||||
[0, -1]
|
||||
]
|
||||
)
|
||||
pt + DIRS[dir] * leng;
|
||||
|
||||
function _px_spiral_go_turn(from, leng, max_leng, clockwise, dir) =
|
||||
let(
|
||||
range = [1:leng],
|
||||
pts = [for(i = range) _px_spiral_forward(from, i, dir % 4, clockwise)],
|
||||
ps = pts[len(pts) - 1],
|
||||
pts2 = [for(i = range) _px_spiral_forward(ps, i, (dir + 1) % 4, clockwise)],
|
||||
pd = pts2[len(pts2) - 1]
|
||||
)
|
||||
concat(pts, pts2, _px_spiral(pd, leng + 1, max_leng, clockwise, dir + 2));
|
||||
|
||||
function _px_spiral(from, leng, max_leng, clockwise, dir) =
|
||||
leng > max_leng ? [] : _px_spiral_go_turn(from, leng, max_leng, clockwise, dir);
|
||||
|
||||
function px_spiral(init_leng, max_leng, clockwise = false) =
|
||||
let(
|
||||
org = [0, 0]
|
||||
)
|
||||
concat([org], _px_spiral(org, init_leng, max_leng, clockwise, 0));
|
40
examples/spiral/xmas_tree.scad
Normal file
40
examples/spiral/xmas_tree.scad
Normal file
@@ -0,0 +1,40 @@
|
||||
use <line2d.scad>;
|
||||
use <starburst.scad>;
|
||||
use <util/rand.scad>;
|
||||
|
||||
base = 100;
|
||||
segments = 150;
|
||||
|
||||
xmas_tree(base, segments);
|
||||
|
||||
module xmas_tree(base, segments) {
|
||||
half_base = base / 2;
|
||||
height = PI * half_base;
|
||||
slope = height / half_base;
|
||||
dx = half_base / segments;
|
||||
dh = height / segments;
|
||||
a = dh / (2 * PI * half_base) * 360 * 3;
|
||||
base_h = dh * 2;
|
||||
seg_w = base_h * 3;
|
||||
|
||||
for(i = [0:segments]) {
|
||||
x = i * dx - half_base;
|
||||
|
||||
color(c = [0, rand(), 0])
|
||||
rotate(a * i)
|
||||
translate([0, 0, dx * i * slope + base_h])
|
||||
linear_extrude(dh)
|
||||
line2d([x, 0], [-x, 0], width = seg_w);
|
||||
}
|
||||
|
||||
color("Sienna")
|
||||
linear_extrude(base_h)
|
||||
circle(half_base + base_h + seg_w, $fn = 48);
|
||||
|
||||
color("yellow")
|
||||
translate([0, 0, height + dh * 6])
|
||||
rotate([90, 0, 540]) {
|
||||
starburst(seg_w * 2.75, seg_w * 1.5, 8, seg_w);
|
||||
mirror([0, 0, 1]) starburst(seg_w * 2.75, seg_w * 1.5, 8, seg_w);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user