Files
ft-parts/buildingblocks.scad
T
2026-04-05 20:11:23 +02:00

318 lines
13 KiB
OpenSCAD

// straight and angeled building blocks
//----------------------- parameters ---------------------------
/* [Block type] */
// Type
Block_type = 0; // [0 : no output, 1:Basic block, 2:Angle block, 3:Symmetric angle block]
/* [Block options] */
// Length of a block
Block_length = 30; // [15.0 : 15.0 : 120.0]
// Is this a flat block (7.5mm)?
Flat_block = false;
// Number of pins
Pins = 1; // [0, 1, 2]
// A hole in the middle of the block?
Has_bore=false;
// Square holes in the middle?
Is_square = false;
/* [Options for the angle block] */
// Angle of the top side
Angle = 7.5;
// Use a pin on the standard angle block?
With_pin = true;
/* [Add. options for the sym. angle block] */
// Which pins should be used?
Which_pins = 3; // [0: Nothing, 1:left side, 2:right side, 3:both sides]
// Which grooves should be used?
Which_grooves = 2; // [0: Nothing, 1:left side, 2:right side, 3:both sides]
// Which kind of groove at the bottom if no grooves on the sides
Which_bottom_groove = 2; // [0: None, 1:Flat groove, 2:Round groove]
// Use short grooves (applied to all grooves)
Has_short_grooves = true;
/* [Hidden] */
// **********************
// ** Static Settings: **
// **********************
include<ft_util.scad>
// --------------------------------------------------------------------
// A basic block 7,5 or 15 x 15 of arbitrary length.
// The 15 x 15 block may have 0 - 2 pins at the small side of the block
// and a hole (either round or a sqare).
// If the small side has no pin, a groove is placed instead of the pin
// The default is a block of 30 mm with a pin and a groove and
// without hole at the center
// The flat block 7.5 x 15 has flat grooves on the long side and round
// holes at the small side. It also has no pins or grooves at the
// bottom or top and no hole in the middle.
// --------------------------------------------------------------------
module basic_block(length=30, pins=1, flatblock = false, bore=false, squarehole=false) {
y_offset = flatblock ? (BASIC_BLOCK_SIZE / 2) : BASIC_BLOCK_SIZE;
difference() {
// First, build the block and cut out the four grooves at the
// long sides
cube([BASIC_BLOCK_SIZE, y_offset, length], center=true);
translate([0, -y_offset/2 ,0])
rotate ([0, 0, 0])
if (flatblock)
flat_groove(length);
else
round_groove(length);
translate([BASIC_BLOCK_HALF, 0, 0])
rotate([0, 0, 90])
round_groove(length);
translate([0, y_offset/2, 0])
rotate([0, 0, 180])
if (flatblock)
flat_groove(length);
else
round_groove(length);
translate([-BASIC_BLOCK_HALF, 0, 0])
rotate([0, 0, 270])
round_groove(length);
// Then, cut out the grooves at the top and bottom as required
if (!flatblock)
top_grooves(length, pins);
// Do we have a hole through the block?
if (!flatblock && bore) {
rotate ([90, 0, 0])
cylinder(h = BASIC_BLOCK_SIZE + MANIFOLD_CORRECTION, r = 2, center = true);
// and if yes, does it have square endings?
if (squarehole) {
translate([0, (BASIC_BLOCK_SIZE - 4.5) / 2, 0])
cube(4.51, center=true);
translate([0, -(BASIC_BLOCK_SIZE - 4.5) / 2, 0])
cube(4.51, center=true);
}
}
}
// Finally add the pins as required
if (!flatblock)
top_pins(length, pins);
}
// --------------------------------------------------------------------
// add the grooves at the top and bottom of the block
// --------------------------------------------------------------------
module top_grooves(length = 30, pins = 1) {
// small correction value for the cutouts
mfc = 0.01;
if (pins < 2) {
translate([0, 0, -length / 2]) {
rotate([90, 0, 0])
round_groove(len = BASIC_BLOCK_SIZE, endcube = 3);
}
// translate([0, BASIC_BLOCK_HALF - GROOVE_RADIUS, -(length - 4.5) / 2])
// cube(GROOVE_RADIUS * 2 + mfc, center=true);
// translate([0, -(BASIC_BLOCK_HALF - GROOVE_RADIUS), -(length - 4.5) / 2])
// cube(GROOVE_RADIUS * 2 + mfc, center=true);
}
if (pins == 0) {
translate([0, 0, length / 2]){
rotate([270, 0, 0])
round_groove(len = BASIC_BLOCK_SIZE, endcube = 3);
}
// translate([0, BASIC_BLOCK_HALF - GROOVE_RADIUS, (length - 4.5) / 2])
// cube(GROOVE_RADIUS * 2 + mfc, center=true);
// translate([0, -BASIC_BLOCK_HALF - GROOVE_RADIUS, (length - 4.5) / 2])
// cube(GROOVE_RADIUS * 2 + mfc, center=true);
}
}
// --------------------------------------------------------------------
// add the pins at the top and bottom of the block
// --------------------------------------------------------------------
module top_pins(length = 30, pins = 1) {
if (pins > 0) {
translate([0, 0, length / 2 - 0.01])
pin(diameter = PIN_DIAMETER, base_width = PIN_BASE_WIDTH, base_length = PIN_BASE_LENGTH);
if (pins == 2) {
translate([0, 0, -length / 2 + 0.01])
rotate([180, 0, 0])
// pin(diameter = PIN_DIAMETER, base_width = PIN_BASE_WIDTH, base_length = PIN_BASE_LENGTH);
pin(diameter = PIN_DIAMETER, base_width = PIN_BASE_WIDTH, base_length = PIN_BASE_LENGTH);
}
}
}
// --------------------------------------------------------------------
// Angle blocks
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// An angle block to build the standard fischertechnik angle blocks
// with 7.5, 15 and 30 degrees. The blocks top and bottom use
// the fischertechnik 15 x 15 grid. It always has a round or flat
// groove at the bottom and may or may not have a pin at the top.
// Caveats:
// - Angles smaller than 6 degrees are unusable because the bottom
// groove intersects with the top surface.
// - Angles greater than 40 degrees look somehow weird because the
// trapezoid sides are quite large. The module is mainly ment for
// angles between the standard fischertechnik angles (from 7.5 to
// 30 degrees) which can not be constructed otherwise.
// - Angles greater than 72 degrees result in realy ugly blocks. Don't
// use them...
// --------------------------------------------------------------------
module angle_block(angle, with_pin=true) {
// calculate the radius based on the requested angle
radius = (angle^2 / 45) - (1.5 * angle) + 40;
// Center the block on the x and y axis
translate([radius, 0, 0])
rotate([270, 0, 0])
difference() {
union() {
// build the basic block
rotate_extrude(angle = angle, $fn = 5)
translate ([-radius, 0, 0])
square(BASIC_BLOCK_SIZE, center = true);
// and attach the pin if required
if(with_pin)
rotate([90, 0, angle])
translate([-radius, 0, 0])
pin();
}
// now remove the groove
translate([-radius, 0, 0])
rotate([0, 0, 180])
if (angle >= 15)
round_groove(BASIC_BLOCK_SIZE);
else
flat_groove(BASIC_BLOCK_SIZE);
}
}
// --------------------------------------------------------------------
// The symmetrical angle block is somehow special. fischertechnik only
// has the 60 degree blocks which are symetric by definition.
// This block has two variants: one with a groove and two pins and one
// with three grooves with a length of 7.5 + 2 mm to get a stable block.
// This module builds blocks with a given angle and two equal sides of
// 15 x 15mm (the fischertechnik grid).
// The length of the base varies, depending on the angle but does NOT
// fit in the fischertechnik grid (except the 60 degree part, of course).
// This module has a lot of parameters:
// angle: The angle between the two 15 x 15 sides
// pins: An integer describing the pins to use on the 15 x 15 sides:
// 0 - No pins at all
// 1 - One pin on the left
// 2 - One pin on the right
// 3 - Two pins, one on each side
// grooves: An integer describing the grooves to use on the 15 x 15
// sides:
// 0 - No grooves at all
// 1 - One groove on the left
// 2 - One groove on the right
// 3 - Two groove, one on each side
// bottom_groove: An integer describing the groove at the bottom.
// 0 - No groove at all
// 1 - A flat groove
// 2 - A round groove. Only used if no grooves are used on
// the 15 x 15 sides.
// short_grooves: Use short grooves instead of a groove through the
// complete block. Gives the block more stability. This
// parameter is applied to all grooves of the block.
// Caveats:
// - Three grooves make no sense if the angle is less than 60 degrees
// because in that case the grooves would overlap.
// - A groove in the bottom makes no sense if the angle is less than
// 30 degrees because it would produce walls which are too thin.
//
// --------------------------------------------------------------------
module symmetrical_angle_block(angle = 45, pins = 2, grooves = 1, bottom_groove = 2, short_grooves = true) {
// some trigonometric calculations for the resulting triangle
base = 2 * BASIC_BLOCK_SIZE * sin(angle / 2);
height = BASIC_BLOCK_SIZE * cos(angle / 2);
offset1 = sqrt(BASIC_BLOCK_HALF^2 - (height/2)^2) - 0.1;
// Calculate the length and position of the grooves based on
// whether we have short grooves or not
flat_groove_len = short_grooves ? BASIC_BLOCK_SIZE / 2 + 2 : BASIC_BLOCK_SIZE;
flat_groove_offset = short_grooves ? -2.75 : 0;
// If we have two pins, they always win ...
which_grooves = pins == 3 ? 0 : grooves;
// center the block
translate([0,-height/2,0])
difference() {
// Get the basic triangle
linear_extrude(height = BASIC_BLOCK_SIZE, center = true)
polygon(points = [[-base/2, 0 ],
[ base/2, 0 ],
[ 0, height]]);
// Now substract all the used grooves:
// Use a bottom groove at all?
if (bottom_groove > 0) {
// Then decide whether to use a flat or round groove
if (which_grooves == 0 && bottom_groove == 2)
round_groove(GROOVE_LENGTH);
else
translate([0, 0, flat_groove_offset])
flat_groove(flat_groove_len);
}
// Cut out the grooves, but only if no pin is on that side
// Remember: the pins always win ...
if (which_grooves > 0) {
if (is_set(which_grooves, 1) && !is_set(pins, 1)) {
translate([-offset1, height / 2, flat_groove_offset])
rotate([0, 0, -90 - angle / 2])
flat_groove(flat_groove_len);
}
if (is_set(which_grooves, 2) && !is_set(pins, 2)) {
translate([offset1, height / 2, flat_groove_offset])
rotate([0, 0, 90 + angle / 2])
flat_groove(flat_groove_len);
}
}
}
// If we have pins, just add them as required
if (pins > 0) {
if (is_set(pins, 1)) {
translate([-offset1, 0, 0])
rotate([-angle / 2, 270, 0])
pin();
}
if (is_set(pins, 2)) {
translate([offset1, 0, 0])
rotate([-angle / 2, 90, 0])
pin();
}
}
}
// --------------------------------------------------------------------
// small helper function to test whether bit 0 (decimal 1) or
// bit 1 (decimal 2) is set.
// Openscad has no bitwise operators :-(
// --------------------------------------------------------------------
function is_set(var, which) = (var == which || var == 3);
// ********************
// ** Build section: **
// ********************
module main() {
if (Block_type == 0) {
// cube_with_cylinder(dir="right");
// pin();
// round_groove();
eyelet();
}
else if (Block_type == 1) {
basic_block(length=Block_length, pins=Pins, flatblock= Flat_block, bore=Has_bore, squarehole=Is_square);
}
else if (Block_type == 2) {
angle_block(7.5, with_pin=With_pin);
translate ([20, 0, 0]) angle_block(15, with_pin=With_pin);
translate ([40, 0, 0]) angle_block(30, with_pin=With_pin);
}
else if (Block_type == 3) {
symmetrical_angle_block(Angle, pins = Which_pins, grooves = Which_grooves, bottom_groove = Which_bottom_groove, short_grooves=Has_short_grooves);
}
}
main();