Mark DiVecchio's O-Gauge Train Layouts

1992 Layout Page

2006 Layout Page

2009 Layout Page

P&LE Postcards by Howard Fogg 

Plasticville Buildings

Portable Layout Page

Train Clubs

Bing Track

Remote Train Control Program

YouTube Channel

OOK Radio Support

Technical Videos


More RTC Videos

ADPCM - Playing clips from .mth sound files

P&LE McKees Rocks Locomotive Shop
3D Printer Project

White Tower Restaurant
3D Printer Project

RFID Train Detection


3D Prints for my Train Layout

This Page last updated on .

Here are some of the 3D prints that I did for my train layout. Some were developed by me and some were found on-line.



P&LE McKees Rocks Locomotive Shop

This 3D print has its own web page - click here.

White Tower Restaurant

This 3D print has its own web page - click here.

New Sign for the Plasticville Frosty Bar

I like Plasticville but the main town on my layout is not Plasticville but is Aliquippa, PA - my hometown. And in Aliquippa, we had a Dairy Queen.
The sign is available on Thingiverse where you can customize it and create gcode which can be sent to one of the on-line 3D print shops : https://www.thingiverse.com/thing:3159254
I used my 3D printer to make a new sign for the Frosty Bar.



Original Sign. I got out my calipers and measured each feature on the sign.

I did the measurements in millimeters since that is the standard unit of measurement used in the 3D modeling program I used. After doing a few, it was clear that Bachmann built the original molds using English measurement. Every measurement was coming out the MKS equivalent of 1/4 inch, 1/8 inch, 3/16 inch, etc.

There are many programs that can be used for 3D modeling. For this project, I used the OpenSCAD program.

I really like this method of modeling because it is programmatic. I used it for my P&LE Locomotive Shop which has thousands of individual bricks. I didn't have to construct each one. I used computer code to do one and then repeated it over and over in a code loop.

For this sign, I created the OpenSCAD code in about an hour - though it took a few tweaks and several test prints to get the results that I wanted.


Here is screen capture of the sign by OpenSCAD. Fonts were a problem especially for the "Frosty Bar" font. I found that the town name was pretty close to "Arial" but the Frosty Bar sign did not match any font that I had available or any font that I could find. I ended up choosing the font "Pump Demi Bold LET". I adjusted the "spacing" parameter to try to match the original sign as well as I could.

Let me know if you have any information about the font used on the "Frosty Bar" sign.

In OpenSCAD, you create 2D objects which you extrude into 3 dimensions or you can create 3D objects directly. I created the basic sign shape from a polygon which I then extruded. I used the "offset" command to make the small fillets at the left and right edges of the sign. To create the "inner" fillets on the left and right inside corners I used  a cylinder subtracted from a cube. Look at the "difference" command in the code.

The color in this rendering is false. I ended up painting the sign.

This step produces an ".stl" file which is used in the next step.
Here is a listing of the Plasticville Frosty Bar Sign.scad file:

//
// Customizable Plasticville Frosty Bar Sign.scad
// Mark DiVecchio
// July 2018 V1.0
// Original development using OpenSCAD 2017.01.20
//
// This SCAD script is licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
/*
My web page: http://www.silogic.com/trains/layout.html
*/
// http://www.silogic.com/trains/layout.html
//
$fn=128 * 1;
//
// CUSTOMIZING
// New Frosty Bar Name
Name = "DAIRY QUEEN";
// New Name Font (On Line Fonts: fonts.google.com)
NameFont = "Pump Demi Bold LET";
// Letter spacing in Bar Name
NameSpacing = 1.1;
// New Town Name
Town = "ALIQUIPPA";
// Town Name Font (On Line Fonts: fonts.google.com)
TownFont = "Arial";
// Letter spacing in Town Name
TownSpacing = 1.3;
// Width of base of sign (enter in mm)
Width = 114;
// Height of base of sign (enter in mm)
Height = 3.14;
// Width of town name portion of sign (enter in mm)
WidthName = 90.04;
// Height of name portion of sign (enter in mm)
HeightName = 6.45;
// Thickness of sign (enter in mm)
Thickness = 1.5;
// Thickness of Letters of the name portion of sign (enter in mm)
ThicknessNameLetters = 2.29;
// Height of Frosty Bar Letters (enter in mm)
HeightFBLetters = 8.25;
// Width of Frosty Bar Letters (enter in mm)
WidthFBLetters = 6.41;
// Height of Town Name letters (enter in mm)
HeightTNLetters = 3.77;
// Width of Town Name Letters (enter in mm)
WidthTNLetters = 4.03;

print_part();

/////////////
// Modules //
/////////////
module print_part() {
sign();
}
module sign () {
// Base (Width * Height x Thickness)
color("peachpuff")
linear_extrude(Thickness) {
offset(r = 0.5) {
polygon(points=[
[0 + 0.5,0 + 0.5],
[0 + 0.5, Height - 0.5],
[Width - 1,Height - 0.5],
[Width - 1, 0 + 0.5]
]);
}
}
// Middle (WidthName x HeightName x Thickness)
color("peachpuff")
linear_extrude(Thickness) {
wval = 4;
offset(r = wval/2) {
polygon(points=[
[((Width - WidthName)/2) + (wval/2),0 + (wval/2)],
[((Width - WidthName)/2) + (wval/2), Height + HeightName - (wval/2)],
[(WidthName + (Width - WidthName)/2) - (wval/2),Height + HeightName - (wval/2)],
[(WidthName + (Width - WidthName)/2) - (wval/2), 0 + (wval/2)]
]);
}
}

// inner fillet - left
color("peachpuff")
difference() {
translate([((Width - WidthName)/2)-2,Height - 2,0])
cube(size = [4, 4, Thickness], center = false);
translate([((Width - WidthName)/2)-2,Height + 2,-0.5])
cylinder(h = Thickness * 2, r=2, center = false);
}

// inner fillet - right
color("peachpuff")
difference() {
translate([(WidthName + (Width - WidthName)/2)-2,Height - 2,0])
cube(size = [4, 4, Thickness], center = false);
translate([(WidthName + (Width - WidthName)/2)+2,Height + 2, -0.5])
cylinder(h = Thickness * 2, r=2, center = false);
}

// Name of Frosty Bar (letters are HeightFBLetters x WidthFBLetters)
color("peachpuff")
translate([Width/2, Height + HeightName, 0])
linear_extrude(Thickness)
text(Name, font=NameFont, size=HeightFBLetters, spacing=NameSpacing, halign="center");

// Name of town (red) (letters are HeightTNLetters x WidthTNLetters)
color("red")
translate([Width/2, Height + ((HeightName - HeightTNLetters)/2), 0])
linear_extrude(ThicknessNameLetters)
text(Town, font=str(TownFont, ":style=Bold"), size=HeightTNLetters, spacing=TownSpacing, halign="center");
}



The slicer program that I use with my Original Prusa i3 MK2s is "Slic3r". A customized version of that program is provided by Prusa. Slic3r reads the *.stl file created by OpenSCAD and slices the design. Output is a "*.gcode" file which is then sent to the 3D printer.

I used the default slicer setting in Slic3r provided by Prusa. It is called "0.15mm OPTIMAL".


Here is the sign as printed. Still on the print bed. I used white PLA because I had it. Since the sign was going to be painted, it didn't matter too much what color PLA was used. Took about an hour to print.


Here is a close up of the sign. You can see the lines of PLA as laid down by the printer. This type of printing does not produce the nice smooth results of the injection molding of the original Bachmann products. Painting helps hide these lines. Other people talk about sanding the object with 200 to 3000 grit sandpaper to remove some of the lines but I've not tried that.


Even though I used white PLA, I still painted the sign white. That paint (from WalMart) helped smooth out the surface. I painted the tops of the red letters of Aliquippa.


Here is the sign in place on the Frosty Bar in the park on my layout (now christened Dairy Queen).


New Sign for the Plasticville Turnpike

Once I had the new Frosty Bar Sign done, it was a quick job to make a new sign for the Plasticville Turnpike.
The sign is available on Thingiverse where you can customize it and create gcode which can be sent to one of the on-line 3D print shops : https://www.thingiverse.com/thing:3189546

Since my layout represents the Pittsburgh & Lake Erie between McKees Rocks and Youngstown, I wanted a turnpike entrance that made sense. The Pennsylvania Turnpike and its Beaver Valley Interchange are the nearest to the P&LE track.

So with the knowledge gained by doing the new Dairy Queen sign, I again used OpenSCAD and wrote a program to create a new turnpike sign. The first step was to measure each piece of the sign. Then I had to pick fonts for the letters. Again, not knowing what fonts Bachmann used, I looked for something close. This time I looked on "Google Fonts". You can google that. I found a font called "Bungee" and used that for the interchange name. For the turnpike name, I stuck with "Arial".

