The Tesseract – Part 3

I was able to make the tesseract model completely parametric so you can create hypercubes with inner and outer squares of different dimensions.

Snap4

I was also able to clean up the script that generates the model using some new things I learned about OpenSCAD scripting. Here’s the script broken down step by step.

First I set up some initial parameters.

$fn = 100;</p>

<p>withColor = true;</p>

<p>largeWidth = 20;
largeEdge = 3;</p>

<p>smallWidth = 10;
smallEdge = 2;

The $fn value sets the number of facets used to generate an arc. Setting it to a high number renders the cylindrical struts that connect vertexes and cubes much smoother. The withColor variable is a boolean that simply determines whether or not the outer cube, inner cube, and structs are rendered in different colors – blue, red, and green respectively (I found it easier to see changes on each piece of the hypercube when they were different colors but I wasn’t sure having different colors would affect the generated STL file and subsequent G-Code since my printer can only print one color at a time). And finally the width and edge variables are the dimensions for the cubes.

Then I created the outer and inner cube vertexes.

// Create outer cube vertexes
frontUpperLeftLarge = [-largeWidth / 2, -largeWidth / 2, largeWidth / 2];
frontUpperRightLarge = [largeWidth / 2, -largeWidth / 2, largeWidth /2];
frontLowerLeftLarge = [-largeWidth / 2, -largeWidth / 2, -largeWidth / 2];
frontLowerRightLarge = [largeWidth / 2, -largeWidth / 2, -largeWidth / 2];</p>

<p>backUpperLeftLarge = [-largeWidth / 2, largeWidth / 2, largeWidth / 2];
backUpperRightLarge = [largeWidth / 2, largeWidth / 2, largeWidth /2];
backLowerLeftLarge = [-largeWidth / 2, largeWidth / 2, -largeWidth / 2];
backLowerRightLarge = [largeWidth / 2, largeWidth / 2, -largeWidth / 2];</p>

<p>// Create inner cube vertexes
frontUpperLeftSmall = [-smallWidth / 2, -smallWidth / 2, smallWidth / 2];
frontUpperRightSmall = [smallWidth / 2, -smallWidth / 2, smallWidth /2];
frontLowerLeftSmall = [-smallWidth / 2, -smallWidth / 2, -smallWidth / 2];
frontLowerRightSmall = [smallWidth / 2, -smallWidth / 2, -smallWidth / 2];</p>

<p>backUpperLeftSmall = [-smallWidth / 2, smallWidth / 2, smallWidth / 2];
backUpperRightSmall = [smallWidth / 2, smallWidth / 2, smallWidth /2];
backLowerLeftSmall = [-smallWidth / 2, smallWidth / 2, -smallWidth / 2];
backLowerRightSmall = [smallWidth / 2, smallWidth / 2, -smallWidth / 2];

I initially thought to simply define each variable without a specific vertex value. Something like this:

frontUpperLeftLarge = [0, 0, 0];

But since variables are set at compile-time, not run-time, it wasn’t possible to to initialize each vertex variable to the origin at the beginning of the script and then set them to their actual value later in the program.

The remaining part of the “main” program is these three lines.

DrawOuterCube(withColor);
DrawInnerCube(withColor);
DrawStruts(withColor);

I discovered that OpenSCAD has a module command which lets you break your larger program into smaller methods that you can call with parameters. I don’t think it’s possible to return values but because OpenSCAD scripts have a notion of “scope”, it’s possible to declare a variable globally at the top of a script and change its value in a module (not great but workable).

The DrawOuterCube method calls two other methods.

module DrawOuterCube(withColor) {</p>

<p>PositionOuterVertexes(withColor);
ExtrudeOuterFrame(withColor);</p>

<p>}

PositionOuterVertexes creates the vertexes of the outer cube.

