3d_print/Sasza/celownik/Chamfer.scad
2025-06-02 12:26:09 +02:00

176 lines
7.8 KiB
OpenSCAD

/**
* This code is published under a
* Creative Commons Attribution-NonCommercial-ShareAlike 3.0
* licence, please respect it.
*
* Chamfered primitives for OpenSCAD v1.2 - By TimeWaster
*/
/**
* chamferCube returns an cube with 45° chamfers on the edges of the
* cube. The chamfers are diectly printable on Fused deposition
* modelling (FDM) printers without support structures.
*
* @param size The size of the cube along the [x, y, z] axis,
* example: [1, 2, 3]
* @param chamfers Which chamfers to render along the [x, y, z] axis,
* example: [[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]
* X axis: 4 values in clockwise order starting from
* the zero point, as seen from "Left view" (Ctrl + 6)
* Y axis: 4 values in clockwise order starting from
* the zero point, as seen from "Front view" (Ctrl + 8)
* Z axis: 4 values in clockwise order starting from
* the zero point, as seen from "Bottom view" (Ctrl + 5)
* @param ch The "height" of the chamfers as seen from
* one of the dimensional planes (The real
* length is side c in a right angled triangle)
*/
module chamferCube(size, chamfers = [undef, undef, undef], ch = 1, ph1 = 1, ph2 = undef, ph3 = undef, ph4 = undef, sizeX = undef, sizeY = undef, sizeZ = undef, chamferHeight = undef, chamferX = undef, chamferY = undef, chamferZ = undef) {
if(size[0]) {
chamferCubeImpl(size[0], size[1], size[2], ch, chamfers[0], chamfers[1], chamfers[2]);
} else {
// keep backwards compatibility
size = (sizeX == undef) ? size : sizeX;
chamfers = (sizeY == undef) ? chamfers : sizeY;
ch = (sizeZ == undef) ? ch : sizeZ;
ph1 = (chamferHeight == undef) ? ph1 : chamferHeight;
ph2 = (chamferX == undef) ? ph2 : chamferX;
ph3 = (chamferY == undef) ? ph3 : chamferY;
ph4 = (chamferZ == undef) ? ph4 : chamferZ;
chamferCubeImpl(size, chamfers, ch, ph1, ph2, ph3, ph4);
}
}
module chamferCubeImpl(sizeX, sizeY, sizeZ, chamferHeight, chamferX, chamferY, chamferZ) {
chamferX = (chamferX == undef) ? [1, 1, 1, 1] : chamferX;
chamferY = (chamferY == undef) ? [1, 1, 1, 1] : chamferY;
chamferZ = (chamferZ == undef) ? [1, 1, 1, 1] : chamferZ;
chamferCLength = sqrt(chamferHeight * chamferHeight * 2);
difference() {
cube([sizeX, sizeY, sizeZ]);
for(x = [0 : 3]) {
chamferSide1 = min(x, 1) - floor(x / 3); // 0 1 1 0
chamferSide2 = floor(x / 2); // 0 0 1 1
if(chamferX[x]) {
translate([-0.1, chamferSide1 * sizeY, -chamferHeight + chamferSide2 * sizeZ])
rotate([45, 0, 0])
cube([sizeX + 0.2, chamferCLength, chamferCLength]);
}
if(chamferY[x]) {
translate([-chamferHeight + chamferSide2 * sizeX, -0.1, chamferSide1 * sizeZ])
rotate([0, 45, 0])
cube([chamferCLength, sizeY + 0.2, chamferCLength]);
}
if(chamferZ[x]) {
translate([chamferSide1 * sizeX, -chamferHeight + chamferSide2 * sizeY, -0.1])
rotate([0, 0, 45])
cube([chamferCLength, chamferCLength, sizeZ + 0.2]);
}
}
}
}
/**
* chamferCylinder returns an cylinder or cone with 45° chamfers on
* the edges of the cylinder. The chamfers are diectly printable on
* Fused deposition modelling (FDM) printers without support structures.
*
* @param h Height of the cylinder
* @param r Radius of the cylinder (At the bottom)
* @param r2 Radius of the cylinder (At the top)
* @param ch The "height" of the chamfer at radius 1 as
* seen from one of the dimensional planes (The
* real length is side c in a right angled triangle)
* @param ch2 The "height" of the chamfer at radius 2 as
* seen from one of the dimensional planes (The
* real length is side c in a right angled triangle)
* @param a The angle of the visible part of a wedge
* starting from the x axis counter-clockwise
* @param q A circle quality factor where 1.0 is a fairly
* good quality, range from 0.0 to 2.0
*/
module chamferCylinder(h, r, r2 = undef, ch = 1, ch2 = undef, a = 0, q = -1.0, height = undef, radius = undef, radius2 = undef, chamferHeight = undef, chamferHeight2 = undef, angle = undef, quality = undef) {
// keep backwards compatibility
h = (height == undef) ? h : height;
r = (radius == undef) ? r : radius;
r2 = (radius2 == undef) ? r2 : radius2;
ch = (chamferHeight == undef) ? ch : chamferHeight;
ch2 = (chamferHeight2 == undef) ? ch2 : chamferHeight2;
a = (angle == undef) ? a : angle;
q = (quality == undef) ? q : quality;
height = h;
radius = r;
radius2 = (r2 == undef) ? r : r2;
chamferHeight = ch;
chamferHeight2 = (ch2 == undef) ? ch : ch2;
angle = a;
quality = q;
module cc() {
upperOverLength = (chamferHeight2 >= 0) ? 0 : 0.01;
lowerOverLength = (chamferHeight >= 0) ? 0 : 0.01;
cSegs = circleSegments(max(radius, radius2), quality);
if(chamferHeight >= 0 || chamferHeight2 >= 0) {
hull() {
if(chamferHeight2 > 0) {
translate([0, 0, height - abs(chamferHeight2)]) cylinder(abs(chamferHeight2), r1 = radius2, r2 = radius2 - chamferHeight2, $fn = cSegs);
}
translate([0, 0, abs(chamferHeight)]) cylinder(height - abs(chamferHeight2) - abs(chamferHeight), r1 = radius, r2 = radius2, $fn = cSegs);
if(chamferHeight > 0) {
cylinder(abs(chamferHeight), r1 = radius - chamferHeight, r2 = radius, $fn = cSegs);
}
}
}
if(chamferHeight < 0 || chamferHeight2 < 0) {
if(chamferHeight2 < 0) {
translate([0, 0, height - abs(chamferHeight2)]) cylinder(abs(chamferHeight2), r1 = radius2, r2 = radius2 - chamferHeight2, $fn = cSegs);
}
translate([0, 0, abs(chamferHeight) - lowerOverLength]) cylinder(height - abs(chamferHeight2) - abs(chamferHeight) + lowerOverLength + upperOverLength, r1 = radius, r2 = radius2, $fn = cSegs);
if(chamferHeight < 0) {
cylinder(abs(chamferHeight), r1 = radius - chamferHeight, r2 = radius, $fn = cSegs);
}
}
}
module box(brim = abs(min(chamferHeight2, 0)) + 1) {
translate([-radius - brim, 0, -brim]) cube([radius * 2 + brim * 2, radius + brim, height + brim * 2]);
}
module hcc() {
intersection() {
cc();
box();
}
}
if(angle <= 0 || angle >= 360) cc();
else {
if(angle > 180) hcc();
difference() {
if(angle <= 180) hcc();
else rotate([0, 0, 180]) hcc();
rotate([0, 0, angle]) box(abs(min(chamferHeight2, 0)) + radius);
}
}
}
/**
* circleSegments calculates the number of segments needed to maintain
* a constant circle quality.
* If a globalSegementsQuality variable exist it will overwrite the
* standard quality setting (1.0). Order of usage is:
* Standard (1.0) <- globalCircleQuality <- Quality parameter
*
* @param r Radius of the circle
* @param q A quality factor, where 1.0 is a fairly good
* quality, range from 0.0 to 2.0
*
* @return The number of segments for the circle
*/
function circleSegments(r, q = -1.0) = (q >= 3 ? q : ((r * PI * 4 + 40) * ((q >= 0.0) ? q : globalCircleQuality)));
// set global quality to 1.0, can be overridden by user
globalCircleQuality = 1.0;