The development and printing steps were the same as I used on the Dairy Queen sign. Look at that section of this web page for the details.


Here is the sign as it appears in OpenSCAD. The colors are false.

Here is the print, still on the print bed.
I printed with blue PLA to save some painting. The blue does not exactly match the blue of the turnpike buildings. But close enough for now.

I printed at 100% fill with 3 perimeters - otherwise using the Prusa defaults for "Original Prusa i3 MK2" and "0.15 mm OPTIMAL" print settings.
I put two copies of the sign on the print bed since two are needed for the Turnpike.
Took about 3 hours to print both signs.
Here is a listing of the Plasticville Turnpike Sign.scad file:

//
// Customizable Plasticville Turnpike Sign.scad
// Mark DiVecchio
// October 2018 V2.0
// Original development using OpenSCAD 2017.01.20
//
// This SCAD script is licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
/*
My web page: http://www.silogic.com/trains/layout.html
*/
// http://www.silogic.com/trains/layout.html
//
$fn=128 * 1;
//
// CUSTOMIZING
// New Interchange Name
INT = "BEAVER VALLEY INTERCHANGE";
// New Interchange Name Font (On Line Fonts: fonts.google.com)
INTFont = "Bungee";
// Letter spacing in Interchange Name
INTSpacing = 1.0;
// New Turnpike Name
Pike = "PENNSYLVANIA TURNPIKE";
// Turnpike Name Font (On Line Fonts: fonts.google.com)
PikeFont = "Arial";
// Letter spacing in Turnpike Name
TPSpacing = 1.1;
// Width of base of sign 6 11/16" (enter in mm)
Width = (6 + 11/16) * 25.4;
// Height of base of sign 0.0875"(enter in mm)
Height = (0.0875) * 25.4;
// Thickness of sign 0.1" (enter in mm)
ThicknessINTLetters = (0.1) * 25.4;
// Spacing to center horizontal brace (enter in mm)
BraceOffset = (0.2665 - 0.08) * 25.4;
// Height of bottom portion of sign (enter in mm)
BottomHeight = (1.035) * 25.4;
// Height of top horizonal Beam (enter in mm)
TopBeamHeight = (0.2) * 25.4;
// Spacing to top horizontal Beam (enter in mm)
TopBeamOffset = (BottomHeight - TopBeamHeight - 1.75);
// Left Center Bar Offset
LCBarOffset = (Height + (1.91 * 25.4));
// Right Center Bar Offset
RCBarOffset = (Width - LCBarOffset - Height);
// Width of top hat
TopWidth = (7 + 11/16) * 25.4;
// Height of top hat
TopHeight = (0.0685) * 25.4;
// Thickness of top hat
TopThickness = (0.15) * 25.4;

//
// Width of turnpike name portion of sign (enter in mm)
WidthName = 90.04;
// Height of turnpike portion of sign (enter in mm)
HeightName = 6.45;

// Thickness of Letters of the turnpike portion of sign (enter in mm)
ThicknessTPLetters = (0.11 * 25.4);
// Height of interchange Letters (enter in mm)
HeightINTLetters = 8.25;
// Width of interchange Letters (enter in mm)
WidthINTLetters = 6.41;
// Height of Turnpike Name letters(enter in mm)
HeightTPLetters = (0.2665 * 25.4);
// Width of Turnpike Name Letters (enter in mm)
WidthTPLetters = 3.5;

print_part();

