/** * The `Matter.Query` module contains methods for performing collision queries. * * See the included usage [examples](https://github.com/liabru/matter-js/tree/master/examples). * * @class Query */ var Query = {}; module.exports = Query; var Vector = require('../geometry/Vector'); var Collision = require('./Collision'); var Bounds = require('../geometry/Bounds'); var Bodies = require('../factory/Bodies'); var Vertices = require('../geometry/Vertices'); (function() { /** * Returns a list of collisions between `body` and `bodies`. * @method collides * @param {body} body * @param {body[]} bodies * @return {collision[]} Collisions */ Query.collides = function(body, bodies) { var collisions = [], bodiesLength = bodies.length, bounds = body.bounds, collides = Collision.collides, overlaps = Bounds.overlaps; for (var i = 0; i < bodiesLength; i++) { var bodyA = bodies[i], partsALength = bodyA.parts.length, partsAStart = partsALength === 1 ? 0 : 1; if (overlaps(bodyA.bounds, bounds)) { for (var j = partsAStart; j < partsALength; j++) { var part = bodyA.parts[j]; if (overlaps(part.bounds, bounds)) { var collision = collides(part, body); if (collision) { collisions.push(collision); break; } } } } } return collisions; }; /** * Casts a ray segment against a set of bodies and returns all collisions, ray width is optional. Intersection points are not provided. * @method ray * @param {body[]} bodies * @param {vector} startPoint * @param {vector} endPoint * @param {number} [rayWidth] * @return {collision[]} Collisions */ Query.ray = function(bodies, startPoint, endPoint, rayWidth) { rayWidth = rayWidth || 1e-100; var rayAngle = Vector.angle(startPoint, endPoint), rayLength = Vector.magnitude(Vector.sub(startPoint, endPoint)), rayX = (endPoint.x + startPoint.x) * 0.5, rayY = (endPoint.y + startPoint.y) * 0.5, ray = Bodies.rectangle(rayX, rayY, rayLength, rayWidth, { angle: rayAngle }), collisions = Query.collides(ray, bodies); for (var i = 0; i < collisions.length; i += 1) { var collision = collisions[i]; collision.body = collision.bodyB = collision.bodyA; } return collisions; }; /** * Returns all bodies whose bounds are inside (or outside if set) the given set of bounds, from the given set of bodies. * @method region * @param {body[]} bodies * @param {bounds} bounds * @param {bool} [outside=false] * @return {body[]} The bodies matching the query */ Query.region = function(bodies, bounds, outside) { var result = []; for (var i = 0; i < bodies.length; i++) { var body = bodies[i], overlaps = Bounds.overlaps(body.bounds, bounds); if ((overlaps && !outside) || (!overlaps && outside)) result.push(body); } return result; }; /** * Returns all bodies whose vertices contain the given point, from the given set of bodies. * @method point * @param {body[]} bodies * @param {vector} point * @return {body[]} The bodies matching the query */ Query.point = function(bodies, point) { var result = []; for (var i = 0; i < bodies.length; i++) { var body = bodies[i]; if (Bounds.contains(body.bounds, point)) { for (var j = body.parts.length === 1 ? 0 : 1; j < body.parts.length; j++) { var part = body.parts[j]; if (Bounds.contains(part.bounds, point) && Vertices.contains(part.vertices, point)) { result.push(body); break; } } } } return result; }; })();