1
0
mirror of https://github.com/JustinSDK/dotSCAD.git synced 2025-09-02 03:02:34 +02:00
This commit is contained in:
Justin Lin
2021-07-01 15:02:03 +08:00
parent 7e41e738e2
commit 131c1aec83
17 changed files with 0 additions and 0 deletions

View 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);
}

View 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):130137
*/
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
View 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);

View 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);

View 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);

View 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
View 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));
}

View 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);

View 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);
}
}
}
}

View 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);
}
}

View 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);
}
}

View 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);
}

View 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);

View 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);

View 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);

View 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));

View 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);
}
}