/////////////
// Modules //
/////////////
module print_part() {
sign();
}
module sign () {
// right Riser
color("blue") translate([Width - Height - 0.5, 0.5, 0])
cube([Height, BottomHeight - Height, ThicknessINTLetters - 0.5]);
// left Riser
color("blue") translate([0, 0.5, 0])
cube([Height, BottomHeight - Height, ThicknessINTLetters - 0.5]);
// left center Riser
color("blue") translate([LCBarOffset, BraceOffset + Height, 0])
cube([Height, BottomHeight - BraceOffset - Height - Height + 0.5, ThicknessINTLetters - 0.5]);
// right center Riser
color("blue") translate([RCBarOffset, BraceOffset + Height, 0])
cube([Height, BottomHeight - BraceOffset - Height - Height + 0.5, ThicknessINTLetters - 0.5]);

// Top Hat
color("blue")
translate([(TopWidth - Width)/-2, BottomHeight, 0])
rotate([90, 0, 0])
linear_extrude(TopHeight) {
offset(r = 0.5) {
polygon(points=[
[0 + 0.5,0 + 0.5],
[0 + 0.5, TopThickness - 0.5],
[TopWidth - 1,TopThickness - 0.5],
[TopWidth - 1, 0 + 0.5]
]);
}
}
// Bottom Beam
// Base (Width * Height * Thickness) with a fillet
color("blue")
linear_extrude(ThicknessINTLetters - 0.5) {
offset(r = 0.5) {
polygon(points=[
[0 + 0.5,0 + 0.5],
[0 + 0.5, Height - 0.5],
[Width - 1,Height - 0.5],
[Width - 1, 0 + 0.5]
]);
}
}
// Middle Beam
// Base (Width * Height * Thickness) with a fillet and translate
color("blue")
translate([0, BraceOffset + Height, 0])
linear_extrude(ThicknessINTLetters - 0.5) {
offset(r = 0.5) {
polygon(points=[
[0 + 0.5,0 + 0.5],
[0 + 0.5, Height - 0.5],
[Width - 1,Height - 0.5],
[Width - 1, 0 + 0.5]
]);
}
}
// Top Beam
// Base (Width * TopBeamHeight * Thickness) with a fillet and translate
color("blue")
translate([0, TopBeamOffset, 0])
linear_extrude(ThicknessINTLetters - 0.5) {
offset(r = 0.5) {
polygon(points=[
[0 + 0.5,0 + 0.5],
[0 + 0.5, TopBeamHeight - 0.5],
[Width - 1,TopBeamHeight - 0.5],
[Width - 1, 0 + 0.5]
]);
}
}

// Name of Interchange (letters are HeightINTLetters x WidthINTLetters)
color("blue")
translate([Width/2, BottomHeight, 0])
linear_extrude(ThicknessINTLetters)
text(INT, font=INTFont, size=HeightINTLetters, spacing=INTSpacing, halign="center");

// Name of Turnpike (blue) (letters are HeightTPLetters x WidthTPLetters)
color("white")
translate([Width/2, Height/2, 0])
linear_extrude(ThicknessTPLetters)
text(Pike, font=str(PikeFont, ":style=Bold"), size=HeightTPLetters, spacing=TPSpacing, halign="center");
}

I painted the turnpike name white to match what Bachmann did on the original turnpike.

Here is the updated Pennsylvania Turnpike sign at the Beaver Valley Interchange, about 20 miles from my childhood home in Aliquippa, PA.
Now I need to make space on my layout for this.



Mini Trash Can

Found on Thingiverse.com  by 3D-Fuel.



I printed this for my O-gauge layout. Reduced in size by 25%. It comes out with pretty thin walls but I had Slic3r watch out for thin perimeters/shells/walls. I set the layers to 0.1mm and it printed pretty well on my Original Prusa i3 MK2s. Printed in black PLA, Bottom spray painted a grayish color.

Parts for my track cleaning car

Fuel Tank (Reservoir d eau)
Found on Thingiverse.com by JEBILO

Diesel Engine  60%
Found on Thingiverse.com by lefab.

Basic car from North East Trains.



Dumpster

Found on Thingiverse.com by Simonarri.



For my O gauge layout, I printed this at 75%, 2 top/bottom/perimeter layers, 10% fill at 0.2mm. I used a piece of wire for the hinge. Filled with scraps of paper.

Picnic Table

Found on Thingiverse.com by PrettySmallThings.
Found on Thingiverse.com by bnoggle.



Grade Crossing

My layout, which uses O gauge tubular track never had very realistic grade crossings since the track is a scale 5 feet(!) high.
The sign is available on Thingiverse where you can customize it and create gcode which can be sent to one of the on-line 3D print shops.
The curved version is at  : https://www.thingiverse.com/thing:2832224
and the straight version is at: https://www.thingiverse.com/thing:3193426

I used OpenSCAD again because of its ability to be customized for different radius curves. There is one OpenSCAD program for curved track where you can select four different radii and one OpenSCAD program for straight track.

Here is a listing of the Grade Crossing Curved.scad file:

//
// Customizable Curved Grade Crossing - Lionel O Tubular Track
// Mark DiVecchio
// March 2018
// Original development using OpenSCAD 2017.01.20
//
// This SCAD script is licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
// V1.0 - original release
// V2.0 - adds ramps
//
// http://www.silogic.com/trains/layout.html
//
// in slicer, rotate y = 180 deg, rotate z = 45 deg (to get long print lines)
// use 2 bottom layers, 0 top layers, rectilinear bottom layers
//
$fn=200*1;
//
// CUSTOMIZING
//

/* Configuration */
// Length of the crossing in inches
Piece_Length = 6; // [3:0.5:10]
// Diameters were taken from measurements of circles
// using the RR-Track program. [O-31, O-42, O-54, O-72]
// in inches from center rail to center rail
// Track Diameter
Diameter = 72.5; //[28.6:O-31, 40.75:O-42, 53.3:O-54, 72.5:O-72]
// Width of each crossing segment in inches (Leave enough space for the wheel flanges)
Top_Width = 0.4;
// Number of sections to break the crossing into
Sections_per_Piece = 5; //[1:10]
// Create grade crossing or ramp (will invert the ramps for printing)?
To_Print = "grade"; // [grade,ramp]
// Ramp Height in inches
Ramp_Height = 0.717;
// Ramp Length in inches
Ramp_Length = 3; //[2:10]
// Ramp Thickness in inches
Ramp_Thickness = 0.1; //[0.1,0.15,0.2,0.25]//
//
/* [Hidden] */
// Bottom Width
Bottom_Width = Top_Width - 0.25;
// Height
Height = 0.319;
// Ledge
Ledge = 0.100;
// Conversion inches to millimeters
inch=25.4;
// Board Spacing slot
Board_Space = 0.02;

print_part();

/////////////
// Modules //
/////////////

module print_part() {

translate([ -(Diameter * inch)/2, 0, 0 ])
{
if (To_Print == "grade") difference() {
union () {
translate([0,0,0])
InnerCurvedCrossing(Diameter);
translate([Board_Space * inch,0,0])
OuterCurvedCrossing(Diameter);
translate([(Board_Space * 1) * -1 * inch,0,0])
Inner2CurvedCrossing(Diameter);
translate([(Board_Space * 2) * 1 * inch,0,0])
Outer2CurvedCrossing(Diameter);
}

union () {
for (chunks = [1 : Sections_per_Piece]) {
rotate([0,0,(Piece_Length* chunks/Sections_per_Piece) / (2 * 3.14159 * (Diameter/2)) * 360]) Slots();
}
}
}
if (To_Print == "ramp") {
rotate([180, 0, 0]) {
translate([0,0,0])
InnerCurvedRamp(Diameter);
translate([0,0,0])
OuterCurvedRamp(Diameter);
}
}
if (To_Print == "grade") {
%translate([0,0,0])
InnerCurvedRamp(Diameter);
%translate([0,0,0])
OuterCurvedRamp(Diameter);
}
}
}

module InnerCurvedRamp(D) {
translate([0,, 0, -(Ramp_Height - Height) * inch])
rotate_extrude(angle=(Piece_Length / (2 * 3.14159 * (D/2))) * 360)
translate([(D/2 - (2 *Top_Width) - (2 * Board_Space) - Ramp_Length) * inch, 0, 0])
rotate([0, 0, To_Print=="ramp" ? -atan(Ramp_Height/Ramp_Length): 0])
polygon([[0,0],
[Ramp_Length * inch, Ramp_Height * inch],
[Ramp_Length * inch, (Ramp_Height - Ramp_Thickness) * inch],
[(Ramp_Length - 0.5) * inch, (Ramp_Height - Ramp_Thickness - (0.5) * (Ramp_Height / Ramp_Length)) * inch],
[(Ramp_Length - 0.5) * inch, 0],
[(Ramp_Length - 0.5 - Ramp_Thickness) * inch, 0],
[(Ramp_Length - 0.5 - Ramp_Thickness) * inch, (Ramp_Height - Ramp_Thickness - (0.5 + Ramp_Thickness) * (Ramp_Height / Ramp_Length)) * inch],
[(Ramp_Thickness * Ramp_Length / Ramp_Height) * inch, 0]
]);
}

module OuterCurvedRamp(D) {
translate([0,, 0, -(Ramp_Height - Height) * inch])
rotate_extrude(angle=(Piece_Length / (2 * 3.14159 * (D/2))) * 360)
translate([(D/2 + (2 *Top_Width) + (3 * Board_Space) + Ramp_Length) * inch, 0, 0])
rotate([0,180,0])
rotate([0, 0, To_Print =="ramp" ? -atan(Ramp_Height/Ramp_Length): 0])
polygon([[0,0],
[Ramp_Length * inch, Ramp_Height * inch],
[Ramp_Length * inch, (Ramp_Height - Ramp_Thickness) * inch],
[(Ramp_Length - 0.5) * inch, (Ramp_Height - Ramp_Thickness - (0.5) * (Ramp_Height / Ramp_Length)) * inch],
[(Ramp_Length - 0.5) * inch, 0],
[(Ramp_Length - 0.5 - Ramp_Thickness) * inch, 0],
[(Ramp_Length - 0.5 - Ramp_Thickness) * inch, (Ramp_Height - Ramp_Thickness - (0.5 + Ramp_Thickness) * (Ramp_Height / Ramp_Length)) * inch],
[(Ramp_Thickness * Ramp_Length / Ramp_Height) * inch, 0]
]);
}


module InnerCurvedCrossing(D) {
// Main Inner curved body
echo("Inner: angle ", (Piece_Length / (2 * 3.14159 * (D/2))) * 360);
rotate_extrude(angle=(Piece_Length / (2 * 3.14159 * (D/2))) * 360)
translate([(D/2 - Top_Width) * inch,0,0])
rotate([0, 0, 0])
polygon([[0,0], // 1
[0,(Height) * inch], // 2
[((Top_Width/3) - Board_Space)* inch,(Height) * inch], // a
[((Top_Width/3) - Board_Space)* inch,(Height - Board_Space) * inch], // b
[((Top_Width/3))* inch,(Height - Board_Space) * inch], // c
[((Top_Width/3))* inch,(Height) * inch], // d
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height) * inch], // e
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height - Board_Space) * inch], // f
[((Top_Width * 2 / 3))* inch,(Height - Board_Space) * inch], // g
[((Top_Width * 2 / 3))* inch,(Height) * inch], // h
[(Top_Width) * inch, (Height) * inch], // 3
[(Top_Width) * inch,(Height - Ledge) * inch], // 4
[(Bottom_Width) *inch, 0]]); // 5
}

module OuterCurvedCrossing(D) {
// Main Outer curved body
echo("Outer: angle ", (Piece_Length / (2 * 3.14159 * (D/2))) * 360);
rotate_extrude(angle=(Piece_Length / (2 * 3.14159 * (D/2))) * 360)
translate([(D/2 + Top_Width) * inch,0,0])
rotate([0,180,0])
polygon([[0,0], // 1
[0,(Height) * inch], // 2
[((Top_Width/3) - Board_Space)* inch,(Height) * inch], // a
[((Top_Width/3) - Board_Space)* inch,(Height - Board_Space) * inch], // b
[((Top_Width/3))* inch,(Height - Board_Space) * inch], // c
[((Top_Width/3))* inch,(Height) * inch], // d
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height) * inch], // e
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height - Board_Space) * inch], // f
[((Top_Width * 2 / 3))* inch,(Height - Board_Space) * inch], // g
[((Top_Width * 2 / 3))* inch,(Height) * inch], // h
[(Top_Width) * inch, (Height) * inch],
[(Top_Width) * inch,(Height - Ledge) * inch],
[(Bottom_Width) *inch, 0]]);
}
module Slots() {
translate([0,Board_Space/2 * inch, ((Board_Space/2) + Height - Board_Space) * inch])
rotate([0, 90, 0])
linear_extrude(height = (Diameter/2 + (Top_Width * 4)) * inch)
square(size = Board_Space * inch, center = true);

}
module Inner2CurvedCrossing(D) {
// Main Inner curved body
echo("Inner2: angle ", (Piece_Length / (2 * 3.14159 * (D/2))) * 360);
rotate_extrude(angle=(Piece_Length / (2 * 3.14159 * (D/2))) * 360)
translate([(D/2 - (Top_Width * 2)) * inch,0,0])
polygon([[0,0], // 1
[0,(Height) * inch], // 2
[((Top_Width/3) - Board_Space)* inch,(Height) * inch], // a
[((Top_Width/3) - Board_Space)* inch,(Height - Board_Space) * inch], // b
[((Top_Width/3))* inch,(Height - Board_Space) * inch], // c
[((Top_Width/3))* inch,(Height) * inch], // d
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height) * inch], // e
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height - Board_Space) * inch], // f
[((Top_Width * 2 / 3))* inch,(Height - Board_Space) * inch], // g
[((Top_Width * 2 / 3))* inch,(Height) * inch], // h
[(Top_Width) * inch, (Height) * inch],
[(Top_Width) * inch,(Height - Ledge) * inch],
[(Bottom_Width) *inch, 0]]);
}

module Outer2CurvedCrossing(D) {
// Main Outer curved body
echo("Outer2: angle ", (Piece_Length / (2 * 3.14159 * (D/2))) * 360);
rotate_extrude(angle=(Piece_Length / (2 * 3.14159 * (D/2))) * 360)
translate([(D/2 + (Top_Width * 2)) * inch,0,0])
rotate([0,180,0])
polygon([[0,0], // 1
[0,(Height) * inch], // 2
[((Top_Width/3) - Board_Space)* inch,(Height) * inch], // a
[((Top_Width/3) - Board_Space)* inch,(Height - Board_Space) * inch], // b
[((Top_Width/3))* inch,(Height - Board_Space) * inch], // c
[((Top_Width/3))* inch,(Height) * inch], // d
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height) * inch], // e
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height - Board_Space) * inch], // f
[((Top_Width * 2 / 3))* inch,(Height - Board_Space) * inch], // g
[((Top_Width * 2 / 3))* inch,(Height) * inch], // h
[(Top_Width) * inch, (Height) * inch],
[(Top_Width) * inch,(Height - Ledge) * inch],
[(Bottom_Width) *inch, 0]]);
}

Here is a listing of the Grade Crossing Straight.scad file:

//
// Customizable Straight Grade Crossing - Lionel O Tubular Track
// Mark DiVecchio
// March 2018
// Original development using OpenSCAD 2017.01.20
//
// This SCAD script is licensed under a
// Creative Commons Attribution-NonCommercial 3.0 Unported License.
//
// V1.0 - Original release
// V2.0 - adds ramps
//
// http://www.silogic.com/trains/layout.html
//
// in slicer, rotate y = 180 deg, rotate z = 45 deg (to get long print lines)
// use 2 bottom layers, 0 top layers, rectilinear bottom layers

$fn=200*1;
//
// CUSTOMIZING
//
/* Configuration */
// Length of the crossing in inches
Piece_Length = 6.0; // [3:0.5:10]
// Width of each crossing segment in inches (Leave enough space for the wheel flanges)
Top_Width = 0.4;
// Number of sections to break the crossing into
Sections_per_Piece = 5; //[1:10]
// Create grade crossing or ramp (will invert the ramps for printing)?
To_Print = "grade"; // [grade,ramp]
// Ramp Height in inches
Ramp_Height = 0.717;
// Ramp Length in inches
Ramp_Length = 3; //[2:10]
// Ramp Thickness in inches
Ramp_Thickness = 0.1; //[0.1,0.15,0.2,0.25]
//
/* [Hidden] */
// Bottom Width
Bottom_Width = Top_Width - 0.25;
// Height of segment - based on measured tubular track
Height = 0.319;
// Ledge
Ledge = 0.100;
// Conversion inches to millimeters
inch=25.4;
// Board Spacing slot
Board_Space = 0.02;

print_part();

/////////////
// Modules //
/////////////

module print_part() {

translate([ -(((2 * Top_Width) + Board_Space) * inch), 0, 0 ]) {
if (To_Print == "grade") difference() {
union () {
StraightCrossingInner(0, 0 * (Top_Width + Board_Space));
StraightCrossingInner(0, 1 * (Top_Width + Board_Space));
StraightCrossingOuter(180, 2 * (Top_Width + Board_Space));
StraightCrossingOuter(180, 3 * (Top_Width + Board_Space));
}
union () {
for (chunks = [1 : Sections_per_Piece]) {
translate ([0, ((Piece_Length * chunks/Sections_per_Piece) - Board_Space) * inch, 0]) Slots();
}
}
}
if (To_Print == "ramp") {
rotate([180, 0, 0]) {
StraightRamp(0,0);
StraightRamp(180, ((2 * (Ramp_Length)) + Board_Space) + 4 * (Top_Width + Board_Space));
}
}
if (To_Print == "grade") {
%StraightRamp(0,0);
%StraightRamp(180, ((2 * (Ramp_Length)) + Board_Space) + 4 * (Top_Width + Board_Space));
}
}
}

module StraightRamp(Angle, Mvmt) {
// Ramp up
translate([(-Ramp_Length - Board_Space) * inch, Piece_Length * inch, -(Ramp_Height - Height) * inch])
rotate([90, 0, 0])
linear_extrude(height = Piece_Length * inch)
translate([(Mvmt) * inch, 0, 0])
rotate([0, Angle, 0])
rotate([0, 0, To_Print =="ramp" ? -atan(Ramp_Height/Ramp_Length): 0])
polygon([[0,0],
[Ramp_Length * inch, Ramp_Height * inch],
[Ramp_Length * inch, (Ramp_Height - Ramp_Thickness) * inch],
[(Ramp_Length - 0.5) * inch, (Ramp_Height - Ramp_Thickness - (0.5) * (Ramp_Height / Ramp_Length)) * inch],
[(Ramp_Length - 0.5) * inch, 0],
[(Ramp_Length - 0.5 - Ramp_Thickness) * inch, 0],
[(Ramp_Length - 0.5 - Ramp_Thickness) * inch, (Ramp_Height - Ramp_Thickness - (0.5 + Ramp_Thickness) * (Ramp_Height / Ramp_Length)) * inch],
[(Ramp_Thickness * Ramp_Length / Ramp_Height) * inch, 0]
]);
}

module StraightCrossingInner(Angle, Mvmt) {
// Main straight body
translate([0, Piece_Length * inch, 0])
rotate([90, 0, 0])
linear_extrude(height = Piece_Length * inch)
translate([(Mvmt) * inch, 0, 0])
rotate([0, Angle, 0])
polygon([[0,0], // 1
[0,(Height) * inch], // 2
[((Top_Width/3) - Board_Space)* inch,(Height) * inch], // a
[((Top_Width/3) - Board_Space)* inch,(Height - Board_Space) * inch], // b
[((Top_Width/3))* inch,(Height - Board_Space) * inch], // c
[((Top_Width/3))* inch,(Height) * inch], // d
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height) * inch], // e
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height - Board_Space) * inch], // f
[((Top_Width * 2 / 3))* inch,(Height - Board_Space) * inch], // g
[((Top_Width * 2 / 3))* inch,(Height) * inch], // h
[(Top_Width) * inch, (Height) * inch], // 3
[(Top_Width) * inch,(Height - Ledge) * inch], // 4
[(Bottom_Width) *inch, 0]]); // 5
}
module StraightCrossingOuter(Angle, Mvmt) {
// Main straight body
translate([0, Piece_Length * inch, 0])
rotate([90, 0, 0])
linear_extrude(height = Piece_Length * inch)
translate([(Mvmt + Top_Width) * inch, 0, 0])
rotate([0, Angle, 0])
polygon([[0,0], // 1
[0,(Height) * inch], // 2
[((Top_Width/3) - Board_Space)* inch,(Height) * inch], // a
[((Top_Width/3) - Board_Space)* inch,(Height - Board_Space) * inch], // b
[((Top_Width/3))* inch,(Height - Board_Space) * inch], // c
[((Top_Width/3))* inch,(Height) * inch], // d
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height) * inch], // e
[((Top_Width * 2 / 3) - Board_Space)* inch,(Height - Board_Space) * inch], // f
[((Top_Width * 2 / 3))* inch,(Height - Board_Space) * inch], // g
[((Top_Width * 2 / 3))* inch,(Height) * inch], // h
[(Top_Width) * inch, (Height) * inch], // 3
[(Top_Width) * inch,(Height - Ledge) * inch], // 4
[(Bottom_Width) *inch, 0]]); // 5
}
module Slots() {
translate([0, 0, (Height - Board_Space) * inch])
cube([(Board_Space + Top_Width) * 4 * inch, Board_Space * inch, Board_Space * inch]);
}


OpenSCAD screen grab



This shows the curved crossing in OpenSCAD. The planks between the track and the ramps are shown. The curvature of the parts change depending on the track radius/diameter that you select.



Here is a photo of a grade crossing with ramps on a O-54 curve. I need to add some Sulptamold or lichen to hide the open space under the ramps. The planks are glued to the track. Notice that there is wheel flange space along the outer rails. The planks are also designed so the top is recessed below the top of the tubular rails.


This site prepared and maintained by Mark DiVecchio

email :  markd@silogic.com

SD&A HOME
 
 Mark's Home Page

The DiVecchio genealogy home page
The Frazzini genealogy home page

This site will be under construction for a while.