module PositionOuterVertexes(withColor) {</p>

<p>if (withColor) {
PositionVertexCube(vertex = frontUpperLeftLarge, length = largeEdge, shade = "blue");
PositionVertexCube(frontUpperRightLarge, largeEdge, "blue");
PositionVertexCube(frontLowerLeftLarge, largeEdge, "blue");
PositionVertexCube(frontLowerRightLarge, largeEdge, "blue");</p>

<p>PositionVertexCube(backUpperLeftLarge, largeEdge, "blue");
PositionVertexCube(backUpperRightLarge, largeEdge, "blue");
PositionVertexCube(backLowerLeftLarge, largeEdge, "blue");
PositionVertexCube(backLowerRightLarge, largeEdge, "blue");
}
else {
PositionVertexCube(vertex = frontUpperLeftLarge, length = largeEdge);
PositionVertexCube(frontUpperRightLarge, largeEdge);
PositionVertexCube(frontLowerLeftLarge, largeEdge);
PositionVertexCube(frontLowerRightLarge, largeEdge);</p>

<p>PositionVertexCube(backUpperLeftLarge, largeEdge);
PositionVertexCube(backUpperRightLarge, largeEdge);
PositionVertexCube(backLowerLeftLarge, largeEdge);
PositionVertexCube(backLowerRightLarge, largeEdge);
}</p>

<p>}

By calling the PositionVertexCube method, passing in the individual vertexes X, Y, and Z coordinates along with the length of the cube and, if withColor is true, the color that the cube should be drawn in. If withColor is false, no colors are drawn and the objects are rendered in what I assume is the standard mustardish yellow (turns out the color command only works when the script is compiled, not when it’s rendered). I also want to mention OpenSCAD’s ability to branch based on conditional expressions using a very simple if/else construct.

PositionVertexCube moves to the specified vertex, sets the color (if applicable), and then draws the cube, centering it on the vertex coordinates.

module PositionVertexCube(vertex, length, shade) {</p>

<p>translate(vertex) color(shade) cube(size = length, center = true);</p>

<p>}

After all the vertex cubes for the outer cube are created the sides of the cube are created by ExtrudeOuterFrame, which creates cylinders from one vertex to another by calling ExtrudeFrameStrut twelve times.

