Skip to content

Instantly share code, notes, and snippets.

@sebastien
Last active March 8, 2016 02:12
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 sebastien/d0198125390e0d798964 to your computer and use it in GitHub Desktop.
Save sebastien/d0198125390e0d798964 to your computer and use it in GitHub Desktop.
// title : Pillars
// author : Sébastien Pierre
// license : MIT License
// revision : 0.003
// file : pillars.jscad
// Gist : https://gist.github.com/d0198125390e0d798964
// Preview : http://openjscad.org/#https://gist.githubusercontent.com/sebastien/d0198125390e0d798964/raw/5a4eb71ec5dd64714961fcbeb859d11dee21deb7/pillars.jscad
// Update : gist-pase -u d0198125390e0d798964 pillars.jscad
function getParameterDefinitions() {
return [
{ name: 'width', type: 'float', initial: 10, caption: "Rows" },
{ name: 'depth', type: 'float', initial: 5, caption: "Columns" },
{ name: 'height', type: 'float', initial: 5, caption: "Pillar height" },
{ name: 'base', type: 'float', initial: 0.3, caption: "Pillar base" },
{ name: 'top', type: 'float', initial: 0.2, caption: "Pillar top" },
{ name: 'sizeJitter', type: 'float', initial: 0.25, caption: "Pillar size jitter" },
{ name: 'posJitter', type: 'float', initial: 2.0, caption: "Pillar position jitter" },
];
}
function data(value, d) {
if (typeof(d)==="undefined"){
return value.__data;
} else {
value.__data = d;
return value;
}
}
function rnd(seed) {
seed = seed || 0;
// FIXME: Custom
return Math.random();
}
function key(x,y,z) {
return (""+x)+","+(""+y)+","+(""+z);
}
function lerp(a,b,t) {
if (typeof(a) === typeof([])) {
return a.map(function(v,i){return lerp(a[i], b[i], t)});
} else {
return a + (b - a) * t;
}
}
function scale(value, sdomain, ddomain) {
var t = (value - sdomain[0]) / (sdomain[1] - sdomain[0]);
return lerp(ddomain[0], ddomain[1], t);
}
function round(value, roundBy) {
return Math.round(value / (roundBy||1)) * roundBy;
}
function jitter(v,f) {
if (typeof(v) === typeof([])) {
return v.map(function(v,i){return jitter(v,f)});
} else {
return v + ((rnd() - 0.5) * f);
}
}
function minmax(a,b) {
return [Math.min(a,b),Math.max(a,b)]
}
function range(s,e) {
var r = [];
s = minmax(s,e); e=s[1] ; s=s[0];
while (s < e) {
r.push(s);
s += 1;
}
return r;
}
function slice(position, r, s) {
r = Math.max(0.1, Math.abs(r));
s = Math.max(8, s || 0);
var res = range(0,s).map(function(a){
a = scale(a,[0,s],[0, 2*Math.PI]);
return [
position[0] + Math.cos(a) * r,
position[1] + Math.sin(a) * r,
position[2]
]
})
return CSG.Polygon.createFromPoints(res);
}
function pillar(origin, destination, originRadius, destinationRadius, slices) {
slices = Math.min(6, Math.abs(slices)||0);
var base = slice(origin, originRadius);
// SEE: https://github.com/Spiritdude/OpenJSCAD.org/wiki/User-Guide#solid-from-slices
return base.solidFromSlices({
numslices:slices,
callback:function(t, slize) {
var p = lerp(origin, destination, t);
var r = lerp(originRadius, destinationRadius, t);
return slice(p, r);
}
})
}
function forest(px, py, ph, params) {
var result=[];
var base = params.base || 0.3;
var top = params.top || 0.2;
var size_jitter = params.sizeJitter || 0.1;
var pos_jitter = params.posJitter || 0.5;
px = params.width || px;
py = params.depth || py;
ph = params.height || ph;
// We generate the pillars
for (var x=0 ; x < px ; x++ ) {
for (var y=0 ; y < py ; y++ ) {
var p = {
base:[x,y,0],
top:[jitter(x, pos_jitter),jitter(y, pos_jitter),ph],
baseR: jitter(base, size_jitter),
topR: jitter(top, size_jitter)
}
result.push(
data(pillar(
p.base, p.top, p.baseR, p.topR
), p)
)
}
}
return result;
}
function links(px, py, ph, pillars,params) {
// We use the data from the parameters
px = params.width || px;
py = params.depth || py;
ph = params.height || ph;
// We extract data from the pillars
var d = pillars.reduce(function(r,e,i){
var p = data(e);
r[key(p.base[0],p.base[1],0)] = p;
return r;
},{});
var res = [];
for (var x=0 ; x < px ; x++ ) {
for (var y=0 ; y < py ; y++ ) {
var p = d[key(x,y)];
// We get a random (x,y) that is not (0,0)
var nx=0, ny=0;
while (nx === 0 && ny === 0) {
nx = round(scale(rnd(), [0,1], [-1, 1]), 1);
ny = round(scale(rnd(), [0,1], [-1, 1]), 1);
}
// We make it relative to (x,y)
nx +=x;
ny +=y;
// We correct the edge cases
if (x === 0) {nx=1;}
if (y === 0) {ny=1;}
if (x == px - 1) {nx = px - 2;}
if (y == py - 1) {ny = py - 2;}
// We get the start and destination pillars
var sp = d[key(x,y,0)];
var dp = d[key(nx,ny,0)];
// We get a coordinate within each pillar
var s = lerp(sp.base, sp.top, rnd());
var e = lerp(dp.base, dp.top, rnd());
// And create a cylinder linking the two
var link = cylinder({
start: s,
end: e,
r1: jitter(0.1, 0.025),
r2: jitter(0.1, 0.025)});
res.push(link);
}
}
return res;
}
function main(params) {
var j = 0.2;
// NOTE: params ill override everything
var f = forest(5,5,5,params);
var l = links(5,5,5,f,params);
return [
//cube({size:[params.width + 1 + j * 2, params.depth + 1 + j *2, 0.1]}
//).translate([-1-j, -1-j, 0])
].concat(l).concat(f);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment