Skip to content

Instantly share code, notes, and snippets.

@tomash
Created December 19, 2019 22:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomash/739e313dc8f9fcc298ed082e6ca844db to your computer and use it in GitHub Desktop.
Save tomash/739e313dc8f9fcc298ed082e6ca844db to your computer and use it in GitHub Desktop.
customizable dropper bottle holder ported to OpenJSCad
// title : Customizable Dropper Bottle Holder
// author : Jean Philippe Neumann, Tomasz Stachewicz
// license : Creative Commons Attribution-ShareAlike 3.0 Unported License
// see http://creativecommons.org/licenses/by-sa/3.0/
// URL : http://www.thingiverse.com/thing:60212
// revision : 0.001
// tags : paint,dropper,bottle,holder
// file : dropper_bottle_holder.jscad
/* setup */
var a, b, borderStrength, bottleBody, bottleBodyDiameter, bottleBodyDiff, bottleBodyRadius, bottleCap, bottleCapDiameter, bottleCavityStrength, c, capHoleHeight, column, columns, depth, extraPillar, holeDiffY, holeTmp, i, isEven, isNotEven, j, maxColumn, maxColumnInEvenRows, maxRow, pillar, pillarA1, pillarA2, pillarB1, pillarB2, pillarStrength, placePillarAbove, placePillarAboveAndRight, placePillarBelow, placePillarBelowAndRight, placePillarLeft, placePillarRight, planeBottom, planeHeightDiff, planeStrengthBottom, planeStrengthTop, planeTop, ref, ref1, row, rows, shape, topRightOrBottomRightPillarPlaced, width;
// main parameters
columns = 3;
rows = 3;
// detail parameters
planeStrengthTop = 4;
planeStrengthBottom = 6;
capHoleHeight = 2;
bottleCavityStrength = 3;
planeHeightDiff = 25;
bottleBodyDiameter = 27.5;
bottleCapDiameter = 8;
borderStrength = 2.5;
// derived parameters
maxColumn = columns - 1;
maxColumnInEvenRows = maxColumn - 1;
maxRow = rows - 1;
bottleBodyRadius = bottleBodyDiameter / 2;
pillarStrength = borderStrength;
bottleBodyDiff = borderStrength + bottleBodyDiameter;
//# calculating the distance between rows with the pythagorean theorem
//# c = hypotenuse between the centers of holes in adjacent rows
c = bottleBodyDiameter + borderStrength;
//# b = cathetus between (the center between two holes on the same row) and (the center of one of the holes)
b = borderStrength / 2 + bottleBodyRadius;
//# a = cathetus between (the center between two holes on the same row) and (the center of the hole directly above it)
a = Math.sqrt(c * c - b * b);
holeDiffY = a;
//# size of the object
width = borderStrength + bottleBodyDiff * columns;
depth = borderStrength + bottleBodyDiff + holeDiffY * maxRow;
/* helper functions */
isNotEven = function(num) {
return !isEven(num);
};
isEven = function(num) {
if (num % 2 === 0) {
return true;
} else {
return false;
}
};
placePillarAbove = function() {
var color, pillar, xDiff;
xDiff = 0;
color = [];
if (isNotEven(row)) {
xDiff = bottleBodyDiff / 2;
color = [0.8, 0.1, 0.1];
} else {
color = [0.1, 0.8, 0.1];
}
pillar = pillarB1.translate([bottleBodyDiff * column + bottleBodyDiff / 2, 0, 0]);
pillar = pillar.setColor(color);
return shape.union(pillar);
};
placePillarAboveAndRight = function() {
var color, pillar, xDiff;
xDiff = 0;
color = [];
if (isNotEven(row)) {
xDiff = bottleBodyDiff / 2;
color = [0.8, 0.1, 0.4];
} else {
color = [0.1, 0.8, 0.4];
}
pillar = pillarB1.translate([bottleBodyDiff * (column + 1), 0, 0]);
pillar = pillar.setColor(color);
return shape.union(pillar);
};
placePillarRight = function() {
var color, pillar, xDiff;
xDiff = 0;
color = [];
if (isNotEven(row)) {
xDiff = bottleBodyDiff / 2;
color = [0.8, 0.4, 0.1];
} else {
color = [0.4, 0.8, 0.1];
}
pillar = extraPillar.translate([bottleBodyDiff * column + bottleBodyDiff / 2 + xDiff, holeDiffY * row, 0]);
pillar = pillar.setColor(color);
return shape.union(pillar);
};
placePillarLeft = function() {
var color, pillar, xDiff;
xDiff = 0;
color = [];
if (isNotEven(row)) {
xDiff = bottleBodyDiff / 2;
color = [0.8, 0.4, 0.8];
} else {
color = [0.4, 0.8, 0.8];
}
pillar = extraPillar.translate([bottleBodyDiff * column - bottleBodyDiff / 2 - xDiff, holeDiffY * row, 0]);
pillar = pillar.setColor(color);
return shape.union(pillar);
};
placePillarBelow = function() {
var color, pillar, xDiff;
xDiff = 0;
if (isNotEven(row)) {
xDiff = bottleBodyDiff / 2;
color = [0.6, 0.3, 0.3];
} else {
color = [0.3, 0.6, 0.3];
}
pillar = pillarA1.translate([bottleBodyDiff * column + xDiff + bottleBodyDiff / 2, 0, 0]);
pillar = pillar.setColor(color);
return shape.union(pillar);
};
placePillarBelowAndRight = function() {
var color, pillar, xDiff;
xDiff = 0;
if (isNotEven(row)) {
xDiff = bottleBodyDiff / 2;
color = [0.6, 0.3, 0.6];
} else {
color = [0.3, 0.6, 0.6];
}
pillar = pillarA1.translate([bottleBodyDiff * (column + 1), 0, 0]);
pillar = pillar.setColor(color);
return union(shape, pillar);
};
/* modeling */
function main() {
planeBottom = cube({size: [width, depth, planeStrengthBottom]});
planeTop = cube({size: [width, depth, planeStrengthTop]});
planeTop = planeTop.translate([0, 0, planeHeightDiff]);
shape = planeBottom.union(planeTop);
pillar = cube({size: [pillarStrength, pillarStrength, planeHeightDiff]});
pillar = pillar.setColor([1, 1, 0]);
extraPillar = pillar.translate([borderStrength / 2 + bottleBodyRadius, borderStrength / 2 + bottleBodyRadius, 0]);
pillarA1 = pillar.translate([0, 0, 0]);
pillarA2 = pillar.translate([width - pillarStrength, 0, 0]);
pillarB1 = pillar.translate([0, depth - pillarStrength, 0]);
pillarB2 = pillar.translate([width - pillarStrength, depth - pillarStrength, 0]);
shape = shape.union(pillarA1).union(pillarA2).union(pillarB1).union(pillarB2);
bottleBody = cylinder({
h: planeHeightDiff + planeStrengthBottom + planeStrengthTop,
r: bottleBodyRadius,
center: true
});
bottleBody = bottleBody.translate([0, 0, planeHeightDiff + planeStrengthBottom * 2 + planeStrengthTop - bottleCavityStrength]);
bottleCap = cylinder({
h: capHoleHeight,
r: bottleCapDiameter / 2,
center: true
});
bottleCap = bottleCap.translate([0, 0, capHoleHeight]);
bottleBody = union(bottleBody, bottleCap);
bottleBody = bottleBody.translate([borderStrength + bottleBodyRadius, borderStrength + bottleBodyRadius, 0]);
for (column = i = 0, ref = maxColumn; 0 <= ref ? i <= ref : i >= ref; column = 0 <= ref ? ++i : --i) {
holeTmp = [];
for (row = j = 0, ref1 = maxRow; 0 <= ref1 ? j <= ref1 : j >= ref1; row = 0 <= ref1 ? ++j : --j) {
if (isNotEven(row)) {
if (column !== maxColumn) {
holeTmp = bottleBody.translate([bottleBodyDiff * column + bottleBodyDiff / 2, holeDiffY * row, 0]);
holeTmp = holeTmp.setColor([1, 0, 0]);
if (rows > 2) {
if (isEven(columns)) {
if (column < maxColumnInEvenRows / 2 && isEven(column)) {
shape = placePillarRight();
} else if (column > maxColumnInEvenRows / 2 - 1 && !isEven(column)) {
shape = placePillarRight();
}
} else if (isEven(column)) {
shape = placePillarRight();
}
}
}
} else {
holeTmp = bottleBody.translate([bottleBodyDiff * column, holeDiffY * row, 0]);
holeTmp = holeTmp.setColor([0, 1, 0]);
if (rows > 3) {
if (column === 0 && row !== 0 && row !== maxRow) {
shape = placePillarLeft();
}
if (column === maxColumn && row !== 0 && row !== maxRow) {
shape = placePillarRight();
}
}
topRightOrBottomRightPillarPlaced = false;
if (row === 0 && (!isEven(columns) && isEven(column) && column > 0 && column < maxColumn)) {
shape = placePillarBelow();
}
if (row === 0 && (isEven(columns) && !isEven(column) && column < maxColumn)) {
shape = placePillarBelowAndRight();
topRightOrBottomRightPillarPlaced = true;
}
if (row === maxRow && (!isEven(columns) && isEven(column) && column > 0 && column < maxColumn)) {
shape = placePillarAbove();
}
if (row === maxRow && (isEven(columns) && !isEven(column) && column < maxColumn)) {
shape = placePillarAboveAndRight();
topRightOrBottomRightPillarPlaced = true;
}
if (rows !== 1 && isEven(columns) && column === columns / 2 - 1 && !topRightOrBottomRightPillarPlaced) {
shape = placePillarRight();
}
}
shape = difference(shape,holeTmp);
}
}
return shape;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment