improvements
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
*.stl
|
*.stl
|
||||||
|
/build/
|
||||||
|
|||||||
39
README.md
@@ -8,18 +8,21 @@ but these are the original tracks you can replicate
|
|||||||
|
|
||||||
As an overview, or why it's worth a try: They print rapidly on modern printers, and cost barely anything.
|
As an overview, or why it's worth a try: They print rapidly on modern printers, and cost barely anything.
|
||||||
|
|
||||||
| Name | Material Cost | Print Time |
|
| Preset | Cost | Time | Image |
|
||||||
| --------------------- | ------------- | ---------- |
|
| ----------------------------- | ----- | ---- | -------------------------------------------------------------------------------- |
|
||||||
| C15 | ~10ct | 45m |
|
| C15 | ~10ct | 45m |  |
|
||||||
| C7 | ~5ct | 15m |
|
| C7 | ~5ct | 15m |  |
|
||||||
| S25 | ~12ct | 1h |
|
| S25 | ~12ct | 1h |  |
|
||||||
| S10 | ~5ct | 15m |
|
| S10 | ~5ct | 15m |  |
|
||||||
| S5 | ~5ct | 15m |
|
| S5 | ~5ct | 15m |  |
|
||||||
| Classic R28 90° Curve | ~25ct | 2h |
|
| S4 | ~5ct | 15m |  |
|
||||||
| Classic R28 45° Curve | ~12ct | 1h |
|
| Classic Full Curve (R28 90°) | ~25ct | 2h |  |
|
||||||
| Classic L32 Straight | ~20ct | 1.5h |
|
| Classic Half Curve (R28 45°) | ~12ct | 1h |  |
|
||||||
| Classic L16 Straight | ~10ct | 45m |
|
| Classic Full Straight (L32) | ~20ct | 1.5h |  |
|
||||||
| Classic L8 Straight | ~5ct | 15m |
|
| Classic Half Straight (L16) | ~10ct | 45m |  |
|
||||||
|
| Classic Quarter Straight (L8) | ~5ct | 15m |  |
|
||||||
|
|
||||||
|
You can also generate your own custom rails with any length, radius or angle.
|
||||||
|
|
||||||
Todo: ramps, switches, train assembly
|
Todo: ramps, switches, train assembly
|
||||||
|
|
||||||
@@ -62,7 +65,7 @@ How it fits
|
|||||||
- An s-curve with C15 moves over 20 studs, diagonals can be done with any length divisible by 5
|
- An s-curve with C15 moves over 20 studs, diagonals can be done with any length divisible by 5
|
||||||
- An s-curve with C7 moves two studs, but diagonals require a full S25 to land cleanly again.
|
- An s-curve with C7 moves two studs, but diagonals require a full S25 to land cleanly again.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Printing
|
## Printing
|
||||||
|
|
||||||
@@ -81,10 +84,10 @@ balance of speed and quality. A short rail will take about an hour to print.
|
|||||||
|
|
||||||
### Filament
|
### Filament
|
||||||
|
|
||||||
| Color | RAL Color | Pantone | PLA Supplier | ABS Supplier |
|
| Color | RAL | PLA Supplier | ABS Supplier |
|
||||||
| ----------------- | ---------- | ------- | ------------ | ------------ |
|
| ----------------- | ---------- | ------------ | ------------ |
|
||||||
| Light Bluish Gray | `RAL 7040` | | dasfilament | |
|
| Light Bluish Gray | `RAL 7040` | dasfilament | |
|
||||||
| Light Gray | `RAL 7005` | | | |
|
| Light Gray | `RAL 7005` | | |
|
||||||
|
|
||||||
- None of these colors will be an exact match, just the texture of 3d printing it can make a huge difference, but usually fall close enough in the range.
|
- None of these colors will be an exact match, just the texture of 3d printing it can make a huge difference, but usually fall close enough in the range.
|
||||||
- The original rails will be in _Light Gray_, not _Light Bluish Gray_, but since I barely own any pre- 2004 color change bricks I chose to match my other bricks instead.
|
- The original rails will be in _Light Gray_, not _Light Bluish Gray_, but since I barely own any pre- 2004 color change bricks I chose to match my other bricks instead.
|
||||||
@@ -100,6 +103,6 @@ _Notes for newcomers:_
|
|||||||
|
|
||||||
In case you are new to 3D printing:
|
In case you are new to 3D printing:
|
||||||
|
|
||||||
- Most filaments (including PLA) release toxic gases when _burned_
|
- Most filaments (including PLA) can release toxic gases when _burned_
|
||||||
- FDM printing can cause fine particle emission
|
- FDM printing can cause fine particle emission
|
||||||
- ABS when heated to normal printing temperatures can release styrene fumes
|
- ABS when heated to normal printing temperatures can release styrene fumes
|
||||||
|
|||||||
BIN
assets/generated/AntiStudInsert.png
Normal file
|
After Width: | Height: | Size: 607 B |
BIN
assets/generated/C15.png
Normal file
|
After Width: | Height: | Size: 710 B |
BIN
assets/generated/C7.png
Normal file
|
After Width: | Height: | Size: 863 B |
BIN
assets/generated/Classic Full Curve.png
Normal file
|
After Width: | Height: | Size: 476 B |
BIN
assets/generated/Classic Full Straight.png
Normal file
|
After Width: | Height: | Size: 396 B |
BIN
assets/generated/Classic Half Curve.png
Normal file
|
After Width: | Height: | Size: 651 B |
BIN
assets/generated/Classic Half Straight.png
Normal file
|
After Width: | Height: | Size: 486 B |
BIN
assets/generated/Classic Quarter Straight.png
Normal file
|
After Width: | Height: | Size: 664 B |
BIN
assets/generated/S10.png
Normal file
|
After Width: | Height: | Size: 596 B |
BIN
assets/generated/S25.png
Normal file
|
After Width: | Height: | Size: 391 B |
BIN
assets/generated/S4.png
Normal file
|
After Width: | Height: | Size: 773 B |
BIN
assets/generated/S5.png
Normal file
|
After Width: | Height: | Size: 761 B |
BIN
assets/generated/StudInsert.png
Normal file
|
After Width: | Height: | Size: 644 B |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
10
build.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
rm -rf build
|
||||||
|
mkdir -p build
|
||||||
|
rm -rf assets/generated
|
||||||
|
mkdir -p assets/generated
|
||||||
|
jq -r '.parameterSets | keys[]' track.json | while read -r preset; do
|
||||||
|
echo "Rendering $preset"
|
||||||
|
openscad -o "build/$preset.stl" -p track.json -P "$preset" track.scad
|
||||||
|
openscad -o "assets/generated/$preset.png" --imgsize=48,48 --render --autocenter --viewall -p track.json -P "$preset" track.scad
|
||||||
|
done
|
||||||
98
track.json
@@ -1,30 +1,88 @@
|
|||||||
{
|
{
|
||||||
"fileFormatVersion": "1",
|
"fileFormatVersion": "1",
|
||||||
"parameterSets": {
|
"parameterSets": {
|
||||||
"90 Degree Curve": {
|
"C15": {
|
||||||
"Radius": "28",
|
"Angle": 1,
|
||||||
"Length": "32",
|
"Length": 15,
|
||||||
"Type": "curve"
|
"Radius": 25,
|
||||||
|
"UseLengthForCurveAngle": true,
|
||||||
|
"Support": false
|
||||||
},
|
},
|
||||||
"Full Straight": {
|
"C7": {
|
||||||
"Radius": "28",
|
"Angle": 1,
|
||||||
"Length": "32",
|
"Length": 7,
|
||||||
"Type": "straight"
|
"Radius": 25,
|
||||||
|
"UseLengthForCurveAngle": true,
|
||||||
|
"Support": false
|
||||||
},
|
},
|
||||||
"Half Straight": {
|
"S25": {
|
||||||
"Radius": "28",
|
"Angle": 0,
|
||||||
"Length": "16",
|
"Length": 25,
|
||||||
"Type": "straight"
|
"Radius": 25,
|
||||||
|
"UseLengthForCurveAngle": true,
|
||||||
|
"Support": false
|
||||||
},
|
},
|
||||||
"Quarter Straight": {
|
"S10": {
|
||||||
"Radius": "28",
|
"Angle": 0,
|
||||||
"Length": "8",
|
"Length": 10,
|
||||||
"Type": "straight"
|
"Radius": 25,
|
||||||
|
"UseLengthForCurveAngle": true,
|
||||||
|
"Support": false
|
||||||
},
|
},
|
||||||
"4 Studs Straight": {
|
"S5": {
|
||||||
"Radius": "28",
|
"Angle": 0,
|
||||||
"Length": "4",
|
"Length": 5,
|
||||||
"Type": "straight"
|
"Radius": 25,
|
||||||
|
"UseLengthForCurveAngle": true,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"S4": {
|
||||||
|
"Angle": 0,
|
||||||
|
"Length": 4,
|
||||||
|
"Radius": 25,
|
||||||
|
"UseLengthForCurveAngle": true,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"Classic Full Straight": {
|
||||||
|
"Angle": 0,
|
||||||
|
"Length": 32,
|
||||||
|
"Radius": 28,
|
||||||
|
"UseLengthForCurveAngle": false,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"Classic Half Straight": {
|
||||||
|
"Angle": 0,
|
||||||
|
"Length": 16,
|
||||||
|
"Radius": 28,
|
||||||
|
"UseLengthForCurveAngle": false,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"Classic Quarter Straight": {
|
||||||
|
"Angle": 0,
|
||||||
|
"Length": 8,
|
||||||
|
"Radius": 28,
|
||||||
|
"UseLengthForCurveAngle": false,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"Classic Full Curve": {
|
||||||
|
"Angle": 90,
|
||||||
|
"Length": 8,
|
||||||
|
"Radius": 28,
|
||||||
|
"UseLengthForCurveAngle": false,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"Classic Half Curve": {
|
||||||
|
"Angle": 45,
|
||||||
|
"Length": 8,
|
||||||
|
"Radius": 28,
|
||||||
|
"UseLengthForCurveAngle": false,
|
||||||
|
"Support": false
|
||||||
|
},
|
||||||
|
"StudInsert": {
|
||||||
|
"Type": "studs"
|
||||||
|
},
|
||||||
|
"AntiStudInsert": {
|
||||||
|
"Type": "antistuds"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
91
track.scad
@@ -4,13 +4,18 @@ include <BOSL2/beziers.scad>;
|
|||||||
/* [Print Settings] */
|
/* [Print Settings] */
|
||||||
// Some feature are generated with respect to the layer height
|
// Some feature are generated with respect to the layer height
|
||||||
LayerHeight = 0.2; // [0.1,0.13,0.2]
|
LayerHeight = 0.2; // [0.1,0.13,0.2]
|
||||||
// Enable built-in support for 3d printing
|
// Mid-print stud inserts allowing the studs to be printed facing up seperately
|
||||||
Support = true;
|
StudInserts = false;
|
||||||
|
// Mid-print slot inserts eliminating the need for supports
|
||||||
|
AntiStudInserts = false;
|
||||||
|
// Part to generate
|
||||||
|
Type = "rail"; // [rail,studs,antistuds]
|
||||||
|
|
||||||
/* [Model Settings] */
|
/* [Model Settings] */
|
||||||
Length = 8; // [4:1:56]
|
Length = 8; // [4:1:56]
|
||||||
// Useful when working with Pythagorean Triples
|
// Useful when working with Pythagorean Triples
|
||||||
UseLengthForCurveAngle = true;
|
UseLengthForCurveAngle = true;
|
||||||
Radius = 28; // [4:1:36]
|
Radius = 25; // [4:1:36]
|
||||||
// The angle the track takes
|
// The angle the track takes
|
||||||
Angle = 0.0;
|
Angle = 0.0;
|
||||||
|
|
||||||
@@ -59,6 +64,35 @@ module tooth() {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module antiStudInsert(carve=true, depth=$studHeight * 2, supportHeight=$LDU * 4, supportWidth=$LDU * 4) {
|
||||||
|
difference() {
|
||||||
|
union() {
|
||||||
|
cube([$tile * 2, $tile, depth + supportHeight], anchor=FRONT+BOTTOM);
|
||||||
|
translate([0, $tile, 0]) cube([$tile * 2 + supportWidth, supportWidth, depth + supportHeight], anchor=FRONT+BOTTOM);
|
||||||
|
translate([0, $tile / 2, 0]) cube([$tile * 2 + supportWidth, supportWidth, depth + supportHeight], anchor=FRONT+BOTTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (carve) {
|
||||||
|
mirror_copy([1, 0, 0])
|
||||||
|
translate([$tile / 2, $tile / 2, 0]) group() {
|
||||||
|
cube([$stud, $stud, depth], anchor=BOTTOM+CENTER);
|
||||||
|
mirror_copy([0, 1, 0])
|
||||||
|
mirror_copy([1, 0, 0])
|
||||||
|
translate([$LDU * 2, $LDU * 2, 0])
|
||||||
|
cube([$stud / 2, $stud / 2, depth], anchor=BOTTOM+FRONT+LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module studInsert(supportThickness = $LDU * 4) {
|
||||||
|
mirror_copy([0, 1, 0]) translate([0, $tile / 2, 0]) group() {
|
||||||
|
cube([supportThickness, $stud, $stud], anchor=RIGHT);
|
||||||
|
cyl(l=$studHeight, d=$stud, $fn=48, anchor=TOP, orient=LEFT);
|
||||||
|
}
|
||||||
|
translate([-supportThickness, 0, 0]) cube([supportThickness, $tile + $stud + $LDU, $stud], anchor=RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
module brickSlot(w=1, l=1, h=3) {
|
module brickSlot(w=1, l=1, h=3) {
|
||||||
cube([$tile * w, $tile * l, $plate * h], anchor=TOP);
|
cube([$tile * w, $tile * l, $plate * h], anchor=TOP);
|
||||||
mirror_copy([1, 0, 0])
|
mirror_copy([1, 0, 0])
|
||||||
@@ -74,26 +108,20 @@ module endCapStraight(includeRail=true) {
|
|||||||
difference() {
|
difference() {
|
||||||
union() {
|
union() {
|
||||||
cube([$width, $tile * 2, $tile], anchor=CENTER);
|
cube([$width, $tile * 2, $tile], anchor=CENTER);
|
||||||
mirror_copy([0, 1, 0])
|
if (!StudInserts) {
|
||||||
translate([0, $tile / 2, 0])
|
mirror_copy([1, 0, 0]) translate([$width / 2, 0, 0]) studInsert();
|
||||||
cyl(l=$width + $studHeight * 2 + $LDU / 2, d=$stud, orient=LEFT, $fn=24);
|
}
|
||||||
|
|
||||||
// End Slot
|
// End Slot
|
||||||
translate([$tile + $LDU, -$tile, 0]) cube([6 * $LDU, $LDU, $tile], anchor=LEFT+BACK);
|
translate([$tile + $LDU, -$tile, 0]) cube([6 * $LDU, $LDU, $tile], anchor=LEFT+BACK);
|
||||||
|
|
||||||
if (Support) {
|
|
||||||
mirror_copy([1, 0, 0]) difference() {
|
|
||||||
translate([$tile * 2 - $studHeight, 0, -$tile / 2]) cube([$LDU * 3, $tile * 2 - $LDU - 2, $LDU * 6], anchor=BOTTOM+RIGHT);
|
|
||||||
mirror_copy([0, 1, 0])
|
|
||||||
translate([0, $tile / 2, 0])
|
|
||||||
cyl(l=$width + $studHeight * 2 + $LDU / 2, d=$stud + LayerHeight * 2, orient=LEFT, $fn=24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Brick slots
|
|
||||||
mirror_copy([1, 0, 0])
|
if (StudInserts) {
|
||||||
translate([$tile / 2, -$tile / 2, $tile / 2 - $plate * 2])
|
mirror_copy([1, 0, 0]) translate([$width / 2, 0, 0]) studInsert();
|
||||||
brickSlot();
|
}
|
||||||
|
|
||||||
|
translate([0, -$tile, $tile / 2 - $plate * 2]) cube([$tile * 2, $tile, $plate], anchor=FRONT+TOP);
|
||||||
|
translate([0, -$tile, $tile / 2 - $plate * 2]) antiStudInsert(carve=false);
|
||||||
|
|
||||||
// Fingernail slot
|
// Fingernail slot
|
||||||
mirror_copy([1, 0, 0])
|
mirror_copy([1, 0, 0])
|
||||||
@@ -113,11 +141,8 @@ module endCapStraight(includeRail=true) {
|
|||||||
cyl(d=$fillet, h=$tile, $fn=12);
|
cyl(d=$fillet, h=$tile, $fn=12);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Support) {
|
if (!AntiStudInserts) {
|
||||||
translate([0, -$tile, -$tile / 2])
|
translate([0, -$tile, $tile / 2 - $plate * 2]) antiStudInsert();
|
||||||
rect_tube(size=[$tile * 2 - $LDU * 2, $tile - $LDU * 2], h=$LDU * 4 - LayerHeight, wall=$LDU * 2, anchor=FRONT+BOTTOM);
|
|
||||||
translate([0, -$tile, -$tile / 2])
|
|
||||||
cube([$LDU * 2, $tile - $LDU * 2, $LDU * 4 - LayerHeight], anchor=FRONT+BOTTOM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includeRail) {
|
if (includeRail) {
|
||||||
@@ -137,6 +162,9 @@ module monorailCurve(r=28, sa, ea, p1) {
|
|||||||
angle = [180 - ea, 180 + sa];
|
angle = [180 - ea, 180 + sa];
|
||||||
points = arc($n_teeth, r=(r * $tile), angle=angle);
|
points = arc($n_teeth, r=(r * $tile), angle=angle);
|
||||||
|
|
||||||
|
echo(points[0] / $tile);
|
||||||
|
echo(points[len(points) - 1] / $tile);
|
||||||
|
|
||||||
translate([r * $tile, 0, 0]) union() {
|
translate([r * $tile, 0, 0]) union() {
|
||||||
translate(points[0]) rot(180 - ea) back($tile) endCapStraight(includeRail=false);
|
translate(points[0]) rot(180 - ea) back($tile) endCapStraight(includeRail=false);
|
||||||
translate(points[len(points) - 1]) rot(sa) back($tile) endCapStraight(includeRail=false);
|
translate(points[len(points) - 1]) rot(sa) back($tile) endCapStraight(includeRail=false);
|
||||||
@@ -176,10 +204,17 @@ module monorailStraight(l) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Angle == 0)
|
if (Type == "rail") {
|
||||||
monorailStraight(l=Length);
|
if (Angle == 0)
|
||||||
else
|
monorailStraight(l=Length);
|
||||||
monorailCurve(Radius, sa=0, ea=UseLengthForCurveAngle ? asin(Length / Radius) : Angle);
|
else
|
||||||
|
monorailCurve(Radius, sa=0, ea=UseLengthForCurveAngle ? asin(Length / Radius) : Angle);
|
||||||
|
} else if (Type == "studs") {
|
||||||
|
rotate([0, -90, 0]) studInsert();
|
||||||
|
} else if (Type == "antistuds") {
|
||||||
|
rotate([180, 0, 180]) antiStudInsert();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// endCapStraight();
|
// endCapStraight();
|
||||||
// translate([28.75, -232, -5.75]) rotate([0, 0, 90]) import("straight.stl");
|
// translate([28.75, -232, -5.75]) rotate([0, 0, 90]) import("straight.stl");
|
||||||
|
|||||||