fieldkit
Version:
Basic building blocks for computational design projects. Written in CoffeeScript for browser and server environments.
152 lines (126 loc) • 3.8 kB
JavaScript
// Generated by CoffeeScript 1.6.3
/*
A simple line from multiple segments, can be sampled at any point.
NOTE this curve does not always run through all given points.
Work with any object type as long as it has x and y number properties.
*/
(function() {
var Polyline, Spline;
Polyline = (function() {
function Polyline(points) {
this.points = points != null ? points : [];
}
Polyline.prototype.add = function(point) {
return points.push(point);
};
Polyline.prototype.size = function() {
return points.length;
};
Polyline.prototype.clear = function() {
var points;
return points = [];
};
Polyline.prototype.point = function(time) {
var median, next, prev;
if (time <= 0) {
return points[0];
} else if (time >= 1) {
return points[points.length - 1];
} else {
median = time * (points.length - 1);
prev = points[Math.floor(median)];
next = points[Math.ceil(median)];
return {
x: prev.x + (next.x - prev.x) * 0.5,
y: prev.y + (next.y - prev.y) * 0.5
};
}
};
return Polyline;
})();
/*
A Catmull-Rom spline (which is a special form of the cubic hermite curve) implementation,
generates a smooth curve/interpolation from a number of Vec2 points.
*/
Spline = (function() {
var beforeLast, first, last, second;
first = second = beforeLast = last = void 0;
Spline.prototype.points = [];
Spline.prototype.needsUpdate = false;
function Spline(points) {
this.points = points != null ? points : [];
this.needsUpdate = this.points.length > 0;
}
Spline.prototype.add = function(point) {
this.points.push(point);
return this.needsUpdate = true;
};
Spline.prototype.size = function() {
return this.points.length;
};
Spline.prototype.clear = function() {
return this.points = [];
};
Spline.prototype.update = function() {
if (this.points.length < 4) {
return;
}
first = this.points[0];
second = this.points[1];
beforeLast = this.points[this.points.length - 2];
last = this.points[this.points.length - 1];
return this.needsUpdate = false;
};
Spline.prototype.point = function(time) {
var i, normalizedTime, partPercentage, result, size, t, t2, t3, timeBetween, tmp1, tmp2, tmp3, tmp4;
if (this.points.length < 4) {
return;
}
if (time <= 0) {
return this.points[0];
} else if (time >= 1) {
return this.points[this.points.length - 1];
} else {
if (this.needsUpdate) {
update();
}
size = this.points.length;
partPercentage = 1.0 / (size - 1);
timeBetween = time / partPercentage;
i = Math.floor(timeBetween);
normalizedTime = timeBetween - i;
t = normalizedTime * 0.5;
t2 = t * normalizedTime;
t3 = t2 * normalizedTime;
tmp1 = void 0;
if (--i === -1) {
tmp1 = first.clone();
} else {
tmp1 = this.points[i].clone();
}
tmp2 = this.points[++i].clone();
tmp3 = this.points[++i].clone();
tmp4 = void 0;
if (++i === size) {
tmp4 = last.clone();
} else {
tmp4 = this.points[i].clone();
}
tmp1.scale(-t3 + 2 * t2 - t);
result = tmp1;
tmp2.scale(3 * t3 - 5 * t2 + 1);
result.add(tmp2);
tmp3.scale(-3 * t3 + 4 * t2 + t);
result.add(tmp3);
tmp4.scale(t3 - t2);
result.add(tmp4);
return result;
}
};
return Spline;
})();
module.exports = {
Polyline: Polyline,
Spline: Spline
};
}).call(this);