Last active
October 6, 2020 18:44
-
-
Save hrgdavor/7419194097fc2ffd42d840f82fc83ca1 to your computer and use it in GitHub Desktop.
openjscad V2 rounded top
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Extrude rounded top From Slices | |
* @description Demonstrating the advanced extrusion using slices to create rounded top | |
* @tags extrude, slice, slices, extrudefromslices, callback | |
* @authors Davor Hrg | |
* @licence MIT License | |
*/ | |
const { circle, square, roundedRectangle } = require('@jscad/modeling').primitives | |
const { translate } = require('@jscad/modeling').transforms | |
const { geom2 } = require('@jscad/modeling').geometries | |
const { extrudeFromSlices, slice } = require('@jscad/modeling').extrusions | |
const { mat4 } = require('@jscad/modeling').maths | |
const main = () => { | |
// demonstrates manipulating the original base through translation and scale to build a 3D geometry | |
const roundTop = (base, {height=4, r1=0.2, r1Percent=0, rx=0.1, ry=0, segments=1}) => { | |
if(r1Percent) r1 = r1Percent * height; | |
ry = ry || rx; | |
// radius is for one side, and scale factor is for both | |
rx = rx*2; | |
ry = ry*2; | |
var numberOfSlices = 2 + segments; | |
var step = 1/(numberOfSlices-1); | |
var angleDelta = Math.PI / (segments) / 2 ; | |
var angleDelta2 = 180 / (segments) / 2 ; | |
var startH = height - r1; | |
var baseSlice = slice.fromSides(geom2.toSides(base)) | |
return extrudeFromSlices({ | |
numberOfSlices, | |
callback: (progress, counter, baseSlice) => { | |
var h = progress * height; | |
let scaleX = 1; | |
let scaleY = 1; | |
if(progress == 1){ // top slice (counter = numSlices-1) | |
scaleX = 1 - rx; | |
scaleY = 1 - ry; | |
}else if(progress == step){ // first top slice (counter = 1) | |
h = startH; | |
}else if(progress > step){ // curve (counter = 2,3,4...) | |
var angle = (counter -1) * angleDelta; | |
h = height - r1 + (Math.sin(angle) * r1); | |
scaleX = 1 - rx + (Math.cos(angle) * rx); | |
scaleY = 1 - rx + (Math.cos(angle) * ry); | |
}else{ | |
// bottom slice (counter = 0) | |
} | |
const scaleMatrix = mat4.fromScaling([scaleX, scaleY, 1]) | |
const transformMatrix = mat4.fromTranslation([0, 0, h]) | |
return slice.transform(mat4.multiply(scaleMatrix, transformMatrix), baseSlice) | |
} | |
}, baseSlice) | |
} | |
var circles = [3,5,8,32]; | |
var ret = [ | |
roundTop(square({size:4}), {height:4, r1Percent:0.2, rx:0.2, segments:1}), | |
translate( [8,0,0], | |
roundTop(roundedRectangle({size:[4,4], roundRadius:0.2*4, segments:4}), {height:4, r1Percent:0.2, rx:0.2, segments:1}) | |
) | |
]; | |
for(var j=0; j<circles.length; j++){ | |
for(var i=0; i<4; i++){ | |
ret.push(translate( [16+j*8,i*8,0], | |
roundTop(circle({radius:2.5, segments:circles[j]}), {height:4, r1Percent:0.2, rx:0.2, segments:(i*2 || 1)}) | |
)); | |
} | |
} | |
for(var i=1; i<4; i++){ | |
ret.push(translate([0,i*8,0], | |
roundTop(square({size:4}), {height:4, r1Percent:0.2, rx:0.2, segments:i*2}) | |
)); | |
ret.push(translate( [8,i*8,0], | |
roundTop(roundedRectangle({size:[4,4], roundRadius:0.2*4, segments:i*2*4}), {height:4, r1Percent:0.2, rx:0.2, segments:i*2}) | |
)); | |
} | |
return ret; | |
} | |
module.exports = { main } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment