// Da Vinci Flint Bridge v. 2.0 (FINAL) // Penned by Kevin Cole 2020.10.22 /////////////////////////////////////////////////////////////////// // // // IMPORTANT: For all occurances of rotations paired with // // translations, THINK about order of operations // // in REVERSE: Read those stanzas from the bottom UP. // // (Start at any of the cube(...) shapes and apply // // the transformations going from the "bottom" line // // of code to the top. // // // /////////////////////////////////////////////////////////////////// $vpr = [60, 0, $t * 360]; // Now with animation! // The above line rotates the camera around a birds-eye view // of the bridge. To enable, select View -> Animate from the // pull-down menu, which adds an animation dialog to the window. // // Then set "FPS" to 30 (or a multiple of 30) and "steps" to // 720 (or a multiple of 360). Increasing FPS means smoother // video (up to the limits of the human eye's resoluton). // Increasing "steps" will decrease the play speed, slowing // down the video. (To capture frames for later animation // use [X] Dump Pictures.) // Notes from scratchpad.scad: // // * Since "sidedness" is identical in Y and Z, forming a square, // Pythagoras tells us that the diagonal (hypotenuse) of a // square always will be a multiple of 1 x 1 x sqrt(2). // * When a square is rotate 45 degrees to become a "diamond", // (sin(45) * side) yields the height of 1/2 of diamond. // * A cube without any translation will have its lower, left, // front corner at the origin [0, 0, 0]. The rotation of that // around the Y origin puts 1/2 of the cube (now a diamond) // beneath the plane. // * So, raising it by that amount (sin(45) * side) puts the // bottom "point" of the diamond properly resting on the plane. // * After that, it's a matter of raising it up and over to // the right by the length of one side, each. // * The astute will realize that the two translates can be // combined. But it is more illustrative to keep them separate. // target (below) where the lower left corner of a square would // touch the center of the bottom of the keel. Using that as the // (X, Y) position on a line with a slope of -1 and using // y = mx + b, we can now solve for the y intercept and x // intercept, which will accurately place the main outer // support beams: // // y = mx + b // x = y // m = -1 // x = -x + b // 2x = b // // So, 2 * target will give the proper placement of the two // main outer support beams long = 16; // Length of long beam short = 10; // Length of short beam side = 0.5; // Size of square cross-section (X by Y) hypot = sin(45) * side; // Length of cross-section diagonal spread = (long - 5) * 0.5; // Y distance from origin inner = true; outer = false; // used for struts target = (1 + (3.5 * sin(45))) * side; // for main outer supports module V_Joints(placement) { // // A pair of gold V joints (four beams total) // // placement = distance from center // Values from 0 to (0.5 * long) - side) union() { translate([0, placement, 0]) color("gold") cube([long, side, side]); // Long beam translate([0, placement - side, 0]) color("gold") cube([side, side, long]); // Long beam } union() { translate([0, -placement, 0]) color("gold") cube([long, side, side]); // Long beam translate([0, -placement - side, 0]) color("gold") cube([side, side, long]); // Long beam } } module Keel() { // // A green "keel" // translate([side, 0, side]) // Move above and to the right translate([0, 0, hypot]) // Raise above horizontal plane rotate([0, 45, 0]) // Rotate around origin translate([0, -long * 0.5, 0]) // Center between joints color("green") cube([side, long, side]); // Long beam } module Cross_Beam() { // // A single blue cross-beam. Currently unused. // translate([-(short - side) * 0.5 * sin(45), -side * 0.5, (short - side) * 0.5 * sin(45)]) translate([hypot, 0, hypot]) translate([side, 0, side]) translate([0, 0, hypot]) rotate([0, 45, 0]) color("blue") cube([short, side, side]); // Short beam } module Cross_Beams(offset) { // // A pair of blue cross-beams // // offset: Distance from center // Values: Between (0.5 * side) and (spread - 0.75) // translate([0, offset, 0]) translate([-(short - side) * 0.5 * sin(45), -side * 0.5, (short - side) * 0.5 * sin(45)]) translate([hypot, 0, hypot]) translate([side, 0, side]) translate([0, 0, hypot]) rotate([0, 45, 0]) color("blue") cube([short, side, side]); // Short beam translate([0, -offset, 0]) translate([-(short - side) * 0.5 * sin(45), -side * 0.5, (short - side) * 0.5 * sin(45)]) translate([hypot, 0, hypot]) translate([side, 0, side]) translate([0, 0, hypot]) rotate([0, 45, 0]) color("blue") cube([short, side, side]); // Short beam } module Outer_Supports(placement) { // // A pair of red top outer supports under cross-beams // // placement: ... // translate([0, 0, placement]) translate([(-sqrt(2) * side), -long * 0.5, 0]) rotate([0, 45, 0]) color("red") cube([side, long, side]); translate([placement, 0, 0]) translate([-hypot, -long * 0.5, -hypot]) rotate([0, 45, 0]) color("red") cube([side, long, side]); } module Struts(placement, inner) { // // Additional pairs of red supports // // placement: Number of feet from bottom of V joint // Values from 0 to "long" // inner: Place struts beneath V joint? // Values: inner (true) or outer (false) // shift = inner ? 2 * side: 0; translate([shift, 0, placement]) translate([(-side), -long * 0.5, 0]) color("red") cube([side, long, side]); translate([placement, 0, shift]) translate([0, -long * 0.5, -side]) color("red") cube([side, long, side]); } module Main() { translate([0, 0, 16.5*sin(45)]) rotate([0, 135, 0]) // "origin" now at top center with Z increasing down and "right" // and X increasing down and "left" union() { V_Joints(spread); // Long beams Keel(); // Long beam Cross_Beams(spread - 0.75); // Short beams Outer_Supports(2*target); // Main outer supports (long) Struts(14, outer); // Additional supports (long) Struts( 8, outer); // Additional supports (long) } } Main();