242 lines
No EOL
8.6 KiB
Microcad
242 lines
No EOL
8.6 KiB
Microcad
/// Ported from https://github.com/Zergie/gridfinity-UltraLight, not all features are supported
|
|
|
|
use std::ops::*;
|
|
use std::geo3d::*;
|
|
use std::geo2d::*;
|
|
use std::debug::assert;
|
|
|
|
const MagnetDiameter = 6.15mm;
|
|
const MagnetDepth = 2.2mm;
|
|
const WallThickness = 1.0mm;
|
|
const OffsetXY = 0.25mm;
|
|
pub const BasicUnitXY = 42.0mm;
|
|
pub const BasicUnitZ = 7.0mm;
|
|
const BasicRadius1 = 4.0mm;
|
|
const BasicRadius2 = 8.0mm;
|
|
const TopClearanceOffset = 0.6mm;
|
|
const StackingLipWidth = 2.6mm;
|
|
const LabelHeight = 1.0mm;
|
|
const MagnetRadius = 0.5 * MagnetDiameter;
|
|
|
|
/// Like std::geo3d::Cube, but not centered
|
|
part CornerCube(width: Length, height: Length, depth: Length) {
|
|
Rect(width, height, x = 0mm, y = 0mm).extrude(z = depth)
|
|
}
|
|
|
|
part BinClean(gridsX: Scalar, gridsY: Scalar, gridsZ: Scalar, magents: Bool) {
|
|
baseCleans = BinBaseCleanSingle(startX = [0..gridsX - 1] * BasicUnitXY, startY = [0..gridsY - 1] * BasicUnitXY, magents);
|
|
|
|
xCorners = [BasicRadius1, (gridsX * BasicUnitXY) - BasicRadius1];
|
|
yCorners = [BasicRadius1, (gridsY * BasicUnitXY) - BasicRadius1];
|
|
|
|
radius0 = BasicRadius1 - OffsetXY;
|
|
height0 = 4.40mm;
|
|
|
|
around = CornerCube(width = gridsX * BasicUnitXY, height = gridsY * BasicUnitXY, depth = gridsZ * BasicUnitZ) -
|
|
Cylinder(height = gridsZ * BasicUnitZ, radius = radius0, offset = 0mm).translate(x = xCorners, y = yCorners).hull();
|
|
|
|
bellowHeight = 12.0mm;
|
|
bellow = CornerCube(width = gridsX * BasicUnitXY, height = gridsY * BasicUnitXY, depth = bellowHeight).translate(z = -bellowHeight);
|
|
|
|
around | baseCleans | bellow
|
|
}
|
|
|
|
part BinBaseCleanSingle(startX: Length = 0.0mm, startY: Length = 0.0mm, widthX = 1.0, widthY = 1.0, magents: Bool) {
|
|
radius0 = 1.05mm - OffsetXY;
|
|
radius1 = 1.85mm - OffsetXY;
|
|
radius2 = BasicRadius1 - OffsetXY;
|
|
height0 = 0.80mm;
|
|
height1 = 1.80mm;
|
|
height2 = 2.15mm;
|
|
|
|
base = CornerCube(width = widthX * BasicUnitXY, height = widthY * BasicUnitXY, depth = height0 + height1 + height2)
|
|
.translate(x = startX, y = startY);
|
|
|
|
corners = (
|
|
x = [startX + BasicRadius1, startX + (widthX * BasicUnitXY) - BasicRadius1],
|
|
y = [startY + BasicRadius1, startY + (widthY * BasicUnitXY) - BasicRadius1]
|
|
);
|
|
|
|
cutout = HullStack(corners, heights = [height0, height1, height2], radii = [
|
|
radius0,
|
|
radius1,
|
|
radius1,
|
|
radius2
|
|
]);
|
|
|
|
if (magents & (widthX == 1.0) & (widthY == 1.0)) {
|
|
(base - cutout) | MagnetHoles(startX, startY)
|
|
} else {
|
|
base - cutout
|
|
}
|
|
}
|
|
|
|
part MagnetHoles(startX: Length = 0.0mm, startY: Length = 0.0mm) {
|
|
xCorners = [startX + BasicRadius2, startX + BasicUnitXY - BasicRadius2];
|
|
yCorners = [startY + BasicRadius2, startY + BasicUnitXY - BasicRadius2];
|
|
|
|
Cylinder(height = MagnetDepth, radius = MagnetRadius, offset = 0mm).translate(x = xCorners, y = yCorners)
|
|
}
|
|
|
|
part BinBody(gridsX: Scalar, gridsY: Scalar, gridsZ: Scalar, hollow: Bool) {
|
|
radius0 = BasicRadius1 - OffsetXY;
|
|
height0 = 4.75mm;
|
|
height1 = 7.0mm - height0;
|
|
height2 = (gridsZ - 1) * BasicUnitZ;
|
|
|
|
corners = (
|
|
x = [BasicRadius1, gridsX * BasicUnitXY - BasicRadius1],
|
|
y = [BasicRadius1, gridsY * BasicUnitXY - BasicRadius1]
|
|
);
|
|
|
|
base = Cylinder(height = height1 + height2, radius = radius0, offset = 0mm)
|
|
.translate(x = corners.x, y = corners.y, height0)
|
|
.hull();
|
|
cutout = Cylinder(height = height1 + height2, radius = radius0 - WallThickness, offset = 0mm)
|
|
.translate(x = corners.x, y = corners.y, height0)
|
|
.hull();
|
|
|
|
if hollow {
|
|
base - cutout
|
|
} else {
|
|
base
|
|
}
|
|
}
|
|
|
|
part BinBaseSingle(startX: Length = 0.0mm, startY: Length = 0.0mm, widthX = 1.0, widthY = 1.0, magents: Bool, ultraLight: Bool) {
|
|
radius0 = 1.05mm - OffsetXY;
|
|
radius1 = 1.85mm - OffsetXY;
|
|
radius2 = BasicRadius1 - OffsetXY;
|
|
height0 = 0.80mm;
|
|
height1 = 1.80mm;
|
|
height2 = 2.15mm;
|
|
|
|
corners = (
|
|
x = [startX + BasicRadius1, startX + widthX * BasicUnitXY - BasicRadius1],
|
|
y = [startY + BasicRadius1, startY + widthY * BasicUnitXY - BasicRadius1]
|
|
);
|
|
|
|
outside = CornerCube(width = widthX * BasicUnitXY, height = widthY * BasicUnitXY, depth = height0 + height1 + height2 + WallThickness)
|
|
.translate(x = startX, y = startY);
|
|
|
|
ultraLightCutout = HullStack(
|
|
corners,
|
|
heights = [
|
|
height0 - 0.5858 * WallThickness,
|
|
height1,
|
|
height2,
|
|
1.4142 * WallThickness
|
|
],
|
|
radii = [
|
|
radius0 - 0.4142 * WallThickness,
|
|
radius1 - WallThickness,
|
|
radius1 - WallThickness,
|
|
radius2 - WallThickness,
|
|
radius2
|
|
],
|
|
offset = WallThickness
|
|
);
|
|
|
|
|
|
showMagnets = magents & (widthX == 1.0) & (widthY == 1.0);
|
|
magnetCutout = MagnetHoles(startX, startY);
|
|
|
|
magnetXCorners = [startX + BasicRadius2, startX + widthX * BasicUnitXY - BasicRadius2];
|
|
magnetYCorners = [startY + BasicRadius2, startY + widthY * BasicUnitXY - BasicRadius2];
|
|
magnetOutside = Cylinder(height = MagnetDepth + WallThickness, radius = MagnetRadius + WallThickness, offset = 0mm).translate(x = magnetXCorners, y = magnetYCorners) - magnetCutout;
|
|
|
|
if (ultraLight & showMagnets) {
|
|
(outside - ultraLightCutout - magnetCutout) | magnetOutside;
|
|
} else if (ultraLight) {
|
|
outside - ultraLightCutout;
|
|
} else if (showMagnets) {
|
|
(outside | magnetOutside) - magnetCutout;
|
|
} else {
|
|
outside
|
|
}
|
|
}
|
|
|
|
part BinBase(gridsX: Scalar, gridsY: Scalar, gridsZ: Scalar, magents: Bool, ultraLight: Bool) {
|
|
BinBaseSingle(startX = [0..gridsX - 1] * BasicUnitXY, startY = [0..gridsY - 1] * BasicUnitXY, magents, ultraLight);
|
|
}
|
|
|
|
part BinStacklip(gridsX: Scalar, gridsY: Scalar, gridsZ: Scalar) {
|
|
radius0 = 1.15mm;
|
|
radius1 = 1.85mm;
|
|
radius2 = BasicRadius1 - OffsetXY;
|
|
height0 = StackingLipWidth - WallThickness;
|
|
height1 = 0.60mm;
|
|
height2 = 0.70mm;
|
|
height3 = 1.80mm;
|
|
height4 = 1.90mm;
|
|
height5 = 0.75mm;
|
|
heightStart = (gridsZ * BasicUnitZ) - (height0 + height1);
|
|
|
|
xCorners = [BasicRadius1, gridsX * BasicUnitXY - BasicRadius1];
|
|
yCorners = [BasicRadius1, gridsY * BasicUnitXY - BasicRadius1];
|
|
|
|
outer = Cylinder(height = height0 + height1 + height2 + height3 + height4 + height5, radius = radius2, offset = 0mm).translate(x = xCorners, y = yCorners, z = heightStart).hull();
|
|
|
|
cutouts = HullStack((x = xCorners, y= yCorners), heights = [height0, height1, height2, height3, height4, height5], radii = [
|
|
radius2 - WallThickness,
|
|
radius0,
|
|
radius0,
|
|
radius1,
|
|
radius1,
|
|
radius2,
|
|
radius2
|
|
], offset = heightStart);
|
|
|
|
outer - cutouts
|
|
}
|
|
|
|
part HullStack(corners: (x: [Length], y: [Length]), heights: [Length], radii: [Length], offset: Length = 0mm) {
|
|
assert(heights.count() == radii.count() - 1, "radii must be an array with one more elements that heights");
|
|
|
|
self = Cylinder(height = heights.head(), radius_bottom = radii.head(), radius_top = radii.tail().head(), offset)
|
|
.translate(x = corners.x, y = corners.y).hull();
|
|
if heights.count() > 1 {
|
|
self | HullStack(corners, heights = heights.tail(), radii = radii.tail(), offset = offset + heights.head())
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
|
|
// A basic bin
|
|
pub part Bin(gridsX = 1, gridsY = 1, gridsZ = 1, magents: Bool = false, ultraLight: Bool = false, center: Bool = true) {
|
|
bin = BinBody(gridsX, gridsY, gridsZ, hollow = true) |
|
|
BinBase(gridsX, gridsY, gridsZ, magents, ultraLight) |
|
|
BinStacklip(gridsX, gridsY, gridsZ) -
|
|
BinClean(gridsX, gridsY, gridsZ, magents);
|
|
if center {
|
|
bin.translate(x = -gridsX * BasicUnitXY / 2, y = -gridsY * BasicUnitXY / 2)
|
|
} else {
|
|
bin
|
|
}
|
|
}
|
|
|
|
part Box_(gridsX = 1, gridsY = 1, gridsZ = 1, magents: Bool = false, lip: Bool = true, center: Bool = true) {
|
|
if lip {
|
|
BinBody(gridsX, gridsY, gridsZ, hollow = false) |
|
|
BinBase(gridsX, gridsY, gridsZ, magents, ultraLight = false) |
|
|
BinStacklip(gridsX, gridsY, gridsZ) -
|
|
BinClean(gridsX, gridsY, gridsZ, magents)
|
|
} else {
|
|
BinBody(gridsX, gridsY, gridsZ, hollow = false) |
|
|
BinBase(gridsX, gridsY, gridsZ, magents, ultraLight = false) -
|
|
BinClean(gridsX, gridsY, gridsZ, magents)
|
|
}
|
|
}
|
|
|
|
/// A solid box, intended as the base for custom cutouts
|
|
pub part Box(gridsX = 1, gridsY = 1, gridsZ = 1, magents: Bool = false, lip: Bool = true, center: Bool = true) {
|
|
box = Box_(gridsX, gridsY, gridsZ, magents, lip, center);
|
|
if center {
|
|
box.translate(x = -gridsX * BasicUnitXY / 2, y = -gridsY * BasicUnitXY / 2)
|
|
} else {
|
|
box
|
|
}
|
|
}
|
|
|
|
|
|
Box(gridsX = 2) |