Skip to content

Instantly share code, notes, and snippets.

@fischman
Last active October 7, 2016 02:37
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 fischman/1bee89022275764f74c927b43c9ec0e6 to your computer and use it in GitHub Desktop.
Save fischman/1bee89022275764f74c927b43c9ec0e6 to your computer and use it in GitHub Desktop.
const badgeWidth = 60; // Really 54mm; extra wiggle for the folds.
const badgeHeight = 90; // Really 85.55mm
const notchHeight = 3.5; // Really 2.5mm
const notchWidth = 14; // Really 12.5mm
const cornerRadius = 2;
// The wings hold the badge sides by being folded over along the Y axis.
const wingWidthRatio = 0.2;
const wingHeightRatio = 0.8;
const wingWidth = wingWidthRatio * badgeWidth;
const wingHeight = wingHeightRatio * badgeHeight;
// The flap holds the badge from below by being folded upwards along
// the X axis.
const flapHeightRatio = 1 - wingHeightRatio;
const flapWidthRatio = 1 - 2*wingWidthRatio;
function getParameterDefinitions() {
return [
{ name: 'layer',
type: 'choice',
values: ['folds', 'outline'],
captions: ['Mark (folds)', 'Cut (outline)'],
caption: 'Layer to render',
},
];
}
function main(params) {
switch (params.layer) {
case 'outline':
return outline();
case 'folds':
return folds();
default:
throw 'Unexpected layer: ' + params.layer;
}
}
function outline() {
var o = [];
o.push(roundedRectangle({
corner1: [0, 0],
corner2: [badgeWidth, badgeHeight],
roundradius: cornerRadius,
}));
const leftWing = roundedRectangle({
corner1: [-wingWidth, badgeHeight-wingHeight],
corner2: [0, badgeHeight],
roundradius: cornerRadius,
});
const rightWing = leftWing.mirroredX().translate([badgeWidth, 0, 0]);
o.push(leftWing);
o.push(rightWing);
const flapHeight = flapHeightRatio * badgeHeight;
const flap = roundedRectangle({
corner1: [0, 0],
corner2: [badgeWidth, -flapHeight],
roundradius: cornerRadius,
}).union(roundedRectangle({
corner1: [wingWidth, -flapHeight],
corner2: [badgeWidth-wingWidth, -badgeHeight],
roundradius: cornerRadius,
squareCorners: [0, 1],
outerFilletCorners: [2,3],
}));
o.push(flap);
const notchBaseWidth = badgeWidth - 2*wingWidth;
const notchBaseHeight = notchHeight * 3;
const notchBase = roundedRectangle({
corner1: [0, 0],
corner2: [notchBaseWidth, notchBaseHeight],
squareCorners: [0, 1],
outerFilletCorners: [0, 1],
roundradius: cornerRadius,
}).subtract(roundedRectangle({
corner1: [(notchBaseWidth-notchWidth)/2, notchHeight],
corner2: [(notchBaseWidth+notchWidth)/2, notchHeight * 2],
roundradius: cornerRadius,
}));
o.push(notchBase.translate([(badgeWidth - notchBaseWidth) / 2, badgeHeight, 0]));
o.push(notchBase.intersect(CAG.rectangle({
// Shave off the outer fillets for the notch on the flap.
corner1: [0, 0],
corner2: [notchBaseWidth, notchBaseHeight],
})).mirroredY().translate([(badgeWidth - notchBaseWidth) / 2, -badgeHeight, 0]));
return o;
}
function folds() {
var o = [];
const wingFold = new CSG.Path2D([[0,badgeHeight-wingHeight+cornerRadius], [0, badgeHeight-cornerRadius]]).expandToCAG(0.5, 1);
o.push(wingFold);
o.push(wingFold.translate([badgeWidth, 0, 0]));
o.push(new CSG.Path2D([[cornerRadius,0], [badgeWidth-cornerRadius, 0]]).expandToCAG(0.5, 1));
return o;
}
// Delegate to CAG.roundedRectangle() but also:
// - fill in corners noted in params.squareCorners, specified as an
// array of ints in 0..3, where 0 is lower-left and index increases
// clockwise.
// - create fillets on the outside of outerFilletCorners (same corner
// spec as above), where each fillet is 4 complements of
// quarter-discs.
// These two enhancements make it easier to build up shapes from
// touching roundedRectangles without holes (squareCorners) and making
// interior joints smooth instead of sharp (outerFilletCorners).
roundedRectangle = function(params) {
var rect = CAG.roundedRectangle(params);
var bounds = rect.getBounds();
var center = [(bounds[0].x + bounds[1].x)/2, (bounds[0].y + bounds[1].y)/2];
// Corner i is given by [bounds[t].x, bounds[s].y] where [t,s] is
// the i'th entry in this array.
var cornersByIndex = [
[0, 0],
[1, 0],
[1, 1],
[0, 1]
];
for (var c in params.squareCorners) {
var cornerBoundsIndexes = cornersByIndex[params.squareCorners[c]];
var corner = [bounds[cornerBoundsIndexes[0]].x, bounds[cornerBoundsIndexes[1]].y];
rect = union(rect, CAG.rectangle({corner1: corner, corner2: center}));
}
for (var c in params.outerFilletCorners) {
var cornerBoundsIndexes = cornersByIndex[params.outerFilletCorners[c]];
var corner = [bounds[cornerBoundsIndexes[0]].x, bounds[cornerBoundsIndexes[1]].y];
rect = union(rect, filletAt(corner, params.roundradius));
}
return rect;
}
// See description of outerFilletCorners above for what this is for.
filletAt = function(center, radius) {
var c0 = [center[0] - radius, center[1] - radius];
var c1 = [center[0] + radius, center[1] - radius];
var c2 = [center[0] + radius, center[1] + radius];
var c3 = [center[0] - radius, center[1] + radius];
return CAG.rectangle({corner1: c0, corner2: c2}).subtract(
union(
CAG.circle({center: c0, radius: radius}),
CAG.circle({center: c1, radius: radius}),
CAG.circle({center: c2, radius: radius}),
CAG.circle({center: c3, radius: radius})
)
);
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment