From 1b59cedcfeea7f63e951e5b50298d6f6a26aa60f Mon Sep 17 00:00:00 2001 From: florianvazelle Date: Wed, 20 Feb 2019 14:28:50 +0100 Subject: [PATCH 1/3] Add out argument in intersect functions --- src/geom/intersects/CircleToCircle.js | 74 +++++++++- src/geom/intersects/CircleToRectangle.js | 49 ++++--- src/geom/intersects/LineToCircle.js | 153 +++++++++++++++----- src/geom/intersects/LineToRectangle.js | 83 ++++------- src/geom/intersects/RectangleToRectangle.js | 35 ++++- src/geom/intersects/RectangleToTriangle.js | 74 +++------- src/geom/intersects/TriangleToCircle.js | 46 +++--- src/geom/intersects/TriangleToLine.js | 49 ++++--- src/geom/intersects/TriangleToTriangle.js | 72 ++++----- 9 files changed, 371 insertions(+), 264 deletions(-) diff --git a/src/geom/intersects/CircleToCircle.js b/src/geom/intersects/CircleToCircle.js index 2a0efcf2a..c8116879d 100644 --- a/src/geom/intersects/CircleToCircle.js +++ b/src/geom/intersects/CircleToCircle.js @@ -4,6 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var Point = require('../point/Point'); +var Equals = require('../circle/Equals'); var DistanceBetween = require('../../math/distance/DistanceBetween'); /** @@ -14,12 +16,80 @@ var DistanceBetween = require('../../math/distance/DistanceBetween'); * * @param {Phaser.Geom.Circle} circleA - The first Circle to check for intersection. * @param {Phaser.Geom.Circle} circleB - The second Circle to check for intersection. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two Circles intersect, otherwise `false`. */ -var CircleToCircle = function (circleA, circleB) +var CircleToCircle = function (circleA, circleB, out) { - return (DistanceBetween(circleA.x, circleA.y, circleB.x, circleB.y) <= (circleA.radius + circleB.radius)); + if (out === undefined) { out = []; } + + var x0 = circleA.x; + var y0 = circleA.y; + var r0 = circleA.radius; + + var x1 = circleB.x; + var y1 = circleB.y; + var r1 = circleB.radius; + + // To optimise, if there's no intersection or if the two circles are identical, then we return false + + if (!(DistanceBetween(x0, y0, x1, y1) <= (r0 + r1))) { return false; } + + if (Equals(circleA, circleB)) { return false; } + + var a, b, c, lambda, x; + + if (y0 === y1) + { + x = (r1 * r1) - (r0 * r0) - (x1 * x1) + (x0 * x0); + + a = 1; + b = -2 * y1; + c = (x1 * x1) + (x * x) - (2 * x1 * x) + (y1 * y1) - (r1 * r1); + + lambda = (b * b) - (4 * a * c); + + if (lambda < 0) { return false; } + else if (lambda === 0) + { + out.push(new Point(x, (-b / (2 * a)))); + return true; + } + else + { + out.push(new Point(x, (-b + Math.sqrt(lambda)) / (2 * a))); + out.push(new Point(x, (-b - Math.sqrt(lambda)) / (2 * a))); + return true; + } + } + else + { + var v1 = (x0 - x1) / (y0 - y1); + var n = (r1 * r1 - r0 * r0 - x1 * x1 + x0 * x0 - y1 * y1 + y0 * y0) / (2 * (y0 - y1)); + + a = (v1 * v1) + 1; + b = (2 * y0 * v1) - (2 * n * v1) - (2 * x0); + c = (x0 * x0) + (y0 * y0) + (n * n) - (r0 * r0) - (2 * y0 * n); + + lambda = (b * b) - (4 * a * c); + + if (lambda < 0) { return false; } + else if (lambda === 0) + { + x = (-b / (2 * a)); + out.push(new Point(x, (n - (x * v1)))); + return true; + } + else + { + x = (-b + Math.sqrt(lambda)) / (2 * a); + out.push(new Point(x, (n - (x * v1)))); + x = (-b - Math.sqrt(lambda)) / (2 * a); + out.push(new Point(x, (n - (x * v1)))); + return true; + } + } }; module.exports = CircleToCircle; diff --git a/src/geom/intersects/CircleToRectangle.js b/src/geom/intersects/CircleToRectangle.js index 2221cffe9..ff7109f0b 100644 --- a/src/geom/intersects/CircleToRectangle.js +++ b/src/geom/intersects/CircleToRectangle.js @@ -4,6 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var LineToCircle = require('./LineToCircle'); + /** * Checks for intersection between a circle and a rectangle. * @@ -12,37 +14,38 @@ * * @param {Phaser.Geom.Circle} circle - The circle to be checked. * @param {Phaser.Geom.Rectangle} rect - The rectangle to be checked. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two objects intersect, otherwise `false`. */ -var CircleToRectangle = function (circle, rect) +var CircleToRectangle = function (circle, rect, out) { - var halfWidth = rect.width / 2; - var halfHeight = rect.height / 2; + if (out === undefined) { out = []; } - var cx = Math.abs(circle.x - rect.x - halfWidth); - var cy = Math.abs(circle.y - rect.y - halfHeight); - var xDist = halfWidth + circle.radius; - var yDist = halfHeight + circle.radius; + var oriLength = out.length; - if (cx > xDist || cy > yDist) - { - return false; - } - else if (cx <= halfWidth || cy <= halfHeight) - { - return true; - } - else - { - var xCornerDist = cx - halfWidth; - var yCornerDist = cy - halfHeight; - var xCornerDistSq = xCornerDist * xCornerDist; - var yCornerDistSq = yCornerDist * yCornerDist; - var maxCornerDistSq = circle.radius * circle.radius; + var lineA = rect.getLineA(); + var lineB = rect.getLineB(); + var lineC = rect.getLineC(); + var lineD = rect.getLineD(); - return (xCornerDistSq + yCornerDistSq <= maxCornerDistSq); + var output = [ [], [], [], [] ]; + + var res = [ + LineToCircle(lineA, circle, output[0]), + LineToCircle(lineB, circle, output[1]), + LineToCircle(lineC, circle, output[2]), + LineToCircle(lineD, circle, output[3]) + ]; + + for (var i = 0; i < 4; i++) + { + if (res[i] && output !== []) { out.concat(output[i]); } } + + if (out.length - oriLength > 0) { return true; } + else if (res[0] || res[1] || res[2] || res[3]) { return true; } + else { return false; } }; module.exports = CircleToRectangle; diff --git a/src/geom/intersects/LineToCircle.js b/src/geom/intersects/LineToCircle.js index 61c896f80..0e27cd774 100644 --- a/src/geom/intersects/LineToCircle.js +++ b/src/geom/intersects/LineToCircle.js @@ -4,6 +4,7 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ + var Contains = require('../circle/Contains'); var Point = require('../point/Point'); @@ -20,59 +21,143 @@ var tmp = new Point(); * @param {Phaser.Geom.Line} line - The line segment to check. * @param {Phaser.Geom.Circle} circle - The circle to check against the line. * @param {(Phaser.Geom.Point|any)} [nearest] - An optional Point-like object. If given the closest point on the Line where the circle intersects will be stored in this object. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two objects intersect, otherwise `false`. */ -var LineToCircle = function (line, circle, nearest) +var LineToCircle = function (line, circle, nearest, out) { if (nearest === undefined) { nearest = tmp; } + if (out === undefined) { out = []; } - if (Contains(circle, line.x1, line.y1)) + var lx0 = line.x1; + var ly0 = line.y1; + + var lx1 = line.x2; + var ly1 = line.y2; + + var cx = circle.x; + var cy = circle.y; + var cr = circle.radius; + + var output = false; + + // define nearest + if (Contains(circle, lx0, ly0)) { - nearest.x = line.x1; - nearest.y = line.y1; + nearest.x = lx0; + nearest.y = ly0; - return true; + output = true; + } + else if (Contains(circle, lx1, ly1)) + { + nearest.x = lx1; + nearest.y = ly1; + + output = true; + } + else + { + var dx = lx1 - lx0; + var dy = ly1 - ly0; + + var lcx = cx - lx0; + var lcy = cy - ly0; + + // project lc onto d, resulting in vector p + var dLen2 = (dx * dx) + (dy * dy); + var px = dx; + var py = dy; + + if (dLen2 > 0) + { + var dp = ((lcx * dx) + (lcy * dy)) / dLen2; + + px *= dp; + py *= dp; + } + + nearest.x = lx0 + px; + nearest.y = ly0 + py; + + // len2 of p + var pLen2 = (px * px) + (py * py); + + output = (pLen2 <= dLen2 && + ((px * dx) + (py * dy)) >= 0 && + Contains(circle, nearest.x, nearest.y)); } - if (Contains(circle, line.x2, line.y2)) - { - nearest.x = line.x2; - nearest.y = line.y2; + if (!output) { return output; } - return true; + // We determine the line equation + + var m, p; + + if (lx0 === lx1) + { + m = lx0; + p = 0; + } + else + { + m = (ly1 - ly0) / (lx1 - lx0); + p = ly0 - m * lx0; } - var dx = line.x2 - line.x1; - var dy = line.y2 - line.y1; + var a = (m * m) + 1; + var b = (-2 * cx) - (2 * cy * m) + (2 * m * p); + var c = (cx * cx) + (cy * cy) + (p * p) - (cr * cr) - (2 * cy * p); - var lcx = circle.x - line.x1; - var lcy = circle.y - line.y1; + var lambda = (b * b) - (4 * a * c); - // project lc onto d, resulting in vector p - var dLen2 = (dx * dx) + (dy * dy); - var px = dx; - var py = dy; + var x, y; - if (dLen2 > 0) + var minx = Math.min(lx0, lx1); + var miny = Math.min(ly0, ly1); + + var maxx = Math.max(lx0, lx1); + var maxy = Math.max(ly0, ly1); + + if (lambda === 0) { - var dp = ((lcx * dx) + (lcy * dy)) / dLen2; - - px *= dp; - py *= dp; + x = (-b / (2 * a)); + y = ((m * x) + p); + if (Math.min(minx, x) === minx && + Math.min(miny, y) === miny && + Math.max(maxx, x) === maxx && + Math.max(maxy, y) === maxy) + { + out.push(new Point(x, y)); + output = true; + } } + else if (lambda > 0) + { + x = (-b + Math.sqrt(lambda)) / (2 * a); + y = ((m * x) + p); + if (Math.min(minx, x) === minx && + Math.min(miny, y) === miny && + Math.max(maxx, x) === maxx && + Math.max(maxy, y) === maxy) + { + out.push(new Point(x, y)); + output = true; + } - nearest.x = line.x1 + px; - nearest.y = line.y1 + py; - - // len2 of p - var pLen2 = (px * px) + (py * py); - - return ( - pLen2 <= dLen2 && - ((px * dx) + (py * dy)) >= 0 && - Contains(circle, nearest.x, nearest.y) - ); + x = (-b - Math.sqrt(lambda)) / (2 * a); + y = ((m * x) + p); + if (Math.min(minx, x) === minx && + Math.min(miny, y) === miny && + Math.max(maxx, x) === maxx && + Math.max(maxy, y) === maxy) + { + out.push(new Point(x, y)); + output = true; + } + } + return output; }; module.exports = LineToCircle; diff --git a/src/geom/intersects/LineToRectangle.js b/src/geom/intersects/LineToRectangle.js index 3197da67b..6848d29e5 100644 --- a/src/geom/intersects/LineToRectangle.js +++ b/src/geom/intersects/LineToRectangle.js @@ -4,6 +4,10 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var Point = require('../point/Point'); +var LineToLine = require('./LineToLine'); +var ContainsPoint = require('../rectangle/ContainsPoint'); + /** * Checks for intersection between the Line and a Rectangle shape, or a rectangle-like * object, with public `x`, `y`, `right` and `bottom` properties, such as a Sprite or Body. @@ -20,76 +24,39 @@ * * @param {Phaser.Geom.Line} line - The Line to check for intersection. * @param {(Phaser.Geom.Rectangle|object)} rect - The Rectangle to check for intersection. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Line and the Rectangle intersect, `false` otherwise. */ -var LineToRectangle = function (line, rect) +var LineToRectangle = function (line, rect, out) { - var x1 = line.x1; - var y1 = line.y1; + if (out === undefined) { out = []; } - var x2 = line.x2; - var y2 = line.y2; + var oriLength = out.length; - var bx1 = rect.x; - var by1 = rect.y; - var bx2 = rect.right; - var by2 = rect.bottom; + var lineA = rect.getLineA(); + var lineB = rect.getLineB(); + var lineC = rect.getLineC(); + var lineD = rect.getLineD(); - var t = 0; + var output = [ new Point(), new Point(), new Point(), new Point() ]; - // If the start or end of the line is inside the rect then we assume - // collision, as rects are solid for our use-case. + var res = [ + LineToLine(lineA, line, output[0]), + LineToLine(lineB, line, output[1]), + LineToLine(lineC, line, output[2]), + LineToLine(lineD, line, output[3]) + ]; - if ((x1 >= bx1 && x1 <= bx2 && y1 >= by1 && y1 <= by2) || - (x2 >= bx1 && x2 <= bx2 && y2 >= by1 && y2 <= by2)) + for (var i = 0; i < 4; i++) { - return true; + if (res[i]) { out.push(output[i]); } } - if (x1 < bx1 && x2 >= bx1) - { - // Left edge - t = y1 + (y2 - y1) * (bx1 - x1) / (x2 - x1); - - if (t > by1 && t <= by2) - { - return true; - } - } - else if (x1 > bx2 && x2 <= bx2) - { - // Right edge - t = y1 + (y2 - y1) * (bx2 - x1) / (x2 - x1); - - if (t >= by1 && t <= by2) - { - return true; - } - } - - if (y1 < by1 && y2 >= by1) - { - // Top edge - t = x1 + (x2 - x1) * (by1 - y1) / (y2 - y1); - - if (t >= bx1 && t <= bx2) - { - return true; - } - } - else if (y1 > by2 && y2 <= by2) - { - // Bottom edge - t = x1 + (x2 - x1) * (by2 - y1) / (y2 - y1); - - if (t >= bx1 && t <= bx2) - { - return true; - } - } - - return false; + if (out.length - oriLength > 0) { return true; } + else if (ContainsPoint(rect, line.getPointA()) || + ContainsPoint(rect, line.getPointB())) { return true; } + else { return false; } }; module.exports = LineToRectangle; diff --git a/src/geom/intersects/RectangleToRectangle.js b/src/geom/intersects/RectangleToRectangle.js index 0c615f52b..abc0ed169 100644 --- a/src/geom/intersects/RectangleToRectangle.js +++ b/src/geom/intersects/RectangleToRectangle.js @@ -4,6 +4,9 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ +var Equals = require('../rectangle/Equals'); +var LineToRectangle = require('./LineToRectangle'); + /** * Checks if two Rectangles intersect. * @@ -14,17 +17,45 @@ * * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check for intersection. * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check for intersection. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two Rectangles intersect, otherwise `false`. */ -var RectangleToRectangle = function (rectA, rectB) +var RectangleToRectangle = function (rectA, rectB, out) { + if (out === undefined) { out = []; } + + if (Equals(rectA, rectB)) { return false; } + if (rectA.width <= 0 || rectA.height <= 0 || rectB.width <= 0 || rectB.height <= 0) { return false; } - return !(rectA.right < rectB.x || rectA.bottom < rectB.y || rectA.x > rectB.right || rectA.y > rectB.bottom); + if (!(rectA.right < rectB.x || rectA.bottom < rectB.y || rectA.x > rectB.right || rectA.y > rectB.bottom)) + { + var lineA = rectA.getLineA(); + var lineB = rectA.getLineB(); + var lineC = rectA.getLineC(); + var lineD = rectA.getLineD(); + + var output = [ [], [], [], [] ]; + + var res = [ + LineToRectangle(lineA, rectB, output[0]), + LineToRectangle(lineB, rectB, output[1]), + LineToRectangle(lineC, rectB, output[2]), + LineToRectangle(lineD, rectB, output[3]) + ]; + + for (var i = 0; i < 4; i++) + { + if (res[i] && output !== []) { out.concat(output[i]); } + } + + return true; + } + return false; }; module.exports = RectangleToRectangle; diff --git a/src/geom/intersects/RectangleToTriangle.js b/src/geom/intersects/RectangleToTriangle.js index 7c62ddfa9..6d85779b4 100644 --- a/src/geom/intersects/RectangleToTriangle.js +++ b/src/geom/intersects/RectangleToTriangle.js @@ -4,10 +4,7 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var LineToLine = require('./LineToLine'); -var Contains = require('../rectangle/Contains'); -var ContainsArray = require('../triangle/ContainsArray'); -var Decompose = require('../rectangle/Decompose'); +var LineToRectangle = require('./LineToRectangle'); /** * Checks for intersection between Rectangle shape and Triangle shape. @@ -17,15 +14,15 @@ var Decompose = require('../rectangle/Decompose'); * * @param {Phaser.Geom.Rectangle} rect - Rectangle object to test. * @param {Phaser.Geom.Triangle} triangle - Triangle object to test. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} A value of `true` if objects intersect; otherwise `false`. */ -var RectangleToTriangle = function (rect, triangle) +var RectangleToTriangle = function (rect, triangle, out) { - // First the cheapest ones: + if (out === undefined) { out = []; } - if ( - triangle.left > rect.right || + if (triangle.left > rect.right || triangle.right < rect.left || triangle.top > rect.bottom || triangle.bottom < rect.top) @@ -33,55 +30,28 @@ var RectangleToTriangle = function (rect, triangle) return false; } - var triA = triangle.getLineA(); - var triB = triangle.getLineB(); - var triC = triangle.getLineC(); + var oriLength = out.length; - // Are any of the triangle points within the rectangle? + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); - if (Contains(rect, triA.x1, triA.y1) || Contains(rect, triA.x2, triA.y2)) + var output = [ [], [], [] ]; + + var res = [ + LineToRectangle(lineA, rect, output[0]), + LineToRectangle(lineB, rect, output[1]), + LineToRectangle(lineC, rect, output[2]) + ]; + + for (var i = 0; i < 3; i++) { - return true; + if (res[i] && output[i] !== []) { out.concat(output[i]); } } - if (Contains(rect, triB.x1, triB.y1) || Contains(rect, triB.x2, triB.y2)) - { - return true; - } - - if (Contains(rect, triC.x1, triC.y1) || Contains(rect, triC.x2, triC.y2)) - { - return true; - } - - // Cheap tests over, now to see if any of the lines intersect ... - - var rectA = rect.getLineA(); - var rectB = rect.getLineB(); - var rectC = rect.getLineC(); - var rectD = rect.getLineD(); - - if (LineToLine(triA, rectA) || LineToLine(triA, rectB) || LineToLine(triA, rectC) || LineToLine(triA, rectD)) - { - return true; - } - - if (LineToLine(triB, rectA) || LineToLine(triB, rectB) || LineToLine(triB, rectC) || LineToLine(triB, rectD)) - { - return true; - } - - if (LineToLine(triC, rectA) || LineToLine(triC, rectB) || LineToLine(triC, rectC) || LineToLine(triC, rectD)) - { - return true; - } - - // None of the lines intersect, so are any rectangle points within the triangle? - - var points = Decompose(rect); - var within = ContainsArray(triangle, points, true); - - return (within.length > 0); + if (out.length - oriLength > 0) { return true; } + else if (res[0] || res[1] || res[2]) { return true; } + else { return false; } }; module.exports = RectangleToTriangle; diff --git a/src/geom/intersects/TriangleToCircle.js b/src/geom/intersects/TriangleToCircle.js index 0dbff8cce..ae2f8e435 100644 --- a/src/geom/intersects/TriangleToCircle.js +++ b/src/geom/intersects/TriangleToCircle.js @@ -5,7 +5,6 @@ */ var LineToCircle = require('./LineToCircle'); -var Contains = require('../triangle/Contains'); /** * Checks if a Triangle and a Circle intersect. @@ -17,15 +16,15 @@ var Contains = require('../triangle/Contains'); * * @param {Phaser.Geom.Triangle} triangle - The Triangle to check for intersection. * @param {Phaser.Geom.Circle} circle - The Circle to check for intersection. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Triangle and the `Circle` intersect, otherwise `false`. */ -var TriangleToCircle = function (triangle, circle) +var TriangleToCircle = function (triangle, circle, out) { - // First the cheapest ones: + if (out === undefined) { out = []; } - if ( - triangle.left > circle.right || + if (triangle.left > circle.right || triangle.right < circle.left || triangle.top > circle.bottom || triangle.bottom < circle.top) @@ -33,27 +32,28 @@ var TriangleToCircle = function (triangle, circle) return false; } - if (Contains(triangle, circle.x, circle.y)) + var oriLength = out.length; + + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + var output = [ [], [], [] ]; + + var res = [ + LineToCircle(lineA, circle, output[0]), + LineToCircle(lineB, circle, output[1]), + LineToCircle(lineC, circle, output[2]) + ]; + + for (var i = 0; i < 3; i++) { - return true; + if (res[i] && output !== []) { out.concat(output[i]); } } - if (LineToCircle(triangle.getLineA(), circle)) - { - return true; - } - - if (LineToCircle(triangle.getLineB(), circle)) - { - return true; - } - - if (LineToCircle(triangle.getLineC(), circle)) - { - return true; - } - - return false; + if (out.length - oriLength > 0) { return true; } + else if (res[0] || res[1] || res[2]) { return true; } + else { return false; } }; module.exports = TriangleToCircle; diff --git a/src/geom/intersects/TriangleToLine.js b/src/geom/intersects/TriangleToLine.js index 657e2b06f..2a9b73dda 100644 --- a/src/geom/intersects/TriangleToLine.js +++ b/src/geom/intersects/TriangleToLine.js @@ -4,12 +4,13 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Contains = require('../triangle/Contains'); +var Point = require('../point/Point'); var LineToLine = require('./LineToLine'); +var ContainsPoint = require('../triangle/ContainsPoint'); /** * Checks if a Triangle and a Line intersect. - * + * * The Line intersects the Triangle if it starts inside of it, ends inside of it, or crosses any of the Triangle's sides. Thus, the Triangle is considered "solid". * * @function Phaser.Geom.Intersects.TriangleToLine @@ -17,34 +18,36 @@ var LineToLine = require('./LineToLine'); * * @param {Phaser.Geom.Triangle} triangle - The Triangle to check with. * @param {Phaser.Geom.Line} line - The Line to check with. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Triangle and the Line intersect, otherwise `false`. */ -var TriangleToLine = function (triangle, line) +var TriangleToLine = function (triangle, line, out) { - // If the Triangle contains either the start or end point of the line, it intersects - if (Contains(triangle, line.getPointA()) || Contains(triangle, line.getPointB())) + if (out === undefined) { out = []; } + var oriLength = out.length; + + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + var output = [ new Point(), new Point(), new Point() ]; + + var res = [ + LineToLine(lineA, line, output[0]), + LineToLine(lineB, line, output[1]), + LineToLine(lineC, line, output[2]) + ]; + + for (var i = 0; i < 3; i++) { - return true; + if (res[i] && output !== []) { out.push(output[i]); } } - // Now check the line against each line of the Triangle - if (LineToLine(triangle.getLineA(), line)) - { - return true; - } - - if (LineToLine(triangle.getLineB(), line)) - { - return true; - } - - if (LineToLine(triangle.getLineC(), line)) - { - return true; - } - - return false; + if (out.length - oriLength > 0) { return true; } + else if (ContainsPoint(triangle, line.getPointA()) || + ContainsPoint(triangle, line.getPointB())) { return true; } + else { return false; } }; module.exports = TriangleToLine; diff --git a/src/geom/intersects/TriangleToTriangle.js b/src/geom/intersects/TriangleToTriangle.js index 58e744e3e..8a1c5bfb5 100644 --- a/src/geom/intersects/TriangleToTriangle.js +++ b/src/geom/intersects/TriangleToTriangle.js @@ -4,9 +4,8 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var ContainsArray = require('../triangle/ContainsArray'); -var Decompose = require('../triangle/Decompose'); -var LineToLine = require('./LineToLine'); +var Equals = require('../triangle/Equals'); +var TriangleToLine = require('./TriangleToLine'); /** * Checks if two Triangles intersect. @@ -18,15 +17,15 @@ var LineToLine = require('./LineToLine'); * * @param {Phaser.Geom.Triangle} triangleA - The first Triangle to check for intersection. * @param {Phaser.Geom.Triangle} triangleB - The second Triangle to check for intersection. + * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Triangles intersect, otherwise `false`. */ -var TriangleToTriangle = function (triangleA, triangleB) +var TriangleToTriangle = function (triangleA, triangleB, out) { - // First the cheapest ones: + if (out === undefined) { out = []; } - if ( - triangleA.left > triangleB.right || + if (triangleA.left > triangleB.right || triangleA.right < triangleB.left || triangleA.top > triangleB.bottom || triangleA.bottom < triangleB.top) @@ -34,51 +33,30 @@ var TriangleToTriangle = function (triangleA, triangleB) return false; } - var lineAA = triangleA.getLineA(); - var lineAB = triangleA.getLineB(); - var lineAC = triangleA.getLineC(); + if (Equals(triangleA, triangleB)) { return false; } - var lineBA = triangleB.getLineA(); - var lineBB = triangleB.getLineB(); - var lineBC = triangleB.getLineC(); + var oriLength = out.length; - // Now check the lines against each line of TriangleB - if (LineToLine(lineAA, lineBA) || LineToLine(lineAA, lineBB) || LineToLine(lineAA, lineBC)) + var lineA = triangleB.getLineA(); + var lineB = triangleB.getLineB(); + var lineC = triangleB.getLineC(); + + var output = [ [], [], [] ]; + + var res = [ + TriangleToLine(triangleA, lineA, output[0]), + TriangleToLine(triangleA, lineB, output[1]), + TriangleToLine(triangleA, lineC, output[2]) + ]; + + for (var i = 0; i < 3; i++) { - return true; + if (res[i] && output[i] !== []) { out.concat(output[i]); } } - if (LineToLine(lineAB, lineBA) || LineToLine(lineAB, lineBB) || LineToLine(lineAB, lineBC)) - { - return true; - } - - if (LineToLine(lineAC, lineBA) || LineToLine(lineAC, lineBB) || LineToLine(lineAC, lineBC)) - { - return true; - } - - // Nope, so check to see if any of the points of triangleA are within triangleB - - var points = Decompose(triangleA); - var within = ContainsArray(triangleB, points, true); - - if (within.length > 0) - { - return true; - } - - // Finally check to see if any of the points of triangleB are within triangleA - - points = Decompose(triangleB); - within = ContainsArray(triangleA, points, true); - - if (within.length > 0) - { - return true; - } - - return false; + if (out.length - oriLength > 0) { return true; } + else if (res[0] || res[1] || res[2]) { return true; } + else { return false; } }; module.exports = TriangleToTriangle; From 0c59c83f6b22e2fb4b48bfc875299feb2e7c3c90 Mon Sep 17 00:00:00 2001 From: florianvazelle Date: Thu, 7 Mar 2019 10:32:25 +0100 Subject: [PATCH 2/3] Create new functions to get intersections --- src/geom/intersects/CircleToCircle.js | 74 +-------- src/geom/intersects/CircleToRectangle.js | 47 +++--- src/geom/intersects/GetCircleToCircle.js | 87 ++++++++++ src/geom/intersects/GetCircleToRectangle.js | 52 ++++++ src/geom/intersects/GetLineToCircle.js | 109 +++++++++++++ src/geom/intersects/GetLineToRectangle.js | 53 ++++++ .../intersects/GetRectangleToRectangle.js | 53 ++++++ src/geom/intersects/GetRectangleToTriangle.js | 50 ++++++ src/geom/intersects/GetTriangleToCircle.js | 51 ++++++ src/geom/intersects/GetTriangleToLine.js | 52 ++++++ src/geom/intersects/GetTriangleToTriangle.js | 51 ++++++ src/geom/intersects/LineToCircle.js | 153 ++++-------------- src/geom/intersects/LineToRectangle.js | 83 +++++++--- src/geom/intersects/RectangleToRectangle.js | 35 +--- src/geom/intersects/RectangleToTriangle.js | 74 ++++++--- src/geom/intersects/TriangleToCircle.js | 46 +++--- src/geom/intersects/TriangleToLine.js | 49 +++--- src/geom/intersects/TriangleToTriangle.js | 72 ++++++--- 18 files changed, 821 insertions(+), 370 deletions(-) create mode 100644 src/geom/intersects/GetCircleToCircle.js create mode 100644 src/geom/intersects/GetCircleToRectangle.js create mode 100644 src/geom/intersects/GetLineToCircle.js create mode 100644 src/geom/intersects/GetLineToRectangle.js create mode 100644 src/geom/intersects/GetRectangleToRectangle.js create mode 100644 src/geom/intersects/GetRectangleToTriangle.js create mode 100644 src/geom/intersects/GetTriangleToCircle.js create mode 100644 src/geom/intersects/GetTriangleToLine.js create mode 100644 src/geom/intersects/GetTriangleToTriangle.js diff --git a/src/geom/intersects/CircleToCircle.js b/src/geom/intersects/CircleToCircle.js index c8116879d..2a0efcf2a 100644 --- a/src/geom/intersects/CircleToCircle.js +++ b/src/geom/intersects/CircleToCircle.js @@ -4,8 +4,6 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Point = require('../point/Point'); -var Equals = require('../circle/Equals'); var DistanceBetween = require('../../math/distance/DistanceBetween'); /** @@ -16,80 +14,12 @@ var DistanceBetween = require('../../math/distance/DistanceBetween'); * * @param {Phaser.Geom.Circle} circleA - The first Circle to check for intersection. * @param {Phaser.Geom.Circle} circleB - The second Circle to check for intersection. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two Circles intersect, otherwise `false`. */ -var CircleToCircle = function (circleA, circleB, out) +var CircleToCircle = function (circleA, circleB) { - if (out === undefined) { out = []; } - - var x0 = circleA.x; - var y0 = circleA.y; - var r0 = circleA.radius; - - var x1 = circleB.x; - var y1 = circleB.y; - var r1 = circleB.radius; - - // To optimise, if there's no intersection or if the two circles are identical, then we return false - - if (!(DistanceBetween(x0, y0, x1, y1) <= (r0 + r1))) { return false; } - - if (Equals(circleA, circleB)) { return false; } - - var a, b, c, lambda, x; - - if (y0 === y1) - { - x = (r1 * r1) - (r0 * r0) - (x1 * x1) + (x0 * x0); - - a = 1; - b = -2 * y1; - c = (x1 * x1) + (x * x) - (2 * x1 * x) + (y1 * y1) - (r1 * r1); - - lambda = (b * b) - (4 * a * c); - - if (lambda < 0) { return false; } - else if (lambda === 0) - { - out.push(new Point(x, (-b / (2 * a)))); - return true; - } - else - { - out.push(new Point(x, (-b + Math.sqrt(lambda)) / (2 * a))); - out.push(new Point(x, (-b - Math.sqrt(lambda)) / (2 * a))); - return true; - } - } - else - { - var v1 = (x0 - x1) / (y0 - y1); - var n = (r1 * r1 - r0 * r0 - x1 * x1 + x0 * x0 - y1 * y1 + y0 * y0) / (2 * (y0 - y1)); - - a = (v1 * v1) + 1; - b = (2 * y0 * v1) - (2 * n * v1) - (2 * x0); - c = (x0 * x0) + (y0 * y0) + (n * n) - (r0 * r0) - (2 * y0 * n); - - lambda = (b * b) - (4 * a * c); - - if (lambda < 0) { return false; } - else if (lambda === 0) - { - x = (-b / (2 * a)); - out.push(new Point(x, (n - (x * v1)))); - return true; - } - else - { - x = (-b + Math.sqrt(lambda)) / (2 * a); - out.push(new Point(x, (n - (x * v1)))); - x = (-b - Math.sqrt(lambda)) / (2 * a); - out.push(new Point(x, (n - (x * v1)))); - return true; - } - } + return (DistanceBetween(circleA.x, circleA.y, circleB.x, circleB.y) <= (circleA.radius + circleB.radius)); }; module.exports = CircleToCircle; diff --git a/src/geom/intersects/CircleToRectangle.js b/src/geom/intersects/CircleToRectangle.js index ff7109f0b..2221cffe9 100644 --- a/src/geom/intersects/CircleToRectangle.js +++ b/src/geom/intersects/CircleToRectangle.js @@ -4,8 +4,6 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var LineToCircle = require('./LineToCircle'); - /** * Checks for intersection between a circle and a rectangle. * @@ -14,38 +12,37 @@ var LineToCircle = require('./LineToCircle'); * * @param {Phaser.Geom.Circle} circle - The circle to be checked. * @param {Phaser.Geom.Rectangle} rect - The rectangle to be checked. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two objects intersect, otherwise `false`. */ -var CircleToRectangle = function (circle, rect, out) +var CircleToRectangle = function (circle, rect) { - if (out === undefined) { out = []; } + var halfWidth = rect.width / 2; + var halfHeight = rect.height / 2; - var oriLength = out.length; + var cx = Math.abs(circle.x - rect.x - halfWidth); + var cy = Math.abs(circle.y - rect.y - halfHeight); + var xDist = halfWidth + circle.radius; + var yDist = halfHeight + circle.radius; - var lineA = rect.getLineA(); - var lineB = rect.getLineB(); - var lineC = rect.getLineC(); - var lineD = rect.getLineD(); - - var output = [ [], [], [], [] ]; - - var res = [ - LineToCircle(lineA, circle, output[0]), - LineToCircle(lineB, circle, output[1]), - LineToCircle(lineC, circle, output[2]), - LineToCircle(lineD, circle, output[3]) - ]; - - for (var i = 0; i < 4; i++) + if (cx > xDist || cy > yDist) { - if (res[i] && output !== []) { out.concat(output[i]); } + return false; } + else if (cx <= halfWidth || cy <= halfHeight) + { + return true; + } + else + { + var xCornerDist = cx - halfWidth; + var yCornerDist = cy - halfHeight; + var xCornerDistSq = xCornerDist * xCornerDist; + var yCornerDistSq = yCornerDist * yCornerDist; + var maxCornerDistSq = circle.radius * circle.radius; - if (out.length - oriLength > 0) { return true; } - else if (res[0] || res[1] || res[2] || res[3]) { return true; } - else { return false; } + return (xCornerDistSq + yCornerDistSq <= maxCornerDistSq); + } }; module.exports = CircleToRectangle; diff --git a/src/geom/intersects/GetCircleToCircle.js b/src/geom/intersects/GetCircleToCircle.js new file mode 100644 index 000000000..541bce924 --- /dev/null +++ b/src/geom/intersects/GetCircleToCircle.js @@ -0,0 +1,87 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var Point = require('../point/Point'); +var CircleToCircle = require('./CircleToCircle'); + +/** + * Checks if two Circles intersect and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetCircleToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circleA - The first Circle to check for intersection. + * @param {Phaser.Geom.Circle} circleB - The second Circle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetCircleToCircle = function (circleA, circleB, out) +{ + if (out === undefined) { out = []; } + + if (CircleToCircle(circleA, circleB)) + { + var x0 = circleA.x; + var y0 = circleA.y; + var r0 = circleA.radius; + + var x1 = circleB.x; + var y1 = circleB.y; + var r1 = circleB.radius; + + var coefficientA, coefficientB, coefficientC, lambda, x; + + if (y0 === y1) + { + x = (r1 * r1) - (r0 * r0) - (x1 * x1) + (x0 * x0); + + coefficientA = 1; + coefficientB = -2 * y1; + coefficientC = (x1 * x1) + (x * x) - (2 * x1 * x) + (y1 * y1) - (r1 * r1); + + lambda = (coefficientB * coefficientB) - (4 * coefficientA * coefficientC); + + if (lambda === 0) + { + out.push(new Point(x, (-coefficientB / (2 * coefficientA)))); + } + else if (lambda > 0) + { + out.push(new Point(x, (-coefficientB + Math.sqrt(lambda)) / (2 * coefficientA))); + out.push(new Point(x, (-coefficientB - Math.sqrt(lambda)) / (2 * coefficientA))); + } + } + else + { + var v1 = (x0 - x1) / (y0 - y1); + var n = (r1 * r1 - r0 * r0 - x1 * x1 + x0 * x0 - y1 * y1 + y0 * y0) / (2 * (y0 - y1)); + + coefficientA = (v1 * v1) + 1; + coefficientB = (2 * y0 * v1) - (2 * n * v1) - (2 * x0); + coefficientC = (x0 * x0) + (y0 * y0) + (n * n) - (r0 * r0) - (2 * y0 * n); + + lambda = (coefficientB * coefficientB) - (4 * coefficientA * coefficientC); + + if (lambda === 0) + { + x = (-coefficientB / (2 * coefficientA)); + out.push(new Point(x, (n - (x * v1)))); + } + else if (lambda > 0) + { + x = (-coefficientB + Math.sqrt(lambda)) / (2 * coefficientA); + out.push(new Point(x, (n - (x * v1)))); + x = (-coefficientB - Math.sqrt(lambda)) / (2 * coefficientA); + out.push(new Point(x, (n - (x * v1)))); + } + } + } + + return out; +}; + +module.exports = GetCircleToCircle; diff --git a/src/geom/intersects/GetCircleToRectangle.js b/src/geom/intersects/GetCircleToRectangle.js new file mode 100644 index 000000000..5d4d3fe05 --- /dev/null +++ b/src/geom/intersects/GetCircleToRectangle.js @@ -0,0 +1,52 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var GetLineToCircle = require('./GetLineToCircle'); +var CircleToRectangle = require('./CircleToRectangle'); + +/** + * Checks for intersection between a circle and a rectangle, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetCircleToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Circle} circle - The circle to be checked. + * @param {Phaser.Geom.Rectangle} rect - The rectangle to be checked. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetCircleToRectangle = function (circle, rect, out) +{ + if (out === undefined) { out = []; } + + if (CircleToRectangle(circle, rect)) + { + var lineA = rect.getLineA(); + var lineB = rect.getLineB(); + var lineC = rect.getLineC(); + var lineD = rect.getLineD(); + + var output = [ [], [], [], [] ]; + + var result = [ + GetLineToCircle(lineA, circle, output[0]), + GetLineToCircle(lineB, circle, output[1]), + GetLineToCircle(lineC, circle, output[2]), + GetLineToCircle(lineD, circle, output[3]) + ]; + + for (var i = 0; i < 4; i++) + { + if (result[i] && output !== []) { out.concat(output[i]); } + } + } + + return out; +}; + +module.exports = GetCircleToRectangle; diff --git a/src/geom/intersects/GetLineToCircle.js b/src/geom/intersects/GetLineToCircle.js new file mode 100644 index 000000000..7fd6b6416 --- /dev/null +++ b/src/geom/intersects/GetLineToCircle.js @@ -0,0 +1,109 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var Point = require('../point/Point'); + +var tmp = new Point(); + +/** + * Checks for intersection between the line segment and circle, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetLineToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The line segment to check. + * @param {Phaser.Geom.Circle} circle - The circle to check against the line. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetLineToCircle = function (line, circle, out) +{ + if (out === undefined) { out = []; } + + if (LineToCircle(line, circle)) + { + var lx1 = line.x1; + var ly1 = line.y1; + + var lx2 = line.x2; + var ly2 = line.y2; + + var cx = circle.x; + var cy = circle.y; + var cr = circle.radius; + + // We determine the line equation + var leadingCoefficient, originOrdinate; + + if (lx1 === lx2) + { + // Linear function + leadingCoefficient = lx1; + originOrdinate = 0; + } + else + { + // Constant function + leadingCoefficient = (ly2 - ly1) / (lx2 - lx1); + originOrdinate = ly1 - leadingCoefficient * lx1; + } + + var coefficientA = (leadingCoefficient * leadingCoefficient) + 1; + var coefficientB = (-2 * cx) - (2 * cy * leadingCoefficient) + (2 * leadingCoefficient * originOrdinate); + var coefficientC = (cx * cx) + (cy * cy) + (originOrdinate * originOrdinate) - (cr * cr) - (2 * cy * originOrdinate); + + var lambda = (coefficientB * coefficientB) - (4 * coefficientA * coefficientC); + + var x, y; + + var xMin = Math.min(lx1, lx2); + var yMin = Math.min(ly1, ly2); + + var xMax = Math.max(lx1, lx2); + var yMax = Math.max(ly1, ly2); + + if (lambda === 0) + { + x = (-coefficientB / (2 * coefficientA)); + y = ((leadingCoefficient * x) + originOrdinate); + if (Math.min(xMin, x) === xMin && + Math.min(yMin, y) === yMin && + Math.max(xMax, x) === xMax && + Math.max(yMax, y) === yMax) + { + out.push(new Point(x, y)); + } + } + else if (lambda > 0) + { + x = (-coefficientB + Math.sqrt(lambda)) / (2 * coefficientA); + y = ((leadingCoefficient * x) + originOrdinate); + if (Math.min(xMin, x) === xMin && + Math.min(yMin, y) === yMin && + Math.max(xMax, x) === xMax && + Math.max(yMax, y) === yMax) + { + out.push(new Point(x, y)); + } + + x = (-coefficientB - Math.sqrt(lambda)) / (2 * coefficientA); + y = ((leadingCoefficient * x) + originOrdinate); + if (Math.min(xMin, x) === xMin && + Math.min(yMin, y) === yMin && + Math.max(xMax, x) === xMax && + Math.max(yMax, y) === yMax) + { + out.push(new Point(x, y)); + } + } + } + + return out; +}; + +module.exports = GetLineToCircle; diff --git a/src/geom/intersects/GetLineToRectangle.js b/src/geom/intersects/GetLineToRectangle.js new file mode 100644 index 000000000..ad0caf715 --- /dev/null +++ b/src/geom/intersects/GetLineToRectangle.js @@ -0,0 +1,53 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var Point = require('../point/Point'); +var GetLineToLine = require('./GetLineToLine'); +var LineToRectangle = require('./LineToRectangle'); + +/** + * Checks for intersection between the Line and a Rectangle shape, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetLineToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Line} line - The Line to check for intersection. + * @param {(Phaser.Geom.Rectangle|object)} rect - The Rectangle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetLineToRectangle = function (line, rect, out) +{ + if (out === undefined) { out = []; } + + if (LineToRectangle(line, rect)) + { + var lineA = rect.getLineA(); + var lineB = rect.getLineB(); + var lineC = rect.getLineC(); + var lineD = rect.getLineD(); + + var output = [ new Point(), new Point(), new Point(), new Point() ]; + + var result = [ + GetLineToLine(lineA, line, output[0]), + GetLineToLine(lineB, line, output[1]), + GetLineToLine(lineC, line, output[2]), + GetLineToLine(lineD, line, output[3]) + ]; + + for (var i = 0; i < 4; i++) + { + if (result[i]) { out.push(output[i]); } + } + } + + return out; +}; + +module.exports = GetLineToRectangle; diff --git a/src/geom/intersects/GetRectangleToRectangle.js b/src/geom/intersects/GetRectangleToRectangle.js new file mode 100644 index 000000000..af32e0940 --- /dev/null +++ b/src/geom/intersects/GetRectangleToRectangle.js @@ -0,0 +1,53 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var GetLineToRectangle = require('./GetLineToRectangle'); +var RectangleToRectangle = require('./RectangleToRectangle'); + +/** + * Checks if two Rectangles intersect and returns the intersection points as a Point object array. + * + * A Rectangle intersects another Rectangle if any part of its bounds is within the other Rectangle's bounds. As such, the two Rectangles are considered "solid". A Rectangle with no width or no height will never intersect another Rectangle. + * + * @function Phaser.Geom.Intersects.GetRectangleToRectangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check for intersection. + * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetRectangleToRectangle = function (rectA, rectB, out) +{ + if (out === undefined) { out = []; } + + if (RectangleToRectangle(rectA, rectB)) + { + var lineA = rectA.getLineA(); + var lineB = rectA.getLineB(); + var lineC = rectA.getLineC(); + var lineD = rectA.getLineD(); + + var output = [ [], [], [], [] ]; + + var result = [ + GetLineToRectangle(lineA, rectB, output[0]), + GetLineToRectangle(lineB, rectB, output[1]), + GetLineToRectangle(lineC, rectB, output[2]), + GetLineToRectangle(lineD, rectB, output[3]) + ]; + + for (var i = 0; i < 4; i++) + { + if (result[i] && output !== []) { out.concat(output[i]); } + } + } + + return out; +}; + +module.exports = GetRectangleToRectangle; diff --git a/src/geom/intersects/GetRectangleToTriangle.js b/src/geom/intersects/GetRectangleToTriangle.js new file mode 100644 index 000000000..7d3bceb33 --- /dev/null +++ b/src/geom/intersects/GetRectangleToTriangle.js @@ -0,0 +1,50 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var RectangleToTriangle = require('./RectangleToTriangle'); +var GetLineToRectangle = require('./GetLineToRectangle'); + +/** + * Checks for intersection between Rectangle shape and Triangle shape, + * and returns the intersection points as a Point object array. + * + * @function Phaser.Geom.Intersects.GetRectangleToTriangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Rectangle} rect - Rectangle object to test. + * @param {Phaser.Geom.Triangle} triangle - Triangle object to test. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetRectangleToTriangle = function (rect, triangle, out) +{ + if (out === undefined) { out = []; } + + if (RectangleToTriangle(rect, triangle)) + { + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + var output = [ [], [], [] ]; + + var result = [ + GetLineToRectangle(lineA, rect, output[0]), + GetLineToRectangle(lineB, rect, output[1]), + GetLineToRectangle(lineC, rect, output[2]) + ]; + + for (var i = 0; i < 3; i++) + { + if (result[i] && output[i] !== []) { out.concat(output[i]); } + } + } + + return out; +}; + +module.exports = GetRectangleToTriangle; diff --git a/src/geom/intersects/GetTriangleToCircle.js b/src/geom/intersects/GetTriangleToCircle.js new file mode 100644 index 000000000..7b61df462 --- /dev/null +++ b/src/geom/intersects/GetTriangleToCircle.js @@ -0,0 +1,51 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var GetLineToCircle = require('./GetLineToCircle'); +var TriangleToCircle = require('./TriangleToCircle'); + +/** + * Checks if a Triangle and a Circle intersect, and returns the intersection points as a Point object array. + * + * A Circle intersects a Triangle if its center is located within it or if any of the Triangle's sides intersect the Circle. As such, the Triangle and the Circle are considered "solid" for the intersection. + * + * @function Phaser.Geom.Intersects.GetTriangleToCircle + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check for intersection. + * @param {Phaser.Geom.Circle} circle - The Circle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetTriangleToCircle = function (triangle, circle, out) +{ + if (out === undefined) { out = []; } + + if (TriangleToCircle(triangle, circle)) + { + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + var output = [ [], [], [] ]; + + var result = [ + GetLineToCircle(lineA, circle, output[0]), + GetLineToCircle(lineB, circle, output[1]), + GetLineToCircle(lineC, circle, output[2]) + ]; + + for (var i = 0; i < 3; i++) + { + if (result[i] && output !== []) { out.concat(output[i]); } + } + } + + return out; +}; + +module.exports = GetTriangleToCircle; diff --git a/src/geom/intersects/GetTriangleToLine.js b/src/geom/intersects/GetTriangleToLine.js new file mode 100644 index 000000000..113fe55a8 --- /dev/null +++ b/src/geom/intersects/GetTriangleToLine.js @@ -0,0 +1,52 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var Point = require('../point/Point'); +var TriangleToLine = require('./TriangleToLine'); +var GetLineToLine = require('./GetLineToLine'); + +/** + * Checks if a Triangle and a Line intersect, and returns the intersection points as a Point object array. + * + * The Line intersects the Triangle if it starts inside of it, ends inside of it, or crosses any of the Triangle's sides. Thus, the Triangle is considered "solid". + * + * @function Phaser.Geom.Intersects.GetTriangleToLine + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangle - The Triangle to check with. + * @param {Phaser.Geom.Line} line - The Line to check with. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetTriangleToLine = function (triangle, line, out) +{ + if (out === undefined) { out = []; } + + if (TriangleToLine(triangle, line)) + { + var lineA = triangle.getLineA(); + var lineB = triangle.getLineB(); + var lineC = triangle.getLineC(); + + var output = [ new Point(), new Point(), new Point() ]; + + var result = [ + GetLineToLine(lineA, line, output[0]), + GetLineToLine(lineB, line, output[1]), + GetLineToLine(lineC, line, output[2]) + ]; + + for (var i = 0; i < 3; i++) + { + if (result[i] && output !== []) { out.push(output[i]); } + } + } + + return out; +}; + +module.exports = GetTriangleToLine; diff --git a/src/geom/intersects/GetTriangleToTriangle.js b/src/geom/intersects/GetTriangleToTriangle.js new file mode 100644 index 000000000..65fe72f78 --- /dev/null +++ b/src/geom/intersects/GetTriangleToTriangle.js @@ -0,0 +1,51 @@ +/** + * @author Richard Davey + * @copyright 2019 Photon Storm Ltd. + * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} + */ + +var Equals = require('../TriangleToTriangle'); +var TriangleToLine = require('./GetTriangleToLine'); + +/** + * Checks if two Triangles intersect, and returns the intersection points as a Point object array. + * + * A Triangle intersects another Triangle if any pair of their lines intersects or if any point of one Triangle is within the other Triangle. Thus, the Triangles are considered "solid". + * + * @function Phaser.Geom.Intersects.GetTriangleToTriangle + * @since 3.0.0 + * + * @param {Phaser.Geom.Triangle} triangleA - The first Triangle to check for intersection. + * @param {Phaser.Geom.Triangle} triangleB - The second Triangle to check for intersection. + * @param {array} [out] - An optional array in which to store the points of intersection. + * + * @return {array} An array with the points of intersection if objects intersect, otherwise an empty array. + */ +var GetTriangleToTriangle = function (triangleA, triangleB, out) +{ + if (out === undefined) { out = []; } + + if (TriangleToTriangle(triangleA, triangleB)) + { + var lineA = triangleB.getLineA(); + var lineB = triangleB.getLineB(); + var lineC = triangleB.getLineC(); + + var output = [ [], [], [] ]; + + var result = [ + GetTriangleToLine(triangleA, lineA, output[0]), + GetTriangleToLine(triangleA, lineB, output[1]), + GetTriangleToLine(triangleA, lineC, output[2]) + ]; + + for (var i = 0; i < 3; i++) + { + if (result[i] && output[i] !== []) { out.concat(output[i]); } + } + } + + return out; +}; + +module.exports = GetTriangleToTriangle; diff --git a/src/geom/intersects/LineToCircle.js b/src/geom/intersects/LineToCircle.js index 0e27cd774..61c896f80 100644 --- a/src/geom/intersects/LineToCircle.js +++ b/src/geom/intersects/LineToCircle.js @@ -4,7 +4,6 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ - var Contains = require('../circle/Contains'); var Point = require('../point/Point'); @@ -21,143 +20,59 @@ var tmp = new Point(); * @param {Phaser.Geom.Line} line - The line segment to check. * @param {Phaser.Geom.Circle} circle - The circle to check against the line. * @param {(Phaser.Geom.Point|any)} [nearest] - An optional Point-like object. If given the closest point on the Line where the circle intersects will be stored in this object. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two objects intersect, otherwise `false`. */ -var LineToCircle = function (line, circle, nearest, out) +var LineToCircle = function (line, circle, nearest) { if (nearest === undefined) { nearest = tmp; } - if (out === undefined) { out = []; } - var lx0 = line.x1; - var ly0 = line.y1; - - var lx1 = line.x2; - var ly1 = line.y2; - - var cx = circle.x; - var cy = circle.y; - var cr = circle.radius; - - var output = false; - - // define nearest - if (Contains(circle, lx0, ly0)) + if (Contains(circle, line.x1, line.y1)) { - nearest.x = lx0; - nearest.y = ly0; + nearest.x = line.x1; + nearest.y = line.y1; - output = true; - } - else if (Contains(circle, lx1, ly1)) - { - nearest.x = lx1; - nearest.y = ly1; - - output = true; - } - else - { - var dx = lx1 - lx0; - var dy = ly1 - ly0; - - var lcx = cx - lx0; - var lcy = cy - ly0; - - // project lc onto d, resulting in vector p - var dLen2 = (dx * dx) + (dy * dy); - var px = dx; - var py = dy; - - if (dLen2 > 0) - { - var dp = ((lcx * dx) + (lcy * dy)) / dLen2; - - px *= dp; - py *= dp; - } - - nearest.x = lx0 + px; - nearest.y = ly0 + py; - - // len2 of p - var pLen2 = (px * px) + (py * py); - - output = (pLen2 <= dLen2 && - ((px * dx) + (py * dy)) >= 0 && - Contains(circle, nearest.x, nearest.y)); + return true; } - if (!output) { return output; } - - // We determine the line equation - - var m, p; - - if (lx0 === lx1) + if (Contains(circle, line.x2, line.y2)) { - m = lx0; - p = 0; - } - else - { - m = (ly1 - ly0) / (lx1 - lx0); - p = ly0 - m * lx0; + nearest.x = line.x2; + nearest.y = line.y2; + + return true; } - var a = (m * m) + 1; - var b = (-2 * cx) - (2 * cy * m) + (2 * m * p); - var c = (cx * cx) + (cy * cy) + (p * p) - (cr * cr) - (2 * cy * p); + var dx = line.x2 - line.x1; + var dy = line.y2 - line.y1; - var lambda = (b * b) - (4 * a * c); + var lcx = circle.x - line.x1; + var lcy = circle.y - line.y1; - var x, y; + // project lc onto d, resulting in vector p + var dLen2 = (dx * dx) + (dy * dy); + var px = dx; + var py = dy; - var minx = Math.min(lx0, lx1); - var miny = Math.min(ly0, ly1); - - var maxx = Math.max(lx0, lx1); - var maxy = Math.max(ly0, ly1); - - if (lambda === 0) + if (dLen2 > 0) { - x = (-b / (2 * a)); - y = ((m * x) + p); - if (Math.min(minx, x) === minx && - Math.min(miny, y) === miny && - Math.max(maxx, x) === maxx && - Math.max(maxy, y) === maxy) - { - out.push(new Point(x, y)); - output = true; - } - } - else if (lambda > 0) - { - x = (-b + Math.sqrt(lambda)) / (2 * a); - y = ((m * x) + p); - if (Math.min(minx, x) === minx && - Math.min(miny, y) === miny && - Math.max(maxx, x) === maxx && - Math.max(maxy, y) === maxy) - { - out.push(new Point(x, y)); - output = true; - } + var dp = ((lcx * dx) + (lcy * dy)) / dLen2; - x = (-b - Math.sqrt(lambda)) / (2 * a); - y = ((m * x) + p); - if (Math.min(minx, x) === minx && - Math.min(miny, y) === miny && - Math.max(maxx, x) === maxx && - Math.max(maxy, y) === maxy) - { - out.push(new Point(x, y)); - output = true; - } + px *= dp; + py *= dp; } - return output; + + nearest.x = line.x1 + px; + nearest.y = line.y1 + py; + + // len2 of p + var pLen2 = (px * px) + (py * py); + + return ( + pLen2 <= dLen2 && + ((px * dx) + (py * dy)) >= 0 && + Contains(circle, nearest.x, nearest.y) + ); }; module.exports = LineToCircle; diff --git a/src/geom/intersects/LineToRectangle.js b/src/geom/intersects/LineToRectangle.js index 6848d29e5..3197da67b 100644 --- a/src/geom/intersects/LineToRectangle.js +++ b/src/geom/intersects/LineToRectangle.js @@ -4,10 +4,6 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Point = require('../point/Point'); -var LineToLine = require('./LineToLine'); -var ContainsPoint = require('../rectangle/ContainsPoint'); - /** * Checks for intersection between the Line and a Rectangle shape, or a rectangle-like * object, with public `x`, `y`, `right` and `bottom` properties, such as a Sprite or Body. @@ -24,39 +20,76 @@ var ContainsPoint = require('../rectangle/ContainsPoint'); * * @param {Phaser.Geom.Line} line - The Line to check for intersection. * @param {(Phaser.Geom.Rectangle|object)} rect - The Rectangle to check for intersection. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Line and the Rectangle intersect, `false` otherwise. */ -var LineToRectangle = function (line, rect, out) +var LineToRectangle = function (line, rect) { - if (out === undefined) { out = []; } + var x1 = line.x1; + var y1 = line.y1; - var oriLength = out.length; + var x2 = line.x2; + var y2 = line.y2; - var lineA = rect.getLineA(); - var lineB = rect.getLineB(); - var lineC = rect.getLineC(); - var lineD = rect.getLineD(); + var bx1 = rect.x; + var by1 = rect.y; + var bx2 = rect.right; + var by2 = rect.bottom; - var output = [ new Point(), new Point(), new Point(), new Point() ]; + var t = 0; - var res = [ - LineToLine(lineA, line, output[0]), - LineToLine(lineB, line, output[1]), - LineToLine(lineC, line, output[2]), - LineToLine(lineD, line, output[3]) - ]; + // If the start or end of the line is inside the rect then we assume + // collision, as rects are solid for our use-case. - for (var i = 0; i < 4; i++) + if ((x1 >= bx1 && x1 <= bx2 && y1 >= by1 && y1 <= by2) || + (x2 >= bx1 && x2 <= bx2 && y2 >= by1 && y2 <= by2)) { - if (res[i]) { out.push(output[i]); } + return true; } - if (out.length - oriLength > 0) { return true; } - else if (ContainsPoint(rect, line.getPointA()) || - ContainsPoint(rect, line.getPointB())) { return true; } - else { return false; } + if (x1 < bx1 && x2 >= bx1) + { + // Left edge + t = y1 + (y2 - y1) * (bx1 - x1) / (x2 - x1); + + if (t > by1 && t <= by2) + { + return true; + } + } + else if (x1 > bx2 && x2 <= bx2) + { + // Right edge + t = y1 + (y2 - y1) * (bx2 - x1) / (x2 - x1); + + if (t >= by1 && t <= by2) + { + return true; + } + } + + if (y1 < by1 && y2 >= by1) + { + // Top edge + t = x1 + (x2 - x1) * (by1 - y1) / (y2 - y1); + + if (t >= bx1 && t <= bx2) + { + return true; + } + } + else if (y1 > by2 && y2 <= by2) + { + // Bottom edge + t = x1 + (x2 - x1) * (by2 - y1) / (y2 - y1); + + if (t >= bx1 && t <= bx2) + { + return true; + } + } + + return false; }; module.exports = LineToRectangle; diff --git a/src/geom/intersects/RectangleToRectangle.js b/src/geom/intersects/RectangleToRectangle.js index abc0ed169..0c615f52b 100644 --- a/src/geom/intersects/RectangleToRectangle.js +++ b/src/geom/intersects/RectangleToRectangle.js @@ -4,9 +4,6 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Equals = require('../rectangle/Equals'); -var LineToRectangle = require('./LineToRectangle'); - /** * Checks if two Rectangles intersect. * @@ -17,45 +14,17 @@ var LineToRectangle = require('./LineToRectangle'); * * @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to check for intersection. * @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to check for intersection. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the two Rectangles intersect, otherwise `false`. */ -var RectangleToRectangle = function (rectA, rectB, out) +var RectangleToRectangle = function (rectA, rectB) { - if (out === undefined) { out = []; } - - if (Equals(rectA, rectB)) { return false; } - if (rectA.width <= 0 || rectA.height <= 0 || rectB.width <= 0 || rectB.height <= 0) { return false; } - if (!(rectA.right < rectB.x || rectA.bottom < rectB.y || rectA.x > rectB.right || rectA.y > rectB.bottom)) - { - var lineA = rectA.getLineA(); - var lineB = rectA.getLineB(); - var lineC = rectA.getLineC(); - var lineD = rectA.getLineD(); - - var output = [ [], [], [], [] ]; - - var res = [ - LineToRectangle(lineA, rectB, output[0]), - LineToRectangle(lineB, rectB, output[1]), - LineToRectangle(lineC, rectB, output[2]), - LineToRectangle(lineD, rectB, output[3]) - ]; - - for (var i = 0; i < 4; i++) - { - if (res[i] && output !== []) { out.concat(output[i]); } - } - - return true; - } - return false; + return !(rectA.right < rectB.x || rectA.bottom < rectB.y || rectA.x > rectB.right || rectA.y > rectB.bottom); }; module.exports = RectangleToRectangle; diff --git a/src/geom/intersects/RectangleToTriangle.js b/src/geom/intersects/RectangleToTriangle.js index 6d85779b4..7c62ddfa9 100644 --- a/src/geom/intersects/RectangleToTriangle.js +++ b/src/geom/intersects/RectangleToTriangle.js @@ -4,7 +4,10 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var LineToRectangle = require('./LineToRectangle'); +var LineToLine = require('./LineToLine'); +var Contains = require('../rectangle/Contains'); +var ContainsArray = require('../triangle/ContainsArray'); +var Decompose = require('../rectangle/Decompose'); /** * Checks for intersection between Rectangle shape and Triangle shape. @@ -14,15 +17,15 @@ var LineToRectangle = require('./LineToRectangle'); * * @param {Phaser.Geom.Rectangle} rect - Rectangle object to test. * @param {Phaser.Geom.Triangle} triangle - Triangle object to test. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} A value of `true` if objects intersect; otherwise `false`. */ -var RectangleToTriangle = function (rect, triangle, out) +var RectangleToTriangle = function (rect, triangle) { - if (out === undefined) { out = []; } + // First the cheapest ones: - if (triangle.left > rect.right || + if ( + triangle.left > rect.right || triangle.right < rect.left || triangle.top > rect.bottom || triangle.bottom < rect.top) @@ -30,28 +33,55 @@ var RectangleToTriangle = function (rect, triangle, out) return false; } - var oriLength = out.length; + var triA = triangle.getLineA(); + var triB = triangle.getLineB(); + var triC = triangle.getLineC(); - var lineA = triangle.getLineA(); - var lineB = triangle.getLineB(); - var lineC = triangle.getLineC(); + // Are any of the triangle points within the rectangle? - var output = [ [], [], [] ]; - - var res = [ - LineToRectangle(lineA, rect, output[0]), - LineToRectangle(lineB, rect, output[1]), - LineToRectangle(lineC, rect, output[2]) - ]; - - for (var i = 0; i < 3; i++) + if (Contains(rect, triA.x1, triA.y1) || Contains(rect, triA.x2, triA.y2)) { - if (res[i] && output[i] !== []) { out.concat(output[i]); } + return true; } - if (out.length - oriLength > 0) { return true; } - else if (res[0] || res[1] || res[2]) { return true; } - else { return false; } + if (Contains(rect, triB.x1, triB.y1) || Contains(rect, triB.x2, triB.y2)) + { + return true; + } + + if (Contains(rect, triC.x1, triC.y1) || Contains(rect, triC.x2, triC.y2)) + { + return true; + } + + // Cheap tests over, now to see if any of the lines intersect ... + + var rectA = rect.getLineA(); + var rectB = rect.getLineB(); + var rectC = rect.getLineC(); + var rectD = rect.getLineD(); + + if (LineToLine(triA, rectA) || LineToLine(triA, rectB) || LineToLine(triA, rectC) || LineToLine(triA, rectD)) + { + return true; + } + + if (LineToLine(triB, rectA) || LineToLine(triB, rectB) || LineToLine(triB, rectC) || LineToLine(triB, rectD)) + { + return true; + } + + if (LineToLine(triC, rectA) || LineToLine(triC, rectB) || LineToLine(triC, rectC) || LineToLine(triC, rectD)) + { + return true; + } + + // None of the lines intersect, so are any rectangle points within the triangle? + + var points = Decompose(rect); + var within = ContainsArray(triangle, points, true); + + return (within.length > 0); }; module.exports = RectangleToTriangle; diff --git a/src/geom/intersects/TriangleToCircle.js b/src/geom/intersects/TriangleToCircle.js index ae2f8e435..0dbff8cce 100644 --- a/src/geom/intersects/TriangleToCircle.js +++ b/src/geom/intersects/TriangleToCircle.js @@ -5,6 +5,7 @@ */ var LineToCircle = require('./LineToCircle'); +var Contains = require('../triangle/Contains'); /** * Checks if a Triangle and a Circle intersect. @@ -16,15 +17,15 @@ var LineToCircle = require('./LineToCircle'); * * @param {Phaser.Geom.Triangle} triangle - The Triangle to check for intersection. * @param {Phaser.Geom.Circle} circle - The Circle to check for intersection. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Triangle and the `Circle` intersect, otherwise `false`. */ -var TriangleToCircle = function (triangle, circle, out) +var TriangleToCircle = function (triangle, circle) { - if (out === undefined) { out = []; } + // First the cheapest ones: - if (triangle.left > circle.right || + if ( + triangle.left > circle.right || triangle.right < circle.left || triangle.top > circle.bottom || triangle.bottom < circle.top) @@ -32,28 +33,27 @@ var TriangleToCircle = function (triangle, circle, out) return false; } - var oriLength = out.length; - - var lineA = triangle.getLineA(); - var lineB = triangle.getLineB(); - var lineC = triangle.getLineC(); - - var output = [ [], [], [] ]; - - var res = [ - LineToCircle(lineA, circle, output[0]), - LineToCircle(lineB, circle, output[1]), - LineToCircle(lineC, circle, output[2]) - ]; - - for (var i = 0; i < 3; i++) + if (Contains(triangle, circle.x, circle.y)) { - if (res[i] && output !== []) { out.concat(output[i]); } + return true; } - if (out.length - oriLength > 0) { return true; } - else if (res[0] || res[1] || res[2]) { return true; } - else { return false; } + if (LineToCircle(triangle.getLineA(), circle)) + { + return true; + } + + if (LineToCircle(triangle.getLineB(), circle)) + { + return true; + } + + if (LineToCircle(triangle.getLineC(), circle)) + { + return true; + } + + return false; }; module.exports = TriangleToCircle; diff --git a/src/geom/intersects/TriangleToLine.js b/src/geom/intersects/TriangleToLine.js index 2a9b73dda..657e2b06f 100644 --- a/src/geom/intersects/TriangleToLine.js +++ b/src/geom/intersects/TriangleToLine.js @@ -4,13 +4,12 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Point = require('../point/Point'); +var Contains = require('../triangle/Contains'); var LineToLine = require('./LineToLine'); -var ContainsPoint = require('../triangle/ContainsPoint'); /** * Checks if a Triangle and a Line intersect. - * + * * The Line intersects the Triangle if it starts inside of it, ends inside of it, or crosses any of the Triangle's sides. Thus, the Triangle is considered "solid". * * @function Phaser.Geom.Intersects.TriangleToLine @@ -18,36 +17,34 @@ var ContainsPoint = require('../triangle/ContainsPoint'); * * @param {Phaser.Geom.Triangle} triangle - The Triangle to check with. * @param {Phaser.Geom.Line} line - The Line to check with. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Triangle and the Line intersect, otherwise `false`. */ -var TriangleToLine = function (triangle, line, out) +var TriangleToLine = function (triangle, line) { - if (out === undefined) { out = []; } - var oriLength = out.length; - - var lineA = triangle.getLineA(); - var lineB = triangle.getLineB(); - var lineC = triangle.getLineC(); - - var output = [ new Point(), new Point(), new Point() ]; - - var res = [ - LineToLine(lineA, line, output[0]), - LineToLine(lineB, line, output[1]), - LineToLine(lineC, line, output[2]) - ]; - - for (var i = 0; i < 3; i++) + // If the Triangle contains either the start or end point of the line, it intersects + if (Contains(triangle, line.getPointA()) || Contains(triangle, line.getPointB())) { - if (res[i] && output !== []) { out.push(output[i]); } + return true; } - if (out.length - oriLength > 0) { return true; } - else if (ContainsPoint(triangle, line.getPointA()) || - ContainsPoint(triangle, line.getPointB())) { return true; } - else { return false; } + // Now check the line against each line of the Triangle + if (LineToLine(triangle.getLineA(), line)) + { + return true; + } + + if (LineToLine(triangle.getLineB(), line)) + { + return true; + } + + if (LineToLine(triangle.getLineC(), line)) + { + return true; + } + + return false; }; module.exports = TriangleToLine; diff --git a/src/geom/intersects/TriangleToTriangle.js b/src/geom/intersects/TriangleToTriangle.js index 8a1c5bfb5..58e744e3e 100644 --- a/src/geom/intersects/TriangleToTriangle.js +++ b/src/geom/intersects/TriangleToTriangle.js @@ -4,8 +4,9 @@ * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Equals = require('../triangle/Equals'); -var TriangleToLine = require('./TriangleToLine'); +var ContainsArray = require('../triangle/ContainsArray'); +var Decompose = require('../triangle/Decompose'); +var LineToLine = require('./LineToLine'); /** * Checks if two Triangles intersect. @@ -17,15 +18,15 @@ var TriangleToLine = require('./TriangleToLine'); * * @param {Phaser.Geom.Triangle} triangleA - The first Triangle to check for intersection. * @param {Phaser.Geom.Triangle} triangleB - The second Triangle to check for intersection. - * @param {array} [out] - An array in which to optionally store the points of intersection. * * @return {boolean} `true` if the Triangles intersect, otherwise `false`. */ -var TriangleToTriangle = function (triangleA, triangleB, out) +var TriangleToTriangle = function (triangleA, triangleB) { - if (out === undefined) { out = []; } + // First the cheapest ones: - if (triangleA.left > triangleB.right || + if ( + triangleA.left > triangleB.right || triangleA.right < triangleB.left || triangleA.top > triangleB.bottom || triangleA.bottom < triangleB.top) @@ -33,30 +34,51 @@ var TriangleToTriangle = function (triangleA, triangleB, out) return false; } - if (Equals(triangleA, triangleB)) { return false; } + var lineAA = triangleA.getLineA(); + var lineAB = triangleA.getLineB(); + var lineAC = triangleA.getLineC(); - var oriLength = out.length; + var lineBA = triangleB.getLineA(); + var lineBB = triangleB.getLineB(); + var lineBC = triangleB.getLineC(); - var lineA = triangleB.getLineA(); - var lineB = triangleB.getLineB(); - var lineC = triangleB.getLineC(); - - var output = [ [], [], [] ]; - - var res = [ - TriangleToLine(triangleA, lineA, output[0]), - TriangleToLine(triangleA, lineB, output[1]), - TriangleToLine(triangleA, lineC, output[2]) - ]; - - for (var i = 0; i < 3; i++) + // Now check the lines against each line of TriangleB + if (LineToLine(lineAA, lineBA) || LineToLine(lineAA, lineBB) || LineToLine(lineAA, lineBC)) { - if (res[i] && output[i] !== []) { out.concat(output[i]); } + return true; } - if (out.length - oriLength > 0) { return true; } - else if (res[0] || res[1] || res[2]) { return true; } - else { return false; } + if (LineToLine(lineAB, lineBA) || LineToLine(lineAB, lineBB) || LineToLine(lineAB, lineBC)) + { + return true; + } + + if (LineToLine(lineAC, lineBA) || LineToLine(lineAC, lineBB) || LineToLine(lineAC, lineBC)) + { + return true; + } + + // Nope, so check to see if any of the points of triangleA are within triangleB + + var points = Decompose(triangleA); + var within = ContainsArray(triangleB, points, true); + + if (within.length > 0) + { + return true; + } + + // Finally check to see if any of the points of triangleB are within triangleA + + points = Decompose(triangleB); + within = ContainsArray(triangleA, points, true); + + if (within.length > 0) + { + return true; + } + + return false; }; module.exports = TriangleToTriangle; From 21f4ec44d8dd741a5f6e56797c74bfdc20cf521a Mon Sep 17 00:00:00 2001 From: florianvazelle Date: Tue, 9 Apr 2019 10:52:35 +0200 Subject: [PATCH 3/3] Final Update --- src/geom/intersects/GetCircleToCircle.js | 3 ++- src/geom/intersects/GetCircleToRectangle.js | 20 +++++------------ src/geom/intersects/GetLineToCircle.js | 6 ++--- src/geom/intersects/GetLineToRectangle.js | 13 ++++++----- .../intersects/GetRectangleToRectangle.js | 20 +++++------------ src/geom/intersects/GetRectangleToTriangle.js | 18 +++++---------- src/geom/intersects/GetTriangleToCircle.js | 18 +++++---------- src/geom/intersects/GetTriangleToLine.js | 13 ++++++----- src/geom/intersects/GetTriangleToTriangle.js | 22 ++++++------------- src/geom/intersects/index.js | 9 ++++++++ 10 files changed, 57 insertions(+), 85 deletions(-) diff --git a/src/geom/intersects/GetCircleToCircle.js b/src/geom/intersects/GetCircleToCircle.js index 541bce924..e992064d9 100644 --- a/src/geom/intersects/GetCircleToCircle.js +++ b/src/geom/intersects/GetCircleToCircle.js @@ -1,5 +1,6 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ diff --git a/src/geom/intersects/GetCircleToRectangle.js b/src/geom/intersects/GetCircleToRectangle.js index 5d4d3fe05..15e4becbe 100644 --- a/src/geom/intersects/GetCircleToRectangle.js +++ b/src/geom/intersects/GetCircleToRectangle.js @@ -1,5 +1,6 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ @@ -31,19 +32,10 @@ var GetCircleToRectangle = function (circle, rect, out) var lineC = rect.getLineC(); var lineD = rect.getLineD(); - var output = [ [], [], [], [] ]; - - var result = [ - GetLineToCircle(lineA, circle, output[0]), - GetLineToCircle(lineB, circle, output[1]), - GetLineToCircle(lineC, circle, output[2]), - GetLineToCircle(lineD, circle, output[3]) - ]; - - for (var i = 0; i < 4; i++) - { - if (result[i] && output !== []) { out.concat(output[i]); } - } + GetLineToCircle(lineA, circle, out); + GetLineToCircle(lineB, circle, out); + GetLineToCircle(lineC, circle, out); + GetLineToCircle(lineD, circle, out); } return out; diff --git a/src/geom/intersects/GetLineToCircle.js b/src/geom/intersects/GetLineToCircle.js index 7fd6b6416..785a01f1b 100644 --- a/src/geom/intersects/GetLineToCircle.js +++ b/src/geom/intersects/GetLineToCircle.js @@ -1,12 +1,12 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ var Point = require('../point/Point'); - -var tmp = new Point(); +var LineToCircle = require('./LineToCircle'); /** * Checks for intersection between the line segment and circle, diff --git a/src/geom/intersects/GetLineToRectangle.js b/src/geom/intersects/GetLineToRectangle.js index ad0caf715..f39c928a8 100644 --- a/src/geom/intersects/GetLineToRectangle.js +++ b/src/geom/intersects/GetLineToRectangle.js @@ -1,11 +1,12 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ var Point = require('../point/Point'); -var GetLineToLine = require('./GetLineToLine'); +var LineToLine = require('./LineToLine'); var LineToRectangle = require('./LineToRectangle'); /** @@ -35,10 +36,10 @@ var GetLineToRectangle = function (line, rect, out) var output = [ new Point(), new Point(), new Point(), new Point() ]; var result = [ - GetLineToLine(lineA, line, output[0]), - GetLineToLine(lineB, line, output[1]), - GetLineToLine(lineC, line, output[2]), - GetLineToLine(lineD, line, output[3]) + LineToLine(lineA, line, output[0]), + LineToLine(lineB, line, output[1]), + LineToLine(lineC, line, output[2]), + LineToLine(lineD, line, output[3]) ]; for (var i = 0; i < 4; i++) diff --git a/src/geom/intersects/GetRectangleToRectangle.js b/src/geom/intersects/GetRectangleToRectangle.js index af32e0940..d082a5aab 100644 --- a/src/geom/intersects/GetRectangleToRectangle.js +++ b/src/geom/intersects/GetRectangleToRectangle.js @@ -1,5 +1,6 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ @@ -32,19 +33,10 @@ var GetRectangleToRectangle = function (rectA, rectB, out) var lineC = rectA.getLineC(); var lineD = rectA.getLineD(); - var output = [ [], [], [], [] ]; - - var result = [ - GetLineToRectangle(lineA, rectB, output[0]), - GetLineToRectangle(lineB, rectB, output[1]), - GetLineToRectangle(lineC, rectB, output[2]), - GetLineToRectangle(lineD, rectB, output[3]) - ]; - - for (var i = 0; i < 4; i++) - { - if (result[i] && output !== []) { out.concat(output[i]); } - } + GetLineToRectangle(lineA, rectB, out); + GetLineToRectangle(lineB, rectB, out); + GetLineToRectangle(lineC, rectB, out); + GetLineToRectangle(lineD, rectB, out); } return out; diff --git a/src/geom/intersects/GetRectangleToTriangle.js b/src/geom/intersects/GetRectangleToTriangle.js index 7d3bceb33..309726756 100644 --- a/src/geom/intersects/GetRectangleToTriangle.js +++ b/src/geom/intersects/GetRectangleToTriangle.js @@ -1,5 +1,6 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ @@ -30,18 +31,9 @@ var GetRectangleToTriangle = function (rect, triangle, out) var lineB = triangle.getLineB(); var lineC = triangle.getLineC(); - var output = [ [], [], [] ]; - - var result = [ - GetLineToRectangle(lineA, rect, output[0]), - GetLineToRectangle(lineB, rect, output[1]), - GetLineToRectangle(lineC, rect, output[2]) - ]; - - for (var i = 0; i < 3; i++) - { - if (result[i] && output[i] !== []) { out.concat(output[i]); } - } + GetLineToRectangle(lineA, rect, out); + GetLineToRectangle(lineB, rect, out); + GetLineToRectangle(lineC, rect, out); } return out; diff --git a/src/geom/intersects/GetTriangleToCircle.js b/src/geom/intersects/GetTriangleToCircle.js index 7b61df462..0a9493de6 100644 --- a/src/geom/intersects/GetTriangleToCircle.js +++ b/src/geom/intersects/GetTriangleToCircle.js @@ -1,5 +1,6 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ @@ -31,18 +32,9 @@ var GetTriangleToCircle = function (triangle, circle, out) var lineB = triangle.getLineB(); var lineC = triangle.getLineC(); - var output = [ [], [], [] ]; - - var result = [ - GetLineToCircle(lineA, circle, output[0]), - GetLineToCircle(lineB, circle, output[1]), - GetLineToCircle(lineC, circle, output[2]) - ]; - - for (var i = 0; i < 3; i++) - { - if (result[i] && output !== []) { out.concat(output[i]); } - } + GetLineToCircle(lineA, circle, out); + GetLineToCircle(lineB, circle, out); + GetLineToCircle(lineC, circle, out); } return out; diff --git a/src/geom/intersects/GetTriangleToLine.js b/src/geom/intersects/GetTriangleToLine.js index 113fe55a8..7e6d70843 100644 --- a/src/geom/intersects/GetTriangleToLine.js +++ b/src/geom/intersects/GetTriangleToLine.js @@ -1,12 +1,13 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ var Point = require('../point/Point'); var TriangleToLine = require('./TriangleToLine'); -var GetLineToLine = require('./GetLineToLine'); +var LineToLine = require('./LineToLine'); /** * Checks if a Triangle and a Line intersect, and returns the intersection points as a Point object array. @@ -35,14 +36,14 @@ var GetTriangleToLine = function (triangle, line, out) var output = [ new Point(), new Point(), new Point() ]; var result = [ - GetLineToLine(lineA, line, output[0]), - GetLineToLine(lineB, line, output[1]), - GetLineToLine(lineC, line, output[2]) + LineToLine(lineA, line, output[0]), + LineToLine(lineB, line, output[1]), + LineToLine(lineC, line, output[2]) ]; for (var i = 0; i < 3; i++) { - if (result[i] && output !== []) { out.push(output[i]); } + if (result[i]) { out.push(output[i]); } } } diff --git a/src/geom/intersects/GetTriangleToTriangle.js b/src/geom/intersects/GetTriangleToTriangle.js index 65fe72f78..2d25a017d 100644 --- a/src/geom/intersects/GetTriangleToTriangle.js +++ b/src/geom/intersects/GetTriangleToTriangle.js @@ -1,11 +1,12 @@ /** - * @author Richard Davey + * @author Florian Vazelle + * @author Geoffrey Glaive * @copyright 2019 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ -var Equals = require('../TriangleToTriangle'); -var TriangleToLine = require('./GetTriangleToLine'); +var TriangleToTriangle = require('./TriangleToTriangle'); +var GetTriangleToLine = require('./GetTriangleToLine'); /** * Checks if two Triangles intersect, and returns the intersection points as a Point object array. @@ -31,18 +32,9 @@ var GetTriangleToTriangle = function (triangleA, triangleB, out) var lineB = triangleB.getLineB(); var lineC = triangleB.getLineC(); - var output = [ [], [], [] ]; - - var result = [ - GetTriangleToLine(triangleA, lineA, output[0]), - GetTriangleToLine(triangleA, lineB, output[1]), - GetTriangleToLine(triangleA, lineC, output[2]) - ]; - - for (var i = 0; i < 3; i++) - { - if (result[i] && output[i] !== []) { out.concat(output[i]); } - } + GetTriangleToLine(triangleA, lineA, out); + GetTriangleToLine(triangleA, lineB, out); + GetTriangleToLine(triangleA, lineC, out); } return out; diff --git a/src/geom/intersects/index.js b/src/geom/intersects/index.js index a3622a9bf..5c2b9592f 100644 --- a/src/geom/intersects/index.js +++ b/src/geom/intersects/index.js @@ -12,7 +12,16 @@ module.exports = { CircleToCircle: require('./CircleToCircle'), CircleToRectangle: require('./CircleToRectangle'), + GetCircleToCircle: require('./GetCircleToCircle'), + GetCircleToRectangle: require('./GetCircleToRectangle'), + GetLineToCircle: require('./GetLineToCircle'), + GetLineToRectangle: require('./GetLineToRectangle'), GetRectangleIntersection: require('./GetRectangleIntersection'), + GetRectangleToRectangle: require('./GetRectangleToRectangle'), + GetRectangleToTriangle: require('./GetRectangleToTriangle'), + GetTriangleToCircle: require('./GetTriangleToCircle'), + GetTriangleToLine: require('./GetTriangleToLine'), + GetTriangleToTriangle: require('./GetTriangleToTriangle'), LineToCircle: require('./LineToCircle'), LineToLine: require('./LineToLine'), LineToRectangle: require('./LineToRectangle'),