UNPKG

p2s

Version:

A JavaScript 2D physics engine.

149 lines (123 loc) 4.02 kB
var Shape = require('./Shape') , vec2 = require('../math/vec2') , shallowClone = require('../utils/Utils').shallowClone; module.exports = Circle; /** * Circle shape class. * @class Circle * @extends Shape * @constructor * @param {options} [options] (Note that this options object will be passed on to the {{#crossLink "Shape"}}{{/crossLink}} constructor.) * @param {number} [options.radius=1] The radius of this circle * * @example * var body = new Body({ mass: 1 }); * var circleShape = new Circle({ * radius: 1 * }); * body.addShape(circleShape); */ function Circle(options){ options = options ? shallowClone(options) : {}; /** * The radius of the circle. * @property radius * @type {number} */ this.radius = options.radius !== undefined ? options.radius : 1; options.type = Shape.CIRCLE; Shape.call(this, options); } Circle.prototype = new Shape(); Circle.prototype.constructor = Circle; /** * @method computeMomentOfInertia * @return {Number} */ Circle.prototype.computeMomentOfInertia = function(){ var r = this.radius; return r * r / 2; }; /** * @method updateBoundingRadius * @return {Number} */ Circle.prototype.updateBoundingRadius = function(){ this.boundingRadius = this.radius; }; /** * @method updateArea * @return {Number} */ Circle.prototype.updateArea = function(){ this.area = Math.PI * this.radius * this.radius; }; /** * @method computeAABB * @param {AABB} out The resulting AABB. * @param {Array} position * @param {Number} angle */ Circle.prototype.computeAABB = function(out, position/*, angle*/){ var r = this.radius; vec2.set(out.upperBound, r, r); vec2.set(out.lowerBound, -r, -r); if(position){ vec2.add(out.lowerBound, out.lowerBound, position); vec2.add(out.upperBound, out.upperBound, position); } }; var Ray_intersectSphere_intersectionPoint = vec2.create(); var Ray_intersectSphere_normal = vec2.create(); /** * @method raycast * @param {RaycastResult} result * @param {Ray} ray * @param {array} position * @param {number} angle */ Circle.prototype.raycast = function(result, ray, position/*, angle*/){ var from = ray.from, to = ray.to, r = this.radius; var a = Math.pow(to[0] - from[0], 2) + Math.pow(to[1] - from[1], 2); var b = 2 * ((to[0] - from[0]) * (from[0] - position[0]) + (to[1] - from[1]) * (from[1] - position[1])); var c = Math.pow(from[0] - position[0], 2) + Math.pow(from[1] - position[1], 2) - Math.pow(r, 2); var delta = Math.pow(b, 2) - 4 * a * c; var intersectionPoint = Ray_intersectSphere_intersectionPoint; var normal = Ray_intersectSphere_normal; if(delta < 0){ // No intersection return; } else if(delta === 0){ // single intersection point vec2.lerp(intersectionPoint, from, to, delta); vec2.subtract(normal, intersectionPoint, position); vec2.normalize(normal,normal); ray.reportIntersection(result, delta, normal, -1); } else { var sqrtDelta = Math.sqrt(delta); var inv2a = 1 / (2 * a); var d1 = (- b - sqrtDelta) * inv2a; var d2 = (- b + sqrtDelta) * inv2a; if(d1 >= 0 && d1 <= 1){ vec2.lerp(intersectionPoint, from, to, d1); vec2.subtract(normal, intersectionPoint, position); vec2.normalize(normal,normal); ray.reportIntersection(result, d1, normal, -1); if(result.shouldStop(ray)){ return; } } if(d2 >= 0 && d2 <= 1){ vec2.lerp(intersectionPoint, from, to, d2); vec2.subtract(normal, intersectionPoint, position); vec2.normalize(normal,normal); ray.reportIntersection(result, d2, normal, -1); } } }; Circle.prototype.pointTest = function(localPoint){ var radius = this.radius; return vec2.squaredLength(localPoint) <= radius * radius; };