Skip to content

Instantly share code, notes, and snippets.

@tmpvar
Created February 21, 2014 07:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmpvar/9130079 to your computer and use it in GitHub Desktop.
Save tmpvar/9130079 to your computer and use it in GitHub Desktop.
cassowary.js distance attempt
// Copyright (C) 1998-2000 Greg J. Badros
// Use of this source code is governed by http://www.apache.org/licenses/LICENSE-2.0
//
// Parts Copyright (C) 2011, Alex Russell (slightlyoff@chromium.org)
var DraggableBox = c.inherit({
initialize: function(x, y, w, h) {
this.width = w || 15;
this.height = h || 15;
if (y == null ) {
this._center = new c.Point(0, 0, x);
} else {
this._center = new c.Point(x, y);
}
},
get center() { return this._center; },
set center(v) {
this._center.x = v.x;
this._center.y = v.y;
},
get x() { return this._center.x; },
get y() { return this._center.y; },
draw: function(ctx) {
if (!this.fixed) {
ctx.strokeRect(this.x.value - (this.width/2),
this.y.value - (this.height/2),
this.width, this.height);
} else {
ctx.beginPath();
ctx.arc(this.x.value, this.y.value, this.width, Math.PI*2, false);
ctx.stroke();
}
},
Contains: function(x, y) {
return ( (x >= this.x.value - this.width/2) &&
(x <= this.x.value + this.width/2) &&
(y >= this.y.value - this.height/2) &&
(y <= this.y.value + this.height/2)
);
},
toString: function() {
return "<" + this.sx + "," + this.sy + ">";
},
});
var QuadDemo = c.inherit({
initialize: function() {
this.canvas = document.getElementById('c');
this.cwidth = this.canvas.width;
this.cheight = this.canvas.height;
this.g = this.canvas.getContext('2d');
var solver = this.solver = new c.SimplexSolver();
this.dbDragging = -1;
var ab = new DraggableBox(200, 100);
var bb = new DraggableBox(200, 200);
var cb = new DraggableBox(210, 200);
var db = this.db = [ab, bb, cb]; // all of them
var mp = this.mp = new Array(4); // midpoints
// Make points stay where you put them
solver.addPointStays([ab.center,
bb.center,
cb.center]);
// helper function for creating "fixed" constraints
var fix = function(point) {
point.fixed = true;
solver.addConstraint(
new c.Equation(point.x.value, new c.Expression(point.x))
).addConstraint(
new c.Equation(point.y.value, new c.Expression(point.y))
);
};
var expr = function(a, b) {
return new c.Expression(a, b);
}
c.Expression.prototype.multiply = function(x) {
if (typeof x == 'number') {
return (this.clone()).multiplyMe(x);
} else if (x instanceof c.Variable) {
return this.clone().addVariable(x, 1);
} else if (x instanceof c.Expression) {
return this.clone().addExpression(x, 1);
} else {
if (this.isConstant) {
return x.times(this.constant);
} else if (x.isConstant) {
return this.times(x.constant);
} else {
throw new c.NonExpression();
}
}
};
var constant = function(val) {
var v = new c.Variable({ value : val });
v.isConstant = true;
return v;
}
// helper function for creating "point-point distance" constraints
var distance = function(p1, p2) {
var x = p1.x.value - p2.x.value;
var y = p1.y.value - p2.y.value;
var distanceSquared = x*x + y*y;
var dx = expr(p1.x).minus(p2.x);
var dy = expr(p1.y).minus(p2.y);
var vardist = dx.multiply(dx).plus(dy.multiply(dy));
var eq = new c.Equation(vardist, -distanceSquared);
solver.addConstraint(eq);
console.log(eq.toString())
};
// fix point b
fix(bb);
distance(bb, cb);
},
mousedown: function(ev) {
var x = ev.pageX - this.canvas.offsetLeft;
var y = ev.pageY - this.canvas.offsetTop;
// console.log('mousedown x,y='+x+','+y);
// console.log('mousedown canvasoffset='+this.canvas.offsetLeft+','+this.canvas.offsetTop);
// console.log('mousedown clientx,y='+ev.clientX+','+ev.clientY);
// console.log('mousedown pagex,y='+ev.pageX+','+ev.pageY);
for ( var a = 0; a < this.db.length; a++ ) {
if ( this.db[a].Contains(x, y) ) {
this.dbDragging = a;
// console.log('dragging #' + a);
break;
}
}
if ( this.dbDragging != -1 ) {
this.draw();
this.solver
.addEditVar(this.db[this.dbDragging].x)
.addEditVar(this.db[this.dbDragging].y)
.beginEdit();
}
return true;
},
mouseup: function(ev) {
if (this.dbDragging != -1 ) {
this.dbDragging = -1;
this.solver.endEdit();
}
this.draw();
return true;
},
mousemove: function(ev) {
var x = ev.pageX - this.canvas.offsetLeft;
var y = ev.pageY - this.canvas.offsetTop;
if ( this.dbDragging != -1 ) {
this.solver
.suggestValue(this.db[this.dbDragging].x, x)
.suggestValue(this.db[this.dbDragging].y, y)
.resolve();
this.draw();
}
return true;
},
touchstart: function(ev) {
if (false) {
document.write("touchstart ev = " + ev + " ");
document.write(ev.pageX + "," + ev.pageY);
document.write("<br/>");
}
this.mousedown(ev.touches.item(0));
if (this.dbDragging != -1) {
ev.preventDefault();
}
},
touchend: function(ev) {
this.mouseup(ev);
},
touchmove: function(ev) {
this.mousemove(ev.touches.item(0));
if (this.dbDragging != -1) {
ev.preventDefault();
}
},
initEvents: function() {
var mouseupHandler = function(ev) {
this.mouseup(ev);
document.removeEventListener('mouseup', mouseupHandler);
}.bind(this);
this.canvas.addEventListener('mousedown',
function(ev) {
this.mousedown(ev);
document.addEventListener('mouseup', mouseupHandler);
}.bind(this),
false
);
['mousemove', 'touchstart', 'touchend', 'touchmove'].forEach(
function(evt) {
this.canvas.addEventListener(evt, this.mousemove.bind(this));
},
this
);
},
draw: function() {
var g = this.g;
var db = this.db;
var mp = this.mp;
g.clearRect(0, 0, this.cwidth, this.cheight);
g.strokeStyle = 'black';
g.beginPath();
g.moveTo(db[0].x.value, db[0].y.value);
g.lineTo(db[1].x.value, db[1].y.value);
g.lineTo(db[2].x.value, db[2].y.value);
// g.lineTo(db[3].x.value, db[3].y.value);
//g.closePath();
g.stroke();
// g.beginPath();
// g.moveTo(mp[0].x.value, mp[0].y.value);
// g.lineTo(mp[1].x.value, mp[1].y.value);
// g.lineTo(mp[2].x.value, mp[2].y.value);
// g.lineTo(mp[3].x.value, mp[3].y.value);
// g.closePath();
// g.stroke();
for (var a = 0; a < this.db.length; ++a) {
if (a == this.dbDragging) {
g.strokeStyle = 'blue';
}
db[a].draw(g);
if (a == this.dbDragging) {
g.strokeStyle = 'black';
}
}
},
});
function runit() {
var qd = new QuadDemo();
document.getElementById("append").innerHTML = ("<br/>" + qd.solver.getInternalInfo());
qd.draw();
qd.initEvents();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment