Skip to content

Instantly share code, notes, and snippets.

@formula1
Created April 12, 2015 04:22
Show Gist options
  • Save formula1/3e5389ddbee6b8376f52 to your computer and use it in GitHub Desktop.
Save formula1/3e5389ddbee6b8376f52 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Verlet Blob Simulation</title>
<meta charset="UTF-8" />
<link rel="stylesheet" href="../css/style.css" type="text/css" media="screen, projection" />
<link href='http://fonts.googleapis.com/css?family=Libre+Baskerville:400,700,400italic' rel='stylesheet' type='text/css'>
<script type="text/javascript" src="wuteva.js"></script>
</head>
<body>
<script type="text/javascript" src="../site/js/common.js"></script>
<div id="header">
<h1><a href="../">verlet-js</a> / <em>Area</em></h1>
<p>
<h4>Author</h4>
<a href="http://subprotocol.com/">Sam Tobia</a>
<h4>Summary</h4>
Test of an area constraint
<h4>Source Code</h4>
<a href="https://github.com/formula1/verlet-js/blob/temp/examples/area0.html">View on GitHub</a>
</p>
</div>
<canvas id="scratch" style="width: 800px; height: 500px; background-color:#000"></canvas>
<script type="text/javascript">
window.onload = function() {
var canvas = document.getElementById("scratch");
// canvas dimensions
var width = parseInt(canvas.style.width);
var height = parseInt(canvas.style.height);
// retina
var dpr = window.devicePixelRatio || 1;
canvas.width = width*dpr;
canvas.height = height*dpr;
canvas.getContext("2d").scale(dpr, dpr);
// simulation
var draw = new VerletDraw(width, height, canvas);
var sim = draw.physics
sim.friction = 1;
var points = 7;
var distance = 100;
var rot = 2*Math.PI/points;
var linearblob = new sim.Composite();
var line_orig = new Vec2(width/4,height/4)
var angularblob = new sim.Composite();
var angu_orig = new Vec2(width*3/4,height*1/4);
var soloblob = new sim.Composite();
var solo_orig = new Vec2(width*1/2,height*1/4);
var rotVec = new Vec2(distance,0);
var orig = new Vec2();
for(var i=0;i<points+2;i++){
if(i < points){
rotVec.rotate(orig,rot);
linearblob.particles.push(
new Particle(rotVec.clone().add(line_orig))
);
angularblob.particles.push(
new Particle(rotVec.clone().add(angu_orig))
);
soloblob.particles.push(
new Particle(rotVec.clone().add(solo_orig))
);
}
if(i > 0 && i < points+1){
linearblob.constraints.push(new DistanceConstraint(
linearblob.particles[i%points],
linearblob.particles[i-1],
0.02
));
}
if(i > 1){
angularblob.constraints.push(new AngleConstraint(
angularblob.particles[(i-2)%points],
angularblob.particles[(i-1)%points],
angularblob.particles[i%points],
0.02
));
}
}
// entities
console.log(linearblob.particles);
console.log(angularblob.particles);
console.log(soloblob.particles);
linearblob.constraints.push(new ScaledAreaConstraint(linearblob.particles,1));
angularblob.constraints.push(new ScaledAreaConstraint(angularblob.particles,1));
soloblob.constraints.push(new ScaledAreaConstraint(soloblob.particles,1));
sim.composites.push(linearblob);
// sim.composites.push(angularblob);
// sim.composites.push(soloblob);
// animation loop
var legIndex = 0;
var loop = function() {
sim.frame(16);
draw.draw();
requestAnimFrame(loop);
};
loop();
};
</script>
<div id="footer">
Copyright 2013 Sub Protocol and other contributors.
<br/><a href="http://subprotocol.com/">http://subprotocol.com/</a>
</div>
</body>
;(function(e,t,n){function i(n,s){if(!t[n]){if(!e[n]){var o=typeof require=="function"&&require;if(!s&&o)return o(n,!0);if(r)return r(n,!0);throw new Error("Cannot find module '"+n+"'")}var u=t[n]={exports:{}};e[n][0].call(u.exports,function(t){var r=e[n][1][t];return i(r?r:t)},u,u.exports)}return t[n].exports}var r=typeof require=="function"&&require;for(var s=0;s<n.length;s++)i(n[s]);return i})({1:[function(require,module,exports){
//this exports all the verlet methods globally, so that the demos work.
require("./verlet-polyfill");
var VerletDraw = require('./verlet-draw')
var VerletJS = require('./verlet')
var constraint = require('./constraint')
require('./objects') //patches VerletJS.prototype (bad)
window.Vec2 = require('./structures/Vec2')
window.VerletJS = VerletJS
window.VerletDraw = VerletDraw;
window.Particle = VerletJS.Particle
for(var i in constraint){
window[i] = constraint[i]
}
},{"./constraint":5,"./objects":6,"./structures/Vec2":7,"./verlet":4,"./verlet-draw":3,"./verlet-polyfill":2}],2:[function(require,module,exports){
if(!Math.sign){
Math.sign = function(x){
if( +x === x ) { // check if a number was given
return (x === 0) ? x : (x > 0) ? 1 : -1;
}
return NaN;
}
}
if(!Math.quadratic){
//x = (-b +- b*b - 4ac )/(2a)
Math.quadratic = function(a,b,c){
var ret = b*b - 4*a*c;
if(ret < 0) return false;
if(ret == 0) return [-b/(2*a)];
a *= 2;
ret = Math.sqrt(ret)/a;
b *= -1/a
return [b + ret, b - ret];
}
}
if(!Math.lawCos){
//x = (-b +- b*b - 4ac )/(2a)
Math.lawCos = function(a,b,c){
return Math.acos(
(-a*a + b*b + c*c)/
(2*b*c)
);
}
}
},{}],3:[function(require,module,exports){
window.requestAnimFrame = window.requestAnimationFrame
|| window.webkitRequestAnimationFrame
|| window.mozRequestAnimationFrame
|| window.oRequestAnimationFrame
|| window.msRequestAnimationFrame
|| function(callback) {
window.setTimeout(callback, 1000 / 60);
};
var VerletJS = require("./verlet.js");
module.exports = VerletDraw;
function VerletDraw(width, height, canvas, physics) {
this.width = width;
this.height = height;
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
this.mouse = new Vec2(0,0);
this.mouseDown = false;
this.draggedEntity = null;
this.selectionRadius = 20;
this.highlightColor = "#4f545c";
this.physics = (!physics)?new VerletJS(width,height):physics;
var _this = this;
this.physics.logic = function(){
// handle dragging of entities
if (_this.draggedEntity)
_this.draggedEntity.pos.set(_this.mouse);
}
// prevent context menu
this.canvas.oncontextmenu = function(e) {
e.preventDefault();
};
this.canvas.onmousedown = function(e) {
_this.mouseDown = true;
var nearest = _this.physics.nearestEntity(_this.mouse,_this.selectionRadius);;
if (nearest) {
_this.draggedEntity = nearest;
console.log(nearest.pos);
}
};
this.canvas.onmouseup = function(e) {
_this.mouseDown = false;
_this.draggedEntity = null;
};
this.canvas.onmousemove = function(e) {
var rect = _this.canvas.getBoundingClientRect();
_this.mouse.x = e.clientX - rect.left;
_this.mouse.y = e.clientY - rect.top;
};
}
VerletDraw.prototype.draw = function() {
var i, c;
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
var composites = this.physics.composites;
for (c in composites) {
// draw constraints
if (composites[c].drawConstraints) {
composites[c].drawConstraints(this.ctx, composites[c]);
} else {
var constraints = composites[c].constraints;
for (i in constraints)
constraints[i].draw(this.ctx);
}
// draw particles
if (composites[c].drawParticles) {
composites[c].drawParticles(this.ctx, composites[c]);
} else {
var particles = composites[c].particles;
for (i in particles)
particles[i].draw(this.ctx);
}
}
// highlight nearest / dragged entity
var nearest = this.draggedEntity || this.physics.nearestEntity(this.mouse,this.selectionRadius);
if (nearest) {
this.ctx.beginPath();
this.ctx.arc(nearest.pos.x, nearest.pos.y, 8, 0, 2*Math.PI);
this.ctx.strokeStyle = this.highlightColor;
this.ctx.stroke();
}
}
},{"./verlet.js":4}],6:[function(require,module,exports){
/*
Copyright 2013 Sub Protocol and other contributors
http://subprotocol.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// generic verlet entities
var VerletJS = require('./verlet')
var Particle = VerletJS.Particle
var constraints = require('./constraint')
var DistanceConstraint = constraints.DistanceConstraint
VerletJS.prototype.point = function(pos) {
var composite = new this.Composite();
composite.particles.push(new Particle(pos));
this.composites.push(composite);
return composite;
}
VerletJS.prototype.lineSegments = function(vertices, stiffness, circle) {
var i;
var composite = new this.Composite();
for (i in vertices) {
composite.particles.push(new Particle(vertices[i]));
if (i > 0)
composite.constraints.push(
new DistanceConstraint(
composite.particles[i],
composite.particles[i-1],
stiffness
)
);
}
if(circle){
composite.constraints.push(
new DistanceConstraint(
composite.particles[composite.particles.length-1],
composite.particles[0],
stiffness
)
)
}
this.composites.push(composite);
return composite;
}
VerletJS.prototype.cloth = function(origin, width, height, segments, pinMod, stiffness) {
var composite = new this.Composite();
var xStride = width/segments;
var yStride = height/segments;
var x,y;
for (y=0;y<segments;++y) {
for (x=0;x<segments;++x) {
var px = origin.x + x*xStride - width/2 + xStride/2;
var py = origin.y + y*yStride - height/2 + yStride/2;
composite.particles.push(new Particle(new Vec2(px, py)));
if (x > 0){
composite.constraints.push(
new DistanceConstraint(
composite.particles[y*segments+x],
composite.particles[y*segments+x-1],
stiffness
)
);
}
if (y > 0){
composite.constraints.push(
new DistanceConstraint(
composite.particles[y*segments+x],
composite.particles[(y-1)*segments+x],
stiffness
)
);
}
}
}
for (x=0;x<segments;++x) {
if (x%pinMod == 0)
composite.pin(x);
}
this.composites.push(composite);
return composite;
}
VerletJS.prototype.tire = function(origin, radius, segments, spokeStiffness, treadStiffness) {
var stride = (2*Math.PI)/segments;
var i;
var composite = new this.Composite();
// particles
for (i=0;i<segments;++i) {
var theta = i*stride;
composite.particles.push(new Particle(new Vec2(origin.x + Math.cos(theta)*radius, origin.y + Math.sin(theta)*radius)));
}
var center = new Particle(origin);
composite.particles.push(center);
// constraints
for (i=0;i<segments;++i) {
composite.constraints.push(
new DistanceConstraint(
composite.particles[i],
composite.particles[(i+1)%segments],
treadStiffness
)
);
composite.constraints.push(
new DistanceConstraint(
composite.particles[i],
center,
spokeStiffness
)
);
composite.constraints.push(
new DistanceConstraint(
composite.particles[i],
composite.particles[(i+5)%segments],
treadStiffness
)
);
}
this.composites.push(composite);
return composite;
}
},{"./constraint":5,"./verlet":4}],4:[function(require,module,exports){
/*
Copyright 2013 Sub Protocol and other contributors
http://subprotocol.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var Vec2 = require('./structures/Vec2');
var Collision = require("./collision/collision");
exports = module.exports = VerletJS;
var Particle = exports.Particle = require("./structures/Particle");
var Composite = exports.Composite = require("./structures/Composite");
exports.Composite = Composite;
function VerletJS(width, height) {
this.width = width;
this.height = height;
this.bounds = function (particle) {
if (particle.pos.y > this.height-1)
particle.pos.y = this.height-1;
if (particle.pos.x < 0)
particle.pos.x = 0;
if (particle.pos.x > this.width-1)
particle.pos.x = this.width-1;
};
// simulation params
this.gravity = new Vec2(0,0.2);
this.friction = 0.99;
this.groundFriction = 0.8;
// holds composite entities
this.composites = [];
}
VerletJS.prototype.Composite = Composite;
VerletJS.prototype.logic = function(){
throw new Error("Logic hasn't been set");
};
VerletJS.prototype.frame = function(step) {
var i, j, c, particles;
for (c in this.composites) {
particles = this.composites[c].particles;
for (i in particles) {
// save last good state
particles[i].lastPos.set(particles[i].pos);
// gravity
particles[i].pos.add(this.gravity);
if (particles[i].pos.y >= this.height-1 && particles[i].vel.length2() > 0.000001) {
particles[i].vel.scale(this.groundFriction);
}
// inertia
particles[i].pos.add(particles[i].vel.scale(this.friction));
}
}
// relax
var stepCoef = 1/step;
for (c in this.composites) {
var constraints = this.composites[c].constraints;
for (i=0;i<step;++i)
for (j in constraints)
constraints[j].relax(stepCoef);
}
// bounds checking
for (c in this.composites) {
particles = this.composites[c].particles;
this.composites[c].aabb.clear();
for (i in particles){
this.bounds(particles[i]);
// calculate velocity
particles[i].vel
.set(particles[i].pos)
.sub(particles[i].lastPos);
// ground friction
this.composites[c].aabb.digestPoint(particles[i].pos);
}
}
Collision(this.composites,step);
this.logic();
};
VerletJS.prototype.nearestEntity = function(target_vec2,radius) {
var c, i;
var d2Nearest = 0;
var entity = null;
var constraintsNearest = null;
// find nearest point
for (c in this.composites) {
var particles = this.composites[c].particles;
for (i in particles) {
var d2 = particles[i].pos.dist2(target_vec2);
if (d2 <= radius*radius && (entity === null || d2 < d2Nearest)) {
entity = particles[i];
constraintsNearest = this.composites[c].constraints;
d2Nearest = d2;
}
}
}
// search for pinned constraints for this entity
for (i in constraintsNearest)
if (constraintsNearest[i] instanceof PinConstraint && constraintsNearest[i].a == entity)
entity = constraintsNearest[i];
return entity;
};
},{"./collision/collision":8,"./structures/Composite":10,"./structures/Particle":9,"./structures/Vec2":7}],5:[function(require,module,exports){
/*
Copyright 2013 Sub Protocol and other contributors
http://subprotocol.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// DistanceConstraint -- constrains to initial distance
// PinConstraint -- constrains to static/fixed point
// AngleConstraint -- constrains 3 particles to an angle
var Vec2 = require("./structures/Vec2")
exports.DistanceConstraint = require("./constraints/DistanceConstraint");
exports.PinConstraint = require("./constraints/PinConstraint");
exports.AngleConstraint = require("./constraints/AngleConstraint");
exports.MidpointAreaConstraint = require("./constraints/AreaConstraint");
exports.ScaledAreaConstraint = require("./constraints/InflateAreaConstraint");
},{"./constraints/AngleConstraint":13,"./constraints/AreaConstraint":14,"./constraints/DistanceConstraint":11,"./constraints/InflateAreaConstraint":15,"./constraints/PinConstraint":12,"./structures/Vec2":7}],11:[function(require,module,exports){
function DistanceConstraint(a, b, stiffness, distance /*optional*/) {
this.a = a;
this.b = b;
this.distance = typeof distance != "undefined" ? distance : a.pos.clone().sub(b.pos).length();
this.stiffness = stiffness;
}
DistanceConstraint.prototype.relax = function(stepCoef) {
var normal = this.a.pos.clone().sub(this.b.pos);
var m = normal.length2();
normal.scale(((this.distance*this.distance - m)/m)*this.stiffness*stepCoef);
this.a.pos.add(normal);
this.b.pos.sub(normal);
}
DistanceConstraint.prototype.draw = function(ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.strokeStyle = "#d8dde2";
ctx.stroke();
}
module.exports = DistanceConstraint;
},{}],13:[function(require,module,exports){
function AngleConstraint(a, b, c, stiffness) {
this.a = a;
this.b = b;
this.c = c;
this.angle = this.b.pos.angle2(this.a.pos, this.c.pos);
this.stiffness = stiffness;
}
AngleConstraint.prototype.relax = function(stepCoef) {
var angle = this.b.pos.angle2(this.a.pos, this.c.pos);
var diff = angle - this.angle;
if (diff <= -Math.PI)
diff += 2*Math.PI;
else if (diff >= Math.PI)
diff -= 2*Math.PI;
diff *= stepCoef*this.stiffness;
this.a.pos.rotate(this.b.pos, diff);
this.c.pos.rotate(this.b.pos, -diff);
this.b.pos.rotate(this.a.pos, diff);
this.b.pos.rotate(this.c.pos, -diff);
}
AngleConstraint.prototype.draw = function(ctx) {
ctx.beginPath();
ctx.moveTo(this.a.pos.x, this.a.pos.y);
ctx.lineTo(this.b.pos.x, this.b.pos.y);
ctx.lineTo(this.c.pos.x, this.c.pos.y);
var tmp = ctx.lineWidth;
ctx.lineWidth = 5;
ctx.strokeStyle = "rgba(255,255,0,0.2)";
ctx.stroke();
ctx.lineWidth = tmp;
}
module.exports = AngleConstraint;
},{}],7:[function(require,module,exports){
/*
Copyright 2013 Sub Protocol and other contributors
http://subprotocol.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// A simple 2-dimensional vector implementation
module.exports = Vec2;
function Vec2(x, y) {
this.x = x || 0;
this.y = y || 0;
var _this = this;
Object.defineProperty(this,"asArray",{
get:function(){
return [_this.x,_this.y];
}
});
}
var temp;
temp = require("./to-value");
for(var i in temp){
Vec2.prototype[i] = temp[i];
}
temp = require("./no-arg");
for(var i in temp){
Vec2.prototype[i] = temp[i];
}
temp = require("./operations");
for(var i in temp){
Vec2.prototype[i] = temp[i];
}
Vec2.prototype.clone = function(){
return new Vec2(this.x,this.y);
};
Vec2.prototype.normal = function() {
var m = Math.sqrt(this.x*this.x + this.y*this.y);
return new Vec2(this.x/m, this.y/m);
};
Vec2.prototype.equals = function(v) {
return this.x == v.x && this.y == v.y;
};
Vec2.prototype.epsilonEquals = function(v, epsilon) {
return Math.abs(this.x - v.x) <= epsilon && Math.abs(this.y - v.y) <= epsilon;
};
Vec2.prototype.isNaN = function(){
if(isNaN(this.x)) return true;
if(isNaN(this.y)) return true;
return false;
};
Vec2.prototype.toString = function() {
return "(" + this.x + ", " + this.y + ")";
};
Vec2.prototype.toArray = function() {
return [this.x,this.y];
};
},{"./no-arg":17,"./operations":18,"./to-value":16}],16:[function(require,module,exports){
var v = module.exports;
v.length = function() {
return Math.sqrt(this.x*this.x + this.y*this.y);
};
v.length2 = function() {
return this.x*this.x + this.y*this.y;
};
v.slope = function(){
return this.y / this.x;
};
v.sum = function(){
return this.y + this.x;
};
v.dist = function(v) {
return Math.sqrt(this.dist2(v));
};
v.dist2 = function(v) {
var x = v.x - this.x;
var y = v.y - this.y;
return x*x + y*y;
};
v.dot = function(v) {
return this.x*v.x + this.y*v.y;
};
v.cross = function(v){
return this.x * v.y - this.y * v.x;
};
v.angle = function(vl,vr) {
if(vr) return this.angle2(vl,vr);
if(vl) return this.angle1(vl);
return Math.atan2(this.x,this.y);
};
v.angle1 = function(v) {
return Math.atan2(this.x*v.y-this.y*v.x,this.x*v.x+this.y*v.y);
};
v.angle2 = function(vLeft, vRight) {
return vLeft.clone().sub(this).angle(vRight.clone().sub(this));
};
},{}],17:[function(require,module,exports){
var v = module.exports;
v.zero = function(){
this.x = 0;
this.y = 0;
return this;
};
v.posinf = function(){
this.x = Number.POSITIVE_INFINITY;
this.y = Number.POSITIVE_INFINITY;
return this;
};
v.neginf = function(){
this.x = Number.NEGATIVE_INFINITY;
this.y = Number.NEGATIVE_INFINITY;
return this;
};
v.normalize = function(){
var len = this.length();
this.x /= len;
this.y /= len;
return this;
};
v.signum = function(){
this.x = this.x>0?1:this.x<0?-1:0;
this.y = this.y>0?1:this.y<0?-1:0;
return this;
};
v.swap = function() {
var temp = this.x;
this.x = this.y;
this.y = temp;
return this;
};
v.abs = function(){
this.x = Math.abs(this.x);
this.y = Math.abs(this.y);
return this;
};
},{}],18:[function(require,module,exports){
var v = module.exports;
v.add = function(v) {
this.x += v.x;
this.y += v.y;
return this;
};
v.sub = function(v){
this.x -= v.x;
this.y -= v.y;
return this;
};
v.mul = function(v) {
if(typeof v == "number"){
return this.scale(v);
}
this.x *= v.x;
this.y *= v.y;
return this;
};
v.div = function(v) {
if(typeof v == "number"){
return this.scale(1/v);
}
this.x /= v.x;
this.y /= v.y;
return this;
};
v.scale = function(coef) {
this.x *= coef;
this.y *= coef;
return this;
};
v.scaleI = function(coef) {
this.x /= coef;
this.y /= coef;
return this;
};
v.pow = function(num){
this.x = Math.pow(this.x,num);
this.y = Math.pow(this.y,num);
return this;
};
v.rotate = function(origin, theta) {
var x = this.x - origin.x;
var y = this.y - origin.y;
this.x = x*Math.cos(theta) - y*Math.sin(theta) + origin.x;
this.y = x*Math.sin(theta) + y*Math.cos(theta) + origin.y;
return this;
};
v.min = function(v){
this.x = Math.min(this.x, v.x);
this.y = Math.min(this.y, v.y);
return this;
};
v.mid = function(v){
this.x = (this.x+v.x)/2;
this.y = (this.y+v.y)/2;
return this;
};
v.max = function(v){
this.x = Math.max(this.x, v.x);
this.y = Math.max(this.y, v.y);
return this;
};
v.set = function(v,y) {
if(typeof y != "undefined"){
this.x = v;
this.y = y;
}else{
this.x = v.x;
this.y = v.y;
}
return this;
};
},{}],10:[function(require,module,exports){
var AABB = require("./AABB");
function Composite() {
this.particles = [];
this.constraints = [];
this.aabb = new AABB();
this.drawParticles = null;
this.drawConstraints = null;
}
Composite.prototype.pin = function(index, pos) {
pos = pos || this.particles[index].pos;
var pc = new PinConstraint(this.particles[index], pos);
this.constraints.push(pc);
return pc;
};
module.exports = Composite;
},{"./AABB":19}],9:[function(require,module,exports){
var Vec2 = require("./Vec2")
function Particle(pos) {
this.pos = (new Vec2()).set(pos);
this.lastPos = (new Vec2()).set(pos);
this.vel = new Vec2();
}
Particle.prototype.draw = function(ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 2, 0, 2*Math.PI);
ctx.fillStyle = "#2dad8f";
ctx.fill();
}
module.exports = Particle;
},{"./Vec2":7}],12:[function(require,module,exports){
var Vec2 = require("../structures/Vec2")
function PinConstraint(a, pos) {
this.a = a;
this.pos = (new Vec2()).set(pos);
}
PinConstraint.prototype.relax = function(stepCoef) {
this.a.pos.set(this.pos);
}
PinConstraint.prototype.draw = function(ctx) {
ctx.beginPath();
ctx.arc(this.pos.x, this.pos.y, 6, 0, 2*Math.PI);
ctx.fillStyle = "rgba(0,153,255,0.1)";
ctx.fill();
}
module.exports = PinConstraint;
},{"../structures/Vec2":7}],14:[function(require,module,exports){
var Vec2 = require("../structures/Vec2");
var Triangle = require("../structures/Triangle");
var Polygon = require("../structures/Polygon");
var AABB = require("../structures/AABB")
function AreaConstraint(points, stiffness) {
if(Array.isArray(points)){
//nothing
}else{
points = Array.prototype.slice.call(arguments,0);
stiffness = points.pop();
}
if(points.length < 3){
throw new Error("need at least three points in args or as an array to retain an area");
}
this.points = Polygon(points);
this.area = this.points.getArea();
this.storedarea = 0;
this.storedmid = 0;
this.storedaabb = new AABB();
if(!this.area || this.area == 0){
throw new Error("cannot calculate a nonexistant area");
}
this.stiffness = stiffness;
}
AreaConstraint.prototype.relax = function(stepCoef) {
var area = 0;//the current area
var mid = new Vec2();
var l = this.points.length;
this.points.forThree(function(prev,curr,next){
area += curr.cross(next);
mid.add(curr.clone().scale(1/l))
})
if(area <= 0){
alert("negative area");
throw new Error("negative area");
}
//I have the two areas
var diff = Math.sqrt((
this.area* //The desired area
(this.stiffness*stepCoef)
+(1-this.stiffness*stepCoef)
*area
)/area);
//I want to have all points to either push away from the mid or towards the mid
//The extremity is dependent on the distance
//Get the distance between mid and point
//make the distance the appropriate proportion
this.storedarea = 0;
this.storedmid = new Vec2();
var _this = this;
var eq = false
var curr_array = [];
this.points.forThree(function(prev,curr,next,i){
var ok = true;
/*
if(curr.equals(next)){
eq = prev;
curr_array.push(curr);
return;
}
if(eq){
prev = eq;
eq = false;
curr_array.push(curr)
}
*/
var tri = new Triangle(prev,curr,next);
if(tri.isConcave()){
if(tri.hasPoint(_this.storedmid)){
problem = true;
}
var intersections = _this.points.getIntersects(prev,curr,i);
if(intersections.length > 0){
//alert("you may get a negative area here");
ok = false;
}
}
if(ok){}
/*
if(curr_array.length){
while(curr_array.length){
_this.storedmid.add(
curr_array.pop().sub(mid).scale(diff).add(mid)
.clone().scale(1/l)
);
}
}else{
*/
_this.storedmid.add(
curr.sub(mid).scale(diff).add(mid)
.clone().scale(1/l)
);
// }
if(curr != _this.points[0]){
_this.storedarea += prev.cross(curr);
}
_this.storedaabb.digestPoint(curr);
})
}
AreaConstraint.prototype.draw = function(ctx) {
var diff = Math.floor(Math.min(255,255*this.area/this.storedarea));
var inv = Math.floor(Math.min(255,255*this.storedarea/this.area));
ctx.beginPath();
ctx.moveTo(this.points[0].x, this.points[0].y);
var _this = this;
var problem = false;
var intersects = [];
var eq = false;
this.points.forThree(function(prev,curr,next,i){
/*
if(curr.equals(next)){
eq = prev
return;
}
if(eq){
prev = eq;
eq = false;
}
*/
var tri = new Triangle(prev,curr,next);
if(tri.isConcave()){
if(tri.hasPoint(_this.storedmid)){
problem = true;
}
}
var intersections = _this.points.getIntersects(prev,curr,i);
if(intersections.length > 0){
// alert("you may get a negative area here");
intersects = intersects.concat(intersections);
}
ctx.lineTo(curr.x,curr.y);
})
var g = (diff < inv)?diff:inv;
ctx.closePath();
ctx.fillStyle="rgba("+diff+","+g+","+inv+",0.6)";
ctx.fill();
for(var i=intersects.length;i--;){
ctx.beginPath();
ctx.arc(
intersects[i].x,
intersects[i].y,
8, 0, 2 * Math.PI, false
);
ctx.fillStyle = "#FF8300";
ctx.fill();
};
var tri = this.points.getDelaney();
for(i = tri.length; i; ) {
ctx.beginPath();
--i; ctx.moveTo(this.points[tri[i]].x, this.points[tri[i]].y);
--i; ctx.lineTo(this.points[tri[i]].x, this.points[tri[i]].y);
--i; ctx.lineTo(this.points[tri[i]].x, this.points[tri[i]].y);
ctx.closePath();
ctx.stroke();
}
ctx.beginPath();
ctx.arc(
this.storedmid.x,
this.storedmid.y,
2, 0, 2 * Math.PI, false
);
ctx.fillStyle = problem?"#FF0000":"#00FF00";
ctx.fill();
}
module.exports = AreaConstraint;
//finding half the area of a circle
// A = pi * r^2
// A/2 = pi/2 * r^2
// dA = pi/d * r^2
// we know current area
// we know desired area
// (dA/cA) * cA = (dA/cA) * pi * r^2
// we're looking for the change in r that corresponds to change in A
// sqrt(A/pi) = r
//new_r = (circle_r/sqrt(Area))
// we find the porportion between cur and desired
// multiply current distance by that porportion
// diff = 1/Math.sqrt(diff);
// diff *= stepCoef*this.stiffness;
/*
This code will not work properly since pushing outward may not work for certian
concave polygons
What is needed is to find a single multiplier that the distance between each point
can be multiplied by to give the area desired
I good example is something such as
There are a few issues here
1) backwards points
- The moment it intersects, we get negative area
2) Intersections around midpoint
- the moment it intersects around the midpoint, it will go haywire
- Can we detect if the angle passes over the midpoint?
-should we compensate for that?
3) The midpoint pushing outward concept actually enforces angle
-It causes angles to generally want to be equalateral
4) Concave till ignoring midpoint
5) midpoint is technically at the bottom despite most of the area being up top
-This problem is where we are calculating the midpoint based of angle points
-Instead of basing it off all points (line segments are points technically)
-sampling points off each segment will give an innaccurate calculation
-after finding total perimiter, is it possible to base the amount of influence
-off of length?
*/
},{"../structures/AABB":19,"../structures/Polygon":21,"../structures/Triangle":20,"../structures/Vec2":7}],15:[function(require,module,exports){
var Vec2 = require("../structures/Vec2");
var Line = require("../structures/Line");
var Triangle = require("../structures/Triangle");
var Polygon = require("../structures/Polygon");
var AABB = require("../structures/AABB")
function AreaConstraint(points, stiffness) {
if(Array.isArray(points)){
//nothing
}else{
points = Array.prototype.slice.call(arguments,0);
stiffness = points.pop();
}
if(points.length < 3){
throw new Error("need at least three points in args or as an array to retain an area");
}
this.points = Polygon(points);
this.area = this.points.getArea();
this.storedarea = 0;
this.storedmid = 0;
this.storedaabb = new AABB();
if(!this.area || this.area == 0){
throw new Error("cannot calculate a nonexistant area");
}
this.stiffness = stiffness;
}
AreaConstraint.prototype.relax = function(stepCoef) {
var area = 0;//the current area
var mid = new Vec2();
var l = this.points.length;
this.points.forThree(function(prev,curr,next){
area += curr.cross(next);
mid.add(curr.clone().scale(1/l))
//perimeter += curr.dist(next);
})
if(area <= 0){
alert("negative area");
throw new Error("negative area");
}
//I have the two areas
var diff = (
this.area* //The desired area
(this.stiffness*stepCoef)
+(1-this.stiffness*stepCoef)
*area
)/area;
var _this = this;
var eq = false
var lastcurr = this.points[this.points.length-1];
var lastnext = this.points[0].clone();
var _prev = this.points[this.points.length-1];
var nm = new Vec2();
this.points.forThree(function(prev,curr,next,i){
var nl = curr.clone();
curr.sub(_prev).scale(diff).add(prev);
nm.add(curr.clone().scale(1/l))
_prev = nl;
})
while(l--){
this.points[l].sub(nm).add(mid);
}
this.storedarea = area*diff;
this.storedmid = mid;
}
AreaConstraint.prototype.draw = function(ctx) {
var diff = Math.floor(Math.min(255,255*this.area/this.storedarea));
var inv = Math.floor(Math.min(255,255*this.storedarea/this.area));
var _this = this;
var problem = false;
var intersects = [];
var eq = false;
var effectivepoints = [];
//fill
var l = this.points.length-1;
ctx.beginPath();
ctx.moveTo(this.points[l].x, this.points[l].y);
while(l--){
ctx.lineTo(this.points[l].x,this.points[l].y);
}
var g = (diff < inv)?diff:inv;
ctx.closePath();
ctx.fillStyle="rgba("+diff+","+g+","+inv+",0.6)";
ctx.fill();
//delaney
/*
var tri = this.points.getDelaney();
for(i = tri.length; i; ) {
ctx.beginPath();
--i; ctx.moveTo(this.points[tri[i]].x, this.points[tri[i]].y);
--i; ctx.lineTo(this.points[tri[i]].x, this.points[tri[i]].y);
--i; ctx.lineTo(this.points[tri[i]].x, this.points[tri[i]].y);
ctx.closePath();
ctx.stroke();
}
*/
//draw perimiter
ctx.lineWidth = 4;
this.points.forThree(function(prev,curr,next,i){
if(curr.equals(next)){
eq = eq||prev
return;
}
if(eq){
prev = eq;
eq = false;
}
effectivepoints.push(curr);
var tri = new Triangle(prev,curr,next);
var mp = tri.getConcaveBisector();
var badarea = false;
if( tri.CA.pointIsLeftOrTop(mp.B) == tri.CA.pointIsLeftOrTop(tri.B)){
ctx.strokeStyle = "#FFFF00";
if(tri.hasPoint(_this.storedmid)){
problem = true;
}
}else{
ctx.strokeStyle = "#FF00FF";
if(tri.partialArea < 0){
badarea = true;
}
}
var intersections = _this.points.intersectsLine(new Line(prev,curr),i);
if(intersections.length > 0){
// alert("you may get a negative area here");
intersects = intersects.concat(intersections);
}
ctx.beginPath();
ctx.moveTo((prev.x+curr.x)/2, (prev.y+curr.y)/2);
ctx.lineTo(curr.x,curr.y);
ctx.lineTo((next.x+curr.x)/2, (next.y+curr.y)/2);
ctx.stroke();
})
ctx.lineWidth = 1;
//intersects
for(var i=intersects.length;i--;){
ctx.beginPath();
ctx.arc(
intersects[i].x,
intersects[i].y,
8, 0, 2 * Math.PI, false
);
ctx.fillStyle = "#FF8300";
ctx.fill();
};
//midpoint
ctx.beginPath();
ctx.arc(
this.storedmid.x,
this.storedmid.y,
2, 0, 2 * Math.PI, false
);
ctx.fillStyle = problem?"#FF0000":"#00FF00";
ctx.fill();
}
module.exports = AreaConstraint;
/*
A = Pir^2
P = 2Pir
P/2Pi = r
A = Pi*(P/(2Pi))^2
A = Pi/Pi^2 * P/2
A = P/2Pi
A = w*h
A/w = h
P = 2w+2h
P/2 = w+h
P/2 - w = h
A = w*(P/2 - w)
A = wP/2 - w^2
P = 2w + 2A/w
A = 1/2 * b * h
a/Sin(A) = b/Sin(b) = c/Sin(b)
b = find max side
c/Sin(90) = h/Sin(A)
Sin(A)*c/Sin(90) = h
A = 1/2 * b * Sin(A)*c/Sin(90)
P = a + b + c
So we know Area
-we know angles
Now we need to figure out the distances
a/Sin(A) = b/Sin(B) = c/Sin(C)
A = Sin(A)* Sin(C) * b^2 / (Sin(B)*Sin(90))
*/
},{"../structures/AABB":19,"../structures/Line":22,"../structures/Polygon":21,"../structures/Triangle":20,"../structures/Vec2":7}],23:[function(require,module,exports){
/*
The High level of this explanation is
1) Each particle is defined as
(position + velocity*time)
2) Using this, I can create a linear equation from two particles where...
m = (positionA.y + velocityA.y*time) - (positionB.y + velocityB.y*time)
/ (positionA.x + velocityA.x*time) - (positionB.x + velocityB.x*time)
and
b = (positionA.y + velocityA.y*time) - (positionA.x + velocityA.x*time)*m
3) Since I'm tring to find the exact time where a point is on a line, the equation
becomes
y = mx + b
(positionP.y + velocityP.y*time) = m*(positionP.x + velocityP.x*time) + b
4) From here its about simplifying the equation until I get something solvable for time
I soon learned that the equation becomes a quadratic equation
a*time^2 + b*time + c
4a)
as a result I can solve all the issue with
(-b (+||-) (b^2 - 4*a*c)^(1/2) ) / (2*a)
4b) if a = 0, then the equation becomes even simpler
time = -c/b
4c) if b is 0 and a is 0, we have nothing.
5) However, The times I'm looking for are specific.
5a) The time should be negative. I don't want to predict the future, I want to fix the past
5b) The time cannot be larger than the current timestep. If it is, we are looking too far back
5c) there may be a possibility that there are two times that fit our description.
as a result, we want to find the one that happened first. A simply Math.min works
6) Return the value!
*/
module.exports.getImpacts = function(susP, lineA, lineB){
var vPsubvA = susP.vel.clone().sub(lineA.vel);
var vAsubvB = lineA.vel.clone().sub(lineB.vel);
var pPsubpA = susP.pos.clone().sub(lineA.pos);
var pAsubpB = lineA.pos.clone().sub(lineB.pos);
var a = vPsubvA.cross(vAsubvB);
var b = vPsubvA.cross(pAsubpB) + pPsubpA.cross(vAsubvB);
var c = pPsubpA.cross(pAsubpB);
if(a === 0){
//no need for quadratic
if(b === 0) return false;
return [-c/b];
}
var squared = Math.pow(b,2) - 4*a*c;
if(squared < 0){
return false;
}
if(squared === 0){
return [-b/(2*a)];
}
var minus = (-b - Math.sqrt(squared))/(2*a);
var plus = (-b + Math.sqrt(squared))/(2*a);
return [minus,plus];
};
module.exports.restrict = function(times, timestep){
var ret = false;
var l = times.length;
while(l--){
if(times[l] > 0) continue;
if(times[l] < -timestep) continue;
ret = Math.min(ret,times[l]);
}
return ret;
};
/*
y = m*x+b
m = (
(time*velA.y + posA.y) - (time*velB.y + posB.y)
/
(time*velA.x + posA.x) - (time*velB.x + posB.x)
)
m = (
time*(velA.y - velB.y) + (posA.y - posB.y)
/
time*(velA.x - velB.x) + (posA.x - posB.x)
)
b = y - m*x
b = (time*velA.y + posA.y) - m*(time*velA.x + posA.x)
y = mx + (time*velA.y + posA.y) - m*(time*velA.x + posA.x)
y = m*(x - (time*velA.x + posA.x)) + (time*velA.y + posA.y)
(y - (time*velA.y + posA.y))*( time*(velA.x - velB.x) + (posA.x - posB.x) )
=
(x - (time*velA.x + posA.x))*( time*(velA.y - velB.y) + (posA.y - posB.y) )
net = (time*vel + pos)
solve for time where x = (time*velP.x + posP.x) and y = (time*velP.y + posP.y)
((time*velP.y + posP.y) - (time*velA.y + posA.y))
*( time*(velA.x - velB.x) + (posA.x - posB.x) )
=
((time*velP.x + posP.x) - (time*velA.x + posA.x))
*( time*(velA.y - velB.y) + (posA.y - posB.y) )
( time*(velP.y - velA.y) + (posP.y - posA.y) )
*( time*(velA.x - velB.x) + (posA.x - posB.x) )
=
( time*(velP.x - velA.x) + (posP.x - posA.x) )
*( time*(velA.y - velB.y) + (posA.y - posB.y) )
( time*time*(velP.y - velA.y)*(velA.x - velB.x))
+ time*(velP.y - velA.y)*(posA.x - posB.x)
+ time*(velA.x - velB.x)*(posP.y - posA.y)
+ (posP.y - posA.y)*(posA.x - posB.x)
)
=
( time*time*(velP.x - velA.x)*(velA.y - velB.y)
+ time*(velP.x - velA.x)*(posA.y - posB.y)
+ time*(velA.y - velB.y)*(posP.x - posA.x)
+ (posP.x - posA.x)*(posA.y - posB.y)
)
0
=
time*time(
(velP.x - velA.x)*(velA.y - velB.y)
- (velP.y - velA.y)*(velA.x - velB.x)
)
+ time*(
(velP.x - velA.x)*(posA.y - posB.y)
+ (velA.y - velB.y)*(posP.x - posA.x)
- (velP.y - velA.y)*(posA.x - posB.x)
- (velA.x - velB.x)*(posP.y - posA.y)
)
+ (posP.x - posA.x)*(posA.y - posB.y)
- (posP.y - posA.y)*(posA.x - posB.x)
0
=
time*time(
(velP.x - velA.x)*(velA.y - velB.y)
- (velP.y - velA.y)*(velA.x - velB.x)
) //cross
+ time*(
(velP.x - velA.x)*(posA.y - posB.y)
- (velP.y - velA.y)*(posA.x - posB.x)
//cross
+ (posP.x - posA.x)*(velA.y - velB.y)
- (posP.y - posA.y)*(velA.x - velB.x)
//cross
)
+ (posP.x - posA.x)*(posA.y - posB.y)
- (posP.y - posA.y)*(posA.x - posB.x)
//cross
*/
},{}],24:[function(require,module,exports){
var Vel = require("./velocities.js");
function getMassAtPoint(a,b,p){
// console.log("need to get the net mass behind the line");
/*
This can be based off liquid dynamics
This can also be based off baseball bats
This cannot be based off an average mass since the mass is actually the entire line
We will be doing baseball bat...
*/
var td = a.pos.dist(b.pos);
//So the situation is like this
//The further away p is from the center point
//-the less mass a single side will have
//The Closer it is
//It will make no difference
var diff = p.pos.dist(a.pos)/td;
var m = 0;
m += getParticleMass(a)*(diff > 0.5)?1-diff:1;
m += getParticleMass(b)*(diff < 0.5?diff:1);
return m;
}
function getElasticityAtPoint(a,b,p){
// console.log("need to get the net elasticity on the point");
var ad = a.pos.dist(p.pos);
var bd = b.pos.dist(p.pos);
return getParticleElasticity(a)*bd/(ad+bd) + getParticleElasticity(b) * ad/ (ad+bd);
}
function getParticleMass(p){
// console.log("need to get the net mass behind the particle");
return 1;
}
function getParticleElasticity(p){
// console.log("need to get the net elasticity behind the particle");
return 0;
}
function collide(p,lp,slope){
//Thank you http://www.euclideanspace.com/physics/dynamics/collision/twod/
var e = (p.elasticity+lp.elasticity)/2;
var ni = (1+e)*(p.mass*lp.mass)/(p.mass + lp.mass);
ni = slope.mul(p.vel.clone().sub(lp.vel).dot(slope)).mul(ni);
p.vel.sub(ni.div(p.mass));
lp.vel.sub(ni.div(lp.mass));
}
function getLiquidMassAtPoint(p,container){
}
function distributeVelocities(p,a,b,time){
// var vels = Vel.getVelocities(a,b,time);
a.pos.add(a.vel.clone().scale(time));
b.pos.add(b.vel.clone().scale(time));
p.pos.add(p.vel.clone().scale(time));
p.mass= getParticleMass(p);
p.elasticity = getParticleElasticity(p);
var lp = {
pos: p.pos.clone(),
vel: Vel.getVelocityAtPoint(a,b,p),
mass: getMassAtPoint(a,b,p),
elasticity:getElasticityAtPoint(a,b,p)
};
var dir = getDirection(a,b,p,time);
// console.log(dir);
collide(p,lp,dir);
Vel.getVelocitiesFromPoint(a,b,lp);
a.pos.sub(a.vel.clone().scale(time));
b.pos.sub(b.vel.clone().scale(time));
p.pos.sub(p.vel.clone().scale(time));
// console.log(a,b,p);
}
function getDirection(a,b,p,time){
var dir = a.pos.clone().sub(b.pos).swap();
var op = p.pos.clone().sub(b.pos).sub(p.vel.clone());
if(dir.mul(-1,1).dist(op) > dir.mul(-1,-1).dist(op)){
return dir.normalize();
}
return dir.mul(-1,-1).normalize();
}
module.exports.distributeVelocities = distributeVelocities;
},{"./velocities.js":25}],19:[function(require,module,exports){
var Vec2 = require("./Vec2");
var Line = require("./Line");
function AABB (points){
this.max = new Vec2().neginf();
this.min = new Vec2().posinf();
if(points){
var l;
if(arguments.length > 1){
l = arguments.length;
while(l--){this.digestPoint(arguments[l]);}
}else{
l = points.length;
while(l--){this.digestPoint(points[l]);}
}
}
}
AABB.prototype.toArray = function(){
return this.min.toArray().concat(this.max.toArray());
};
AABB.prototype.clear = function(){
this.max.neginf();
this.min.posinf();
};
AABB.prototype.digestPoint = function(point){
this.max.max(point);
this.min.min(point);
};
AABB.prototype.intersectsAABB = function(oAABB){
if(this.min.x >= oAABB.max.x) return false;
if(this.min.y >= oAABB.max.y) return false;
if(oAABB.min.x >= this.max.x) return false;
if(oAABB.min.y >= this.max.y) return false;
return true;
};
AABB.prototype.sub = function(oAABB){
this.min.max(oAABB.min);
this.max.min(oAABB.max);
return this;
};
AABB.prototype.getSuspects =function(particles){
var lines = [];
var inside = [];
var done = [];
var l = particles.length;
var len = l;
var xboo = false, yboo = false;
var temp, ari, ll;
while(l--){
xboo = ( particles[l].pos.x <= this.max.x &&
particles[l].pos.x >= this.min.x );
yboo = ( particles[l].pos.y <= this.max.y &&
particles[l].pos.y >= this.min.y );
if(!xboo && !yboo) continue;
if(xboo && yboo){
inside.push(l);
}
ari = [[(l+len-1)%len,l], [l, (l+1)%len]];
ll = 2;
while(ll--){
if(done.indexOf(ari[ll].join("|")) !== -1) continue;
done.push(ari[ll].join("|"));
var p1 = particles[ari[ll][0]].pos;
var p2 = particles[ari[ll][1]].pos;
if(this.containsPoint(p1) || this.containsPoint(p2)){
lines.push(ari[ll]);
continue;
}
temp = new AABB(p1, p2);
if(!this.intersectsAABB(temp)) continue;
temp = new Line(p1,p2);
if(!this.intersectsLine(temp)) continue;
lines.push(ari[ll]);
}
}
return {inside:inside, lines:lines};
};
AABB.prototype.containsPoint = function(point){
if(point.x > this.max.x) return false;
if(point.y > this.max.y) return false;
if(point.x < this.min.x) return false;
if(point.y < this.min.y) return false;
return true;
};
AABB.prototype.intersectsLine = function(line){
var tline = new Line(this.max, new Vec2(this.min.x,this.max.y));
var p = tline.intersectsLineSegment(line);
if(p && this.containsPoint(p)) return true;
tline = new Line(this.max, new Vec2(this.max.x,this.min.y));
p = tline.intersectsLineSegment(line);
if(p && this.containsPoint(p)) return true;
tline = new Line(this.min, new Vec2(this.max.x,this.min.y));
p = tline.intersectsLineSegment(line);
if(p && this.containsPoint(p)) return true;
tline = new Line(this.min, new Vec2(this.min.x,this.max.y));
p = tline.intersectsLineSegment(line);
if(p && this.containsPoint(p)) return true;
return false;
};
AABB.prototype.intersectsCircle = function(c){
if(c.containsPoint(this.max)) return true;
if(c.containsPoint(this.min)) return true;
if(c.containsPoint(new Vec2(this.min.x,this.max.y))) return true;
if(c.containsPoint(new Vec2(this.max.x,this.min.y))) return true;
return false;
};
module.exports = AABB;
},{"./Line":22,"./Vec2":7}],25:[function(require,module,exports){
function getVelocities(A1,B1,time){
//Getting the midpoint between the points before velocities
var M1 = A1.pos.clone().mid(B1.pos);
//Getting the "angle" before vels, if one is 0, we need to divide the other
var Ang1 = A1.pos.clone().sub(B1.pos);
//Getting the distance before vels
var D1 = A1.pos.dist(B1.pos);
//Getting the positions after velocities
var A2 = A1.pos.clone().add(A1.vel.clone().scale(time));
var B2 = B1.pos.clone().add(B1.vel.clone().scale(time));
//Getting the midpoint between the points after velocities
var M2 = A2.clone().mid(B2);
//Getting the "angle" after vels
var Ang2 = A2.clone().sub(B2);
//Getting the distance after vels
var D2 = A2.dist(B2);
//Linear Velocity is the difference between the midpoints
var linearvel = M2.clone().sub(M1);
//Expanding Velocity is the velocity that is parrallel to the line
//Rotational velocity is the velocity that is perpendicular to the line
var A1_er_Vel = A1.vel.clone().sub(linearvel);
var B1_er_Vel = B1.vel.clone().sub(linearvel);
//expansion velocity is the difference between the distances
var expandvel = 0;
//Use law of cosigns to find the angular velocity?
var rotatevel = 0;
if(Math.abs(Ang1.angle() - Ang2.angle()) > 0.0001){
//we only worry about rotational vels if the slopes are different
//If it was real rotational velocity, this would not fly
//The Angle we're looking for is opposite of the distance between the new point and old
//The radius is the other two lengths
//I am aware this is not correct
rotatevel = Math.acos(1 - Math.pow(A2.dist(A1),2) / (Math.pow(D2,2)/2));
}
if(rotatevel === 0){
if(Math.abs(D2 - D1) > 0.000001){
//Normalized in resp00ect to A and M
//expansion velocity is the difference between the distances
expandvel = A1.pos.clone().sub(M1).div(D1).abs().mul(D2-D1);
}
//We don't need to worry about Expansive velocities if no change in rotation and distance
}else{
console.log("we have an angle?");
//technically expansive velocities are higly dependent on rotational
//But in reality, if there is a "rotational" vel
//there will be a expansive vel since "rotational" vel's actually cut through
//The radius because all velocities are linear
}
return {
cache:{
before:{a:A1,b:B1,m:M1,ang:Ang1,d:D1},
after:{a:A2,b:B2,m:M2,ang:Ang2,d:D2}
},
linearvel: linearvel,
expandvel: expandvel,
rotatevel: rotatevel
};
}
/*
net_vel.x*distance = parrallel_magnitude*net_slope.x +
-1*perpendicular_magnitude*net_slope.y
net_vel.y*distance = parrallel_magnitude*net_slope.y +
+ perpendicular_magnitude*net_slope.x
*/
function getParallelVelocity(net_vel,net_slope){
var dist = net_slope.length();
// var per = (net_slope.x*par - net_vel.x*dist)/net_slope.y;
// var par*net_slope.y = net_vel.y*dist - net_slope.x*per
// var par*net_slope.y = net_vel.y*dist - net_slope.x*(net_slope.x*par - net_vel.x*dist)/net_slope.y
// var par*net_slope.y = net_vel.y*dist - net_slope.x/net_slope.y*(net_slope.x*par - net_vel.x*dist)
// var par*net_slope.y = net_vel.y*dist - net_slope.x/net_slope.y*net_slope.x*par + net_slope.x/net_slope.y*net_vel.x*dist
// var par*net_slope.y + net_slope.x/net_slope.y*net_slope.x*par = net_vel.y*dist + net_slope.x/net_slope.y*net_vel.x*dist
// var par(net_slope.y + net_slope.x*net_slope.x/net_slope.y) = net_vel.y*dist + net_slope.x/net_slope.y*net_vel.x*dist
// var par(net_slope.y + net_slope.x*net_slope.x/net_slope.y) = net_vel.y*dist + net_vel.x*dist*net_slope.x/net_slope.y
// var par(net_slope.y + net_slope.x*net_slope.x/net_slope.y) = dist*(net_vel.y + net_vel.x*net_slope.x/net_slope.y)
// var par = dist*(net_vel.y + net_vel.x*net_slope.x/net_slope.y)/(net_slope.y + net_slope.x*net_slope.x/net_slope.y)
// var par = dist*net_slop.y(net_vel.y + net_vel.x*net_slope.x/net_slope.y)/(net_slope.y*net_slope.y + net_slope.y*net_slope.x*net_slope.x/net_slope.y)
// var par = dist*(net_vel.y*net_slop.y + net_vel.x*net_slope.x)/(net_slope.y*net_slope.y + net_slope.x*net_slope.x)
// var par = dist*(net_vel.y*net_slop.y + net_vel.x*net_slope.x)/(net_slope.y^2 + net_slope.x^2)
}
/*
net_vel.x*distance = parrallel_magnitude*net_slope.x +
-1*perpendicular_magnitude*net_slope.y
net_vel.y*distance = parrallel_magnitude*net_slope.y +
+ perpendicular_magnitude*net_slope.x
*/
function getPerpendicularVelocity(net_vel,net_slope){
var dist = net_slope.length();
// var par = (net_vel.x*dist + net_slope.y*per)/net_slope.x;
// var net_slope.x*per = net_vel.y*dist - net_slope.y*par;
// var net_slope.x*per = net_vel.y*dist - net_slope.y*(net_vel.x*dist + net_slope.y*per)/net_slope.x;
// var net_slope.x*per = net_vel.y*dist - net_slope.y/net_slope.x*(net_vel.x*dist + net_slope.y*per);
// var net_slope.x*per = net_vel.y*dist - net_vel.x*dist*net_slope.y/net_slope.x - net_slope.y*per*net_slope.y/net_slope.x;
// var net_slope.x*per + net_slope.y*per*net_slope.y/net_slope.x = net_vel.y*dist - net_vel.x*dist*net_slope.y/net_slope.x;
// var per*(net_slope.x + net_slope.y*net_slope.y/net_slope.x) = net_vel.y*dist - net_vel.x*dist*net_slope.y/net_slope.x;
// var per*net_slope.x*(net_slope.x + net_slope.y*net_slope.y/net_slope.x) = net_vel.y*dist*net_slope.x - net_vel.x*dist*net_slope.y;
// var per*(net_slope.x*net_slope.x + net_slope.y*net_slope.y) = net_vel.y*dist*net_slope.x - net_vel.x*dist*net_slope.y;
// var per = (net_vel.y*dist*net_slope.x - net_vel.x*dist*net_slope.y)/(net_slope.x*net_slope.x + net_slope.y*net_slope.y);
// var per = dist*(net_vel.y*net_slope.x - net_vel.x*net_slope.y)/(net_slope.x^2 + net_slope.y^2);
}
function getNetVelocityAtPoint(P1,vels){
var M1 = vels.cache.before.m;
var PD1 = P1.dist(M1);
var D1 = vels.cache.before.d;
var vel = vels.linearvel.clone();
if(vels.rotatevel === 0){
if(vels.expandvel === 0) return vel;
return vel.add(vels.expandvel.mul(P1.clone().sub(M1).signum())*PD1*2/D1);
}
}
function getVelocityAtPoint(A,B,P){
var ad = A.pos.dist(P.pos);
var bd = B.pos.dist(P.pos);
return A.vel.clone().mul(bd).div(ad+bd).add(B.vel.clone().mul(ad).div(ad+bd));
}
function getVelocitiesFromPoint(A,B,P){
var ad = A.pos.dist(P.pos);
var bd = B.pos.dist(P.pos);
var nd = ad+bd;
//
// A = (ad+bd)*(P - B.vel.clone().mul(ad).div(ad+bd))/bd;
// B = (ad+bd)*(P - A.vel.clone().mul(bd).div(ad+bd))/ad;
A.vel.mul(ad).div(nd).add(P.vel.mul(bd).div(nd));
B.vel.mul(bd).div(nd).add(P.vel.mul(ad).div(nd));
}
module.exports.getVelocityAtPoint = getVelocityAtPoint;
module.exports.getVelocitiesFromPoint = getVelocitiesFromPoint;
module.exports.getNetVelocityAtPoint = getNetVelocityAtPoint;
module.exports.getVelocities = getVelocities;
/*
We have the angle of the Line between point A and B
we must then understand how much of the velocity at point A is
-perpendicular
-parrallel
Parrellel line's definition assumes
-The angle between the two lines are 0 or 180
-the slope of the lines are equal
-the vector's of the line can be
- (-x, -slope*x) or (x, slope*x)
- (-y/slope, -y) or (y/slope, y)
Perpendicular line's definition assumes
-The angle between the two lines are 90 or 270
-The slope of the lines are -1*(x/y)
-The vector's of the line can be
- (-slope*x, -x) or (slope*x, x)
- (-y, -y/slope) or (y, y/slope)
f(net_vel) = parrallel_magnitude*normal_slope + perpendicular_magnitude*normal_slope
normal_slope = net_slope/distance
f(net_vel) = parrallel_magnitude*net_slope/distance
+ perpendicular_magnitude*net_slope_swapped/distance
net_vel = parrallel_magnitude*net_slope/distance
+ perpendicular_magnitude*net_slope_swapped/distance
net_vel*distance = parrallel_magnitude*net_slope
+ perpendicular_magnitude*-1*net_slope_swapped
net_vel.x*distance = parrallel_magnitude*net_slope.x +
+ perpendicular_magnitude*-1*net_slope.y
net_vel.y*distance = parrallel_magnitude*net_slope.y +
+ perpendicular_magnitude*net_slope.x
perpendicular_magnitude = (net_vel.y*distance - parrallel_magnitude*net_slope.y)/net_slope.x
net_vel.x*distance =
parrallel_magnitude*net_slope.x -
net_slope.y*(net_vel.y*distance - parrallel_magnitude*net_slope.y)/net_slope.x
net_vel.x*distance =
parrallel_magnitude*net_slope.x -
net_slope.y/net_slope.x*(net_vel.y*distance - parrallel_magnitude*net_slope.y)
net_vel.x*distance =
parrallel_magnitude*net_slope.x -
net_slope.y/net_slope.x*net_vel.y*distance
+ net_slope.y/net_slope.x*parrallel_magnitude*net_slope.y
net_vel.x*distance + net_slope.y/net_slope.x*net_vel.y*distance
=
parrallel_magnitude(net_slope.x + net_slope.y*net_slope.y/net_slope.x)
parrallel_magnitude
=
net_vel.x*distance + net_slope.y/net_slope.x*net_vel.y*distance
/(net_slope.x - + net_slope.y*net_slope.y/net_slope.x)
parrallel_magnitude = (net_vel.y*distance - perpendicular_magnitude*net_slope.x)
/net_slope.y
net_vel.x*distance = (net_vel.y*distance - perpendicular_magnitude*net_slope.x)
/net_slope.y
+ perpendicular_magnitude*-1*net_slope.y
net_vel.x*distance =
net_vel.y*distance/net_slope.y
- perpendicular_magnitude*net_slope.x/net_slope.y
+ perpendicular_magnitude*-1*net_slope.y
net_vel.x*distance - net_vel.y*distance/net_slope.y =
-1*(net_slope.x/net_slope.y + net_slope.y)
* perpendicular_magnitude
perpendicular_magnitude =
(net_vel.x*distance - net_vel.y*distance/net_slope.y)
/ -1*(net_slope.x/net_slope.y + net_slope.y)
perpendicular_magnitude =
distance*(net_vel.x - net_vel.y/net_slope.y)
/ (-1*(net_slope.x/net_slope.y + net_slope.y))
perpendicular_magnitude =
distance*(net_vel.x - net_vel.y/net_slope.y)
/ (-1*(net_slope.x/net_slope.y + net_slope.y))
parrallel_magnitude =
(
net_vel.y*distance -
(
distance*(net_vel.x - net_vel.y/net_slope.y)
/ (-1*(net_slope.x/net_slope.y + net_slope.y))
)*net_slope.x
)/net_slope.y
parrallel_magnitude =
distance*(
net_vel.y -
(
(net_vel.x - net_vel.y/net_slope.y)
/ (-1*(net_slope.x/net_slope.y + net_slope.y))
)*net_slope.x
)/net_slope.y
*/
},{}],8:[function(require,module,exports){
var AABB = require("../structures/AABB");
var Line = require("../structures/Line");
var boxIntersect = require("box-intersect");
var Time = require("./time");
var Momentum = require("./momentum");
function toExport(composites,step){
var l = composites.length;
var aabbs = new Array(l);
while(l--){
aabbs[l] = composites[l].aabb.toArray();
}
var intersects = boxIntersect(aabbs);
if(!(l = intersects.length)) return;
while(l--){
handleSuspects(
composites[intersects[l][0]],
composites[intersects[l][1]],
step
);
}
}
function handleSuspects(compositeA, compositeB, timestep){
var l, ll, i;
var manifold = compositeA.aabb.sub(compositeB.aabb);
var suspectsA = manifold.getSuspects(compositeA.particles);
var suspectsB = manifold.getSuspects(compositeB.particles);
if(suspectsA.lines.length === 0 || suspectsB.lines.length === 0){
return false;
}
if(suspectsA.inside.length === 0 && suspectsB.inside.length === 0){
return false;
}
l = suspectsA.inside.length;
while(l--){
ll = suspectsB.lines.length;
while(ll--){
runCollision(
compositeA.particles[suspectsA.inside[l]], //the point
compositeB.particles[suspectsB.lines[ll][0]], //a of the line
compositeB.particles[suspectsB.lines[ll][1]], //b of the line
timestep
);
}
}
l = suspectsB.inside.length;
while(l--){
ll = suspectsA.lines.length;
while(ll--){
runCollision(
compositeB.particles[suspectsB.inside[l]], //the point
compositeA.particles[suspectsA.lines[ll][0]], //a of the line
compositeA.particles[suspectsA.lines[ll][1]], //b of the line
timestep
);
}
}
// console.log("collision solved");
}
function runCollision(p,a,b,timestep){
//this finds the time difference in which they first intersect
var res = Time.getImpacts(p, a, b);
if(!res) return false;
res = Time.restrict(res,timestep);
if(!res) return false;
res /= timestep;
Momentum.distributeVelocities(p,a,b,res);
}
module.exports = toExport;
},{"../structures/AABB":19,"../structures/Line":22,"./momentum":24,"./time":23,"box-intersect":26}],21:[function(require,module,exports){
function Polygon(oPoints){
var l = oPoints.length;
var i = l;
var points = Array(i);
while (i--) {
points[l-i-1] = oPoints[i].pos||oPoints[i];
}
for(var i in Polygon.prototype){
Object.defineProperty(points,i,{
enumerable: false,
value: Polygon.prototype[i].bind(points)
});
}
return points;
}
Polygon.prototype.clone = function(){
var points = this.slice(0);
for(var i in Polygon.prototype){
Object.defineProperty(points,i,{
enumerable: false,
value:Polygon.prototype[i].bind(points)
});
}
return points;
}
Polygon.prototype.forThree = function(fn,skip){
var l = this.length;
var i = l - (skip||0);
while(i--){
var prev = (i+1)%l;//((i == 0)?l:i) -1
var curr = i;
var next = (i+l-1)%l; //i == l-1?0:i+1
fn.call(this,this[prev],this[curr],this[next], curr);
}
}
var cachable = require("./cacheable");
for(var i in cachable){
Polygon.prototype[i] = cachable[i]
}
var intersects = require("./intersects");
for(var i in intersects){
Polygon.prototype[i] = intersects[i]
}
module.exports = Polygon;
},{"./cacheable":27,"./intersects":28}],22:[function(require,module,exports){
var Vec2 = require("../Vec2");
function Line(A,B){
if(A.equals(B))
throw new Error("cannot construct line when A == B");
this.A = A;
this.B = B;
this.angledSlope = A.clone().sub(B).normalize();
this.slope = this.angledSlope.scale(
Math.sign(this.angledSlope.x)||Math.sign(this.angledSlope.y)
);
this.inv_slope = (this.slope.y == 0)?false:this.slope.x/this.slope.y;
this.true_slope = (this.slope.x == 0)?false:this.slope.y/this.slope.x;
this.yint = (this.true_slope !== false)?-this.true_slope*A.x + A.y:false;
this.xint = (this.inv_slope !== false)?-this.inv_slope*A.y + A.x:false;
this.mid = A.clone().mid(B);
this.length2 = A.dist2(B);
this.length = Math.sqrt(this.length2);
this.cross = A.cross(B);
}
Line.prototype.toString = function(){
return "limits:["+A+","+B+"]," +
"intercepts:("+this.yint+","+thisxint+")";
"slope:("+this.slope+"), ";
}
var interesctions = require("./intersects.js");
for(var i in interesctions){
Line.prototype[i] = interesctions[i];
}
var eq = require("./questions.js");
for(var i in eq){
Line.prototype[i] = eq[i];
}
//This should be in cacheable
Line.prototype.perpendicularBisector = function(){
var mid = this.mid;
var A = this.A.clone().sub(mid).swap();
var B = A.clone();
A.y *= -1
B.x *= -1;
A.add(mid);
B.add(mid);
return new Line(A,B);
}
Line.prototype.getYValue = function(x){
if(!this.slope.x) return false;
return x*this.true_slope + this.yint;
};
Line.prototype.getXValue = function(y){
if(!this.slope.y) return false;
return y*this.inv_slope + this.xint;
};
module.exports = Line;
},{"../Vec2":7,"./intersects.js":29,"./questions.js":30}],30:[function(require,module,exports){
var Line = {};
Line.equals = function(line){
return this.A.equals(line.A)
&& this.B.equals(line.B);
}
Line.epsilonEquals = function(line, epsilon) {
return this.A.epsilonEquals(line.A,epsilon)
&& this.B.epsilonEquals(line.B,epsilon);
}
Line.equalSlope = function(line) {
return this.slope.equals(line.slope)
&& (this.xint)?this.xint == line.xint
:this.yint == line.yint;
}
Line.epsilonEqualSlope = function(line, epsilon) {
return this.slope.epsilonEquals(line.slope,epsilon)
&& (this.xint)?Math.abs(this.xint - line.xint) <= epsilon
:Math.abs(this.yint - line.yint) <= epsilon
}
Line.equalMagnitude = function(line) {
return this.slope.equals(line.slope)
&& this.length == line.length
}
Line.epsilonEqualMagnitude = function(line, epsilon) {
return this.slope.epsilonEquals(line.slope,epsilon)
&& Math.abs(this.length - line.length) <= epsilon
}
module.exports = Line;
},{}],20:[function(require,module,exports){
var Vec2 = require("../Vec2");
var Line = require("../Line");
function Triangle(A,B,C){
if(A.equals(B) || B.equals(C) || C.equals(A))
throw new Error("cannot create triangle when two points are the same")
this.A = A;
this.B = B;
this.C = C;
this.AB = new Line(A,B);
this.BC = new Line(B,C);
this.CA = new Line(C,A);
this.ABC = Math.lawCos(this.CA.length, this.AB.length, this.BC.length);
this.BCA = Math.asin(Math.sin(this.ABC)*this.CA.length/this.AB.length);
this.CAB = Math.asin(Math.sin(this.ABC)*this.BC.length/this.AB.length);
this.perimiter = this.AB.length + this.BC.length + this.CA.length
this.partialArea = this.AB.cross + this.BC.cross + this.CA.cross
this.area = Math.abs(this.partialArea);
}
var interesctions = require("./intersects.js");
for(var i in interesctions){
Triangle.prototype[i] = interesctions[i];
}
var questions = require("./questions.js");
for(var i in questions){
Triangle.prototype[i] = questions[i];
}
var cacheable = require("./cacheable.js");
Triangle.prototype.getConcaveBisector = cacheable.getConcaveBisector;
module.exports = Triangle;
},{"../Line":22,"../Vec2":7,"./cacheable.js":33,"./intersects.js":31,"./questions.js":32}],31:[function(require,module,exports){
var Triangle = {};
Triangle.hasPoint = function(point){
//http://www.blackpawn.com/texts/pointinpoly/
// Compute vectors
var v0 = this.C.clone().sub(this.B);
var v1 = this.A.clone().sub(this.B);
var v2 = point.clone().sub(this.B);
// Compute dot products
var dot00 = v0.dot(v0);
var dot01 = v0.dot(v1);
var dot02 = v0.dot(v2);
var dot11 = v1.dot(v1);
var dot12 = v1.dot(v2);
// Compute barycentric coordinates
var invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
var u = (dot11 * dot02 - dot01 * dot12) * invDenom
var v = (dot00 * dot12 - dot01 * dot02) * invDenom
// Check if point is in triangle
return (u >= 0) && (v >= 0) && (u + v < 1)
}
module.exports = Triangle;
},{}],32:[function(require,module,exports){
var Triangle = {};
var sqrt2 = Math.pow(2,1/2);
Triangle.isConcave = function(a,b,c){
//rotate the points around B to make B and A parrallel to the X axis
//If the line BC is negative, it is Concave
//If the line BC is positive, it is Convex
var ac = new Line(a,c);
// A should always be rotated -PI/2
return ac.pointIsLeftOrTop(ac.perpendicularBisector().A)
== ac.pointIsLeftOrTop(b);
// return Math.sign(p.x) == Math.sign(b.x) && Math.sign(p.y) == Math.sign(b.y);
}
Triangle.anglePrimer = function(){
return this.CA.length - sqrt2*(this.AB.length+this.BC.length)/2;
}
Triangle.isAcute = function(){
return this.anglePrimer() < 0;
}
Triangle.isObtuse = function(){
return this.anglePrimer() > 0;
}
Triangle.isRight = function(){
return this.anglePrimer() == 0;
}
Triangle.equals = function(tri){
return this.A.equals(tri.A)
&& this.B.equals(tri.B)
&& this.C.equals(tri.C);
}
Triangle.epsilonEquals = function(tri, epsilon) {
return this.A.epsilonEquals(tri.A,epsilon)
&& this.B.epsilonEquals(tri.B,epsilon)
&& this.C.epsilonEquals(tri.C,epsilon);
}
Triangle.equalShape = function(tri) {
return this.area == tri.area && this.perimiter == tri.perimiter
}
Triangle.epsilonEqualShape = function(tri,epsilon) {
return Math.abs(this.area - tri.area)/27 <= epsilon
&& Math.abs(this.perimiter - tri.perimiter)/9 <= epsilon;
}
Triangle.equalAngles = function(tri) {
var keys = ["ABC","BCA", "CAB"];
var i = 3;
var j;
while(i--){
j = 3;
while(j--){
if(this[keys[i]] == tri[keys[i]]) break;
}
if(j < 0) return false;
}
return true;
}
module.exports = Triangle;
},{}],33:[function(require,module,exports){
var Triangle = {};
Triangle.getConcaveBisector = function(){
return this.CA.perpendicularBisector();
}
Triangle.AB = function(){
return new Line(this.A,this.B);
}
Triangle.BC = function(){
return new Line(B,C);
}
Triangle.CA = function(){
return new Line(C,A);
}
Triangle.ABC = function(){
return Math.lawCos(this.CA.length, this.AB.length, this.BC.length);
}
Triangle.BCA = function(){
return Math.asin(Math.sin(this.ABC)*this.CA.length/this.AB.length);
}
Triangle.CAB = function(){
return Math.asin(Math.sin(this.ABC)*this.BC.length/this.AB.length);
}
Triangle.perimiter = function(){
return this.AB.length + this.BC.length + this.CA.length
}
Triangle.partialArea = function(){
return this.AB.cross + this.BC.cross + this.CA.cross
}
Triangle.area = function(){
return Math.abs(this.partialArea);
}
module.exports = Triangle;
},{}],29:[function(require,module,exports){
var Vec2 = require("../Vec2");
var Line = {};
Line.intersectsLine = function(lineB){
var lineA = this;
if(lineA.slope.equals(lineB.slope)) return false;
var intersect = new Vec2();
//lineA should take care of any special conditions
if(lineA.slope.x === 0 || lineB.slope.x === 0){
if(lineA.slope.y === 0 || lineB.slope.y === 0){
return new Vec2(
(lineA.slope.x === 0)?lineA.xint:lineB.xint,
(lineA.slope.y === 0)?lineA.yint:lineB.yint
);
}
//I don't care which one is which 0
//calculate in respect to X
intersect.y = (lineA.xint-lineB.xint)/(lineB.inv_slope-lineA.inv_slope);
intersect.x = lineA.inv_slope*intersect.y + lineA.xint;
}else{
intersect.x = (lineA.yint-lineB.yint)/(lineB.true_slope-lineA.true_slope);
intersect.y = lineA.true_slope*intersect.x + lineA.yint;
}
return intersect;
}
Line.intersectsLineSegment = function(line){
var intersect = this.intersectsLine(line);
if(!intersect) return false;
if(!(new Vec2().posinf().min(this.A).min(this.B).max(intersect).equals(intersect)))
return false;
if(!(new Vec2().neginf().max(this.A).max(this.B).min(intersect).equals(intersect)))
return false;
if(!(new Vec2().posinf().min(line.A).min(line.B).max(intersect).equals(intersect)))
return false;
if(!(new Vec2().neginf().max(line.A).max(line.B).min(intersect).equals(intersect)))
return false;
return intersect;
}
Line.pointIsLeftOrTop = function(p){
//get slopes of the lines
//see if a ray cast from 0,0 intersects it
return this.B.clone().sub(this.A).cross(p.clone().sub(this.A)) < 0;
};
Line.intersectsPoint = function(p){
if(!this.slope.x) return this.xint == p.x;
return p.y == p.x*this.slope.slope() + this.yint;
};
module.exports = Line;
},{"../Vec2":7}],26:[function(require,module,exports){
'use strict'
module.exports = boxIntersectWrapper
var pool = require('typedarray-pool')
var sweep = require('./lib/sweep')
var boxIntersectIter = require('./lib/intersect')
function boxEmpty(d, box) {
for(var j=0; j<d; ++j) {
if(!(box[j] <= box[j+d])) {
return true
}
}
return false
}
//Unpack boxes into a flat typed array, remove empty boxes
function convertBoxes(boxes, d, data, ids) {
var ptr = 0
var count = 0
for(var i=0, n=boxes.length; i<n; ++i) {
var b = boxes[i]
if(boxEmpty(d, b)) {
continue
}
for(var j=0; j<2*d; ++j) {
data[ptr++] = b[j]
}
ids[count++] = i
}
return count
}
//Perform type conversions, check bounds
function boxIntersect(red, blue, visit, full) {
var n = red.length
var m = blue.length
//If either array is empty, then we can skip this whole thing
if(n <= 0 || m <= 0) {
return
}
//Compute dimension, if it is 0 then we skip
var d = (red[0].length)>>>1
if(d <= 0) {
return
}
var retval
//Convert red boxes
var redList = pool.mallocDouble(2*d*n)
var redIds = pool.mallocInt32(n)
n = convertBoxes(red, d, redList, redIds)
if(n > 0) {
if(d === 1 && full) {
//Special case: 1d complete
sweep.init(n)
retval = sweep.sweepComplete(
d, visit,
0, n, redList, redIds,
0, n, redList, redIds)
} else {
//Convert blue boxes
var blueList = pool.mallocDouble(2*d*m)
var blueIds = pool.mallocInt32(m)
m = convertBoxes(blue, d, blueList, blueIds)
if(m > 0) {
sweep.init(n+m)
if(d === 1) {
//Special case: 1d bipartite
retval = sweep.sweepBipartite(
d, visit,
0, n, redList, redIds,
0, m, blueList, blueIds)
} else {
//General case: d>1
retval = boxIntersectIter(
d, visit, full,
n, redList, redIds,
m, blueList, blueIds)
}
pool.free(blueList)
pool.free(blueIds)
}
}
pool.free(redList)
pool.free(redIds)
}
return retval
}
//User-friendly wrapper, handle full input and no-visitor cases
function boxIntersectWrapper(arg0, arg1, arg2) {
var result
switch(arguments.length) {
case 1:
result = []
boxIntersect(arg0, arg0, function(i,j) {
result.push([i, j])
}, true)
return result
case 2:
if(typeof arg1 === 'function') {
var visit = arg1
return boxIntersect(arg0, arg0, visit, true)
} else {
result = []
boxIntersect(arg0, arg1, function(i,j) {
result.push([i, j])
}, false)
return result
}
case 3:
return boxIntersect(arg0, arg1, arg2, false)
default:
throw new Error('box-intersect: Invalid arguments')
}
}
},{"./lib/intersect":35,"./lib/sweep":34,"typedarray-pool":36}],27:[function(require,module,exports){
var Vec2 = require("../Vec2");
var Polygon = {};
Polygon.getMidPoint = function(){
var l = this.length;
var mid = new Vec2();
for(var i=this.length;i--;){
mid.add(this[i].clone().scale(1/l));
};
return mid;
}
Polygon.getArea = function(){
var net = 0;
//http://www.wikihow.com/Calculate-the-Area-of-a-Polygon
this.forThree(function(a,b,c){
net += b.cross(c);
})
return net;
}
Polygon.getAABB = function(){
var max = new Vec2(Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY);
var min = new Vec2(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY);
for(var i=this.length;i--;){
max.max(this[i]);
min.min(this[i]);
}
return {max:max,min:min};
}
module.exports = Polygon
},{"../Vec2":7}],28:[function(require,module,exports){
var AABB = require("../AABB")
var Line = require("../Line");
var Polygon = {};
Polygon.intersectsLine = function(line,skip){
//creating smaller aabbs
//We're going to detect intersection by slope
//however, the point of intersection may be outside of the of the possible area
//as a result we're creating a smaller aabb thats the maxes and minimums of the current area
var tAABB = new AABB(line.A,line.B);
var intersections = [];
this.forThree(function(oprev,ocurr,onext){
if(line.A == ocurr) return;
if(line.B == oprev) return;
if(oprev == line.A) return;
var oAABB = new AABB(oprev,ocurr);
if(!tAABB.intersectsAABB(oAABB)) return;
//I would like to cache the oprev->ocurr line if possible
//I would also prefer searching only for lines with the appropiate AABBs
var intersect = line.intersectsLine(new Line(oprev,ocurr));
if(!intersect) return;
var netAABB = {
max: oAABB.max.min(tAABB.max),
min: oAABB.min.max(tAABB.min)
};
//If intersect point isn't between the two points, this isn't for us.
if(!tAABB.containsPoint(intersect)) return;
intersections.push(intersect);
},skip);
return intersections;
}
module.exports = Polygon;
},{"../AABB":19,"../Line":22}],37:[function(require,module,exports){
'use strict';
//This code is extracted from ndarray-sort
//It is inlined here as a temporary workaround
module.exports = wrapper;
var INSERT_SORT_CUTOFF = 32
function wrapper(data, n0) {
if (n0 <= 4*INSERT_SORT_CUTOFF) {
insertionSort(0, n0 - 1, data);
} else {
quickSort(0, n0 - 1, data);
}
}
function insertionSort(left, right, data) {
var ptr = 2*(left+1)
for(var i=left+1; i<=right; ++i) {
var a = data[ptr++]
var b = data[ptr++]
var j = i
var jptr = ptr-2
while(j-- > left) {
var x = data[jptr-2]
var y = data[jptr-1]
if(x < a) {
break
} else if(x === a && y < b) {
break
}
data[jptr] = x
data[jptr+1] = y
jptr -= 2
}
data[jptr] = a
data[jptr+1] = b
}
}
function swap(i, j, data) {
i *= 2
j *= 2
var x = data[i]
var y = data[i+1]
data[i] = data[j]
data[i+1] = data[j+1]
data[j] = x
data[j+1] = y
}
function move(i, j, data) {
i *= 2
j *= 2
data[i] = data[j]
data[i+1] = data[j+1]
}
function rotate(i, j, k, data) {
i *= 2
j *= 2
k *= 2
var x = data[i]
var y = data[i+1]
data[i] = data[j]
data[i+1] = data[j+1]
data[j] = data[k]
data[j+1] = data[k+1]
data[k] = x
data[k+1] = y
}
function shufflePivot(i, j, px, py, data) {
i *= 2
j *= 2
data[i] = data[j]
data[j] = px
data[i+1] = data[j+1]
data[j+1] = py
}
function compare(i, j, data) {
i *= 2
j *= 2
var x = data[i],
y = data[j]
if(x < y) {
return false
} else if(x === y) {
return data[i+1] > data[j+1]
}
return true
}
function comparePivot(i, y, b, data) {
i *= 2
var x = data[i]
if(x < y) {
return true
} else if(x === y) {
return data[i+1] < b
}
return false
}
function quickSort(left, right, data) {
var sixth = (right - left + 1) / 6 | 0,
index1 = left + sixth,
index5 = right - sixth,
index3 = left + right >> 1,
index2 = index3 - sixth,
index4 = index3 + sixth,
el1 = index1,
el2 = index2,
el3 = index3,
el4 = index4,
el5 = index5,
less = left + 1,
great = right - 1,
tmp = 0
if(compare(el1, el2, data)) {
tmp = el1
el1 = el2
el2 = tmp
}
if(compare(el4, el5, data)) {
tmp = el4
el4 = el5
el5 = tmp
}
if(compare(el1, el3, data)) {
tmp = el1
el1 = el3
el3 = tmp
}
if(compare(el2, el3, data)) {
tmp = el2
el2 = el3
el3 = tmp
}
if(compare(el1, el4, data)) {
tmp = el1
el1 = el4
el4 = tmp
}
if(compare(el3, el4, data)) {
tmp = el3
el3 = el4
el4 = tmp
}
if(compare(el2, el5, data)) {
tmp = el2
el2 = el5
el5 = tmp
}
if(compare(el2, el3, data)) {
tmp = el2
el2 = el3
el3 = tmp
}
if(compare(el4, el5, data)) {
tmp = el4
el4 = el5
el5 = tmp
}
var pivot1X = data[2*el2]
var pivot1Y = data[2*el2+1]
var pivot2X = data[2*el4]
var pivot2Y = data[2*el4+1]
var ptr0 = 2 * el1;
var ptr2 = 2 * el3;
var ptr4 = 2 * el5;
var ptr5 = 2 * index1;
var ptr6 = 2 * index3;
var ptr7 = 2 * index5;
for (var i1 = 0; i1 < 2; ++i1) {
var x = data[ptr0+i1];
var y = data[ptr2+i1];
var z = data[ptr4+i1];
data[ptr5+i1] = x;
data[ptr6+i1] = y;
data[ptr7+i1] = z;
}
move(index2, left, data)
move(index4, right, data)
for (var k = less; k <= great; ++k) {
if (comparePivot(k, pivot1X, pivot1Y, data)) {
if (k !== less) {
swap(k, less, data)
}
++less;
} else {
if (!comparePivot(k, pivot2X, pivot2Y, data)) {
while (true) {
if (!comparePivot(great, pivot2X, pivot2Y, data)) {
if (--great < k) {
break;
}
continue;
} else {
if (comparePivot(great, pivot1X, pivot1Y, data)) {
rotate(k, less, great, data)
++less;
--great;
} else {
swap(k, great, data)
--great;
}
break;
}
}
}
}
}
shufflePivot(left, less-1, pivot1X, pivot1Y, data)
shufflePivot(right, great+1, pivot2X, pivot2Y, data)
if (less - 2 - left <= INSERT_SORT_CUTOFF) {
insertionSort(left, less - 2, data);
} else {
quickSort(left, less - 2, data);
}
if (right - (great + 2) <= INSERT_SORT_CUTOFF) {
insertionSort(great + 2, right, data);
} else {
quickSort(great + 2, right, data);
}
if (great - less <= INSERT_SORT_CUTOFF) {
insertionSort(less, great, data);
} else {
quickSort(less, great, data);
}
}
},{}],38:[function(require,module,exports){
'use strict'
var DIMENSION = 'd'
var AXIS = 'ax'
var VISIT = 'vv'
var FLIP = 'fp'
var ELEM_SIZE = 'es'
var RED_START = 'rs'
var RED_END = 're'
var RED_BOXES = 'rb'
var RED_INDEX = 'ri'
var RED_PTR = 'rp'
var BLUE_START = 'bs'
var BLUE_END = 'be'
var BLUE_BOXES = 'bb'
var BLUE_INDEX = 'bi'
var BLUE_PTR = 'bp'
var RETVAL = 'rv'
var INNER_LABEL = 'Q'
var ARGS = [
DIMENSION,
AXIS,
VISIT,
RED_START,
RED_END,
RED_BOXES,
RED_INDEX,
BLUE_START,
BLUE_END,
BLUE_BOXES,
BLUE_INDEX
]
function generateBruteForce(redMajor, flip, full) {
var funcName = 'bruteForce' +
(redMajor ? 'Red' : 'Blue') +
(flip ? 'Flip' : '') +
(full ? 'Full' : '')
var code = ['function ', funcName, '(', ARGS.join(), '){',
'var ', ELEM_SIZE, '=2*', DIMENSION, ';']
var redLoop =
'for(var i=' + RED_START + ',' + RED_PTR + '=' + ELEM_SIZE + '*' + RED_START + ';' +
'i<' + RED_END +';' +
'++i,' + RED_PTR + '+=' + ELEM_SIZE + '){' +
'var x0=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '],' +
'x1=' + RED_BOXES + '[' + AXIS + '+' + RED_PTR + '+' + DIMENSION + '],' +
'xi=' + RED_INDEX + '[i];'
var blueLoop =
'for(var j=' + BLUE_START + ',' + BLUE_PTR + '=' + ELEM_SIZE + '*' + BLUE_START + ';' +
'j<' + BLUE_END + ';' +
'++j,' + BLUE_PTR + '+=' + ELEM_SIZE + '){' +
'var y0=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '],' +
(full ? 'y1=' + BLUE_BOXES + '[' + AXIS + '+' + BLUE_PTR + '+' + DIMENSION + '],' : '') +
'yi=' + BLUE_INDEX + '[j];'
if(redMajor) {
code.push(redLoop, INNER_LABEL, ':', blueLoop)
} else {
code.push(blueLoop, INNER_LABEL, ':', redLoop)
}
if(full) {
code.push('if(y1<x0||x1<y0)continue;')
} else if(flip) {
code.push('if(y0<=x0||x1<y0)continue;')
} else {
code.push('if(y0<x0||x1<y0)continue;')
}
code.push('for(var k='+AXIS+'+1;k<'+DIMENSION+';++k){'+
'var r0='+RED_BOXES+'[k+'+RED_PTR+'],'+
'r1='+RED_BOXES+'[k+'+DIMENSION+'+'+RED_PTR+'],'+
'b0='+BLUE_BOXES+'[k+'+BLUE_PTR+'],'+
'b1='+BLUE_BOXES+'[k+'+DIMENSION+'+'+BLUE_PTR+'];'+
'if(r1<b0||b1<r0)continue ' + INNER_LABEL + ';}' +
'var ' + RETVAL + '=' + VISIT + '(')
if(flip) {
code.push('yi,xi')
} else {
code.push('xi,yi')
}
code.push(');if(' + RETVAL + '!==void 0)return ' + RETVAL + ';}}}')
return {
name: funcName,
code: code.join('')
}
}
function bruteForcePlanner(full) {
var funcName = 'bruteForce' + (full ? 'Full' : 'Partial')
var prefix = []
var fargs = ARGS.slice()
if(!full) {
fargs.splice(3, 0, FLIP)
}
var code = ['function ' + funcName + '(' + fargs.join() + '){']
function invoke(redMajor, flip) {
var res = generateBruteForce(redMajor, flip, full)
prefix.push(res.code)
code.push('return ' + res.name + '(' + ARGS.join() + ');')
}
code.push('if(' + RED_END + '-' + RED_START + '>' +
BLUE_END + '-' + BLUE_START + '){')
if(full) {
invoke(true, false)
code.push('}else{')
invoke(false, false)
} else {
code.push('if(' + FLIP + '){')
invoke(true, true)
code.push('}else{')
invoke(true, false)
code.push('}}else{if(' + FLIP + '){')
invoke(false, true)
code.push('}else{')
invoke(false, false)
code.push('}')
}
code.push('}}return ' + funcName)
var codeStr = prefix.join('') + code.join('')
var proc = new Function(codeStr)
return proc()
}
exports.partial = bruteForcePlanner(false)
exports.full = bruteForcePlanner(true)
},{}],39:[function(require,module,exports){
'use strict'
module.exports = genPartition
var code = 'for(var j=2*a,k=j*c,l=k,m=c,n=b,o=a+b,p=c;d>p;++p,k+=j){var _;if($)if(m===p)m+=1,l+=j;else{for(var s=0;j>s;++s){var t=e[k+s];e[k+s]=e[l],e[l++]=t}var u=f[p];f[p]=f[m],f[m++]=u}}return m'
function genPartition(predicate, args) {
var fargs ='abcdef'.split('').concat(args)
var reads = []
if(predicate.indexOf('lo') >= 0) {
reads.push('lo=e[k+n]')
}
if(predicate.indexOf('hi') >= 0) {
reads.push('hi=e[k+o]')
}
fargs.push(
code.replace('_', reads.join())
.replace('$', predicate))
return Function.apply(void 0, fargs)
}
},{}],34:[function(require,module,exports){
(function(){'use strict'
module.exports = {
init: sqInit,
sweepBipartite: sweepBipartite,
sweepComplete: sweepComplete,
scanBipartite: scanBipartite,
scanComplete: scanComplete
}
var pool = require('typedarray-pool')
var bits = require('bit-twiddle')
var isort = require('./sort')
//Flag for blue
var BLUE_FLAG = (1<<28)
//1D sweep event queue stuff (use pool to save space)
var INIT_CAPACITY = 1024
var RED_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY)
var RED_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY)
var BLUE_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY)
var BLUE_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY)
var COMMON_SWEEP_QUEUE = pool.mallocInt32(INIT_CAPACITY)
var COMMON_SWEEP_INDEX = pool.mallocInt32(INIT_CAPACITY)
var SWEEP_EVENTS = pool.mallocDouble(INIT_CAPACITY * 8)
//Reserves memory for the 1D sweep data structures
function sqInit(count) {
var rcount = bits.nextPow2(count)
if(RED_SWEEP_QUEUE.length < rcount) {
pool.free(RED_SWEEP_QUEUE)
RED_SWEEP_QUEUE = pool.mallocInt32(rcount)
}
if(RED_SWEEP_INDEX.length < rcount) {
pool.free(RED_SWEEP_INDEX)
RED_SWEEP_INDEX = pool.mallocInt32(rcount)
}
if(BLUE_SWEEP_QUEUE.length < rcount) {
pool.free(BLUE_SWEEP_QUEUE)
BLUE_SWEEP_QUEUE = pool.mallocInt32(rcount)
}
if(BLUE_SWEEP_INDEX.length < rcount) {
pool.free(BLUE_SWEEP_INDEX)
BLUE_SWEEP_INDEX = pool.mallocInt32(rcount)
}
if(COMMON_SWEEP_QUEUE.length < rcount) {
pool.free(COMMON_SWEEP_QUEUE)
COMMON_SWEEP_QUEUE = pool.mallocInt32(rcount)
}
if(COMMON_SWEEP_INDEX.length < rcount) {
pool.free(COMMON_SWEEP_INDEX)
COMMON_SWEEP_INDEX = pool.mallocInt32(rcount)
}
var eventLength = 8 * rcount
if(SWEEP_EVENTS.length < eventLength) {
pool.free(SWEEP_EVENTS)
SWEEP_EVENTS = pool.mallocDouble(eventLength)
}
}
//Remove an item from the active queue in O(1)
function sqPop(queue, index, count, item) {
var idx = index[item]
var top = queue[count-1]
queue[idx] = top
index[top] = idx
}
//Insert an item into the active queue in O(1)
function sqPush(queue, index, count, item) {
queue[count] = item
index[item] = count
}
//Recursion base case: use 1D sweep algorithm
function sweepBipartite(
d, visit,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex) {
//store events as pairs [coordinate, idx]
//
// red create: -(idx+1)
// red destroy: idx
// blue create: -(idx+BLUE_FLAG)
// blue destroy: idx+BLUE_FLAG
//
var ptr = 0
var elemSize = 2*d
var istart = d-1
var iend = elemSize-1
for(var i=redStart; i<redEnd; ++i) {
var idx = redIndex[i]
var redOffset = elemSize*i
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
SWEEP_EVENTS[ptr++] = -(idx+1)
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
SWEEP_EVENTS[ptr++] = idx
}
for(var i=blueStart; i<blueEnd; ++i) {
var idx = blueIndex[i]+BLUE_FLAG
var blueOffset = elemSize*i
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
SWEEP_EVENTS[ptr++] = -idx
SWEEP_EVENTS[ptr++] = blue[blueOffset+iend]
SWEEP_EVENTS[ptr++] = idx
}
//process events from left->right
var n = ptr >>> 1
isort(SWEEP_EVENTS, n)
var redActive = 0
var blueActive = 0
for(var i=0; i<n; ++i) {
var e = SWEEP_EVENTS[2*i+1]|0
if(e >= BLUE_FLAG) {
//blue destroy event
e = (e-BLUE_FLAG)|0
sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, e)
} else if(e >= 0) {
//red destroy event
sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e)
} else if(e <= -BLUE_FLAG) {
//blue create event
e = (-e-BLUE_FLAG)|0
for(var j=0; j<redActive; ++j) {
var retval = visit(RED_SWEEP_QUEUE[j], e)
if(retval !== void 0) {
return retval
}
}
sqPush(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive++, e)
} else {
//red create event
e = (-e-1)|0
for(var j=0; j<blueActive; ++j) {
var retval = visit(e, BLUE_SWEEP_QUEUE[j])
if(retval !== void 0) {
return retval
}
}
sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, e)
}
}
}
//Complete sweep
function sweepComplete(d, visit,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex) {
var ptr = 0
var elemSize = 2*d
var istart = d-1
var iend = elemSize-1
for(var i=redStart; i<redEnd; ++i) {
var idx = (redIndex[i]+1)<<1
var redOffset = elemSize*i
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
SWEEP_EVENTS[ptr++] = -idx
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
SWEEP_EVENTS[ptr++] = idx
}
for(var i=blueStart; i<blueEnd; ++i) {
var idx = (blueIndex[i]+1)<<1
var blueOffset = elemSize*i
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
SWEEP_EVENTS[ptr++] = (-idx)|1
SWEEP_EVENTS[ptr++] = blue[blueOffset+iend]
SWEEP_EVENTS[ptr++] = idx|1
}
//process events from left->right
var n = ptr >>> 1
isort(SWEEP_EVENTS, n)
var redActive = 0
var blueActive = 0
var commonActive = 0
for(var i=0; i<n; ++i) {
var e = SWEEP_EVENTS[2*i+1]|0
var color = e&1
if(i < n-1 && (e>>1) === (SWEEP_EVENTS[2*i+3]>>1)) {
color = 2
i += 1
}
if(e < 0) {
//Create event
var id = -(e>>1) - 1
//Intersect with common
for(var j=0; j<commonActive; ++j) {
var retval = visit(COMMON_SWEEP_QUEUE[j], id)
if(retval !== void 0) {
return retval
}
}
if(color !== 0) {
//Intersect with red
for(var j=0; j<redActive; ++j) {
var retval = visit(RED_SWEEP_QUEUE[j], id)
if(retval !== void 0) {
return retval
}
}
}
if(color !== 1) {
//Intersect with blue
for(var j=0; j<blueActive; ++j) {
var retval = visit(BLUE_SWEEP_QUEUE[j], id)
if(retval !== void 0) {
return retval
}
}
}
if(color === 0) {
//Red
sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, id)
} else if(color === 1) {
//Blue
sqPush(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive++, id)
} else if(color === 2) {
//Both
sqPush(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive++, id)
}
} else {
//Destroy event
var id = (e>>1) - 1
if(color === 0) {
//Red
sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, id)
} else if(color === 1) {
//Blue
sqPop(BLUE_SWEEP_QUEUE, BLUE_SWEEP_INDEX, blueActive--, id)
} else if(color === 2) {
//Both
sqPop(COMMON_SWEEP_QUEUE, COMMON_SWEEP_INDEX, commonActive--, id)
}
}
}
}
//Sweep and prune/scanline algorithm:
// Scan along axis, detect intersections
// Brute force all boxes along axis
function scanBipartite(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex) {
var ptr = 0
var elemSize = 2*d
var istart = axis
var iend = axis+d
var redShift = 1
var blueShift = 1
if(flip) {
blueShift = BLUE_FLAG
} else {
redShift = BLUE_FLAG
}
for(var i=redStart; i<redEnd; ++i) {
var idx = i + redShift
var redOffset = elemSize*i
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
SWEEP_EVENTS[ptr++] = -idx
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
SWEEP_EVENTS[ptr++] = idx
}
for(var i=blueStart; i<blueEnd; ++i) {
var idx = i + blueShift
var blueOffset = elemSize*i
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
SWEEP_EVENTS[ptr++] = -idx
}
//process events from left->right
var n = ptr >>> 1
isort(SWEEP_EVENTS, n)
var redActive = 0
for(var i=0; i<n; ++i) {
var e = SWEEP_EVENTS[2*i+1]|0
if(e < 0) {
var idx = -e
var isRed = false
if(idx >= BLUE_FLAG) {
isRed = !flip
idx -= BLUE_FLAG
} else {
isRed = !!flip
idx -= 1
}
if(isRed) {
sqPush(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive++, idx)
} else {
var blueId = blueIndex[idx]
var bluePtr = elemSize * idx
var b0 = blue[bluePtr+axis+1]
var b1 = blue[bluePtr+axis+1+d]
red_loop:
for(var j=0; j<redActive; ++j) {
var oidx = RED_SWEEP_QUEUE[j]
var redPtr = elemSize * oidx
if(b1 < red[redPtr+axis+1] ||
red[redPtr+axis+1+d] < b0) {
continue
}
for(var k=axis+2; k<d; ++k) {
if(blue[bluePtr + k + d] < red[redPtr + k] ||
red[redPtr + k + d] < blue[bluePtr + k]) {
continue red_loop
}
}
var redId = redIndex[oidx]
var retval
if(flip) {
retval = visit(blueId, redId)
} else {
retval = visit(redId, blueId)
}
if(retval !== void 0) {
return retval
}
}
}
} else {
sqPop(RED_SWEEP_QUEUE, RED_SWEEP_INDEX, redActive--, e - redShift)
}
}
}
function scanComplete(
d, axis, visit,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex) {
var ptr = 0
var elemSize = 2*d
var istart = axis
var iend = axis+d
for(var i=redStart; i<redEnd; ++i) {
var idx = i + BLUE_FLAG
var redOffset = elemSize*i
SWEEP_EVENTS[ptr++] = red[redOffset+istart]
SWEEP_EVENTS[ptr++] = -idx
SWEEP_EVENTS[ptr++] = red[redOffset+iend]
SWEEP_EVENTS[ptr++] = idx
}
for(var i=blueStart; i<blueEnd; ++i) {
var idx = i + 1
var blueOffset = elemSize*i
SWEEP_EVENTS[ptr++] = blue[blueOffset+istart]
SWEEP_EVENTS[ptr++] = -idx
}
//process events from left->right
var n = ptr >>> 1
isort(SWEEP_EVENTS, n)
var redActive = 0
for(var i=0; i<n; ++i) {
var e = SWEEP_EVENTS[2*i+1]|0
if(e < 0) {
var idx = -e
if(idx >= BLUE_FLAG) {
RED_SWEEP_QUEUE[redActive++] = idx - BLUE_FLAG
} else {
idx -= 1
var blueId = blueIndex[idx]
var bluePtr = elemSize * idx
var b0 = blue[bluePtr+axis+1]
var b1 = blue[bluePtr+axis+1+d]
red_loop:
for(var j=0; j<redActive; ++j) {
var oidx = RED_SWEEP_QUEUE[j]
var redId = redIndex[oidx]
if(redId === blueId) {
break
}
var redPtr = elemSize * oidx
if(b1 < red[redPtr+axis+1] ||
red[redPtr+axis+1+d] < b0) {
continue
}
for(var k=axis+2; k<d; ++k) {
if(blue[bluePtr + k + d] < red[redPtr + k] ||
red[redPtr + k + d] < blue[bluePtr + k]) {
continue red_loop
}
}
var retval = visit(redId, blueId)
if(retval !== void 0) {
return retval
}
}
}
} else {
var idx = e - BLUE_FLAG
for(var j=redActive-1; j>=0; --j) {
if(RED_SWEEP_QUEUE[j] === idx) {
for(var k=j+1; k<redActive; ++k) {
RED_SWEEP_QUEUE[k-1] = RED_SWEEP_QUEUE[k]
}
break
}
}
--redActive
}
}
}
})()
},{"./sort":37,"bit-twiddle":40,"typedarray-pool":36}],35:[function(require,module,exports){
'use strict'
module.exports = boxIntersectIter
var pool = require('typedarray-pool')
var bits = require('bit-twiddle')
var bruteForce = require('./brute')
var bruteForcePartial = bruteForce.partial
var bruteForceFull = bruteForce.full
var sweep = require('./sweep')
var findMedian = require('./median')
var genPartition = require('./partition')
//Twiddle parameters
var BRUTE_FORCE_CUTOFF = 128 //Cut off for brute force search
var SCAN_CUTOFF = (1<<22) //Cut off for two way scan
var SCAN_COMPLETE_CUTOFF = (1<<22)
//Partition functions
var partitionInteriorContainsInterval = genPartition(
'!(lo>=p0)&&!(p1>=hi)',
['p0', 'p1'])
var partitionStartEqual = genPartition(
'lo===p0',
['p0'])
var partitionStartLessThan = genPartition(
'lo<p0',
['p0'])
var partitionEndLessThanEqual = genPartition(
'hi<=p0',
['p0'])
var partitionContainsPoint = genPartition(
'lo<=p0&&p0<=hi',
['p0'])
var partitionContainsPointProper = genPartition(
'lo<p0&&p0<=hi',
['p0'])
//Frame size for iterative loop
var IFRAME_SIZE = 6
var DFRAME_SIZE = 2
//Data for box statck
var INIT_CAPACITY = 1024
var BOX_ISTACK = pool.mallocInt32(INIT_CAPACITY)
var BOX_DSTACK = pool.mallocDouble(INIT_CAPACITY)
//Initialize iterative loop queue
function iterInit(d, count) {
var levels = (8 * bits.log2(count+1) * (d+1))|0
var maxInts = bits.nextPow2(IFRAME_SIZE*levels)
if(BOX_ISTACK.length < maxInts) {
pool.free(BOX_ISTACK)
BOX_ISTACK = pool.mallocInt32(maxInts)
}
var maxDoubles = bits.nextPow2(DFRAME_SIZE*levels)
if(BOX_DSTACK < maxDoubles) {
pool.free(BOX_DSTACK)
BOX_DSTACK = pool.mallocDouble(maxDoubles)
}
}
//Append item to queue
function iterPush(ptr,
axis,
redStart, redEnd,
blueStart, blueEnd,
state,
lo, hi) {
var iptr = IFRAME_SIZE * ptr
BOX_ISTACK[iptr] = axis
BOX_ISTACK[iptr+1] = redStart
BOX_ISTACK[iptr+2] = redEnd
BOX_ISTACK[iptr+3] = blueStart
BOX_ISTACK[iptr+4] = blueEnd
BOX_ISTACK[iptr+5] = state
var dptr = DFRAME_SIZE * ptr
BOX_DSTACK[dptr] = lo
BOX_DSTACK[dptr+1] = hi
}
//Special case: Intersect single point with list of intervals
function onePointPartial(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueOffset, blue, blueId) {
var elemSize = 2 * d
var bluePtr = blueOffset * elemSize
var blueX = blue[bluePtr + axis]
red_loop:
for(var i=redStart, redPtr=redStart*elemSize; i<redEnd; ++i, redPtr+=elemSize) {
var r0 = red[redPtr+axis]
var r1 = red[redPtr+axis+d]
if(blueX < r0 || r1 < blueX) {
continue
}
if(flip && blueX === r0) {
continue
}
var redId = redIndex[i]
for(var j=axis+1; j<d; ++j) {
var r0 = red[redPtr+j]
var r1 = red[redPtr+j+d]
var b0 = blue[bluePtr+j]
var b1 = blue[bluePtr+j+d]
if(r1 < b0 || b1 < r0) {
continue red_loop
}
}
var retval
if(flip) {
retval = visit(blueId, redId)
} else {
retval = visit(redId, blueId)
}
if(retval !== void 0) {
return retval
}
}
}
//Special case: Intersect one point with list of intervals
function onePointFull(
d, axis, visit,
redStart, redEnd, red, redIndex,
blueOffset, blue, blueId) {
var elemSize = 2 * d
var bluePtr = blueOffset * elemSize
var blueX = blue[bluePtr + axis]
red_loop:
for(var i=redStart, redPtr=redStart*elemSize; i<redEnd; ++i, redPtr+=elemSize) {
var redId = redIndex[i]
if(redId === blueId) {
continue
}
var r0 = red[redPtr+axis]
var r1 = red[redPtr+axis+d]
if(blueX < r0 || r1 < blueX) {
continue
}
for(var j=axis+1; j<d; ++j) {
var r0 = red[redPtr+j]
var r1 = red[redPtr+j+d]
var b0 = blue[bluePtr+j]
var b1 = blue[bluePtr+j+d]
if(r1 < b0 || b1 < r0) {
continue red_loop
}
}
var retval = visit(redId, blueId)
if(retval !== void 0) {
return retval
}
}
}
//The main box intersection routine
function boxIntersectIter(
d, visit, initFull,
xSize, xBoxes, xIndex,
ySize, yBoxes, yIndex) {
//Reserve memory for stack
iterInit(d, xSize + ySize)
var top = 0
var elemSize = 2 * d
var retval
iterPush(top++,
0,
0, xSize,
0, ySize,
initFull ? 16 : 0,
-Infinity, Infinity)
if(!initFull) {
iterPush(top++,
0,
0, ySize,
0, xSize,
1,
-Infinity, Infinity)
}
while(top > 0) {
top -= 1
var iptr = top * IFRAME_SIZE
var axis = BOX_ISTACK[iptr]
var redStart = BOX_ISTACK[iptr+1]
var redEnd = BOX_ISTACK[iptr+2]
var blueStart = BOX_ISTACK[iptr+3]
var blueEnd = BOX_ISTACK[iptr+4]
var state = BOX_ISTACK[iptr+5]
var dptr = top * DFRAME_SIZE
var lo = BOX_DSTACK[dptr]
var hi = BOX_DSTACK[dptr+1]
//Unpack state info
var flip = (state & 1)
var full = !!(state & 16)
//Unpack indices
var red = xBoxes
var redIndex = xIndex
var blue = yBoxes
var blueIndex = yIndex
if(flip) {
red = yBoxes
redIndex = yIndex
blue = xBoxes
blueIndex = xIndex
}
if(state & 2) {
redEnd = partitionStartLessThan(
d, axis,
redStart, redEnd, red, redIndex,
hi)
if(redStart >= redEnd) {
continue
}
}
if(state & 4) {
redStart = partitionEndLessThanEqual(
d, axis,
redStart, redEnd, red, redIndex,
lo)
if(redStart >= redEnd) {
continue
}
}
var redCount = redEnd - redStart
var blueCount = blueEnd - blueStart
if(full) {
if(d * redCount * (redCount + blueCount) < SCAN_COMPLETE_CUTOFF) {
retval = sweep.scanComplete(
d, axis, visit,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
continue
}
} else {
if(d * Math.min(redCount, blueCount) < BRUTE_FORCE_CUTOFF) {
//If input small, then use brute force
retval = bruteForcePartial(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
continue
} else if(d * redCount * blueCount < SCAN_CUTOFF) {
//If input medium sized, then use sweep and prune
retval = sweep.scanBipartite(
d, axis, visit, flip,
redStart, redEnd, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
continue
}
}
//First, find all red intervals whose interior contains (lo,hi)
var red0 = partitionInteriorContainsInterval(
d, axis,
redStart, redEnd, red, redIndex,
lo, hi)
//Lower dimensional case
if(redStart < red0) {
if(d * (red0 - redStart) < BRUTE_FORCE_CUTOFF) {
//Special case for small inputs: use brute force
retval = bruteForceFull(
d, axis+1, visit,
redStart, red0, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
if(retval !== void 0) {
return retval
}
} else if(axis === d-2) {
if(flip) {
retval = sweep.sweepBipartite(
d, visit,
blueStart, blueEnd, blue, blueIndex,
redStart, red0, red, redIndex)
} else {
retval = sweep.sweepBipartite(
d, visit,
redStart, red0, red, redIndex,
blueStart, blueEnd, blue, blueIndex)
}
if(retval !== void 0) {
return retval
}
} else {
iterPush(top++,
axis+1,
redStart, red0,
blueStart, blueEnd,
flip,
-Infinity, Infinity)
iterPush(top++,
axis+1,
blueStart, blueEnd,
redStart, red0,
flip^1,
-Infinity, Infinity)
}
}
//Divide and conquer phase
if(red0 < redEnd) {
//Cut blue into 3 parts:
//
// Points < mid point
// Points = mid point
// Points > mid point
//
var blue0 = findMedian(
d, axis,
blueStart, blueEnd, blue, blueIndex)
var mid = blue[elemSize * blue0 + axis]
var blue1 = partitionStartEqual(
d, axis,
blue0, blueEnd, blue, blueIndex,
mid)
//Right case
if(blue1 < blueEnd) {
iterPush(top++,
axis,
red0, redEnd,
blue1, blueEnd,
(flip|4) + (full ? 16 : 0),
mid, hi)
}
//Left case
if(blueStart < blue0) {
iterPush(top++,
axis,
red0, redEnd,
blueStart, blue0,
(flip|2) + (full ? 16 : 0),
lo, mid)
}
//Center case (the hard part)
if(blue0 + 1 === blue1) {
//Optimization: Range with exactly 1 point, use a brute force scan
if(full) {
retval = onePointFull(
d, axis, visit,
red0, redEnd, red, redIndex,
blue0, blue, blueIndex[blue0])
} else {
retval = onePointPartial(
d, axis, visit, flip,
red0, redEnd, red, redIndex,
blue0, blue, blueIndex[blue0])
}
if(retval !== void 0) {
return retval
}
} else if(blue0 < blue1) {
var red1
if(full) {
//If full intersection, need to handle special case
red1 = partitionContainsPoint(
d, axis,
red0, redEnd, red, redIndex,
mid)
if(red0 < red1) {
var redX = partitionStartEqual(
d, axis,
red0, red1, red, redIndex,
mid)
if(axis === d-2) {
//Degenerate sweep intersection:
// [red0, redX] with [blue0, blue1]
if(red0 < redX) {
retval = sweep.sweepComplete(
d, visit,
red0, redX, red, redIndex,
blue0, blue1, blue, blueIndex)
if(retval !== void 0) {
return retval
}
}
//Normal sweep intersection:
// [redX, red1] with [blue0, blue1]
if(redX < red1) {
retval = sweep.sweepBipartite(
d, visit,
redX, red1, red, redIndex,
blue0, blue1, blue, blueIndex)
if(retval !== void 0) {
return retval
}
}
} else {
if(red0 < redX) {
iterPush(top++,
axis+1,
red0, redX,
blue0, blue1,
16,
-Infinity, Infinity)
}
if(redX < red1) {
iterPush(top++,
axis+1,
redX, red1,
blue0, blue1,
0,
-Infinity, Infinity)
iterPush(top++,
axis+1,
blue0, blue1,
redX, red1,
1,
-Infinity, Infinity)
}
}
}
} else {
if(flip) {
red1 = partitionContainsPointProper(
d, axis,
red0, redEnd, red, redIndex,
mid)
} else {
red1 = partitionContainsPoint(
d, axis,
red0, redEnd, red, redIndex,
mid)
}
if(red0 < red1) {
if(axis === d-2) {
if(flip) {
retval = sweep.sweepBipartite(
d, visit,
blue0, blue1, blue, blueIndex,
red0, red1, red, redIndex)
} else {
retval = sweep.sweepBipartite(
d, visit,
red0, red1, red, redIndex,
blue0, blue1, blue, blueIndex)
}
} else {
iterPush(top++,
axis+1,
red0, red1,
blue0, blue1,
flip,
-Infinity, Infinity)
iterPush(top++,
axis+1,
blue0, blue1,
red0, red1,
flip^1,
-Infinity, Infinity)
}
}
}
}
}
}
}
},{"./brute":38,"./median":41,"./partition":39,"./sweep":34,"bit-twiddle":40,"typedarray-pool":36}],41:[function(require,module,exports){
'use strict'
module.exports = findMedian
var genPartition = require('./partition')
var partitionStartLessThan = genPartition('lo<p0', ['p0'])
var PARTITION_THRESHOLD = 8 //Cut off for using insertion sort in findMedian
//Base case for median finding: Use insertion sort
function insertionSort(d, axis, start, end, boxes, ids) {
var elemSize = 2 * d
var boxPtr = elemSize * (start+1) + axis
for(var i=start+1; i<end; ++i, boxPtr+=elemSize) {
var x = boxes[boxPtr]
for(var j=i, ptr=elemSize*(i-1);
j>start && boxes[ptr+axis] > x;
--j, ptr-=elemSize) {
//Swap
var aPtr = ptr
var bPtr = ptr+elemSize
for(var k=0; k<elemSize; ++k, ++aPtr, ++bPtr) {
var y = boxes[aPtr]
boxes[aPtr] = boxes[bPtr]
boxes[bPtr] = y
}
var tmp = ids[j]
ids[j] = ids[j-1]
ids[j-1] = tmp
}
}
}
//Find median using quick select algorithm
// takes O(n) time with high probability
function findMedian(d, axis, start, end, boxes, ids) {
if(end <= start+1) {
return start
}
var lo = start
var hi = end
var mid = ((end + start) >>> 1)
var elemSize = 2*d
var pivot = mid
var value = boxes[elemSize*mid+axis]
while(lo < hi) {
if(hi - lo < PARTITION_THRESHOLD) {
insertionSort(d, axis, lo, hi, boxes, ids)
value = boxes[elemSize*mid+axis]
break
}
//Select pivot using median-of-3
var count = hi - lo
var pivot0 = (Math.random()*count+lo)|0
var value0 = boxes[elemSize*pivot0 + axis]
var pivot1 = (Math.random()*count+lo)|0
var value1 = boxes[elemSize*pivot1 + axis]
var pivot2 = (Math.random()*count+lo)|0
var value2 = boxes[elemSize*pivot2 + axis]
if(value0 <= value1) {
if(value2 >= value1) {
pivot = pivot1
value = value1
} else if(value0 >= value2) {
pivot = pivot0
value = value0
} else {
pivot = pivot2
value = value2
}
} else {
if(value1 >= value2) {
pivot = pivot1
value = value1
} else if(value2 >= value0) {
pivot = pivot0
value = value0
} else {
pivot = pivot2
value = value2
}
}
//Swap pivot to end of array
var aPtr = elemSize * (hi-1)
var bPtr = elemSize * pivot
for(var i=0; i<elemSize; ++i, ++aPtr, ++bPtr) {
var x = boxes[aPtr]
boxes[aPtr] = boxes[bPtr]
boxes[bPtr] = x
}
var y = ids[hi-1]
ids[hi-1] = ids[pivot]
ids[pivot] = y
//Partition using pivot
pivot = partitionStartLessThan(
d, axis,
lo, hi-1, boxes, ids,
value)
//Swap pivot back
var aPtr = elemSize * (hi-1)
var bPtr = elemSize * pivot
for(var i=0; i<elemSize; ++i, ++aPtr, ++bPtr) {
var x = boxes[aPtr]
boxes[aPtr] = boxes[bPtr]
boxes[bPtr] = x
}
var y = ids[hi-1]
ids[hi-1] = ids[pivot]
ids[pivot] = y
//Swap pivot to last pivot
if(mid < pivot) {
hi = pivot-1
while(lo < hi &&
boxes[elemSize*(hi-1)+axis] === value) {
hi -= 1
}
hi += 1
} else if(pivot < mid) {
lo = pivot + 1
while(lo < hi &&
boxes[elemSize*lo+axis] === value) {
lo += 1
}
} else {
break
}
}
//Make sure pivot is at start
return partitionStartLessThan(
d, axis,
start, mid, boxes, ids,
boxes[elemSize*mid+axis])
}
},{"./partition":39}],42:[function(require,module,exports){
"use strict"
function dupe_array(count, value, i) {
var c = count[i]|0
if(c <= 0) {
return []
}
var result = new Array(c), j
if(i === count.length-1) {
for(j=0; j<c; ++j) {
result[j] = value
}
} else {
for(j=0; j<c; ++j) {
result[j] = dupe_array(count, value, i+1)
}
}
return result
}
function dupe_number(count, value) {
var result, i
result = new Array(count)
for(i=0; i<count; ++i) {
result[i] = value
}
return result
}
function dupe(count, value) {
if(typeof value === "undefined") {
value = 0
}
switch(typeof count) {
case "number":
if(count > 0) {
return dupe_number(count|0, value)
}
break
case "object":
if(typeof (count.length) === "number") {
return dupe_array(count, value, 0)
}
break
}
return []
}
module.exports = dupe
},{}],40:[function(require,module,exports){
/**
* Bit twiddling hacks for JavaScript.
*
* Author: Mikola Lysenko
*
* Ported from Stanford bit twiddling hack library:
* http://graphics.stanford.edu/~seander/bithacks.html
*/
"use strict"; "use restrict";
//Number of bits in an integer
var INT_BITS = 32;
//Constants
exports.INT_BITS = INT_BITS;
exports.INT_MAX = 0x7fffffff;
exports.INT_MIN = -1<<(INT_BITS-1);
//Returns -1, 0, +1 depending on sign of x
exports.sign = function(v) {
return (v > 0) - (v < 0);
}
//Computes absolute value of integer
exports.abs = function(v) {
var mask = v >> (INT_BITS-1);
return (v ^ mask) - mask;
}
//Computes minimum of integers x and y
exports.min = function(x, y) {
return y ^ ((x ^ y) & -(x < y));
}
//Computes maximum of integers x and y
exports.max = function(x, y) {
return x ^ ((x ^ y) & -(x < y));
}
//Checks if a number is a power of two
exports.isPow2 = function(v) {
return !(v & (v-1)) && (!!v);
}
//Computes log base 2 of v
exports.log2 = function(v) {
var r, shift;
r = (v > 0xFFFF) << 4; v >>>= r;
shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift;
shift = (v > 0xF ) << 2; v >>>= shift; r |= shift;
shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift;
return r | (v >> 1);
}
//Computes log base 10 of v
exports.log10 = function(v) {
return (v >= 1000000000) ? 9 : (v >= 100000000) ? 8 : (v >= 10000000) ? 7 :
(v >= 1000000) ? 6 : (v >= 100000) ? 5 : (v >= 10000) ? 4 :
(v >= 1000) ? 3 : (v >= 100) ? 2 : (v >= 10) ? 1 : 0;
}
//Counts number of bits
exports.popCount = function(v) {
v = v - ((v >>> 1) & 0x55555555);
v = (v & 0x33333333) + ((v >>> 2) & 0x33333333);
return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24;
}
//Counts number of trailing zeros
function countTrailingZeros(v) {
var c = 32;
v &= -v;
if (v) c--;
if (v & 0x0000FFFF) c -= 16;
if (v & 0x00FF00FF) c -= 8;
if (v & 0x0F0F0F0F) c -= 4;
if (v & 0x33333333) c -= 2;
if (v & 0x55555555) c -= 1;
return c;
}
exports.countTrailingZeros = countTrailingZeros;
//Rounds to next power of 2
exports.nextPow2 = function(v) {
v += v === 0;
--v;
v |= v >>> 1;
v |= v >>> 2;
v |= v >>> 4;
v |= v >>> 8;
v |= v >>> 16;
return v + 1;
}
//Rounds down to previous power of 2
exports.prevPow2 = function(v) {
v |= v >>> 1;
v |= v >>> 2;
v |= v >>> 4;
v |= v >>> 8;
v |= v >>> 16;
return v - (v>>>1);
}
//Computes parity of word
exports.parity = function(v) {
v ^= v >>> 16;
v ^= v >>> 8;
v ^= v >>> 4;
v &= 0xf;
return (0x6996 >>> v) & 1;
}
var REVERSE_TABLE = new Array(256);
(function(tab) {
for(var i=0; i<256; ++i) {
var v = i, r = i, s = 7;
for (v >>>= 1; v; v >>>= 1) {
r <<= 1;
r |= v & 1;
--s;
}
tab[i] = (r << s) & 0xff;
}
})(REVERSE_TABLE);
//Reverse bits in a 32 bit word
exports.reverse = function(v) {
return (REVERSE_TABLE[ v & 0xff] << 24) |
(REVERSE_TABLE[(v >>> 8) & 0xff] << 16) |
(REVERSE_TABLE[(v >>> 16) & 0xff] << 8) |
REVERSE_TABLE[(v >>> 24) & 0xff];
}
//Interleave bits of 2 coordinates with 16 bits. Useful for fast quadtree codes
exports.interleave2 = function(x, y) {
x &= 0xFFFF;
x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
x = (x | (x << 2)) & 0x33333333;
x = (x | (x << 1)) & 0x55555555;
y &= 0xFFFF;
y = (y | (y << 8)) & 0x00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F;
y = (y | (y << 2)) & 0x33333333;
y = (y | (y << 1)) & 0x55555555;
return x | (y << 1);
}
//Extracts the nth interleaved component
exports.deinterleave2 = function(v, n) {
v = (v >>> n) & 0x55555555;
v = (v | (v >>> 1)) & 0x33333333;
v = (v | (v >>> 2)) & 0x0F0F0F0F;
v = (v | (v >>> 4)) & 0x00FF00FF;
v = (v | (v >>> 16)) & 0x000FFFF;
return (v << 16) >> 16;
}
//Interleave bits of 3 coordinates, each with 10 bits. Useful for fast octree codes
exports.interleave3 = function(x, y, z) {
x &= 0x3FF;
x = (x | (x<<16)) & 4278190335;
x = (x | (x<<8)) & 251719695;
x = (x | (x<<4)) & 3272356035;
x = (x | (x<<2)) & 1227133513;
y &= 0x3FF;
y = (y | (y<<16)) & 4278190335;
y = (y | (y<<8)) & 251719695;
y = (y | (y<<4)) & 3272356035;
y = (y | (y<<2)) & 1227133513;
x |= (y << 1);
z &= 0x3FF;
z = (z | (z<<16)) & 4278190335;
z = (z | (z<<8)) & 251719695;
z = (z | (z<<4)) & 3272356035;
z = (z | (z<<2)) & 1227133513;
return x | (z << 2);
}
//Extracts nth interleaved component of a 3-tuple
exports.deinterleave3 = function(v, n) {
v = (v >>> n) & 1227133513;
v = (v | (v>>>2)) & 3272356035;
v = (v | (v>>>4)) & 251719695;
v = (v | (v>>>8)) & 4278190335;
v = (v | (v>>>16)) & 0x3FF;
return (v<<22)>>22;
}
//Computes next combination in colexicographic order (this is mistakenly called nextPermutation on the bit twiddling hacks page)
exports.nextCombination = function(v) {
var t = v | (v - 1);
return (t + 1) | (((~t & -~t) - 1) >>> (countTrailingZeros(v) + 1));
}
},{}],43:[function(require,module,exports){
require=(function(e,t,n,r){function i(r){if(!n[r]){if(!t[r]){if(e)return e(r);throw new Error("Cannot find module '"+r+"'")}var s=n[r]={exports:{}};t[r][0](function(e){var n=t[r][1][e];return i(n?n:e)},s,s.exports)}return n[r].exports}for(var s=0;s<r.length;s++)i(r[s]);return i})(typeof require!=="undefined"&&require,{1:[function(require,module,exports){
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isBE ? 0 : (nBytes - 1),
d = isBE ? 1 : -1,
s = buffer[offset + i];
i += d;
e = s & ((1 << (-nBits)) - 1);
s >>= (-nBits);
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
m = e & ((1 << (-nBits)) - 1);
e >>= (-nBits);
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity);
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isBE ? (nBytes - 1) : 0,
d = isBE ? -1 : 1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
buffer[offset + i - d] |= s * 128;
};
},{}],2:[function(require,module,exports){
(function(){// UTILITY
var util = require('util');
var Buffer = require("buffer").Buffer;
var pSlice = Array.prototype.slice;
function objectKeys(object) {
if (Object.keys) return Object.keys(object);
var result = [];
for (var name in object) {
if (Object.prototype.hasOwnProperty.call(object, name)) {
result.push(name);
}
}
return result;
}
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.message = options.message;
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
}
};
util.inherits(assert.AssertionError, Error);
function replacer(key, value) {
if (value === undefined) {
return '' + value;
}
if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) {
return value.toString();
}
if (typeof value === 'function' || value instanceof RegExp) {
return value.toString();
}
return value;
}
function truncate(s, n) {
if (typeof s == 'string') {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
assert.AssertionError.prototype.toString = function() {
if (this.message) {
return [this.name + ':', this.message].join(' ');
} else {
return [
this.name + ':',
truncate(JSON.stringify(this.actual, replacer), 128),
this.operator,
truncate(JSON.stringify(this.expected, replacer), 128)
].join(' ');
}
};
// assert.AssertionError instanceof Error
assert.AssertionError.__proto__ = Error.prototype;
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!!!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
if (actual.length != expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) return false;
}
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (actual instanceof Date && expected instanceof Date) {
return actual.getTime() === expected.getTime();
// 7.3. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if (typeof actual != 'object' && typeof expected != 'object') {
return actual == expected;
// 7.4. For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isUndefinedOrNull(value) {
return value === null || value === undefined;
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b) {
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
return false;
// an identical 'prototype' property.
if (a.prototype !== b.prototype) return false;
//~~~I've managed to break Object.keys through screwy arguments passing.
// Converting to array solves the problem.
if (isArguments(a)) {
if (!isArguments(b)) {
return false;
}
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
try {
var ka = objectKeys(a),
kb = objectKeys(b),
key, i;
} catch (e) {//happens when one is a string literal and the other isn't
return false;
}
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length != kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key])) return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (expected instanceof RegExp) {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
} else if (expected.call({}, actual) === true) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (typeof expected === 'string') {
message = expected;
expected = null;
}
try {
block();
} catch (e) {
actual = e;
}
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail('Missing expected exception' + message);
}
if (!shouldThrow && expectedException(actual, expected)) {
fail('Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function(err) { if (err) {throw err;}};
})()
},{"util":3,"buffer":4}],"buffer-browserify":[function(require,module,exports){
module.exports=require('q9TxCC');
},{}],"q9TxCC":[function(require,module,exports){
(function(){function SlowBuffer (size) {
this.length = size;
};
var assert = require('assert');
exports.INSPECT_MAX_BYTES = 50;
function toHex(n) {
if (n < 16) return '0' + n.toString(16);
return n.toString(16);
}
function utf8ToBytes(str) {
var byteArray = [];
for (var i = 0; i < str.length; i++)
if (str.charCodeAt(i) <= 0x7F)
byteArray.push(str.charCodeAt(i));
else {
var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
for (var j = 0; j < h.length; j++)
byteArray.push(parseInt(h[j], 16));
}
return byteArray;
}
function asciiToBytes(str) {
var byteArray = []
for (var i = 0; i < str.length; i++ )
// Node's code seems to be doing this and not & 0x7F..
byteArray.push( str.charCodeAt(i) & 0xFF );
return byteArray;
}
function base64ToBytes(str) {
return require("base64-js").toByteArray(str);
}
SlowBuffer.byteLength = function (str, encoding) {
switch (encoding || "utf8") {
case 'hex':
return str.length / 2;
case 'utf8':
case 'utf-8':
return utf8ToBytes(str).length;
case 'ascii':
case 'binary':
return str.length;
case 'base64':
return base64ToBytes(str).length;
default:
throw new Error('Unknown encoding');
}
};
function blitBuffer(src, dst, offset, length) {
var pos, i = 0;
while (i < length) {
if ((i+offset >= dst.length) || (i >= src.length))
break;
dst[i + offset] = src[i];
i++;
}
return i;
}
SlowBuffer.prototype.utf8Write = function (string, offset, length) {
var bytes, pos;
return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
};
SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
var bytes, pos;
return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
};
SlowBuffer.prototype.binaryWrite = SlowBuffer.prototype.asciiWrite;
SlowBuffer.prototype.base64Write = function (string, offset, length) {
var bytes, pos;
return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
};
SlowBuffer.prototype.base64Slice = function (start, end) {
var bytes = Array.prototype.slice.apply(this, arguments)
return require("base64-js").fromByteArray(bytes);
}
function decodeUtf8Char(str) {
try {
return decodeURIComponent(str);
} catch (err) {
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
}
}
SlowBuffer.prototype.utf8Slice = function () {
var bytes = Array.prototype.slice.apply(this, arguments);
var res = "";
var tmp = "";
var i = 0;
while (i < bytes.length) {
if (bytes[i] <= 0x7F) {
res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
tmp = "";
} else
tmp += "%" + bytes[i].toString(16);
i++;
}
return res + decodeUtf8Char(tmp);
}
SlowBuffer.prototype.asciiSlice = function () {
var bytes = Array.prototype.slice.apply(this, arguments);
var ret = "";
for (var i = 0; i < bytes.length; i++)
ret += String.fromCharCode(bytes[i]);
return ret;
}
SlowBuffer.prototype.binarySlice = SlowBuffer.prototype.asciiSlice;
SlowBuffer.prototype.inspect = function() {
var out = [],
len = this.length;
for (var i = 0; i < len; i++) {
out[i] = toHex(this[i]);
if (i == exports.INSPECT_MAX_BYTES) {
out[i + 1] = '...';
break;
}
}
return '<SlowBuffer ' + out.join(' ') + '>';
};
SlowBuffer.prototype.hexSlice = function(start, end) {
var len = this.length;
if (!start || start < 0) start = 0;
if (!end || end < 0 || end > len) end = len;
var out = '';
for (var i = start; i < end; i++) {
out += toHex(this[i]);
}
return out;
};
SlowBuffer.prototype.toString = function(encoding, start, end) {
encoding = String(encoding || 'utf8').toLowerCase();
start = +start || 0;
if (typeof end == 'undefined') end = this.length;
// Fastpath empty strings
if (+end == start) {
return '';
}
switch (encoding) {
case 'hex':
return this.hexSlice(start, end);
case 'utf8':
case 'utf-8':
return this.utf8Slice(start, end);
case 'ascii':
return this.asciiSlice(start, end);
case 'binary':
return this.binarySlice(start, end);
case 'base64':
return this.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}
};
SlowBuffer.prototype.hexWrite = function(string, offset, length) {
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
// must be an even number of digits
var strLen = string.length;
if (strLen % 2) {
throw new Error('Invalid hex string');
}
if (length > strLen / 2) {
length = strLen / 2;
}
for (var i = 0; i < length; i++) {
var byte = parseInt(string.substr(i * 2, 2), 16);
if (isNaN(byte)) throw new Error('Invalid hex string');
this[offset + i] = byte;
}
SlowBuffer._charsWritten = i * 2;
return i;
};
SlowBuffer.prototype.write = function(string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length;
length = undefined;
}
} else { // legacy
var swap = encoding;
encoding = offset;
offset = length;
length = swap;
}
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
encoding = String(encoding || 'utf8').toLowerCase();
switch (encoding) {
case 'hex':
return this.hexWrite(string, offset, length);
case 'utf8':
case 'utf-8':
return this.utf8Write(string, offset, length);
case 'ascii':
return this.asciiWrite(string, offset, length);
case 'binary':
return this.binaryWrite(string, offset, length);
case 'base64':
return this.base64Write(string, offset, length);
case 'ucs2':
case 'ucs-2':
return this.ucs2Write(string, offset, length);
default:
throw new Error('Unknown encoding');
}
};
// slice(start, end)
SlowBuffer.prototype.slice = function(start, end) {
if (end === undefined) end = this.length;
if (end > this.length) {
throw new Error('oob');
}
if (start > end) {
throw new Error('oob');
}
return new Buffer(this, end - start, +start);
};
SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
var temp = [];
for (var i=sourcestart; i<sourceend; i++) {
assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
temp.push(this[i]);
}
for (var i=targetstart; i<targetstart+temp.length; i++) {
target[i] = temp[i-targetstart];
}
};
SlowBuffer.prototype.fill = function(value, start, end) {
if (end > this.length) {
throw new Error('oob');
}
if (start > end) {
throw new Error('oob');
}
for (var i = start; i < end; i++) {
this[i] = value;
}
}
function coerce(length) {
// Coerce length to a number (possibly NaN), round up
// in case it's fractional (e.g. 123.456) then do a
// double negate to coerce a NaN to 0. Easy, right?
length = ~~Math.ceil(+length);
return length < 0 ? 0 : length;
}
// Buffer
function Buffer(subject, encoding, offset) {
if (!(this instanceof Buffer)) {
return new Buffer(subject, encoding, offset);
}
var type;
// Are we slicing?
if (typeof offset === 'number') {
this.length = coerce(encoding);
this.parent = subject;
this.offset = offset;
} else {
// Find the length
switch (type = typeof subject) {
case 'number':
this.length = coerce(subject);
break;
case 'string':
this.length = Buffer.byteLength(subject, encoding);
break;
case 'object': // Assume object is an array
this.length = coerce(subject.length);
break;
default:
throw new Error('First argument needs to be a number, ' +
'array or string.');
}
if (this.length > Buffer.poolSize) {
// Big buffer, just alloc one.
this.parent = new SlowBuffer(this.length);
this.offset = 0;
} else {
// Small buffer.
if (!pool || pool.length - pool.used < this.length) allocPool();
this.parent = pool;
this.offset = pool.used;
pool.used += this.length;
}
// Treat array-ish objects as a byte array.
if (isArrayIsh(subject)) {
for (var i = 0; i < this.length; i++) {
if (subject instanceof Buffer) {
this.parent[i + this.offset] = subject.readUInt8(i);
}
else {
this.parent[i + this.offset] = subject[i];
}
}
} else if (type == 'string') {
// We are a string
this.length = this.write(subject, 0, encoding);
}
}
}
function isArrayIsh(subject) {
return Array.isArray(subject) || Buffer.isBuffer(subject) ||
subject && typeof subject === 'object' &&
typeof subject.length === 'number';
}
exports.SlowBuffer = SlowBuffer;
exports.Buffer = Buffer;
Buffer.poolSize = 8 * 1024;
var pool;
function allocPool() {
pool = new SlowBuffer(Buffer.poolSize);
pool.used = 0;
}
// Static methods
Buffer.isBuffer = function isBuffer(b) {
return b instanceof Buffer || b instanceof SlowBuffer;
};
Buffer.concat = function (list, totalLength) {
if (!Array.isArray(list)) {
throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
list should be an Array.");
}
if (list.length === 0) {
return new Buffer(0);
} else if (list.length === 1) {
return list[0];
}
if (typeof totalLength !== 'number') {
totalLength = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
totalLength += buf.length;
}
}
var buffer = new Buffer(totalLength);
var pos = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
buf.copy(buffer, pos);
pos += buf.length;
}
return buffer;
};
// Inspect
Buffer.prototype.inspect = function inspect() {
var out = [],
len = this.length;
for (var i = 0; i < len; i++) {
out[i] = toHex(this.parent[i + this.offset]);
if (i == exports.INSPECT_MAX_BYTES) {
out[i + 1] = '...';
break;
}
}
return '<Buffer ' + out.join(' ') + '>';
};
Buffer.prototype.get = function get(i) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this.parent[this.offset + i];
};
Buffer.prototype.set = function set(i, v) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this.parent[this.offset + i] = v;
};
// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
Buffer.prototype.write = function(string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length;
length = undefined;
}
} else { // legacy
var swap = encoding;
encoding = offset;
offset = length;
length = swap;
}
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
encoding = String(encoding || 'utf8').toLowerCase();
var ret;
switch (encoding) {
case 'hex':
ret = this.parent.hexWrite(string, this.offset + offset, length);
break;
case 'utf8':
case 'utf-8':
ret = this.parent.utf8Write(string, this.offset + offset, length);
break;
case 'ascii':
ret = this.parent.asciiWrite(string, this.offset + offset, length);
break;
case 'binary':
ret = this.parent.binaryWrite(string, this.offset + offset, length);
break;
case 'base64':
// Warning: maxLength not taken into account in base64Write
ret = this.parent.base64Write(string, this.offset + offset, length);
break;
case 'ucs2':
case 'ucs-2':
ret = this.parent.ucs2Write(string, this.offset + offset, length);
break;
default:
throw new Error('Unknown encoding');
}
Buffer._charsWritten = SlowBuffer._charsWritten;
return ret;
};
// toString(encoding, start=0, end=buffer.length)
Buffer.prototype.toString = function(encoding, start, end) {
encoding = String(encoding || 'utf8').toLowerCase();
if (typeof start == 'undefined' || start < 0) {
start = 0;
} else if (start > this.length) {
start = this.length;
}
if (typeof end == 'undefined' || end > this.length) {
end = this.length;
} else if (end < 0) {
end = 0;
}
start = start + this.offset;
end = end + this.offset;
switch (encoding) {
case 'hex':
return this.parent.hexSlice(start, end);
case 'utf8':
case 'utf-8':
return this.parent.utf8Slice(start, end);
case 'ascii':
return this.parent.asciiSlice(start, end);
case 'binary':
return this.parent.binarySlice(start, end);
case 'base64':
return this.parent.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.parent.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}
};
// byteLength
Buffer.byteLength = SlowBuffer.byteLength;
// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function fill(value, start, end) {
value || (value = 0);
start || (start = 0);
end || (end = this.length);
if (typeof value === 'string') {
value = value.charCodeAt(0);
}
if (!(typeof value === 'number') || isNaN(value)) {
throw new Error('value is not a number');
}
if (end < start) throw new Error('end < start');
// Fill 0 bytes; we're done
if (end === start) return 0;
if (this.length == 0) return 0;
if (start < 0 || start >= this.length) {
throw new Error('start out of bounds');
}
if (end < 0 || end > this.length) {
throw new Error('end out of bounds');
}
return this.parent.fill(value,
start + this.offset,
end + this.offset);
};
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function(target, target_start, start, end) {
var source = this;
start || (start = 0);
end || (end = this.length);
target_start || (target_start = 0);
if (end < start) throw new Error('sourceEnd < sourceStart');
// Copy 0 bytes; we're done
if (end === start) return 0;
if (target.length == 0 || source.length == 0) return 0;
if (target_start < 0 || target_start >= target.length) {
throw new Error('targetStart out of bounds');
}
if (start < 0 || start >= source.length) {
throw new Error('sourceStart out of bounds');
}
if (end < 0 || end > source.length) {
throw new Error('sourceEnd out of bounds');
}
// Are we oob?
if (end > this.length) {
end = this.length;
}
if (target.length - target_start < end - start) {
end = target.length - target_start + start;
}
return this.parent.copy(target.parent,
target_start + target.offset,
start + this.offset,
end + this.offset);
};
// slice(start, end)
Buffer.prototype.slice = function(start, end) {
if (end === undefined) end = this.length;
if (end > this.length) throw new Error('oob');
if (start > end) throw new Error('oob');
return new Buffer(this.parent, end - start, +start + this.offset);
};
// Legacy methods for backwards compatibility.
Buffer.prototype.utf8Slice = function(start, end) {
return this.toString('utf8', start, end);
};
Buffer.prototype.binarySlice = function(start, end) {
return this.toString('binary', start, end);
};
Buffer.prototype.asciiSlice = function(start, end) {
return this.toString('ascii', start, end);
};
Buffer.prototype.utf8Write = function(string, offset) {
return this.write(string, offset, 'utf8');
};
Buffer.prototype.binaryWrite = function(string, offset) {
return this.write(string, offset, 'binary');
};
Buffer.prototype.asciiWrite = function(string, offset) {
return this.write(string, offset, 'ascii');
};
Buffer.prototype.readUInt8 = function(offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return;
return buffer.parent[buffer.offset + offset];
};
function readUInt16(buffer, offset, isBigEndian, noAssert) {
var val = 0;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return 0;
if (isBigEndian) {
val = buffer.parent[buffer.offset + offset] << 8;
if (offset + 1 < buffer.length) {
val |= buffer.parent[buffer.offset + offset + 1];
}
} else {
val = buffer.parent[buffer.offset + offset];
if (offset + 1 < buffer.length) {
val |= buffer.parent[buffer.offset + offset + 1] << 8;
}
}
return val;
}
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
return readUInt16(this, offset, false, noAssert);
};
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
return readUInt16(this, offset, true, noAssert);
};
function readUInt32(buffer, offset, isBigEndian, noAssert) {
var val = 0;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return 0;
if (isBigEndian) {
if (offset + 1 < buffer.length)
val = buffer.parent[buffer.offset + offset + 1] << 16;
if (offset + 2 < buffer.length)
val |= buffer.parent[buffer.offset + offset + 2] << 8;
if (offset + 3 < buffer.length)
val |= buffer.parent[buffer.offset + offset + 3];
val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
} else {
if (offset + 2 < buffer.length)
val = buffer.parent[buffer.offset + offset + 2] << 16;
if (offset + 1 < buffer.length)
val |= buffer.parent[buffer.offset + offset + 1] << 8;
val |= buffer.parent[buffer.offset + offset];
if (offset + 3 < buffer.length)
val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
}
return val;
}
Buffer.prototype.readUInt32LE = function(offset, noAssert) {
return readUInt32(this, offset, false, noAssert);
};
Buffer.prototype.readUInt32BE = function(offset, noAssert) {
return readUInt32(this, offset, true, noAssert);
};
/*
* Signed integer types, yay team! A reminder on how two's complement actually
* works. The first bit is the signed bit, i.e. tells us whether or not the
* number should be positive or negative. If the two's complement value is
* positive, then we're done, as it's equivalent to the unsigned representation.
*
* Now if the number is positive, you're pretty much done, you can just leverage
* the unsigned translations and return those. Unfortunately, negative numbers
* aren't quite that straightforward.
*
* At first glance, one might be inclined to use the traditional formula to
* translate binary numbers between the positive and negative values in two's
* complement. (Though it doesn't quite work for the most negative value)
* Mainly:
* - invert all the bits
* - add one to the result
*
* Of course, this doesn't quite work in Javascript. Take for example the value
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
* course, Javascript will do the following:
*
* > ~0xff80
* -65409
*
* Whoh there, Javascript, that's not quite right. But wait, according to
* Javascript that's perfectly correct. When Javascript ends up seeing the
* constant 0xff80, it has no notion that it is actually a signed number. It
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
* binary negation, it casts it into a signed value, (positive 0xff80). Then
* when you perform binary negation on that, it turns it into a negative number.
*
* Instead, we're going to have to use the following general formula, that works
* in a rather Javascript friendly way. I'm glad we don't support this kind of
* weird numbering scheme in the kernel.
*
* (BIT-MAX - (unsigned)val + 1) * -1
*
* The astute observer, may think that this doesn't make sense for 8-bit numbers
* (really it isn't necessary for them). However, when you get 16-bit numbers,
* you do. Let's go back to our prior example and see how this will look:
*
* (0xffff - 0xff80 + 1) * -1
* (0x007f + 1) * -1
* (0x0080) * -1
*/
Buffer.prototype.readInt8 = function(offset, noAssert) {
var buffer = this;
var neg;
if (!noAssert) {
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to read beyond buffer length');
}
if (offset >= buffer.length) return;
neg = buffer.parent[buffer.offset + offset] & 0x80;
if (!neg) {
return (buffer.parent[buffer.offset + offset]);
}
return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
};
function readInt16(buffer, offset, isBigEndian, noAssert) {
var neg, val;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to read beyond buffer length');
}
val = readUInt16(buffer, offset, isBigEndian, noAssert);
neg = val & 0x8000;
if (!neg) {
return val;
}
return (0xffff - val + 1) * -1;
}
Buffer.prototype.readInt16LE = function(offset, noAssert) {
return readInt16(this, offset, false, noAssert);
};
Buffer.prototype.readInt16BE = function(offset, noAssert) {
return readInt16(this, offset, true, noAssert);
};
function readInt32(buffer, offset, isBigEndian, noAssert) {
var neg, val;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
val = readUInt32(buffer, offset, isBigEndian, noAssert);
neg = val & 0x80000000;
if (!neg) {
return (val);
}
return (0xffffffff - val + 1) * -1;
}
Buffer.prototype.readInt32LE = function(offset, noAssert) {
return readInt32(this, offset, false, noAssert);
};
Buffer.prototype.readInt32BE = function(offset, noAssert) {
return readInt32(this, offset, true, noAssert);
};
function readFloat(buffer, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
23, 4);
}
Buffer.prototype.readFloatLE = function(offset, noAssert) {
return readFloat(this, offset, false, noAssert);
};
Buffer.prototype.readFloatBE = function(offset, noAssert) {
return readFloat(this, offset, true, noAssert);
};
function readDouble(buffer, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset + 7 < buffer.length,
'Trying to read beyond buffer length');
}
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
52, 8);
}
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
return readDouble(this, offset, false, noAssert);
};
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
return readDouble(this, offset, true, noAssert);
};
/*
* We have to make sure that the value is a valid integer. This means that it is
* non-negative. It has no fractional component and that it does not exceed the
* maximum allowed value.
*
* value The number to check for validity
*
* max The maximum value
*/
function verifuint(value, max) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value >= 0,
'specified a negative value for writing an unsigned value');
assert.ok(value <= max, 'value is larger than maximum value for type');
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xff);
}
if (offset < buffer.length) {
buffer.parent[buffer.offset + offset] = value;
}
};
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xffff);
}
for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) {
buffer.parent[buffer.offset + offset + i] =
(value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>>
(isBigEndian ? 1 - i : i) * 8;
}
}
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
writeUInt16(this, value, offset, false, noAssert);
};
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
writeUInt16(this, value, offset, true, noAssert);
};
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xffffffff);
}
for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) {
buffer.parent[buffer.offset + offset + i] =
(value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff;
}
}
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
writeUInt32(this, value, offset, false, noAssert);
};
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
writeUInt32(this, value, offset, true, noAssert);
};
/*
* We now move onto our friends in the signed number category. Unlike unsigned
* numbers, we're going to have to worry a bit more about how we put values into
* arrays. Since we are only worrying about signed 32-bit values, we're in
* slightly better shape. Unfortunately, we really can't do our favorite binary
* & in this system. It really seems to do the wrong thing. For example:
*
* > -32 & 0xff
* 224
*
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
* this aren't treated as a signed number. Ultimately a bad thing.
*
* What we're going to want to do is basically create the unsigned equivalent of
* our representation and pass that off to the wuint* functions. To do that
* we're going to do the following:
*
* - if the value is positive
* we can pass it directly off to the equivalent wuint
* - if the value is negative
* we do the following computation:
* mb + val + 1, where
* mb is the maximum unsigned value in that byte size
* val is the Javascript negative integer
*
*
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
* you do out the computations:
*
* 0xffff - 128 + 1
* 0xffff - 127
* 0xff80
*
* You can then encode this value as the signed version. This is really rather
* hacky, but it should work and get the job done which is our goal here.
*/
/*
* A series of checks to make sure we actually have a signed 32-bit number
*/
function verifsint(value, max, min) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value <= max, 'value larger than maximum allowed value');
assert.ok(value >= min, 'value smaller than minimum allowed value');
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
function verifIEEE754(value, max, min) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value <= max, 'value larger than maximum allowed value');
assert.ok(value >= min, 'value smaller than minimum allowed value');
}
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7f, -0x80);
}
if (value >= 0) {
buffer.writeUInt8(value, offset, noAssert);
} else {
buffer.writeUInt8(0xff + value + 1, offset, noAssert);
}
};
function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7fff, -0x8000);
}
if (value >= 0) {
writeUInt16(buffer, value, offset, isBigEndian, noAssert);
} else {
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
}
}
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
writeInt16(this, value, offset, false, noAssert);
};
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
writeInt16(this, value, offset, true, noAssert);
};
function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7fffffff, -0x80000000);
}
if (value >= 0) {
writeUInt32(buffer, value, offset, isBigEndian, noAssert);
} else {
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
}
}
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
writeInt32(this, value, offset, false, noAssert);
};
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
writeInt32(this, value, offset, true, noAssert);
};
function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to write beyond buffer length');
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
}
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
23, 4);
}
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
writeFloat(this, value, offset, false, noAssert);
};
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
writeFloat(this, value, offset, true, noAssert);
};
function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 7 < buffer.length,
'Trying to write beyond buffer length');
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
}
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
52, 8);
}
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
writeDouble(this, value, offset, false, noAssert);
};
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
writeDouble(this, value, offset, true, noAssert);
};
SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
})()
},{"assert":2,"./buffer_ieee754":1,"base64-js":5}],3:[function(require,module,exports){
var events = require('events');
exports.isArray = isArray;
exports.isDate = function(obj){return Object.prototype.toString.call(obj) === '[object Date]'};
exports.isRegExp = function(obj){return Object.prototype.toString.call(obj) === '[object RegExp]'};
exports.print = function () {};
exports.puts = function () {};
exports.debug = function() {};
exports.inspect = function(obj, showHidden, depth, colors) {
var seen = [];
var stylize = function(str, styleType) {
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
var styles =
{ 'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39] };
var style =
{ 'special': 'cyan',
'number': 'blue',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red' }[styleType];
if (style) {
return '\033[' + styles[style][0] + 'm' + str +
'\033[' + styles[style][1] + 'm';
} else {
return str;
}
};
if (! colors) {
stylize = function(str, styleType) { return str; };
}
function format(value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (value && typeof value.inspect === 'function' &&
// Filter out the util module, it's inspect function is special
value !== exports &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
return value.inspect(recurseTimes);
}
// Primitive types cannot have properties
switch (typeof value) {
case 'undefined':
return stylize('undefined', 'undefined');
case 'string':
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return stylize(simple, 'string');
case 'number':
return stylize('' + value, 'number');
case 'boolean':
return stylize('' + value, 'boolean');
}
// For some reason typeof null is "object", so special case here.
if (value === null) {
return stylize('null', 'null');
}
// Look up the keys of the object.
var visible_keys = Object_keys(value);
var keys = showHidden ? Object_getOwnPropertyNames(value) : visible_keys;
// Functions without properties can be shortcutted.
if (typeof value === 'function' && keys.length === 0) {
if (isRegExp(value)) {
return stylize('' + value, 'regexp');
} else {
var name = value.name ? ': ' + value.name : '';
return stylize('[Function' + name + ']', 'special');
}
}
// Dates without properties can be shortcutted
if (isDate(value) && keys.length === 0) {
return stylize(value.toUTCString(), 'date');
}
var base, type, braces;
// Determine the object type
if (isArray(value)) {
type = 'Array';
braces = ['[', ']'];
} else {
type = 'Object';
braces = ['{', '}'];
}
// Make functions say that they are functions
if (typeof value === 'function') {
var n = value.name ? ': ' + value.name : '';
base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']';
} else {
base = '';
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + value.toUTCString();
}
if (keys.length === 0) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return stylize('' + value, 'regexp');
} else {
return stylize('[Object]', 'special');
}
}
seen.push(value);
var output = keys.map(function(key) {
var name, str;
if (value.__lookupGetter__) {
if (value.__lookupGetter__(key)) {
if (value.__lookupSetter__(key)) {
str = stylize('[Getter/Setter]', 'special');
} else {
str = stylize('[Getter]', 'special');
}
} else {
if (value.__lookupSetter__(key)) {
str = stylize('[Setter]', 'special');
}
}
}
if (visible_keys.indexOf(key) < 0) {
name = '[' + key + ']';
}
if (!str) {
if (seen.indexOf(value[key]) < 0) {
if (recurseTimes === null) {
str = format(value[key]);
} else {
str = format(value[key], recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (isArray(value)) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = stylize('[Circular]', 'special');
}
}
if (typeof name === 'undefined') {
if (type === 'Array' && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = stylize(name, 'string');
}
}
return name + ': ' + str;
});
seen.pop();
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.length + 1;
}, 0);
if (length > 50) {
output = braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
} else {
output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
return output;
}
return format(obj, (typeof depth === 'undefined' ? 2 : depth));
};
function isArray(ar) {
return ar instanceof Array ||
Array.isArray(ar) ||
(ar && ar !== Object.prototype && isArray(ar.__proto__));
}
function isRegExp(re) {
return re instanceof RegExp ||
(typeof re === 'object' && Object.prototype.toString.call(re) === '[object RegExp]');
}
function isDate(d) {
if (d instanceof Date) return true;
if (typeof d !== 'object') return false;
var properties = Date.prototype && Object_getOwnPropertyNames(Date.prototype);
var proto = d.__proto__ && Object_getOwnPropertyNames(d.__proto__);
return JSON.stringify(proto) === JSON.stringify(properties);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
exports.log = function (msg) {};
exports.pump = null;
var Object_keys = Object.keys || function (obj) {
var res = [];
for (var key in obj) res.push(key);
return res;
};
var Object_getOwnPropertyNames = Object.getOwnPropertyNames || function (obj) {
var res = [];
for (var key in obj) {
if (Object.hasOwnProperty.call(obj, key)) res.push(key);
}
return res;
};
var Object_create = Object.create || function (prototype, properties) {
// from es5-shim
var object;
if (prototype === null) {
object = { '__proto__' : null };
}
else {
if (typeof prototype !== 'object') {
throw new TypeError(
'typeof prototype[' + (typeof prototype) + '] != \'object\''
);
}
var Type = function () {};
Type.prototype = prototype;
object = new Type();
object.__proto__ = prototype;
}
if (typeof properties !== 'undefined' && Object.defineProperties) {
Object.defineProperties(object, properties);
}
return object;
};
exports.inherits = function(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object_create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (typeof f !== 'string') {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(exports.inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j': return JSON.stringify(args[i++]);
default:
return x;
}
});
for(var x = args[i]; i < len; x = args[++i]){
if (x === null || typeof x !== 'object') {
str += ' ' + x;
} else {
str += ' ' + exports.inspect(x);
}
}
return str;
};
},{"events":6}],5:[function(require,module,exports){
(function (exports) {
'use strict';
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function b64ToByteArray(b64) {
var i, j, l, tmp, placeHolders, arr;
if (b64.length % 4 > 0) {
throw 'Invalid string. Length must be a multiple of 4';
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
placeHolders = b64.indexOf('=');
placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
// base64 is 4/3 + up to two characters of the original data
arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length;
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
arr.push((tmp & 0xFF0000) >> 16);
arr.push((tmp & 0xFF00) >> 8);
arr.push(tmp & 0xFF);
}
if (placeHolders === 2) {
tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
arr.push(tmp & 0xFF);
} else if (placeHolders === 1) {
tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
arr.push((tmp >> 8) & 0xFF);
arr.push(tmp & 0xFF);
}
return arr;
}
function uint8ToBase64(uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length;
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
};
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
output += tripletToBase64(temp);
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1];
output += lookup[temp >> 2];
output += lookup[(temp << 4) & 0x3F];
output += '==';
break;
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
output += lookup[temp >> 10];
output += lookup[(temp >> 4) & 0x3F];
output += lookup[(temp << 2) & 0x3F];
output += '=';
break;
}
return output;
}
module.exports.toByteArray = b64ToByteArray;
module.exports.fromByteArray = uint8ToBase64;
}());
},{}],7:[function(require,module,exports){
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isBE ? 0 : (nBytes - 1),
d = isBE ? 1 : -1,
s = buffer[offset + i];
i += d;
e = s & ((1 << (-nBits)) - 1);
s >>= (-nBits);
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
m = e & ((1 << (-nBits)) - 1);
e >>= (-nBits);
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity);
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isBE ? (nBytes - 1) : 0,
d = isBE ? -1 : 1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
buffer[offset + i - d] |= s * 128;
};
},{}],8:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
process.nextTick = (function () {
var canSetImmediate = typeof window !== 'undefined'
&& window.setImmediate;
var canPost = typeof window !== 'undefined'
&& window.postMessage && window.addEventListener
;
if (canSetImmediate) {
return function (f) { return window.setImmediate(f) };
}
if (canPost) {
var queue = [];
window.addEventListener('message', function (ev) {
if (ev.source === window && ev.data === 'process-tick') {
ev.stopPropagation();
if (queue.length > 0) {
var fn = queue.shift();
fn();
}
}
}, true);
return function nextTick(fn) {
queue.push(fn);
window.postMessage('process-tick', '*');
};
}
return function nextTick(fn) {
setTimeout(fn, 0);
};
})();
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.binding = function (name) {
throw new Error('process.binding is not supported');
}
// TODO(shtylman)
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
},{}],6:[function(require,module,exports){
(function(process){if (!process.EventEmitter) process.EventEmitter = function () {};
var EventEmitter = exports.EventEmitter = process.EventEmitter;
var isArray = typeof Array.isArray === 'function'
? Array.isArray
: function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]'
}
;
function indexOf (xs, x) {
if (xs.indexOf) return xs.indexOf(x);
for (var i = 0; i < xs.length; i++) {
if (x === xs[i]) return i;
}
return -1;
}
// By default EventEmitters will print a warning if more than
// 10 listeners are added to it. This is a useful default which
// helps finding memory leaks.
//
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
var defaultMaxListeners = 10;
EventEmitter.prototype.setMaxListeners = function(n) {
if (!this._events) this._events = {};
this._events.maxListeners = n;
};
EventEmitter.prototype.emit = function(type) {
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events || !this._events.error ||
(isArray(this._events.error) && !this._events.error.length))
{
if (arguments[1] instanceof Error) {
throw arguments[1]; // Unhandled 'error' event
} else {
throw new Error("Uncaught, unspecified 'error' event.");
}
return false;
}
}
if (!this._events) return false;
var handler = this._events[type];
if (!handler) return false;
if (typeof handler == 'function') {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
var args = Array.prototype.slice.call(arguments, 1);
handler.apply(this, args);
}
return true;
} else if (isArray(handler)) {
var args = Array.prototype.slice.call(arguments, 1);
var listeners = handler.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].apply(this, args);
}
return true;
} else {
return false;
}
};
// EventEmitter is defined in src/node_events.cc
// EventEmitter.prototype.emit() is also defined there.
EventEmitter.prototype.addListener = function(type, listener) {
if ('function' !== typeof listener) {
throw new Error('addListener only takes instances of Function');
}
if (!this._events) this._events = {};
// To avoid recursion in the case that type == "newListeners"! Before
// adding it to the listeners, first emit "newListeners".
this.emit('newListener', type, listener);
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
} else if (isArray(this._events[type])) {
// Check for listener leak
if (!this._events[type].warned) {
var m;
if (this._events.maxListeners !== undefined) {
m = this._events.maxListeners;
} else {
m = defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
console.trace();
}
}
// If we've already got an array, just append.
this._events[type].push(listener);
} else {
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
var self = this;
self.on(type, function g() {
self.removeListener(type, g);
listener.apply(this, arguments);
});
return this;
};
EventEmitter.prototype.removeListener = function(type, listener) {
if ('function' !== typeof listener) {
throw new Error('removeListener only takes instances of Function');
}
// does not use listeners(), so no side effect of creating _events[type]
if (!this._events || !this._events[type]) return this;
var list = this._events[type];
if (isArray(list)) {
var i = indexOf(list, listener);
if (i < 0) return this;
list.splice(i, 1);
if (list.length == 0)
delete this._events[type];
} else if (this._events[type] === listener) {
delete this._events[type];
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
if (arguments.length === 0) {
this._events = {};
return this;
}
// does not use listeners(), so no side effect of creating _events[type]
if (type && this._events && this._events[type]) this._events[type] = null;
return this;
};
EventEmitter.prototype.listeners = function(type) {
if (!this._events) this._events = {};
if (!this._events[type]) this._events[type] = [];
if (!isArray(this._events[type])) {
this._events[type] = [this._events[type]];
}
return this._events[type];
};
})(require("__browserify_process"))
},{"__browserify_process":8}],4:[function(require,module,exports){
(function(){function SlowBuffer (size) {
this.length = size;
};
var assert = require('assert');
exports.INSPECT_MAX_BYTES = 50;
function toHex(n) {
if (n < 16) return '0' + n.toString(16);
return n.toString(16);
}
function utf8ToBytes(str) {
var byteArray = [];
for (var i = 0; i < str.length; i++)
if (str.charCodeAt(i) <= 0x7F)
byteArray.push(str.charCodeAt(i));
else {
var h = encodeURIComponent(str.charAt(i)).substr(1).split('%');
for (var j = 0; j < h.length; j++)
byteArray.push(parseInt(h[j], 16));
}
return byteArray;
}
function asciiToBytes(str) {
var byteArray = []
for (var i = 0; i < str.length; i++ )
// Node's code seems to be doing this and not & 0x7F..
byteArray.push( str.charCodeAt(i) & 0xFF );
return byteArray;
}
function base64ToBytes(str) {
return require("base64-js").toByteArray(str);
}
SlowBuffer.byteLength = function (str, encoding) {
switch (encoding || "utf8") {
case 'hex':
return str.length / 2;
case 'utf8':
case 'utf-8':
return utf8ToBytes(str).length;
case 'ascii':
return str.length;
case 'base64':
return base64ToBytes(str).length;
default:
throw new Error('Unknown encoding');
}
};
function blitBuffer(src, dst, offset, length) {
var pos, i = 0;
while (i < length) {
if ((i+offset >= dst.length) || (i >= src.length))
break;
dst[i + offset] = src[i];
i++;
}
return i;
}
SlowBuffer.prototype.utf8Write = function (string, offset, length) {
var bytes, pos;
return SlowBuffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length);
};
SlowBuffer.prototype.asciiWrite = function (string, offset, length) {
var bytes, pos;
return SlowBuffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length);
};
SlowBuffer.prototype.base64Write = function (string, offset, length) {
var bytes, pos;
return SlowBuffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length);
};
SlowBuffer.prototype.base64Slice = function (start, end) {
var bytes = Array.prototype.slice.apply(this, arguments)
return require("base64-js").fromByteArray(bytes);
}
function decodeUtf8Char(str) {
try {
return decodeURIComponent(str);
} catch (err) {
return String.fromCharCode(0xFFFD); // UTF 8 invalid char
}
}
SlowBuffer.prototype.utf8Slice = function () {
var bytes = Array.prototype.slice.apply(this, arguments);
var res = "";
var tmp = "";
var i = 0;
while (i < bytes.length) {
if (bytes[i] <= 0x7F) {
res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]);
tmp = "";
} else
tmp += "%" + bytes[i].toString(16);
i++;
}
return res + decodeUtf8Char(tmp);
}
SlowBuffer.prototype.asciiSlice = function () {
var bytes = Array.prototype.slice.apply(this, arguments);
var ret = "";
for (var i = 0; i < bytes.length; i++)
ret += String.fromCharCode(bytes[i]);
return ret;
}
SlowBuffer.prototype.inspect = function() {
var out = [],
len = this.length;
for (var i = 0; i < len; i++) {
out[i] = toHex(this[i]);
if (i == exports.INSPECT_MAX_BYTES) {
out[i + 1] = '...';
break;
}
}
return '<SlowBuffer ' + out.join(' ') + '>';
};
SlowBuffer.prototype.hexSlice = function(start, end) {
var len = this.length;
if (!start || start < 0) start = 0;
if (!end || end < 0 || end > len) end = len;
var out = '';
for (var i = start; i < end; i++) {
out += toHex(this[i]);
}
return out;
};
SlowBuffer.prototype.toString = function(encoding, start, end) {
encoding = String(encoding || 'utf8').toLowerCase();
start = +start || 0;
if (typeof end == 'undefined') end = this.length;
// Fastpath empty strings
if (+end == start) {
return '';
}
switch (encoding) {
case 'hex':
return this.hexSlice(start, end);
case 'utf8':
case 'utf-8':
return this.utf8Slice(start, end);
case 'ascii':
return this.asciiSlice(start, end);
case 'binary':
return this.binarySlice(start, end);
case 'base64':
return this.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}
};
SlowBuffer.prototype.hexWrite = function(string, offset, length) {
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
// must be an even number of digits
var strLen = string.length;
if (strLen % 2) {
throw new Error('Invalid hex string');
}
if (length > strLen / 2) {
length = strLen / 2;
}
for (var i = 0; i < length; i++) {
var byte = parseInt(string.substr(i * 2, 2), 16);
if (isNaN(byte)) throw new Error('Invalid hex string');
this[offset + i] = byte;
}
SlowBuffer._charsWritten = i * 2;
return i;
};
SlowBuffer.prototype.write = function(string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length;
length = undefined;
}
} else { // legacy
var swap = encoding;
encoding = offset;
offset = length;
length = swap;
}
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
encoding = String(encoding || 'utf8').toLowerCase();
switch (encoding) {
case 'hex':
return this.hexWrite(string, offset, length);
case 'utf8':
case 'utf-8':
return this.utf8Write(string, offset, length);
case 'ascii':
return this.asciiWrite(string, offset, length);
case 'binary':
return this.binaryWrite(string, offset, length);
case 'base64':
return this.base64Write(string, offset, length);
case 'ucs2':
case 'ucs-2':
return this.ucs2Write(string, offset, length);
default:
throw new Error('Unknown encoding');
}
};
// slice(start, end)
SlowBuffer.prototype.slice = function(start, end) {
if (end === undefined) end = this.length;
if (end > this.length) {
throw new Error('oob');
}
if (start > end) {
throw new Error('oob');
}
return new Buffer(this, end - start, +start);
};
SlowBuffer.prototype.copy = function(target, targetstart, sourcestart, sourceend) {
var temp = [];
for (var i=sourcestart; i<sourceend; i++) {
assert.ok(typeof this[i] !== 'undefined', "copying undefined buffer bytes!");
temp.push(this[i]);
}
for (var i=targetstart; i<targetstart+temp.length; i++) {
target[i] = temp[i-targetstart];
}
};
function coerce(length) {
// Coerce length to a number (possibly NaN), round up
// in case it's fractional (e.g. 123.456) then do a
// double negate to coerce a NaN to 0. Easy, right?
length = ~~Math.ceil(+length);
return length < 0 ? 0 : length;
}
// Buffer
function Buffer(subject, encoding, offset) {
if (!(this instanceof Buffer)) {
return new Buffer(subject, encoding, offset);
}
var type;
// Are we slicing?
if (typeof offset === 'number') {
this.length = coerce(encoding);
this.parent = subject;
this.offset = offset;
} else {
// Find the length
switch (type = typeof subject) {
case 'number':
this.length = coerce(subject);
break;
case 'string':
this.length = Buffer.byteLength(subject, encoding);
break;
case 'object': // Assume object is an array
this.length = coerce(subject.length);
break;
default:
throw new Error('First argument needs to be a number, ' +
'array or string.');
}
if (this.length > Buffer.poolSize) {
// Big buffer, just alloc one.
this.parent = new SlowBuffer(this.length);
this.offset = 0;
} else {
// Small buffer.
if (!pool || pool.length - pool.used < this.length) allocPool();
this.parent = pool;
this.offset = pool.used;
pool.used += this.length;
}
// Treat array-ish objects as a byte array.
if (isArrayIsh(subject)) {
for (var i = 0; i < this.length; i++) {
this.parent[i + this.offset] = subject[i];
}
} else if (type == 'string') {
// We are a string
this.length = this.write(subject, 0, encoding);
}
}
}
function isArrayIsh(subject) {
return Array.isArray(subject) || Buffer.isBuffer(subject) ||
subject && typeof subject === 'object' &&
typeof subject.length === 'number';
}
exports.SlowBuffer = SlowBuffer;
exports.Buffer = Buffer;
Buffer.poolSize = 8 * 1024;
var pool;
function allocPool() {
pool = new SlowBuffer(Buffer.poolSize);
pool.used = 0;
}
// Static methods
Buffer.isBuffer = function isBuffer(b) {
return b instanceof Buffer || b instanceof SlowBuffer;
};
Buffer.concat = function (list, totalLength) {
if (!Array.isArray(list)) {
throw new Error("Usage: Buffer.concat(list, [totalLength])\n \
list should be an Array.");
}
if (list.length === 0) {
return new Buffer(0);
} else if (list.length === 1) {
return list[0];
}
if (typeof totalLength !== 'number') {
totalLength = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
totalLength += buf.length;
}
}
var buffer = new Buffer(totalLength);
var pos = 0;
for (var i = 0; i < list.length; i++) {
var buf = list[i];
buf.copy(buffer, pos);
pos += buf.length;
}
return buffer;
};
// Inspect
Buffer.prototype.inspect = function inspect() {
var out = [],
len = this.length;
for (var i = 0; i < len; i++) {
out[i] = toHex(this.parent[i + this.offset]);
if (i == exports.INSPECT_MAX_BYTES) {
out[i + 1] = '...';
break;
}
}
return '<Buffer ' + out.join(' ') + '>';
};
Buffer.prototype.get = function get(i) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this.parent[this.offset + i];
};
Buffer.prototype.set = function set(i, v) {
if (i < 0 || i >= this.length) throw new Error('oob');
return this.parent[this.offset + i] = v;
};
// write(string, offset = 0, length = buffer.length-offset, encoding = 'utf8')
Buffer.prototype.write = function(string, offset, length, encoding) {
// Support both (string, offset, length, encoding)
// and the legacy (string, encoding, offset, length)
if (isFinite(offset)) {
if (!isFinite(length)) {
encoding = length;
length = undefined;
}
} else { // legacy
var swap = encoding;
encoding = offset;
offset = length;
length = swap;
}
offset = +offset || 0;
var remaining = this.length - offset;
if (!length) {
length = remaining;
} else {
length = +length;
if (length > remaining) {
length = remaining;
}
}
encoding = String(encoding || 'utf8').toLowerCase();
var ret;
switch (encoding) {
case 'hex':
ret = this.parent.hexWrite(string, this.offset + offset, length);
break;
case 'utf8':
case 'utf-8':
ret = this.parent.utf8Write(string, this.offset + offset, length);
break;
case 'ascii':
ret = this.parent.asciiWrite(string, this.offset + offset, length);
break;
case 'binary':
ret = this.parent.binaryWrite(string, this.offset + offset, length);
break;
case 'base64':
// Warning: maxLength not taken into account in base64Write
ret = this.parent.base64Write(string, this.offset + offset, length);
break;
case 'ucs2':
case 'ucs-2':
ret = this.parent.ucs2Write(string, this.offset + offset, length);
break;
default:
throw new Error('Unknown encoding');
}
Buffer._charsWritten = SlowBuffer._charsWritten;
return ret;
};
// toString(encoding, start=0, end=buffer.length)
Buffer.prototype.toString = function(encoding, start, end) {
encoding = String(encoding || 'utf8').toLowerCase();
if (typeof start == 'undefined' || start < 0) {
start = 0;
} else if (start > this.length) {
start = this.length;
}
if (typeof end == 'undefined' || end > this.length) {
end = this.length;
} else if (end < 0) {
end = 0;
}
start = start + this.offset;
end = end + this.offset;
switch (encoding) {
case 'hex':
return this.parent.hexSlice(start, end);
case 'utf8':
case 'utf-8':
return this.parent.utf8Slice(start, end);
case 'ascii':
return this.parent.asciiSlice(start, end);
case 'binary':
return this.parent.binarySlice(start, end);
case 'base64':
return this.parent.base64Slice(start, end);
case 'ucs2':
case 'ucs-2':
return this.parent.ucs2Slice(start, end);
default:
throw new Error('Unknown encoding');
}
};
// byteLength
Buffer.byteLength = SlowBuffer.byteLength;
// fill(value, start=0, end=buffer.length)
Buffer.prototype.fill = function fill(value, start, end) {
value || (value = 0);
start || (start = 0);
end || (end = this.length);
if (typeof value === 'string') {
value = value.charCodeAt(0);
}
if (!(typeof value === 'number') || isNaN(value)) {
throw new Error('value is not a number');
}
if (end < start) throw new Error('end < start');
// Fill 0 bytes; we're done
if (end === start) return 0;
if (this.length == 0) return 0;
if (start < 0 || start >= this.length) {
throw new Error('start out of bounds');
}
if (end < 0 || end > this.length) {
throw new Error('end out of bounds');
}
return this.parent.fill(value,
start + this.offset,
end + this.offset);
};
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
Buffer.prototype.copy = function(target, target_start, start, end) {
var source = this;
start || (start = 0);
end || (end = this.length);
target_start || (target_start = 0);
if (end < start) throw new Error('sourceEnd < sourceStart');
// Copy 0 bytes; we're done
if (end === start) return 0;
if (target.length == 0 || source.length == 0) return 0;
if (target_start < 0 || target_start >= target.length) {
throw new Error('targetStart out of bounds');
}
if (start < 0 || start >= source.length) {
throw new Error('sourceStart out of bounds');
}
if (end < 0 || end > source.length) {
throw new Error('sourceEnd out of bounds');
}
// Are we oob?
if (end > this.length) {
end = this.length;
}
if (target.length - target_start < end - start) {
end = target.length - target_start + start;
}
return this.parent.copy(target.parent,
target_start + target.offset,
start + this.offset,
end + this.offset);
};
// slice(start, end)
Buffer.prototype.slice = function(start, end) {
if (end === undefined) end = this.length;
if (end > this.length) throw new Error('oob');
if (start > end) throw new Error('oob');
return new Buffer(this.parent, end - start, +start + this.offset);
};
// Legacy methods for backwards compatibility.
Buffer.prototype.utf8Slice = function(start, end) {
return this.toString('utf8', start, end);
};
Buffer.prototype.binarySlice = function(start, end) {
return this.toString('binary', start, end);
};
Buffer.prototype.asciiSlice = function(start, end) {
return this.toString('ascii', start, end);
};
Buffer.prototype.utf8Write = function(string, offset) {
return this.write(string, offset, 'utf8');
};
Buffer.prototype.binaryWrite = function(string, offset) {
return this.write(string, offset, 'binary');
};
Buffer.prototype.asciiWrite = function(string, offset) {
return this.write(string, offset, 'ascii');
};
Buffer.prototype.readUInt8 = function(offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to read beyond buffer length');
}
return buffer.parent[buffer.offset + offset];
};
function readUInt16(buffer, offset, isBigEndian, noAssert) {
var val = 0;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to read beyond buffer length');
}
if (isBigEndian) {
val = buffer.parent[buffer.offset + offset] << 8;
val |= buffer.parent[buffer.offset + offset + 1];
} else {
val = buffer.parent[buffer.offset + offset];
val |= buffer.parent[buffer.offset + offset + 1] << 8;
}
return val;
}
Buffer.prototype.readUInt16LE = function(offset, noAssert) {
return readUInt16(this, offset, false, noAssert);
};
Buffer.prototype.readUInt16BE = function(offset, noAssert) {
return readUInt16(this, offset, true, noAssert);
};
function readUInt32(buffer, offset, isBigEndian, noAssert) {
var val = 0;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
if (isBigEndian) {
val = buffer.parent[buffer.offset + offset + 1] << 16;
val |= buffer.parent[buffer.offset + offset + 2] << 8;
val |= buffer.parent[buffer.offset + offset + 3];
val = val + (buffer.parent[buffer.offset + offset] << 24 >>> 0);
} else {
val = buffer.parent[buffer.offset + offset + 2] << 16;
val |= buffer.parent[buffer.offset + offset + 1] << 8;
val |= buffer.parent[buffer.offset + offset];
val = val + (buffer.parent[buffer.offset + offset + 3] << 24 >>> 0);
}
return val;
}
Buffer.prototype.readUInt32LE = function(offset, noAssert) {
return readUInt32(this, offset, false, noAssert);
};
Buffer.prototype.readUInt32BE = function(offset, noAssert) {
return readUInt32(this, offset, true, noAssert);
};
/*
* Signed integer types, yay team! A reminder on how two's complement actually
* works. The first bit is the signed bit, i.e. tells us whether or not the
* number should be positive or negative. If the two's complement value is
* positive, then we're done, as it's equivalent to the unsigned representation.
*
* Now if the number is positive, you're pretty much done, you can just leverage
* the unsigned translations and return those. Unfortunately, negative numbers
* aren't quite that straightforward.
*
* At first glance, one might be inclined to use the traditional formula to
* translate binary numbers between the positive and negative values in two's
* complement. (Though it doesn't quite work for the most negative value)
* Mainly:
* - invert all the bits
* - add one to the result
*
* Of course, this doesn't quite work in Javascript. Take for example the value
* of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of
* course, Javascript will do the following:
*
* > ~0xff80
* -65409
*
* Whoh there, Javascript, that's not quite right. But wait, according to
* Javascript that's perfectly correct. When Javascript ends up seeing the
* constant 0xff80, it has no notion that it is actually a signed number. It
* assumes that we've input the unsigned value 0xff80. Thus, when it does the
* binary negation, it casts it into a signed value, (positive 0xff80). Then
* when you perform binary negation on that, it turns it into a negative number.
*
* Instead, we're going to have to use the following general formula, that works
* in a rather Javascript friendly way. I'm glad we don't support this kind of
* weird numbering scheme in the kernel.
*
* (BIT-MAX - (unsigned)val + 1) * -1
*
* The astute observer, may think that this doesn't make sense for 8-bit numbers
* (really it isn't necessary for them). However, when you get 16-bit numbers,
* you do. Let's go back to our prior example and see how this will look:
*
* (0xffff - 0xff80 + 1) * -1
* (0x007f + 1) * -1
* (0x0080) * -1
*/
Buffer.prototype.readInt8 = function(offset, noAssert) {
var buffer = this;
var neg;
if (!noAssert) {
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to read beyond buffer length');
}
neg = buffer.parent[buffer.offset + offset] & 0x80;
if (!neg) {
return (buffer.parent[buffer.offset + offset]);
}
return ((0xff - buffer.parent[buffer.offset + offset] + 1) * -1);
};
function readInt16(buffer, offset, isBigEndian, noAssert) {
var neg, val;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to read beyond buffer length');
}
val = readUInt16(buffer, offset, isBigEndian, noAssert);
neg = val & 0x8000;
if (!neg) {
return val;
}
return (0xffff - val + 1) * -1;
}
Buffer.prototype.readInt16LE = function(offset, noAssert) {
return readInt16(this, offset, false, noAssert);
};
Buffer.prototype.readInt16BE = function(offset, noAssert) {
return readInt16(this, offset, true, noAssert);
};
function readInt32(buffer, offset, isBigEndian, noAssert) {
var neg, val;
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
val = readUInt32(buffer, offset, isBigEndian, noAssert);
neg = val & 0x80000000;
if (!neg) {
return (val);
}
return (0xffffffff - val + 1) * -1;
}
Buffer.prototype.readInt32LE = function(offset, noAssert) {
return readInt32(this, offset, false, noAssert);
};
Buffer.prototype.readInt32BE = function(offset, noAssert) {
return readInt32(this, offset, true, noAssert);
};
function readFloat(buffer, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset + 3 < buffer.length,
'Trying to read beyond buffer length');
}
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
23, 4);
}
Buffer.prototype.readFloatLE = function(offset, noAssert) {
return readFloat(this, offset, false, noAssert);
};
Buffer.prototype.readFloatBE = function(offset, noAssert) {
return readFloat(this, offset, true, noAssert);
};
function readDouble(buffer, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset + 7 < buffer.length,
'Trying to read beyond buffer length');
}
return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian,
52, 8);
}
Buffer.prototype.readDoubleLE = function(offset, noAssert) {
return readDouble(this, offset, false, noAssert);
};
Buffer.prototype.readDoubleBE = function(offset, noAssert) {
return readDouble(this, offset, true, noAssert);
};
/*
* We have to make sure that the value is a valid integer. This means that it is
* non-negative. It has no fractional component and that it does not exceed the
* maximum allowed value.
*
* value The number to check for validity
*
* max The maximum value
*/
function verifuint(value, max) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value >= 0,
'specified a negative value for writing an unsigned value');
assert.ok(value <= max, 'value is larger than maximum value for type');
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
Buffer.prototype.writeUInt8 = function(value, offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xff);
}
buffer.parent[buffer.offset + offset] = value;
};
function writeUInt16(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xffff);
}
if (isBigEndian) {
buffer.parent[buffer.offset + offset] = (value & 0xff00) >>> 8;
buffer.parent[buffer.offset + offset + 1] = value & 0x00ff;
} else {
buffer.parent[buffer.offset + offset + 1] = (value & 0xff00) >>> 8;
buffer.parent[buffer.offset + offset] = value & 0x00ff;
}
}
Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) {
writeUInt16(this, value, offset, false, noAssert);
};
Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) {
writeUInt16(this, value, offset, true, noAssert);
};
function writeUInt32(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'trying to write beyond buffer length');
verifuint(value, 0xffffffff);
}
if (isBigEndian) {
buffer.parent[buffer.offset + offset] = (value >>> 24) & 0xff;
buffer.parent[buffer.offset + offset + 1] = (value >>> 16) & 0xff;
buffer.parent[buffer.offset + offset + 2] = (value >>> 8) & 0xff;
buffer.parent[buffer.offset + offset + 3] = value & 0xff;
} else {
buffer.parent[buffer.offset + offset + 3] = (value >>> 24) & 0xff;
buffer.parent[buffer.offset + offset + 2] = (value >>> 16) & 0xff;
buffer.parent[buffer.offset + offset + 1] = (value >>> 8) & 0xff;
buffer.parent[buffer.offset + offset] = value & 0xff;
}
}
Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) {
writeUInt32(this, value, offset, false, noAssert);
};
Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) {
writeUInt32(this, value, offset, true, noAssert);
};
/*
* We now move onto our friends in the signed number category. Unlike unsigned
* numbers, we're going to have to worry a bit more about how we put values into
* arrays. Since we are only worrying about signed 32-bit values, we're in
* slightly better shape. Unfortunately, we really can't do our favorite binary
* & in this system. It really seems to do the wrong thing. For example:
*
* > -32 & 0xff
* 224
*
* What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of
* this aren't treated as a signed number. Ultimately a bad thing.
*
* What we're going to want to do is basically create the unsigned equivalent of
* our representation and pass that off to the wuint* functions. To do that
* we're going to do the following:
*
* - if the value is positive
* we can pass it directly off to the equivalent wuint
* - if the value is negative
* we do the following computation:
* mb + val + 1, where
* mb is the maximum unsigned value in that byte size
* val is the Javascript negative integer
*
*
* As a concrete value, take -128. In signed 16 bits this would be 0xff80. If
* you do out the computations:
*
* 0xffff - 128 + 1
* 0xffff - 127
* 0xff80
*
* You can then encode this value as the signed version. This is really rather
* hacky, but it should work and get the job done which is our goal here.
*/
/*
* A series of checks to make sure we actually have a signed 32-bit number
*/
function verifsint(value, max, min) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value <= max, 'value larger than maximum allowed value');
assert.ok(value >= min, 'value smaller than minimum allowed value');
assert.ok(Math.floor(value) === value, 'value has a fractional component');
}
function verifIEEE754(value, max, min) {
assert.ok(typeof (value) == 'number',
'cannot write a non-number as a number');
assert.ok(value <= max, 'value larger than maximum allowed value');
assert.ok(value >= min, 'value smaller than minimum allowed value');
}
Buffer.prototype.writeInt8 = function(value, offset, noAssert) {
var buffer = this;
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7f, -0x80);
}
if (value >= 0) {
buffer.writeUInt8(value, offset, noAssert);
} else {
buffer.writeUInt8(0xff + value + 1, offset, noAssert);
}
};
function writeInt16(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 1 < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7fff, -0x8000);
}
if (value >= 0) {
writeUInt16(buffer, value, offset, isBigEndian, noAssert);
} else {
writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert);
}
}
Buffer.prototype.writeInt16LE = function(value, offset, noAssert) {
writeInt16(this, value, offset, false, noAssert);
};
Buffer.prototype.writeInt16BE = function(value, offset, noAssert) {
writeInt16(this, value, offset, true, noAssert);
};
function writeInt32(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to write beyond buffer length');
verifsint(value, 0x7fffffff, -0x80000000);
}
if (value >= 0) {
writeUInt32(buffer, value, offset, isBigEndian, noAssert);
} else {
writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert);
}
}
Buffer.prototype.writeInt32LE = function(value, offset, noAssert) {
writeInt32(this, value, offset, false, noAssert);
};
Buffer.prototype.writeInt32BE = function(value, offset, noAssert) {
writeInt32(this, value, offset, true, noAssert);
};
function writeFloat(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 3 < buffer.length,
'Trying to write beyond buffer length');
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38);
}
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
23, 4);
}
Buffer.prototype.writeFloatLE = function(value, offset, noAssert) {
writeFloat(this, value, offset, false, noAssert);
};
Buffer.prototype.writeFloatBE = function(value, offset, noAssert) {
writeFloat(this, value, offset, true, noAssert);
};
function writeDouble(buffer, value, offset, isBigEndian, noAssert) {
if (!noAssert) {
assert.ok(value !== undefined && value !== null,
'missing value');
assert.ok(typeof (isBigEndian) === 'boolean',
'missing or invalid endian');
assert.ok(offset !== undefined && offset !== null,
'missing offset');
assert.ok(offset + 7 < buffer.length,
'Trying to write beyond buffer length');
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308);
}
require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian,
52, 8);
}
Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) {
writeDouble(this, value, offset, false, noAssert);
};
Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) {
writeDouble(this, value, offset, true, noAssert);
};
SlowBuffer.prototype.readUInt8 = Buffer.prototype.readUInt8;
SlowBuffer.prototype.readUInt16LE = Buffer.prototype.readUInt16LE;
SlowBuffer.prototype.readUInt16BE = Buffer.prototype.readUInt16BE;
SlowBuffer.prototype.readUInt32LE = Buffer.prototype.readUInt32LE;
SlowBuffer.prototype.readUInt32BE = Buffer.prototype.readUInt32BE;
SlowBuffer.prototype.readInt8 = Buffer.prototype.readInt8;
SlowBuffer.prototype.readInt16LE = Buffer.prototype.readInt16LE;
SlowBuffer.prototype.readInt16BE = Buffer.prototype.readInt16BE;
SlowBuffer.prototype.readInt32LE = Buffer.prototype.readInt32LE;
SlowBuffer.prototype.readInt32BE = Buffer.prototype.readInt32BE;
SlowBuffer.prototype.readFloatLE = Buffer.prototype.readFloatLE;
SlowBuffer.prototype.readFloatBE = Buffer.prototype.readFloatBE;
SlowBuffer.prototype.readDoubleLE = Buffer.prototype.readDoubleLE;
SlowBuffer.prototype.readDoubleBE = Buffer.prototype.readDoubleBE;
SlowBuffer.prototype.writeUInt8 = Buffer.prototype.writeUInt8;
SlowBuffer.prototype.writeUInt16LE = Buffer.prototype.writeUInt16LE;
SlowBuffer.prototype.writeUInt16BE = Buffer.prototype.writeUInt16BE;
SlowBuffer.prototype.writeUInt32LE = Buffer.prototype.writeUInt32LE;
SlowBuffer.prototype.writeUInt32BE = Buffer.prototype.writeUInt32BE;
SlowBuffer.prototype.writeInt8 = Buffer.prototype.writeInt8;
SlowBuffer.prototype.writeInt16LE = Buffer.prototype.writeInt16LE;
SlowBuffer.prototype.writeInt16BE = Buffer.prototype.writeInt16BE;
SlowBuffer.prototype.writeInt32LE = Buffer.prototype.writeInt32LE;
SlowBuffer.prototype.writeInt32BE = Buffer.prototype.writeInt32BE;
SlowBuffer.prototype.writeFloatLE = Buffer.prototype.writeFloatLE;
SlowBuffer.prototype.writeFloatBE = Buffer.prototype.writeFloatBE;
SlowBuffer.prototype.writeDoubleLE = Buffer.prototype.writeDoubleLE;
SlowBuffer.prototype.writeDoubleBE = Buffer.prototype.writeDoubleBE;
})()
},{"assert":2,"./buffer_ieee754":7,"base64-js":9}],9:[function(require,module,exports){
(function (exports) {
'use strict';
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
function b64ToByteArray(b64) {
var i, j, l, tmp, placeHolders, arr;
if (b64.length % 4 > 0) {
throw 'Invalid string. Length must be a multiple of 4';
}
// the number of equal signs (place holders)
// if there are two placeholders, than the two characters before it
// represent one byte
// if there is only one, then the three characters before it represent 2 bytes
// this is just a cheap hack to not do indexOf twice
placeHolders = b64.indexOf('=');
placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0;
// base64 is 4/3 + up to two characters of the original data
arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders);
// if there are placeholders, only get up to the last complete 4 chars
l = placeHolders > 0 ? b64.length - 4 : b64.length;
for (i = 0, j = 0; i < l; i += 4, j += 3) {
tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]);
arr.push((tmp & 0xFF0000) >> 16);
arr.push((tmp & 0xFF00) >> 8);
arr.push(tmp & 0xFF);
}
if (placeHolders === 2) {
tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4);
arr.push(tmp & 0xFF);
} else if (placeHolders === 1) {
tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2);
arr.push((tmp >> 8) & 0xFF);
arr.push(tmp & 0xFF);
}
return arr;
}
function uint8ToBase64(uint8) {
var i,
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
output = "",
temp, length;
function tripletToBase64 (num) {
return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];
};
// go through the array every three bytes, we'll deal with trailing stuff later
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);
output += tripletToBase64(temp);
}
// pad the end with zeros, but make sure to not forget the extra bytes
switch (extraBytes) {
case 1:
temp = uint8[uint8.length - 1];
output += lookup[temp >> 2];
output += lookup[(temp << 4) & 0x3F];
output += '==';
break;
case 2:
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]);
output += lookup[temp >> 10];
output += lookup[(temp >> 4) & 0x3F];
output += lookup[(temp << 2) & 0x3F];
output += '=';
break;
}
return output;
}
module.exports.toByteArray = b64ToByteArray;
module.exports.fromByteArray = uint8ToBase64;
}());
},{}]},{},[])
;;module.exports=require("buffer-browserify")
},{}],36:[function(require,module,exports){
(function(Buffer,global){'use strict'
var bits = require('bit-twiddle')
var dup = require('dup')
//Legacy pool support
if(!global.__TYPEDARRAY_POOL) {
global.__TYPEDARRAY_POOL = {
UINT8 : dup([32, 0])
, UINT16 : dup([32, 0])
, UINT32 : dup([32, 0])
, INT8 : dup([32, 0])
, INT16 : dup([32, 0])
, INT32 : dup([32, 0])
, FLOAT : dup([32, 0])
, DOUBLE : dup([32, 0])
, DATA : dup([32, 0])
, UINT8C : dup([32, 0])
, BUFFER : dup([32, 0])
}
}
var hasUint8C = (typeof Uint8ClampedArray) !== 'undefined'
var POOL = global.__TYPEDARRAY_POOL
//Upgrade pool
if(!POOL.UINT8C) {
POOL.UINT8C = dup([32, 0])
}
if(!POOL.BUFFER) {
POOL.BUFFER = dup([32, 0])
}
//New technique: Only allocate from ArrayBufferView and Buffer
var DATA = POOL.DATA
, BUFFER = POOL.BUFFER
exports.free = function free(array) {
if(Buffer.isBuffer(array)) {
BUFFER[bits.log2(array.length)].push(array)
} else {
if(Object.prototype.toString.call(array) !== '[object ArrayBuffer]') {
array = array.buffer
}
if(!array) {
return
}
var n = array.length || array.byteLength
var log_n = bits.log2(n)|0
DATA[log_n].push(array)
}
}
function freeArrayBuffer(buffer) {
if(!buffer) {
return
}
var n = buffer.length || buffer.byteLength
var log_n = bits.log2(n)
DATA[log_n].push(buffer)
}
function freeTypedArray(array) {
freeArrayBuffer(array.buffer)
}
exports.freeUint8 =
exports.freeUint16 =
exports.freeUint32 =
exports.freeInt8 =
exports.freeInt16 =
exports.freeInt32 =
exports.freeFloat32 =
exports.freeFloat =
exports.freeFloat64 =
exports.freeDouble =
exports.freeUint8Clamped =
exports.freeDataView = freeTypedArray
exports.freeArrayBuffer = freeArrayBuffer
exports.freeBuffer = function freeBuffer(array) {
BUFFER[bits.log2(array.length)].push(array)
}
exports.malloc = function malloc(n, dtype) {
if(dtype === undefined || dtype === 'arraybuffer') {
return mallocArrayBuffer(n)
} else {
switch(dtype) {
case 'uint8':
return mallocUint8(n)
case 'uint16':
return mallocUint16(n)
case 'uint32':
return mallocUint32(n)
case 'int8':
return mallocInt8(n)
case 'int16':
return mallocInt16(n)
case 'int32':
return mallocInt32(n)
case 'float':
case 'float32':
return mallocFloat(n)
case 'double':
case 'float64':
return mallocDouble(n)
case 'uint8_clamped':
return mallocUint8Clamped(n)
case 'buffer':
return mallocBuffer(n)
case 'data':
case 'dataview':
return mallocDataView(n)
default:
return null
}
}
return null
}
function mallocArrayBuffer(n) {
var n = bits.nextPow2(n)
var log_n = bits.log2(n)
var d = DATA[log_n]
if(d.length > 0) {
return d.pop()
}
return new ArrayBuffer(n)
}
exports.mallocArrayBuffer = mallocArrayBuffer
function mallocUint8(n) {
return new Uint8Array(mallocArrayBuffer(n), 0, n)
}
exports.mallocUint8 = mallocUint8
function mallocUint16(n) {
return new Uint16Array(mallocArrayBuffer(2*n), 0, n)
}
exports.mallocUint16 = mallocUint16
function mallocUint32(n) {
return new Uint32Array(mallocArrayBuffer(4*n), 0, n)
}
exports.mallocUint32 = mallocUint32
function mallocInt8(n) {
return new Int8Array(mallocArrayBuffer(n), 0, n)
}
exports.mallocInt8 = mallocInt8
function mallocInt16(n) {
return new Int16Array(mallocArrayBuffer(2*n), 0, n)
}
exports.mallocInt16 = mallocInt16
function mallocInt32(n) {
return new Int32Array(mallocArrayBuffer(4*n), 0, n)
}
exports.mallocInt32 = mallocInt32
function mallocFloat(n) {
return new Float32Array(mallocArrayBuffer(4*n), 0, n)
}
exports.mallocFloat32 = exports.mallocFloat = mallocFloat
function mallocDouble(n) {
return new Float64Array(mallocArrayBuffer(8*n), 0, n)
}
exports.mallocFloat64 = exports.mallocDouble = mallocDouble
function mallocUint8Clamped(n) {
if(hasUint8C) {
return new Uint8ClampedArray(mallocArrayBuffer(n), 0, n)
} else {
return mallocUint8(n)
}
}
exports.mallocUint8Clamped = mallocUint8Clamped
function mallocDataView(n) {
return new DataView(mallocArrayBuffer(n), 0, n)
}
exports.mallocDataView = mallocDataView
function mallocBuffer(n) {
n = bits.nextPow2(n)
var log_n = bits.log2(n)
var cache = BUFFER[log_n]
if(cache.length > 0) {
return cache.pop()
}
return new Buffer(n)
}
exports.mallocBuffer = mallocBuffer
exports.clearCache = function clearCache() {
for(var i=0; i<32; ++i) {
POOL.UINT8[i].length = 0
POOL.UINT16[i].length = 0
POOL.UINT32[i].length = 0
POOL.INT8[i].length = 0
POOL.INT16[i].length = 0
POOL.INT32[i].length = 0
POOL.FLOAT[i].length = 0
POOL.DOUBLE[i].length = 0
POOL.UINT8C[i].length = 0
DATA[i].length = 0
BUFFER[i].length = 0
}
}
})(require("__browserify_buffer").Buffer,window)
},{"__browserify_buffer":43,"bit-twiddle":40,"dup":42}]},{},[1])
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment