Some of my works, such as Character tower generator, Text Sphere or Spinning picture ornament, need spirals.
I will talk about how to design these models in the later documents. As for now, I'll talk about how to realize the spirals of these models. One of the solutions is using small and intensive cubes on the path of the spiral. Several of my works took this answer, but I'm not satisfied with it. I'm always looking for a better way to create these lines.
If we have a polyline3D
module and calculate all points on the path of the spiral, the problem can be solved. However, how to create this polyline3D
module?
A line from two points
In Line, I mentioned how to create a line on the x-y plane. We use two points to determine a line at that time. If we want to create a line in 3D space, the first task is also realizing a line from two points.
You might think that we use the built-in polygon
module to realize the polyline
module and there is also a built-in polyhedron
module which can uses vertices to create any regular or irregular shape. Can it create a 3D line? It's possible, however, creating vertices for a 3D line is not easy. Is there an easy way?
Do you remember the hull
operation mentioned in Boolean operations and hull? If you hull
several modules, you create the outer covering for them. I listed an example at that time.
radius = 10;
hull() {
circle(radius);
translate([2 * radius, 0, 0])
circle(radius);
}
The hull
operation covers the two circles.
Think about it. If these two circles have a longer distant, the model will look like a line. We can assign the centers and use the circle's diameter as the line width. It is what I mentioned in Line. There are other ways to implement a line.
If it's not two circles but two spheres, and we hull
them, what will happen? Sound like an easy way to realize a 3D line.
module line3D(p1, p2, thickness, fn = 24) {
$fn = fn;
hull() {
translate(p1) sphere(thickness / 2);
translate(p2) sphere(thickness / 2);
}
}
line3D([1, 1, 1], [10, 10, 10], 1, 3);
Ya, we make it!
Because spheres consist of the line, we leave a fn
parameter which represents the resolution of the line. The hull
operation is slow, so a bigger fn
takes more time to render a line.
polyline3D
Now, we have a line from two points. Similarly, you just take two points and draw a line sequentially until consuming all points.
module line3D(p1, p2, thickness, fn = 24) {
$fn = fn;
hull() {
translate(p1) sphere(thickness / 2);
translate(p2) sphere(thickness / 2);
}
}
module polyline3D(points, thickness, fn) {
module polyline3D_inner(points, index) {
if(index < len(points)) {
line3D(points[index - 1], points[index], thickness, fn);
polyline3D_inner(points, index + 1);
}
}
polyline3D_inner(points, 1);
}
points = [[1, 2, 3], [4, -5, -6], [-1, -3, -5], [0, 0, 0]];
polyline3D(points, 1, 3);
It seems pretty good.
Realizing a spiral
Here's an exercise. Try to implement the spiral in Character tower generator. The following code is one implementation.
module line3D(p1, p2, thickness, fn = 24) {
$fn = fn;
hull() {
translate(p1) sphere(thickness / 2);
translate(p2) sphere(thickness / 2);
}
}
module polyline3D(points, thickness, fn) {
module polyline3D_inner(points, index) {
if(index < len(points)) {
line3D(points[index - 1], points[index], thickness, fn);
polyline3D_inner(points, index + 1);
}
}
polyline3D_inner(points, 1);
}
r = 20;
h = 5;
fa = 15;
circles = 10;
points = [
for(a = [0:fa:360 * circles])
[r * cos(a), r * sin(a), h / (360 / fa) * (a / fa)]
];
polyline3D(points, 1, 3);
It creates the model below.
I'll explain more about the code in Text and cylinder.
One more exercise! Try to realize the spiral in Spinning picture ornament. The following code is one possible realization.
module line3D(p1, p2, thickness, fn = 24) {
$fn = fn;
hull() {
translate(p1) sphere(thickness / 2);
translate(p2) sphere(thickness / 2);
}
}
module polyline3D(points, thickness, fn) {
module polyline3D_inner(points, index) {
if(index < len(points)) {
line3D(points[index - 1], points[index], thickness, fn);
polyline3D_inner(points, index + 1);
}
}
polyline3D_inner(points, 1);
}
r = 50;
points = [
for(a = [0:180])
[r * cos(-90 + a) * cos(a), r * cos(-90 + a) * sin(a), r * sin(-90 + a)]
];
for(i = [0:7]) {
rotate(45 * i) polyline3D(points, 2, 3);
}
The model is as follow.
I'll explain more about the code in Text and sphere.
Last words, isn't it a joy to solve a problem which always didn't have a satisfactory solution :)