module ExtrudeOuterFrame(withColor) {</p>

<p>if (withColor) {
ExtrudeFrameStrut(frontUpperLeftLarge,[0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backUpperLeftLarge, [0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backUpperLeftLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backUpperRightLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerLeftLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerRightLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(frontLowerRightLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerRightLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
}
else {
ExtrudeFrameStrut(frontUpperLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backUpperLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backUpperLeftLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backUpperRightLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerLeftLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerRightLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(frontLowerRightLarge, [0, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerRightLarge, [0, 0, 0], largeWidth, largeEdge);
}</p>

<p>}

ExtrudeFrameStrut take the following parameters – the starting vertexes’ X, Y, and Z coordinates, the rotation of the circle that the cylindrical side is created from, the length and diameter of the cylindrical side, and its color, if applicable.

module ExtrudeFrameStrut(vertex, rotation, strutLength, strutDiameter, shade) {</p>

<p>translate(vertex)
rotate(a = rotation)
color(shade)
linear_extrude(height = strutLength, center = false)
circle(diameter = strutDiameter);</p>

<p>}

The inner cube is drawn the same way as the outer cube using its own dimensions. DrawInnerCube calls its own custom methods, PositionInnerVertexes and ExtrudeInnerFrame.

module DrawInnerCube() {</p>

<p>PositionInnerVertexes(withColor);
ExtrudeInnerFrame(withColor);</p>

<p>}

Though they have different names, these two methods call the exact same “helper” methods that were used to draw the outer cubes vertexes and sides, PositionVertexCube and ExtrudeFrameStrut, respectively.

module PositionInnerVertexes(withColor) {</p>

<p>if (withColor) {
PositionVertexCube(frontUpperLeftSmall, smallEdge, "red");
PositionVertexCube(frontUpperRightSmall, smallEdge, "red");
PositionVertexCube(frontLowerLeftSmall, smallEdge, "red");
PositionVertexCube(frontLowerRightSmall, smallEdge, "red");
PositionVertexCube(backUpperLeftSmall, smallEdge, "red");
PositionVertexCube(backUpperRightSmall, smallEdge, "red");
PositionVertexCube(backLowerLeftSmall, smallEdge, "red");
PositionVertexCube(backLowerRightSmall, smallEdge, "red");
}
else {
PositionVertexCube(frontUpperLeftSmall, smallEdge);
PositionVertexCube(frontUpperRightSmall, smallEdge);
PositionVertexCube(frontLowerLeftSmall, smallEdge);
PositionVertexCube(frontLowerRightSmall, smallEdge);
PositionVertexCube(backUpperLeftSmall, smallEdge);
PositionVertexCube(backUpperRightSmall, smallEdge);
PositionVertexCube(backLowerLeftSmall, smallEdge);
PositionVertexCube(backLowerRightSmall, smallEdge);
}</p>

<p>}</p>

<p>module ExtrudeInnerFrame(withColor) {</p>

<p>if (withColor) {
ExtrudeFrameStrut(frontUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backUpperLeftSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backUpperRightSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerLeftSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerRightSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(frontLowerRightSmall, [0, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerRightSmall, [0, 0, 0], smallWidth, smallEdge, "red");
}
else {
ExtrudeFrameStrut(frontUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backUpperLeftSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backUpperRightSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerLeftSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerRightSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(frontLowerRightSmall, [0, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerRightSmall, [0, 0, 0], smallWidth, smallEdge);
}</p>

<p>}

Creating the struts between the outer and inner cubes was the most interesting programming part of this refactoring. If you remember from my previous post it was possible to create some “broken” hypercubes by entering certain parameters.

Snap8

This was because the length of each strut distance from an outer vertex to an inner vertex was calculated using the width and edge of the smaller, inner cube. The strut length was directly proportional to the cube width so when the width got smaller the strut length was smaller and it wouldn’t reach all the way to the inner vertex (and when the inner cube got bigger the struct reached and went past the inner vertex).

The solution was to calculate the strut length using the actual distance between the outer and inner vertexes.

Some quick googling turned up this formula for calculating the distance between two points in a three dimensional space:

Point 1 [x1, y1, z1]
Point 2 [x2, y2, z1]

xDistance = x2 - x1
yDistance = y2 - y1
zDistance = z2 - z1

Distance between Point 1 and Point 2 = Square root(xDistance * xDistance + yDistance * yDistance + zDistance * zDistance)

Which translates into this OpenSCAD code.

module ExtrudeStrut(start, end, rotation, strutDiameter, shade) {</p>

<p>strutDistanceX = end[0] - start[0];
strutDistanceY = end[1] - start[1];
strutDistanceZ = end[2] - start[2];</p>

<p>strutLength = sqrt(
strutDistanceX * strutDistanceX +
strutDistanceY * strutDistanceY +
strutDistanceZ * strutDistanceZ);</p>

<p>translate(start)
rotate(a = rotation)
color(shade)
linear_extrude(height = strutLength, center = false)
circle(diameter = strutDiameter);
}

After drawing the the outer and inner cubes the “main” program calls the DrawStruts method.

DrawOuterCube(withColor);
DrawInnerCube(withColor);
DrawStruts(withColor);

Which calls ExtrudeStrut eight times to connect each outer and inner vertex.

module DrawStruts(withColor) {</p>

<p>if (withColor) {
ExtrudeStrut(frontUpperLeftLarge, frontUpperLeftSmall, [0, 125, 45], smallEdge, "green");
ExtrudeStrut(frontUpperRightLarge, frontUpperRightSmall, [0, 125, 135], smallEdge, "green");
ExtrudeStrut(frontLowerRightLarge, frontLowerRightSmall, [0, 55, 135], smallEdge, "green");
ExtrudeStrut(frontLowerLeftLarge, frontLowerLeftSmall, [0, 55, 45], smallEdge, "green");
ExtrudeStrut(backUpperLeftLarge, backUpperLeftSmall, [0, 125, 315], smallEdge, "green");
ExtrudeStrut(backUpperRightLarge, backUpperRightSmall, [0, 125, 225], smallEdge, "green");
ExtrudeStrut(backLowerRightLarge, backLowerRightSmall, [0, 55, 225], smallEdge, "green");
ExtrudeStrut(backLowerLeftLarge, backLowerLeftSmall, [0, 55, 315], smallEdge, "green");
}
else {
ExtrudeStrut(frontUpperLeftLarge, frontUpperLeftSmall, [0, 125, 45], smallEdge);
ExtrudeStrut(frontUpperRightLarge, frontUpperRightSmall, [0, 125, 135], smallEdge);
ExtrudeStrut(frontLowerRightLarge, frontLowerRightSmall, [0, 55, 135], smallEdge);
ExtrudeStrut(frontLowerLeftLarge, frontLowerLeftSmall, [0, 55, 45], smallEdge);
ExtrudeStrut(backUpperLeftLarge, backUpperLeftSmall, [0, 125, 315], smallEdge);
ExtrudeStrut(backUpperRightLarge, backUpperRightSmall, [0, 125, 225], smallEdge);
ExtrudeStrut(backLowerRightLarge, backLowerRightSmall, [0, 55, 225], smallEdge);
ExtrudeStrut(backLowerLeftLarge, backLowerLeftSmall, [0, 55, 315], smallEdge);
}</p>

<p>}

Snap1

Here’s the entire script from start to end.

$fn = 100;
 
withColor = true;
 
largeWidth = 20;
largeEdge = 3;
 
smallWidth = 10;
smallEdge = 2;
 
/* Variables are set at compile-time, not run-time, so we have to set them to their actual
values here instead of initializing them to [0, 0, 0] and setting them later */
 
// Create outer cube vertexes
frontUpperLeftLarge = [-largeWidth / 2, -largeWidth / 2, largeWidth / 2];
frontUpperRightLarge = [largeWidth / 2, -largeWidth / 2, largeWidth /2];
frontLowerLeftLarge = [-largeWidth / 2, -largeWidth / 2, -largeWidth / 2];
frontLowerRightLarge = [largeWidth / 2, -largeWidth / 2, -largeWidth / 2];
 
backUpperLeftLarge = [-largeWidth / 2, largeWidth / 2, largeWidth / 2];
backUpperRightLarge = [largeWidth / 2, largeWidth / 2, largeWidth /2];
backLowerLeftLarge = [-largeWidth / 2, largeWidth / 2, -largeWidth / 2];
backLowerRightLarge = [largeWidth / 2, largeWidth / 2, -largeWidth / 2];
 
// Create inner cube vertexes
frontUpperLeftSmall = [-smallWidth / 2, -smallWidth / 2, smallWidth / 2];
frontUpperRightSmall = [smallWidth / 2, -smallWidth / 2, smallWidth /2];
frontLowerLeftSmall = [-smallWidth / 2, -smallWidth / 2, -smallWidth / 2];
frontLowerRightSmall = [smallWidth / 2, -smallWidth / 2, -smallWidth / 2];
 
backUpperLeftSmall = [-smallWidth / 2, smallWidth / 2, smallWidth / 2];
backUpperRightSmall = [smallWidth / 2, smallWidth / 2, smallWidth /2];
backLowerLeftSmall = [-smallWidth / 2, smallWidth / 2, -smallWidth / 2];
backLowerRightSmall = [smallWidth / 2, smallWidth / 2, -smallWidth / 2];
 
DrawOuterCube(withColor);
DrawInnerCube(withColor);
DrawStruts(withColor);
 
module DrawOuterCube(withColor) {
 
PositionOuterVertexes(withColor);
ExtrudeOuterFrame(withColor);
 
}
 
module PositionOuterVertexes(withColor) {
 
if (withColor) {
PositionVertexCube(vertex = frontUpperLeftLarge, length = largeEdge, shade = "blue");
PositionVertexCube(frontUpperRightLarge, largeEdge, "blue");
PositionVertexCube(frontLowerLeftLarge, largeEdge, "blue");
PositionVertexCube(frontLowerRightLarge, largeEdge, "blue");
 
PositionVertexCube(backUpperLeftLarge, largeEdge, "blue");
PositionVertexCube(backUpperRightLarge, largeEdge, "blue");
PositionVertexCube(backLowerLeftLarge, largeEdge, "blue");
PositionVertexCube(backLowerRightLarge, largeEdge, "blue");
}
else {
PositionVertexCube(vertex = frontUpperLeftLarge, length = largeEdge);
PositionVertexCube(frontUpperRightLarge, largeEdge);
PositionVertexCube(frontLowerLeftLarge, largeEdge);
PositionVertexCube(frontLowerRightLarge, largeEdge);
 
PositionVertexCube(backUpperLeftLarge, largeEdge);
PositionVertexCube(backUpperRightLarge, largeEdge);
PositionVertexCube(backLowerLeftLarge, largeEdge);
PositionVertexCube(backLowerRightLarge, largeEdge);
}
 
}
 
module PositionVertexCube(vertex, length, shade) {
 
translate(vertex) color(shade) cube(size = length, center = true);
 
}
 
module ExtrudeOuterFrame(withColor) {
 
// Vertex, rotation, strutLength, strutDiameter, shade
 
if (withColor) {
ExtrudeFrameStrut(frontUpperLeftLarge,[0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backUpperLeftLarge, [0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backUpperLeftLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backUpperRightLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerLeftLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerRightLarge, [90, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(frontLowerRightLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
ExtrudeFrameStrut(backLowerRightLarge, [0, 0, 0], largeWidth, largeEdge, "blue");
}
else {
ExtrudeFrameStrut(frontUpperLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backUpperLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerLeftLarge, [0, 90, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backUpperLeftLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backUpperRightLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerLeftLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerRightLarge, [90, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(frontLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(frontLowerRightLarge, [0, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerLeftLarge, [0, 0, 0], largeWidth, largeEdge);
ExtrudeFrameStrut(backLowerRightLarge, [0, 0, 0], largeWidth, largeEdge);
}
 
}
 
module ExtrudeFrameStrut(vertex, rotation, strutLength, strutDiameter, shade) {
 
translate(vertex)
rotate(a = rotation)
color(shade)
linear_extrude(height = strutLength, center = false)
circle(diameter = strutDiameter);
 
}
 
module DrawInnerCube() {
 
PositionInnerVertexes(withColor);
ExtrudeInnerFrame(withColor);
 
}
 
module PositionInnerVertexes(withColor) {
 
if (withColor) {
PositionVertexCube(frontUpperLeftSmall, smallEdge, "red");
PositionVertexCube(frontUpperRightSmall, smallEdge, "red");
PositionVertexCube(frontLowerLeftSmall, smallEdge, "red");
PositionVertexCube(frontLowerRightSmall, smallEdge, "red");
PositionVertexCube(backUpperLeftSmall, smallEdge, "red");
PositionVertexCube(backUpperRightSmall, smallEdge, "red");
PositionVertexCube(backLowerLeftSmall, smallEdge, "red");
PositionVertexCube(backLowerRightSmall, smallEdge, "red");
}
else {
PositionVertexCube(frontUpperLeftSmall, smallEdge);
PositionVertexCube(frontUpperRightSmall, smallEdge);
PositionVertexCube(frontLowerLeftSmall, smallEdge);
PositionVertexCube(frontLowerRightSmall, smallEdge);
PositionVertexCube(backUpperLeftSmall, smallEdge);
PositionVertexCube(backUpperRightSmall, smallEdge);
PositionVertexCube(backLowerLeftSmall, smallEdge);
PositionVertexCube(backLowerRightSmall, smallEdge);
}
 
}
 
module ExtrudeInnerFrame(withColor) {
 
// Vertex, rotation, strutLength, strutDiameter, shade
if (withColor) {
ExtrudeFrameStrut(frontUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backUpperLeftSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backUpperRightSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerLeftSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerRightSmall, [90, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(frontLowerRightSmall, [0, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge, "red");
ExtrudeFrameStrut(backLowerRightSmall, [0, 0, 0], smallWidth, smallEdge, "red");
}
else {
ExtrudeFrameStrut(frontUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backUpperLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerLeftSmall, [0, 90, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backUpperLeftSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backUpperRightSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerLeftSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerRightSmall, [90, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(frontLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(frontLowerRightSmall, [0, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerLeftSmall, [0, 0, 0], smallWidth, smallEdge);
ExtrudeFrameStrut(backLowerRightSmall, [0, 0, 0], smallWidth, smallEdge);
}
 
}
 
module ExtrudeStrut(start, end, rotation, strutDiameter, shade) {
 
strutDistanceX = end[0] - start[0];
strutDistanceY = end[1] - start[1];
strutDistanceZ = end[2] - start[2];
 
strutLength = sqrt(
strutDistanceX * strutDistanceX +
strutDistanceY * strutDistanceY +
strutDistanceZ * strutDistanceZ);
 
translate(start)
rotate(a = rotation)
color(shade)
linear_extrude(height = strutLength, center = false)
circle(diameter = strutDiameter);
}
 
module DrawStruts(withColor) {
 
if (withColor) {
ExtrudeStrut(frontUpperLeftLarge, frontUpperLeftSmall, [0, 125, 45], smallEdge, "green");
ExtrudeStrut(frontUpperRightLarge, frontUpperRightSmall, [0, 125, 135], smallEdge, "green");
ExtrudeStrut(frontLowerRightLarge, frontLowerRightSmall, [0, 55, 135], smallEdge, "green");
ExtrudeStrut(frontLowerLeftLarge, frontLowerLeftSmall, [0, 55, 45], smallEdge, "green");
ExtrudeStrut(backUpperLeftLarge, backUpperLeftSmall, [0, 125, 315], smallEdge, "green");
ExtrudeStrut(backUpperRightLarge, backUpperRightSmall, [0, 125, 225], smallEdge, "green");
ExtrudeStrut(backLowerRightLarge, backLowerRightSmall, [0, 55, 225], smallEdge, "green");
ExtrudeStrut(backLowerLeftLarge, backLowerLeftSmall, [0, 55, 315], smallEdge, "green");
}
else {
ExtrudeStrut(frontUpperLeftLarge, frontUpperLeftSmall, [0, 125, 45], smallEdge);
ExtrudeStrut(frontUpperRightLarge, frontUpperRightSmall, [0, 125, 135], smallEdge);
ExtrudeStrut(frontLowerRightLarge, frontLowerRightSmall, [0, 55, 135], smallEdge);
ExtrudeStrut(frontLowerLeftLarge, frontLowerLeftSmall, [0, 55, 45], smallEdge);
ExtrudeStrut(backUpperLeftLarge, backUpperLeftSmall, [0, 125, 315], smallEdge);
ExtrudeStrut(backUpperRightLarge, backUpperRightSmall, [0, 125, 225], smallEdge);
ExtrudeStrut(backLowerRightLarge, backLowerRightSmall, [0, 55, 225], smallEdge);
ExtrudeStrut(backLowerLeftLarge, backLowerLeftSmall, [0, 55, 315], smallEdge);
}
 
}
 
module ExtrudeStrut(start, end, rotation, strutDiameter, shade) {
 
strutDistanceX = end[0] - start[0];
strutDistanceY = end[1] - start[1];
strutDistanceZ = end[2] - start[2];
 
strutLength = sqrt(
strutDistanceX * strutDistanceX +
strutDistanceY * strutDistanceY +
strutDistanceZ * strutDistanceZ);
 
translate(start)
rotate(a = rotation)
color(shade)
linear_extrude(height = strutLength, center = false)
circle(diameter = strutDiameter);
}

There are a couple of things I’d like to work on before I upload it to Thingiverse.

  1. Experiment with making the struts rectangular instead of circular (I think those would print better)
  2. Investigate the possibility of printing the tesseract with support material in place to prevent sagging (there’s a Slic3r setting)
  3. Look into using the OpenSCAD Assign statement to see if it’s possible to change the value of a variable at run-time
This entry was posted in Other and tagged . Bookmark the permalink.