Show:

File: src/body/Body.js

                                /**
                                * The `Matter.Body` module contains methods for creating and manipulating rigid bodies.
                                * For creating bodies with common configurations such as rectangles, circles and other polygons see the module `Matter.Bodies`.
                                *
                                * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples).
                                
                                * @class Body
                                */
                                
                                var Body = {};
                                
                                module.exports = Body;
                                
                                var Vertices = require('../geometry/Vertices');
                                var Vector = require('../geometry/Vector');
                                var Sleeping = require('../core/Sleeping');
                                var Common = require('../core/Common');
                                var Bounds = require('../geometry/Bounds');
                                var Axes = require('../geometry/Axes');
                                
                                (function() {
                                
                                    Body._timeCorrection = true;
                                    Body._inertiaScale = 4;
                                    Body._nextCollidingGroupId = 1;
                                    Body._nextNonCollidingGroupId = -1;
                                    Body._nextCategory = 0x0001;
                                    Body._baseDelta = 1000 / 60;
                                
                                    /**
                                     * Creates a new rigid body model. The options parameter is an object that specifies any properties you wish to override the defaults.
                                     * All properties have default values, and many are pre-calculated automatically based on other properties.
                                     * Vertices must be specified in clockwise order.
                                     * See the properties section below for detailed information on what you can pass via the `options` object.
                                     * @method create
                                     * @param {} options
                                     * @return {body} body
                                     */
                                    Body.create = function(options) {
                                        var defaults = {
                                            id: Common.nextId(),
                                            type: 'body',
                                            label: 'Body',
                                            parts: [],
                                            plugin: {},
                                            angle: 0,
                                            vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
                                            position: { x: 0, y: 0 },
                                            force: { x: 0, y: 0 },
                                            torque: 0,
                                            positionImpulse: { x: 0, y: 0 },
                                            constraintImpulse: { x: 0, y: 0, angle: 0 },
                                            totalContacts: 0,
                                            speed: 0,
                                            angularSpeed: 0,
                                            velocity: { x: 0, y: 0 },
                                            angularVelocity: 0,
                                            isSensor: false,
                                            isStatic: false,
                                            isSleeping: false,
                                            motion: 0,
                                            sleepThreshold: 60,
                                            density: 0.001,
                                            restitution: 0,
                                            friction: 0.1,
                                            frictionStatic: 0.5,
                                            frictionAir: 0.01,
                                            collisionFilter: {
                                                category: 0x0001,
                                                mask: 0xFFFFFFFF,
                                                group: 0
                                            },
                                            slop: 0.05,
                                            timeScale: 1,
                                            render: {
                                                visible: true,
                                                opacity: 1,
                                                strokeStyle: null,
                                                fillStyle: null,
                                                lineWidth: null,
                                                sprite: {
                                                    xScale: 1,
                                                    yScale: 1,
                                                    xOffset: 0,
                                                    yOffset: 0
                                                }
                                            },
                                            events: null,
                                            bounds: null,
                                            chamfer: null,
                                            circleRadius: 0,
                                            positionPrev: null,
                                            anglePrev: 0,
                                            parent: null,
                                            axes: null,
                                            area: 0,
                                            mass: 0,
                                            inertia: 0,
                                            deltaTime: 1000 / 60,
                                            _original: null
                                        };
                                
                                        var body = Common.extend(defaults, options);
                                
                                        _initProperties(body, options);
                                
                                        return body;
                                    };
                                
                                    /**
                                     * Returns the next unique group index for which bodies will collide.
                                     * If `isNonColliding` is `true`, returns the next unique group index for which bodies will _not_ collide.
                                     * See `body.collisionFilter` for more information.
                                     * @method nextGroup
                                     * @param {bool} [isNonColliding=false]
                                     * @return {Number} Unique group index
                                     */
                                    Body.nextGroup = function(isNonColliding) {
                                        if (isNonColliding)
                                            return Body._nextNonCollidingGroupId--;
                                
                                        return Body._nextCollidingGroupId++;
                                    };
                                
                                    /**
                                     * Returns the next unique category bitfield (starting after the initial default category `0x0001`).
                                     * There are 32 available. See `body.collisionFilter` for more information.
                                     * @method nextCategory
                                     * @return {Number} Unique category bitfield
                                     */
                                    Body.nextCategory = function() {
                                        Body._nextCategory = Body._nextCategory << 1;
                                        return Body._nextCategory;
                                    };
                                
                                    /**
                                     * Initialises body properties.
                                     * @method _initProperties
                                     * @private
                                     * @param {body} body
                                     * @param {} [options]
                                     */
                                    var _initProperties = function(body, options) {
                                        options = options || {};
                                
                                        // init required properties (order is important)
                                        Body.set(body, {
                                            bounds: body.bounds || Bounds.create(body.vertices),
                                            positionPrev: body.positionPrev || Vector.clone(body.position),
                                            anglePrev: body.anglePrev || body.angle,
                                            vertices: body.vertices,
                                            parts: body.parts || [body],
                                            isStatic: body.isStatic,
                                            isSleeping: body.isSleeping,
                                            parent: body.parent || body
                                        });
                                
                                        Vertices.rotate(body.vertices, body.angle, body.position);
                                        Axes.rotate(body.axes, body.angle);
                                        Bounds.update(body.bounds, body.vertices, body.velocity);
                                
                                        // allow options to override the automatically calculated properties
                                        Body.set(body, {
                                            axes: options.axes || body.axes,
                                            area: options.area || body.area,
                                            mass: options.mass || body.mass,
                                            inertia: options.inertia || body.inertia
                                        });
                                
                                        // render properties
                                        var defaultFillStyle = (body.isStatic ? '#14151f' : Common.choose(['#f19648', '#f5d259', '#f55a3c', '#063e7b', '#ececd1'])),
                                            defaultStrokeStyle = body.isStatic ? '#555' : '#ccc',
                                            defaultLineWidth = body.isStatic && body.render.fillStyle === null ? 1 : 0;
                                        body.render.fillStyle = body.render.fillStyle || defaultFillStyle;
                                        body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;
                                        body.render.lineWidth = body.render.lineWidth || defaultLineWidth;
                                        body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);
                                        body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);
                                    };
                                
                                    /**
                                     * Given a property and a value (or map of), sets the property(s) on the body, using the appropriate setter functions if they exist.
                                     * Prefer to use the actual setter functions in performance critical situations.
                                     * @method set
                                     * @param {body} body
                                     * @param {} settings A property name (or map of properties and values) to set on the body.
                                     * @param {} value The value to set if `settings` is a single property name.
                                     */
                                    Body.set = function(body, settings, value) {
                                        var property;
                                
                                        if (typeof settings === 'string') {
                                            property = settings;
                                            settings = {};
                                            settings[property] = value;
                                        }
                                
                                        for (property in settings) {
                                            if (!Object.prototype.hasOwnProperty.call(settings, property))
                                                continue;
                                
                                            value = settings[property];
                                            switch (property) {
                                
                                            case 'isStatic':
                                                Body.setStatic(body, value);
                                                break;
                                            case 'isSleeping':
                                                Sleeping.set(body, value);
                                                break;
                                            case 'mass':
                                                Body.setMass(body, value);
                                                break;
                                            case 'density':
                                                Body.setDensity(body, value);
                                                break;
                                            case 'inertia':
                                                Body.setInertia(body, value);
                                                break;
                                            case 'vertices':
                                                Body.setVertices(body, value);
                                                break;
                                            case 'position':
                                                Body.setPosition(body, value);
                                                break;
                                            case 'angle':
                                                Body.setAngle(body, value);
                                                break;
                                            case 'velocity':
                                                Body.setVelocity(body, value);
                                                break;
                                            case 'angularVelocity':
                                                Body.setAngularVelocity(body, value);
                                                break;
                                            case 'speed':
                                                Body.setSpeed(body, value);
                                                break;
                                            case 'angularSpeed':
                                                Body.setAngularSpeed(body, value);
                                                break;
                                            case 'parts':
                                                Body.setParts(body, value);
                                                break;
                                            case 'centre':
                                                Body.setCentre(body, value);
                                                break;
                                            default:
                                                body[property] = value;
                                
                                            }
                                        }
                                    };
                                
                                    /**
                                     * Sets the body as static, including isStatic flag and setting mass and inertia to Infinity.
                                     * @method setStatic
                                     * @param {body} body
                                     * @param {bool} isStatic
                                     */
                                    Body.setStatic = function(body, isStatic) {
                                        for (var i = 0; i < body.parts.length; i++) {
                                            var part = body.parts[i];
                                            part.isStatic = isStatic;
                                
                                            if (isStatic) {
                                                part._original = {
                                                    restitution: part.restitution,
                                                    friction: part.friction,
                                                    mass: part.mass,
                                                    inertia: part.inertia,
                                                    density: part.density,
                                                    inverseMass: part.inverseMass,
                                                    inverseInertia: part.inverseInertia
                                                };
                                
                                                part.restitution = 0;
                                                part.friction = 1;
                                                part.mass = part.inertia = part.density = Infinity;
                                                part.inverseMass = part.inverseInertia = 0;
                                
                                                part.positionPrev.x = part.position.x;
                                                part.positionPrev.y = part.position.y;
                                                part.anglePrev = part.angle;
                                                part.angularVelocity = 0;
                                                part.speed = 0;
                                                part.angularSpeed = 0;
                                                part.motion = 0;
                                            } else if (part._original) {
                                                part.restitution = part._original.restitution;
                                                part.friction = part._original.friction;
                                                part.mass = part._original.mass;
                                                part.inertia = part._original.inertia;
                                                part.density = part._original.density;
                                                part.inverseMass = part._original.inverseMass;
                                                part.inverseInertia = part._original.inverseInertia;
                                
                                                part._original = null;
                                            }
                                        }
                                    };
                                
                                    /**
                                     * Sets the mass of the body. Inverse mass, density and inertia are automatically updated to reflect the change.
                                     * @method setMass
                                     * @param {body} body
                                     * @param {number} mass
                                     */
                                    Body.setMass = function(body, mass) {
                                        var moment = body.inertia / (body.mass / 6);
                                        body.inertia = moment * (mass / 6);
                                        body.inverseInertia = 1 / body.inertia;
                                
                                        body.mass = mass;
                                        body.inverseMass = 1 / body.mass;
                                        body.density = body.mass / body.area;
                                    };
                                
                                    /**
                                     * Sets the density of the body. Mass and inertia are automatically updated to reflect the change.
                                     * @method setDensity
                                     * @param {body} body
                                     * @param {number} density
                                     */
                                    Body.setDensity = function(body, density) {
                                        Body.setMass(body, density * body.area);
                                        body.density = density;
                                    };
                                
                                    /**
                                     * Sets the moment of inertia of the body. This is the second moment of area in two dimensions.
                                     * Inverse inertia is automatically updated to reflect the change. Mass is not changed.
                                     * @method setInertia
                                     * @param {body} body
                                     * @param {number} inertia
                                     */
                                    Body.setInertia = function(body, inertia) {
                                        body.inertia = inertia;
                                        body.inverseInertia = 1 / body.inertia;
                                    };
                                
                                    /**
                                     * Sets the body's vertices and updates body properties accordingly, including inertia, area and mass (with respect to `body.density`).
                                     * Vertices will be automatically transformed to be orientated around their centre of mass as the origin.
                                     * They are then automatically translated to world space based on `body.position`.
                                     *
                                     * The `vertices` argument should be passed as an array of `Matter.Vector` points (or a `Matter.Vertices` array).
                                     * Vertices must form a convex hull. Concave vertices must be decomposed into convex parts.
                                     * 
                                     * @method setVertices
                                     * @param {body} body
                                     * @param {vector[]} vertices
                                     */
                                    Body.setVertices = function(body, vertices) {
                                        // change vertices
                                        if (vertices[0].body === body) {
                                            body.vertices = vertices;
                                        } else {
                                            body.vertices = Vertices.create(vertices, body);
                                        }
                                
                                        // update properties
                                        body.axes = Axes.fromVertices(body.vertices);
                                        body.area = Vertices.area(body.vertices);
                                        Body.setMass(body, body.density * body.area);
                                
                                        // orient vertices around the centre of mass at origin (0, 0)
                                        var centre = Vertices.centre(body.vertices);
                                        Vertices.translate(body.vertices, centre, -1);
                                
                                        // update inertia while vertices are at origin (0, 0)
                                        Body.setInertia(body, Body._inertiaScale * Vertices.inertia(body.vertices, body.mass));
                                
                                        // update geometry
                                        Vertices.translate(body.vertices, body.position);
                                        Bounds.update(body.bounds, body.vertices, body.velocity);
                                    };
                                
                                    /**
                                     * Sets the parts of the `body` and updates mass, inertia and centroid.
                                     * Each part will have its parent set to `body`.
                                     * By default the convex hull will be automatically computed and set on `body`, unless `autoHull` is set to `false.`
                                     * Note that this method will ensure that the first part in `body.parts` will always be the `body`.
                                     * @method setParts
                                     * @param {body} body
                                     * @param {body[]} parts
                                     * @param {bool} [autoHull=true]
                                     */
                                    Body.setParts = function(body, parts, autoHull) {
                                        var i;
                                
                                        // add all the parts, ensuring that the first part is always the parent body
                                        parts = parts.slice(0);
                                        body.parts.length = 0;
                                        body.parts.push(body);
                                        body.parent = body;
                                
                                        for (i = 0; i < parts.length; i++) {
                                            var part = parts[i];
                                            if (part !== body) {
                                                part.parent = body;
                                                body.parts.push(part);
                                            }
                                        }
                                
                                        if (body.parts.length === 1)
                                            return;
                                
                                        autoHull = typeof autoHull !== 'undefined' ? autoHull : true;
                                
                                        // find the convex hull of all parts to set on the parent body
                                        if (autoHull) {
                                            var vertices = [];
                                            for (i = 0; i < parts.length; i++) {
                                                vertices = vertices.concat(parts[i].vertices);
                                            }
                                
                                            Vertices.clockwiseSort(vertices);
                                
                                            var hull = Vertices.hull(vertices),
                                                hullCentre = Vertices.centre(hull);
                                
                                            Body.setVertices(body, hull);
                                            Vertices.translate(body.vertices, hullCentre);
                                        }
                                
                                        // sum the properties of all compound parts of the parent body
                                        var total = Body._totalProperties(body);
                                
                                        body.area = total.area;
                                        body.parent = body;
                                        body.position.x = total.centre.x;
                                        body.position.y = total.centre.y;
                                        body.positionPrev.x = total.centre.x;
                                        body.positionPrev.y = total.centre.y;
                                
                                        Body.setMass(body, total.mass);
                                        Body.setInertia(body, total.inertia);
                                        Body.setPosition(body, total.centre);
                                    };
                                
                                    /**
                                     * Set the centre of mass of the body. 
                                     * The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation.
                                     * The centre of mass is the point the body rotates about and can be used to simulate non-uniform density.
                                     * This is equal to moving `body.position` but not the `body.vertices`.
                                     * Invalid if the `centre` falls outside the body's convex hull.
                                     * @method setCentre
                                     * @param {body} body
                                     * @param {vector} centre
                                     * @param {bool} relative
                                     */
                                    Body.setCentre = function(body, centre, relative) {
                                        if (!relative) {
                                            body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x);
                                            body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y);
                                            body.position.x = centre.x;
                                            body.position.y = centre.y;
                                        } else {
                                            body.positionPrev.x += centre.x;
                                            body.positionPrev.y += centre.y;
                                            body.position.x += centre.x;
                                            body.position.y += centre.y;
                                        }
                                    };
                                
                                    /**
                                     * Sets the position of the body. By default velocity is unchanged.
                                     * If `updateVelocity` is `true` then velocity is inferred from the change in position.
                                     * @method setPosition
                                     * @param {body} body
                                     * @param {vector} position
                                     * @param {boolean} [updateVelocity=false]
                                     */
                                    Body.setPosition = function(body, position, updateVelocity) {
                                        var delta = Vector.sub(position, body.position);
                                
                                        if (updateVelocity) {
                                            body.positionPrev.x = body.position.x;
                                            body.positionPrev.y = body.position.y;
                                            body.velocity.x = delta.x;
                                            body.velocity.y = delta.y;
                                            body.speed = Vector.magnitude(delta);
                                        } else {
                                            body.positionPrev.x += delta.x;
                                            body.positionPrev.y += delta.y;
                                        }
                                
                                        for (var i = 0; i < body.parts.length; i++) {
                                            var part = body.parts[i];
                                            part.position.x += delta.x;
                                            part.position.y += delta.y;
                                            Vertices.translate(part.vertices, delta);
                                            Bounds.update(part.bounds, part.vertices, body.velocity);
                                        }
                                    };
                                
                                    /**
                                     * Sets the angle of the body. By default angular velocity is unchanged.
                                     * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle.
                                     * @method setAngle
                                     * @param {body} body
                                     * @param {number} angle
                                     * @param {boolean} [updateVelocity=false]
                                     */
                                    Body.setAngle = function(body, angle, updateVelocity) {
                                        var delta = angle - body.angle;
                                        
                                        if (updateVelocity) {
                                            body.anglePrev = body.angle;
                                            body.angularVelocity = delta;
                                            body.angularSpeed = Math.abs(delta);
                                        } else {
                                            body.anglePrev += delta;
                                        }
                                
                                        for (var i = 0; i < body.parts.length; i++) {
                                            var part = body.parts[i];
                                            part.angle += delta;
                                            Vertices.rotate(part.vertices, delta, body.position);
                                            Axes.rotate(part.axes, delta);
                                            Bounds.update(part.bounds, part.vertices, body.velocity);
                                            if (i > 0) {
                                                Vector.rotateAbout(part.position, delta, body.position, part.position);
                                            }
                                        }
                                    };
                                
                                    /**
                                     * Sets the current linear velocity of the body.  
                                     * Affects body speed.
                                     * @method setVelocity
                                     * @param {body} body
                                     * @param {vector} velocity
                                     */
                                    Body.setVelocity = function(body, velocity) {
                                        var timeScale = body.deltaTime / Body._baseDelta;
                                        body.positionPrev.x = body.position.x - velocity.x * timeScale;
                                        body.positionPrev.y = body.position.y - velocity.y * timeScale;
                                        body.velocity.x = (body.position.x - body.positionPrev.x) / timeScale;
                                        body.velocity.y = (body.position.y - body.positionPrev.y) / timeScale;
                                        body.speed = Vector.magnitude(body.velocity);
                                    };
                                
                                    /**
                                     * Gets the current linear velocity of the body.
                                     * @method getVelocity
                                     * @param {body} body
                                     * @return {vector} velocity
                                     */
                                    Body.getVelocity = function(body) {
                                        var timeScale = Body._baseDelta / body.deltaTime;
                                
                                        return {
                                            x: (body.position.x - body.positionPrev.x) * timeScale,
                                            y: (body.position.y - body.positionPrev.y) * timeScale
                                        };
                                    };
                                
                                    /**
                                     * Gets the current linear speed of the body.  
                                     * Equivalent to the magnitude of its velocity.
                                     * @method getSpeed
                                     * @param {body} body
                                     * @return {number} speed
                                     */
                                    Body.getSpeed = function(body) {
                                        return Vector.magnitude(Body.getVelocity(body));
                                    };
                                
                                    /**
                                     * Sets the current linear speed of the body.  
                                     * Direction is maintained. Affects body velocity.
                                     * @method setSpeed
                                     * @param {body} body
                                     * @param {number} speed
                                     */
                                    Body.setSpeed = function(body, speed) {
                                        Body.setVelocity(body, Vector.mult(Vector.normalise(Body.getVelocity(body)), speed));
                                    };
                                
                                    /**
                                     * Sets the current rotational velocity of the body.  
                                     * Affects body angular speed.
                                     * @method setAngularVelocity
                                     * @param {body} body
                                     * @param {number} velocity
                                     */
                                    Body.setAngularVelocity = function(body, velocity) {
                                        var timeScale = body.deltaTime / Body._baseDelta;
                                        body.anglePrev = body.angle - velocity * timeScale;
                                        body.angularVelocity = (body.angle - body.anglePrev) / timeScale;
                                        body.angularSpeed = Math.abs(body.angularVelocity);
                                    };
                                
                                    /**
                                     * Gets the current rotational velocity of the body.
                                     * @method getAngularVelocity
                                     * @param {body} body
                                     * @return {number} angular velocity
                                     */
                                    Body.getAngularVelocity = function(body) {
                                        return (body.angle - body.anglePrev) * Body._baseDelta / body.deltaTime;
                                    };
                                
                                    /**
                                     * Gets the current rotational speed of the body.  
                                     * Equivalent to the magnitude of its angular velocity.
                                     * @method getAngularSpeed
                                     * @param {body} body
                                     * @return {number} angular speed
                                     */
                                    Body.getAngularSpeed = function(body) {
                                        return Math.abs(Body.getAngularVelocity(body));
                                    };
                                
                                    /**
                                     * Sets the current rotational speed of the body.  
                                     * Direction is maintained. Affects body angular velocity.
                                     * @method setAngularSpeed
                                     * @param {body} body
                                     * @param {number} speed
                                     */
                                    Body.setAngularSpeed = function(body, speed) {
                                        Body.setAngularVelocity(body, Common.sign(Body.getAngularVelocity(body)) * speed);
                                    };
                                
                                    /**
                                     * Moves a body by a given vector relative to its current position. By default velocity is unchanged.
                                     * If `updateVelocity` is `true` then velocity is inferred from the change in position.
                                     * @method translate
                                     * @param {body} body
                                     * @param {vector} translation
                                     * @param {boolean} [updateVelocity=false]
                                     */
                                    Body.translate = function(body, translation, updateVelocity) {
                                        Body.setPosition(body, Vector.add(body.position, translation), updateVelocity);
                                    };
                                
                                    /**
                                     * Rotates a body by a given angle relative to its current angle. By default angular velocity is unchanged.
                                     * If `updateVelocity` is `true` then angular velocity is inferred from the change in angle.
                                     * @method rotate
                                     * @param {body} body
                                     * @param {number} rotation
                                     * @param {vector} [point]
                                     * @param {boolean} [updateVelocity=false]
                                     */
                                    Body.rotate = function(body, rotation, point, updateVelocity) {
                                        if (!point) {
                                            Body.setAngle(body, body.angle + rotation, updateVelocity);
                                        } else {
                                            var cos = Math.cos(rotation),
                                                sin = Math.sin(rotation),
                                                dx = body.position.x - point.x,
                                                dy = body.position.y - point.y;
                                                
                                            Body.setPosition(body, {
                                                x: point.x + (dx * cos - dy * sin),
                                                y: point.y + (dx * sin + dy * cos)
                                            }, updateVelocity);
                                
                                            Body.setAngle(body, body.angle + rotation, updateVelocity);
                                        }
                                    };
                                
                                    /**
                                     * Scales the body, including updating physical properties (mass, area, axes, inertia), from a world-space point (default is body centre).
                                     * @method scale
                                     * @param {body} body
                                     * @param {number} scaleX
                                     * @param {number} scaleY
                                     * @param {vector} [point]
                                     */
                                    Body.scale = function(body, scaleX, scaleY, point) {
                                        var totalArea = 0,
                                            totalInertia = 0;
                                
                                        point = point || body.position;
                                
                                        for (var i = 0; i < body.parts.length; i++) {
                                            var part = body.parts[i];
                                
                                            // scale vertices
                                            Vertices.scale(part.vertices, scaleX, scaleY, point);
                                
                                            // update properties
                                            part.axes = Axes.fromVertices(part.vertices);
                                            part.area = Vertices.area(part.vertices);
                                            Body.setMass(part, body.density * part.area);
                                
                                            // update inertia (requires vertices to be at origin)
                                            Vertices.translate(part.vertices, { x: -part.position.x, y: -part.position.y });
                                            Body.setInertia(part, Body._inertiaScale * Vertices.inertia(part.vertices, part.mass));
                                            Vertices.translate(part.vertices, { x: part.position.x, y: part.position.y });
                                
                                            if (i > 0) {
                                                totalArea += part.area;
                                                totalInertia += part.inertia;
                                            }
                                
                                            // scale position
                                            part.position.x = point.x + (part.position.x - point.x) * scaleX;
                                            part.position.y = point.y + (part.position.y - point.y) * scaleY;
                                
                                            // update bounds
                                            Bounds.update(part.bounds, part.vertices, body.velocity);
                                        }
                                
                                        // handle parent body
                                        if (body.parts.length > 1) {
                                            body.area = totalArea;
                                
                                            if (!body.isStatic) {
                                                Body.setMass(body, body.density * totalArea);
                                                Body.setInertia(body, totalInertia);
                                            }
                                        }
                                
                                        // handle circles
                                        if (body.circleRadius) { 
                                            if (scaleX === scaleY) {
                                                body.circleRadius *= scaleX;
                                            } else {
                                                // body is no longer a circle
                                                body.circleRadius = null;
                                            }
                                        }
                                    };
                                
                                    /**
                                     * Performs an update by integrating the equations of motion on the `body`.
                                     * This is applied every update by `Matter.Engine` automatically.
                                     * @method update
                                     * @param {body} body
                                     * @param {number} [deltaTime=16.666]
                                     */
                                    Body.update = function(body, deltaTime) {
                                        deltaTime = (typeof deltaTime !== 'undefined' ? deltaTime : (1000 / 60)) * body.timeScale;
                                
                                        var deltaTimeSquared = deltaTime * deltaTime,
                                            correction = Body._timeCorrection ? deltaTime / (body.deltaTime || deltaTime) : 1;
                                
                                        // from the previous step
                                        var frictionAir = 1 - body.frictionAir * (deltaTime / Common._baseDelta),
                                            velocityPrevX = (body.position.x - body.positionPrev.x) * correction,
                                            velocityPrevY = (body.position.y - body.positionPrev.y) * correction;
                                
                                        // update velocity with Verlet integration
                                        body.velocity.x = (velocityPrevX * frictionAir) + (body.force.x / body.mass) * deltaTimeSquared;
                                        body.velocity.y = (velocityPrevY * frictionAir) + (body.force.y / body.mass) * deltaTimeSquared;
                                
                                        body.positionPrev.x = body.position.x;
                                        body.positionPrev.y = body.position.y;
                                        body.position.x += body.velocity.x;
                                        body.position.y += body.velocity.y;
                                        body.deltaTime = deltaTime;
                                
                                        // update angular velocity with Verlet integration
                                        body.angularVelocity = ((body.angle - body.anglePrev) * frictionAir * correction) + (body.torque / body.inertia) * deltaTimeSquared;
                                        body.anglePrev = body.angle;
                                        body.angle += body.angularVelocity;
                                
                                        // transform the body geometry
                                        for (var i = 0; i < body.parts.length; i++) {
                                            var part = body.parts[i];
                                
                                            Vertices.translate(part.vertices, body.velocity);
                                            
                                            if (i > 0) {
                                                part.position.x += body.velocity.x;
                                                part.position.y += body.velocity.y;
                                            }
                                
                                            if (body.angularVelocity !== 0) {
                                                Vertices.rotate(part.vertices, body.angularVelocity, body.position);
                                                Axes.rotate(part.axes, body.angularVelocity);
                                                if (i > 0) {
                                                    Vector.rotateAbout(part.position, body.angularVelocity, body.position, part.position);
                                                }
                                            }
                                
                                            Bounds.update(part.bounds, part.vertices, body.velocity);
                                        }
                                    };
                                
                                    /**
                                     * Updates properties `body.velocity`, `body.speed`, `body.angularVelocity` and `body.angularSpeed` which are normalised in relation to `Body._baseDelta`.
                                     * @method updateVelocities
                                     * @param {body} body
                                     */
                                    Body.updateVelocities = function(body) {
                                        var timeScale = Body._baseDelta / body.deltaTime,
                                            bodyVelocity = body.velocity;
                                
                                        bodyVelocity.x = (body.position.x - body.positionPrev.x) * timeScale;
                                        bodyVelocity.y = (body.position.y - body.positionPrev.y) * timeScale;
                                        body.speed = Math.sqrt((bodyVelocity.x * bodyVelocity.x) + (bodyVelocity.y * bodyVelocity.y));
                                
                                        body.angularVelocity = (body.angle - body.anglePrev) * timeScale;
                                        body.angularSpeed = Math.abs(body.angularVelocity);
                                    };
                                
                                    /**
                                     * Applies the `force` to the `body` from the force origin `position` in world-space, over a single timestep, including applying any resulting angular torque.
                                     * 
                                     * Forces are useful for effects like gravity, wind or rocket thrust, but can be difficult in practice when precise control is needed. In these cases see `Body.setVelocity` and `Body.setPosition` as an alternative.
                                     * 
                                     * The force from this function is only applied once for the duration of a single timestep, in other words the duration depends directly on the current engine update `delta` and the rate of calls to this function.
                                     * 
                                     * Therefore to account for time, you should apply the force constantly over as many engine updates as equivalent to the intended duration.
                                     * 
                                     * If all or part of the force duration is some fraction of a timestep, first multiply the force by `duration / timestep`.
                                     * 
                                     * The force origin `position` in world-space must also be specified. Passing `body.position` will result in zero angular effect as the force origin would be at the centre of mass.
                                     * 
                                     * The `body` will take time to accelerate under a force, the resulting effect depends on duration of the force, the body mass and other forces on the body including friction combined.
                                     * @method applyForce
                                     * @param {body} body
                                     * @param {vector} position The force origin in world-space. Pass `body.position` to avoid angular torque.
                                     * @param {vector} force
                                     */
                                    Body.applyForce = function(body, position, force) {
                                        var offset = { x: position.x - body.position.x, y: position.y - body.position.y };
                                        body.force.x += force.x;
                                        body.force.y += force.y;
                                        body.torque += offset.x * force.y - offset.y * force.x;
                                    };
                                
                                    /**
                                     * Returns the sums of the properties of all compound parts of the parent body.
                                     * @method _totalProperties
                                     * @private
                                     * @param {body} body
                                     * @return {}
                                     */
                                    Body._totalProperties = function(body) {
                                        // from equations at:
                                        // https://ecourses.ou.edu/cgi-bin/ebook.cgi?doc=&topic=st&chap_sec=07.2&page=theory
                                        // http://output.to/sideway/default.asp?qno=121100087
                                
                                        var properties = {
                                            mass: 0,
                                            area: 0,
                                            inertia: 0,
                                            centre: { x: 0, y: 0 }
                                        };
                                
                                        // sum the properties of all compound parts of the parent body
                                        for (var i = body.parts.length === 1 ? 0 : 1; i < body.parts.length; i++) {
                                            var part = body.parts[i],
                                                mass = part.mass !== Infinity ? part.mass : 1;
                                
                                            properties.mass += mass;
                                            properties.area += part.area;
                                            properties.inertia += part.inertia;
                                            properties.centre = Vector.add(properties.centre, Vector.mult(part.position, mass));
                                        }
                                
                                        properties.centre = Vector.div(properties.centre, properties.mass);
                                
                                        return properties;
                                    };
                                
                                    /*
                                    *
                                    *  Events Documentation
                                    *
                                    */
                                
                                    /**
                                    * Fired when a body starts sleeping (where `this` is the body).
                                    *
                                    * @event sleepStart
                                    * @this {body} The body that has started sleeping
                                    * @param {} event An event object
                                    * @param {} event.source The source object of the event
                                    * @param {} event.name The name of the event
                                    */
                                
                                    /**
                                    * Fired when a body ends sleeping (where `this` is the body).
                                    *
                                    * @event sleepEnd
                                    * @this {body} The body that has ended sleeping
                                    * @param {} event An event object
                                    * @param {} event.source The source object of the event
                                    * @param {} event.name The name of the event
                                    */
                                
                                    /*
                                    *
                                    *  Properties Documentation
                                    *
                                    */
                                
                                    /**
                                     * An integer `Number` uniquely identifying number generated in `Body.create` by `Common.nextId`.
                                     *
                                     * @property id
                                     * @type number
                                     */
                                
                                    /**
                                     * _Read only_. Set by `Body.create`.
                                     * 
                                     * A `String` denoting the type of object.
                                     *
                                     * @readOnly
                                     * @property type
                                     * @type string
                                     * @default "body"
                                     */
                                
                                    /**
                                     * An arbitrary `String` name to help the user identify and manage bodies.
                                     *
                                     * @property label
                                     * @type string
                                     * @default "Body"
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setParts` to set. 
                                     * 
                                     * An array of bodies that make up this body. 
                                     * The first body in the array must always be a self reference to the current body instance.
                                     * All bodies in the `parts` array together form a single rigid compound body.
                                     * Parts are allowed to overlap, have gaps or holes or even form concave bodies.
                                     * Parts themselves should never be added to a `World`, only the parent body should be.
                                     * Use `Body.setParts` when setting parts to ensure correct updates of all properties.
                                     *
                                     * @readOnly
                                     * @property parts
                                     * @type body[]
                                     */
                                
                                    /**
                                     * An object reserved for storing plugin-specific properties.
                                     *
                                     * @property plugin
                                     * @type {}
                                     */
                                
                                    /**
                                     * _Read only_. Updated by `Body.setParts`.
                                     * 
                                     * A reference to the body that this is a part of. See `body.parts`.
                                     * This is a self reference if the body is not a part of another body.
                                     *
                                     * @readOnly
                                     * @property parent
                                     * @type body
                                     */
                                
                                    /**
                                     * A `Number` specifying the angle of the body, in radians.
                                     *
                                     * @property angle
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setVertices` or `Body.setParts` to set. See also `Bodies.fromVertices`.
                                     * 
                                     * An array of `Vector` objects that specify the convex hull of the rigid body.
                                     * These should be provided about the origin `(0, 0)`. E.g.
                                     *
                                     * `[{ x: 0, y: 0 }, { x: 25, y: 50 }, { x: 50, y: 0 }]`
                                     * 
                                     * Vertices must always be convex, in clockwise order and must not contain any duplicate points.
                                     * 
                                     * Concave vertices should be decomposed into convex `parts`, see `Bodies.fromVertices` and `Body.setParts`.
                                     *
                                     * When set the vertices are translated such that `body.position` is at the centre of mass.
                                     * Many other body properties are automatically calculated from these vertices when set including `density`, `area` and `inertia`.
                                     * 
                                     * The module `Matter.Vertices` contains useful methods for working with vertices.
                                     *
                                     * @readOnly
                                     * @property vertices
                                     * @type vector[]
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setPosition` to set. 
                                     * 
                                     * A `Vector` that specifies the current world-space position of the body.
                                     * 
                                     * @readOnly
                                     * @property position
                                     * @type vector
                                     * @default { x: 0, y: 0 }
                                     */
                                
                                    /**
                                     * A `Vector` that accumulates the total force applied to the body for a single update.
                                     * Force is zeroed after every `Engine.update`, so constant forces should be applied for every update they are needed. See also `Body.applyForce`.
                                     * 
                                     * @property force
                                     * @type vector
                                     * @default { x: 0, y: 0 }
                                     */
                                
                                    /**
                                     * A `Number` that accumulates the total torque (turning force) applied to the body for a single update. See also `Body.applyForce`.
                                     * Torque is zeroed after every `Engine.update`, so constant torques should be applied for every update they are needed.
                                     *
                                     * Torques result in angular acceleration on every update, which depends on body inertia and the engine update delta.
                                     * 
                                     * @property torque
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setSpeed` to set. 
                                     * 
                                     * See `Body.getSpeed` for details.
                                     * 
                                     * Equivalent to the magnitude of `body.velocity` (always positive).
                                     * 
                                     * @readOnly
                                     * @property speed
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setVelocity` to set. 
                                     * 
                                     * See `Body.getVelocity` for details.
                                     * 
                                     * Equivalent to the magnitude of `body.angularVelocity` (always positive).
                                     * 
                                     * @readOnly
                                     * @property velocity
                                     * @type vector
                                     * @default { x: 0, y: 0 }
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setAngularSpeed` to set. 
                                     * 
                                     * See `Body.getAngularSpeed` for details.
                                     * 
                                     * 
                                     * @readOnly
                                     * @property angularSpeed
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setAngularVelocity` to set. 
                                     * 
                                     * See `Body.getAngularVelocity` for details.
                                     * 
                                     *
                                     * @readOnly
                                     * @property angularVelocity
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setStatic` to set. 
                                     * 
                                     * A flag that indicates whether a body is considered static. A static body can never change position or angle and is completely fixed.
                                     *
                                     * @readOnly
                                     * @property isStatic
                                     * @type boolean
                                     * @default false
                                     */
                                
                                    /**
                                     * A flag that indicates whether a body is a sensor. Sensor triggers collision events, but doesn't react with colliding body physically.
                                     *
                                     * @property isSensor
                                     * @type boolean
                                     * @default false
                                     */
                                
                                    /**
                                     * _Read only_. Use `Sleeping.set` to set. 
                                     * 
                                     * A flag that indicates whether the body is considered sleeping. A sleeping body acts similar to a static body, except it is only temporary and can be awoken.
                                     *
                                     * @readOnly
                                     * @property isSleeping
                                     * @type boolean
                                     * @default false
                                     */
                                
                                    /**
                                     * _Read only_. Calculated during engine update only when sleeping is enabled.
                                     * 
                                     * A `Number` that loosely measures the amount of movement a body currently has.
                                     *
                                     * Derived from `body.speed^2 + body.angularSpeed^2`. See `Sleeping.update`.
                                     * 
                                     * @readOnly
                                     * @property motion
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * A `Number` that defines the length of time during which this body must have near-zero velocity before it is set as sleeping by the `Matter.Sleeping` module (if sleeping is enabled by the engine).
                                     * 
                                     * @property sleepThreshold
                                     * @type number
                                     * @default 60
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setDensity` to set. 
                                     * 
                                     * A `Number` that defines the density of the body (mass per unit area).
                                     * 
                                     * Mass will also be updated when set.
                                     *
                                     * @readOnly
                                     * @property density
                                     * @type number
                                     * @default 0.001
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setMass` to set. 
                                     * 
                                     * A `Number` that defines the mass of the body.
                                     * 
                                     * Density will also be updated when set.
                                     * 
                                     * @readOnly
                                     * @property mass
                                     * @type number
                                     */
                                
                                    /**
                                     * _Read only_. Use `Body.setMass` to set. 
                                     * 
                                     * A `Number` that defines the inverse mass of the body (`1 / mass`).
                                     *
                                     * @readOnly
                                     * @property inverseMass
                                     * @type number
                                     */
                                
                                    /**
                                     * _Read only_. Automatically calculated when vertices, mass or density are set or set through `Body.setInertia`.
                                     * 
                                     * A `Number` that defines the moment of inertia of the body. This is the second moment of area in two dimensions.
                                     * 
                                     * Can be manually set to `Infinity` to prevent rotation of the body. See `Body.setInertia`.
                                     * 
                                     * @readOnly
                                     * @property inertia
                                     * @type number
                                     */
                                
                                    /**
                                     * _Read only_. Automatically calculated when vertices, mass or density are set or calculated by `Body.setInertia`.
                                     * 
                                     * A `Number` that defines the inverse moment of inertia of the body (`1 / inertia`).
                                     * 
                                     * @readOnly
                                     * @property inverseInertia
                                     * @type number
                                     */
                                
                                    /**
                                     * A `Number` that defines the restitution (elasticity) of the body. The value is always positive and is in the range `(0, 1)`.
                                     * A value of `0` means collisions may be perfectly inelastic and no bouncing may occur. 
                                     * A value of `0.8` means the body may bounce back with approximately 80% of its kinetic energy.
                                     * Note that collision response is based on _pairs_ of bodies, and that `restitution` values are _combined_ with the following formula:
                                     *
                                     * `Math.max(bodyA.restitution, bodyB.restitution)`
                                     *
                                     * @property restitution
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * A `Number` that defines the friction of the body. The value is always positive and is in the range `(0, 1)`.
                                     * A value of `0` means that the body may slide indefinitely.
                                     * A value of `1` means the body may come to a stop almost instantly after a force is applied.
                                     *
                                     * The effects of the value may be non-linear. 
                                     * High values may be unstable depending on the body.
                                     * The engine uses a Coulomb friction model including static and kinetic friction.
                                     * Note that collision response is based on _pairs_ of bodies, and that `friction` values are _combined_ with the following formula:
                                     *
                                     * `Math.min(bodyA.friction, bodyB.friction)`
                                     *
                                     * @property friction
                                     * @type number
                                     * @default 0.1
                                     */
                                
                                    /**
                                     * A `Number` that defines the static friction of the body (in the Coulomb friction model). 
                                     * A value of `0` means the body will never 'stick' when it is nearly stationary and only dynamic `friction` is used.
                                     * The higher the value (e.g. `10`), the more force it will take to initially get the body moving when nearly stationary.
                                     * This value is multiplied with the `friction` property to make it easier to change `friction` and maintain an appropriate amount of static friction.
                                     *
                                     * @property frictionStatic
                                     * @type number
                                     * @default 0.5
                                     */
                                
                                    /**
                                     * A `Number` that defines the air friction of the body (air resistance). 
                                     * A value of `0` means the body will never slow as it moves through space.
                                     * The higher the value, the faster a body slows when moving through space.
                                     * The effects of the value are non-linear. 
                                     *
                                     * @property frictionAir
                                     * @type number
                                     * @default 0.01
                                     */
                                
                                    /**
                                     * An `Object` that specifies the collision filtering properties of this body.
                                     *
                                     * Collisions between two bodies will obey the following rules:
                                     * - If the two bodies have the same non-zero value of `collisionFilter.group`,
                                     *   they will always collide if the value is positive, and they will never collide
                                     *   if the value is negative.
                                     * - If the two bodies have different values of `collisionFilter.group` or if one
                                     *   (or both) of the bodies has a value of 0, then the category/mask rules apply as follows:
                                     *
                                     * Each body belongs to a collision category, given by `collisionFilter.category`. This
                                     * value is used as a bit field and the category should have only one bit set, meaning that
                                     * the value of this property is a power of two in the range [1, 2^31]. Thus, there are 32
                                     * different collision categories available.
                                     *
                                     * Each body also defines a collision bitmask, given by `collisionFilter.mask` which specifies
                                     * the categories it collides with (the value is the bitwise AND value of all these categories).
                                     *
                                     * Using the category/mask rules, two bodies `A` and `B` collide if each includes the other's
                                     * category in its mask, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0`
                                     * are both true.
                                     *
                                     * @property collisionFilter
                                     * @type object
                                     */
                                
                                    /**
                                     * An Integer `Number`, that specifies the collision group this body belongs to.
                                     * See `body.collisionFilter` for more information.
                                     *
                                     * @property collisionFilter.group
                                     * @type object
                                     * @default 0
                                     */
                                
                                    /**
                                     * A bit field that specifies the collision category this body belongs to.
                                     * The category value should have only one bit set, for example `0x0001`.
                                     * This means there are up to 32 unique collision categories available.
                                     * See `body.collisionFilter` for more information.
                                     *
                                     * @property collisionFilter.category
                                     * @type object
                                     * @default 1
                                     */
                                
                                    /**
                                     * A bit mask that specifies the collision categories this body may collide with.
                                     * See `body.collisionFilter` for more information.
                                     *
                                     * @property collisionFilter.mask
                                     * @type object
                                     * @default -1
                                     */
                                
                                    /**
                                     * A `Number` that specifies a thin boundary around the body where it is allowed to slightly sink into other bodies.
                                     * 
                                     * This is required for proper collision response, including friction and restitution effects.
                                     * 
                                     * The default should generally suffice in most cases. You may need to decrease this value for very small bodies that are nearing the default value in scale.
                                     *
                                     * @property slop
                                     * @type number
                                     * @default 0.05
                                     */
                                
                                    /**
                                     * A `Number` that specifies per-body time scaling.
                                     *
                                     * @property timeScale
                                     * @type number
                                     * @default 1
                                     */
                                
                                    /**
                                     * _Read only_. Updated during engine update.
                                     * 
                                     * A `Number` that records the last delta time value used to update this body.
                                     * Used to calculate speed and velocity.
                                     *
                                     * @readOnly
                                     * @property deltaTime
                                     * @type number
                                     * @default 1000 / 60
                                     */
                                
                                    /**
                                     * An `Object` that defines the rendering properties to be consumed by the module `Matter.Render`.
                                     *
                                     * @property render
                                     * @type object
                                     */
                                
                                    /**
                                     * A flag that indicates if the body should be rendered.
                                     *
                                     * @property render.visible
                                     * @type boolean
                                     * @default true
                                     */
                                
                                    /**
                                     * Sets the opacity to use when rendering.
                                     *
                                     * @property render.opacity
                                     * @type number
                                     * @default 1
                                    */
                                
                                    /**
                                     * An `Object` that defines the sprite properties to use when rendering, if any.
                                     *
                                     * @property render.sprite
                                     * @type object
                                     */
                                
                                    /**
                                     * An `String` that defines the path to the image to use as the sprite texture, if any.
                                     *
                                     * @property render.sprite.texture
                                     * @type string
                                     */
                                     
                                    /**
                                     * A `Number` that defines the scaling in the x-axis for the sprite, if any.
                                     *
                                     * @property render.sprite.xScale
                                     * @type number
                                     * @default 1
                                     */
                                
                                    /**
                                     * A `Number` that defines the scaling in the y-axis for the sprite, if any.
                                     *
                                     * @property render.sprite.yScale
                                     * @type number
                                     * @default 1
                                     */
                                
                                    /**
                                      * A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width).
                                      *
                                      * @property render.sprite.xOffset
                                      * @type number
                                      * @default 0
                                      */
                                
                                    /**
                                      * A `Number` that defines the offset in the y-axis for the sprite (normalised by texture height).
                                      *
                                      * @property render.sprite.yOffset
                                      * @type number
                                      * @default 0
                                      */
                                
                                    /**
                                     * A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined).
                                     * A value of `0` means no outline will be rendered.
                                     *
                                     * @property render.lineWidth
                                     * @type number
                                     * @default 0
                                     */
                                
                                    /**
                                     * A `String` that defines the fill style to use when rendering the body (if a sprite is not defined).
                                     * It is the same as when using a canvas, so it accepts CSS style property values.
                                     *
                                     * @property render.fillStyle
                                     * @type string
                                     * @default a random colour
                                     */
                                
                                    /**
                                     * A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined).
                                     * It is the same as when using a canvas, so it accepts CSS style property values.
                                     *
                                     * @property render.strokeStyle
                                     * @type string
                                     * @default a random colour
                                     */
                                
                                    /**
                                     * _Read only_. Calculated automatically when vertices are set.
                                     * 
                                     * An array of unique axis vectors (edge normals) used for collision detection.
                                     * These are automatically calculated when vertices are set.
                                     * They are constantly updated by `Body.update` during the simulation.
                                     *
                                     * @readOnly
                                     * @property axes
                                     * @type vector[]
                                     */
                                     
                                    /**
                                     * _Read only_. Calculated automatically when vertices are set.
                                     * 
                                     * A `Number` that measures the area of the body's convex hull.
                                     * 
                                     * @readOnly
                                     * @property area
                                     * @type string
                                     * @default 
                                     */
                                
                                    /**
                                     * A `Bounds` object that defines the AABB region for the body.
                                     * It is automatically calculated when vertices are set and constantly updated by `Body.update` during simulation.
                                     * 
                                     * @property bounds
                                     * @type bounds
                                     */
                                
                                })();