/** * Flade - Flash Dynamics Engine * Release 0.4 alpha * AngularConstraint class * Copyright 2004, 2005 Alec Cove * * This file is part of Flade. The Flash Dynamics Engine. * * Flade is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Flade is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Flade; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Flash is a registered trademark of Macromedia */ AngularConstraint = function(pA, pB, pC) { this.pA = pA.curr; this.pB = pB.curr; this.pC = pC.curr; this.lineA = new Line(pA, pB); this.lineB = new Line(pB, pC); // lineC is the reference line for getting the angle of the line segments this.pD = new Vector(this.pB.x + 0, this.pB.y - 1); this.lineC = new Line(this.pB, this.pD); // theta to constrain to -- domain is -Math.PI to Math.PI this.targetTheta = this.calcTheta(this.pA, this.pB, this.pC); // coefficient of stiffness this.coeffStiff = 1; } AngularConstraint.prototype.resolve = function() { var center = this.getCentroid(); // make sure the reference line position gets updated this.lineC.p2.x = this.lineC.p1.x + 0; this.lineC.p2.y = this.lineC.p1.y - 1; var abRadius = this.pA.distance(this.pB); var bcRadius = this.pB.distance(this.pC); var thetaABC = this.calcTheta(this.pA, this.pB, this.pC); var thetaABD = this.calcTheta(this.pA, this.pB, this.pD); var thetaCBD = this.calcTheta(this.pC, this.pB, this.pD); var halfTheta = (this.targetTheta - thetaABC) / 2; var paTheta = thetaABD + halfTheta * this.coeffStiff; var pcTheta = thetaCBD - halfTheta * this.coeffStiff; this.pA.x = abRadius * Math.sin(paTheta) + this.pB.x; this.pA.y = abRadius * Math.cos(paTheta) + this.pB.y; this.pC.x = bcRadius * Math.sin(pcTheta) + this.pB.x; this.pC.y = bcRadius * Math.cos(pcTheta) + this.pB.y; // move corrected angle to pre corrected center var newCenter = this.getCentroid(); var dfx = newCenter.x - center.x; var dfy = newCenter.y - center.y; this.pA.x -= dfx; this.pA.y -= dfy; this.pB.x -= dfx; this.pB.y -= dfy; this.pC.x -= dfx; this.pC.y -= dfy; } AngularConstraint.prototype.calcTheta = function(pa, pb, pc) { var AB = new Vector(pb.x - pa.x, pb.y - pa.y); var BC = new Vector(pc.x - pb.x, pc.y - pb.y); var dotProd = AB.dot(BC); var crossProd = AB.cross(BC); return Math.atan2(crossProd, dotProd); } AngularConstraint.prototype.setTheta = function(t) { this.targetTheta = t; } AngularConstraint.prototype.getTheta = function(t) { return this.targetTheta; } AngularConstraint.prototype.paint = function() { // do nothing (except just maintain the constraint interface) } AngularConstraint.prototype.getCentroid = function() { var avgX = (this.pA.x + this.pB.x + this.pC.x) / 3; var avgY = (this.pA.y + this.pB.y + this.pC.y) / 3; return new Vector(avgX, avgY); } // Line helper object Line = function(p1, p2) { this.p1 = p1; this.p2 = p2; }