Jump to content

# Phaser.Line.intersects does not work for floats

Go to solution Solved by CtlAltDel,

## Recommended Posts

Phaser.Line.intersects does not work for floats. Take these two lines for example:

`var line1 = new Phaser.Line(507.39999999999986, 271.60000000000014, 888.3738480697393, 576);var line2 = new Phaser.Line(384, 320, 608, 320);var intersection = Phaser.Line.intersects(line1, line2); // This is null`

I did not delve into the Phaser code, but it's pretty apparent the issue has to do with floats. I pulled the intersection function from this post and did some modification to it to work as I expected with floats:

`function linesIntersect (line1, line2) {        var x1 = line1.start.x, y1 = line1.start.y, x2 = line1.end.x, y2 = line1.end.y;        var x3 = line2.start.x, y3 = line2.start.y, x4 = line2.end.x, y4 = line2.end.y;        var realx=((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));        var realy=((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));        // These next lines where we round are key. If we don't do this, this function acts         // the same as Phaser.Line.intersects        x1 = Math.round(x1), y1 = Math.round(y1), x2 = Math.round(x2), y2 = Math.round(y2),         x3 = Math.round(x3), y3 = Math.round(y3), x4 = Math.round(x4), y4 = Math.round(y4);        var x = Math.round(realx);        var y = Math.round(realy);        if (isNaN(x)||isNaN(y)) {            return;        } else {            if (x1>=x2) {                if (!(x2<=x&&x<=x1)) {return;}            } else {                if (!(x1<=x&&x<=x2)) {return;}            }            if (y1>=y2) {                if (!(y2<=y&&y<=y1)) {return;}            } else {                if (!(y1<=y&&y<=y2)) {return;}            }            if (x3>=x4) {                if (!(x4<=x&&x<=x3)) {return;}            } else {                if (!(x3<=x&&x<=x4)) {return;}            }            if (y3>=y4) {                if (!(y4<=y&&y<=y3)) {return;}            } else {                if (!(y3<=y&&y<=y4)) {return;}            }        }        return {x: realx, y: realy};        }`

Of course, this has the chance of returning an intersection point where two lines don't actually intersect but are really close to intersecting, but I think this is preferable to not acknowledging an intersection when there actually is one.

I can make the modification myself and submit the pull request, but I wanted to get thoughts from others on whether or not this change makes sense. So, thoughts?

##### Share on other sites
• Solution

Just tested the code and the problem is the intersection is at:

Phaser.Point {x567.9753424657532y319.99999999999994copyFromfunctioninvertfunctionsetTofunction}

Which is ofcourse real close to the 320. This has to do with floating point accuracy.

I added a rounding to 3 decimals in the Phaser.Line.intersectsPoints function:
`    /*    Round to 3 decimals here, due to javascript floating point is 'broken'    http://stackoverflow.com/questions/11832914/round-to-at-most-2-decimal-places-in-javascript    See workaround explanation there in accepted answer there..    */    result.x = Math.round( ((((b1 * c2) - (b2 * c1)) / denom)+0.00001)*1000 ) / 1000;    result.y = Math.round( ((((a2 * c1) - (a1 * c2)) / denom)+0.00001)*1000 ) / 1000;`

That seems to fix the issues properly. 3 decimal accuracy should be plenty.

Will make a pull request shortly.

##### Share on other sites

Just tested the code and the problem is the intersection is at:

Phaser.Point {x567.9753424657532y319.99999999999994copyFrom: function, invert: function, setTo: function…}

Which is ofcourse real close to the 320. This has to do with floating point accuracy.

I added a rounding to 3 decimals in the Phaser.Line.intersectsPoints function:
`    /*    Round to 3 decimals here, due to javascript floating point is 'broken'    http://stackoverflow.com/questions/11832914/round-to-at-most-2-decimal-places-in-javascript    See workaround explanation there in accepted answer there..    */    result.x = Math.round( ((((b1 * c2) - (b2 * c1)) / denom)+0.00001)*1000 ) / 1000;    result.y = Math.round( ((((a2 * c1) - (a1 * c2)) / denom)+0.00001)*1000 ) / 1000;`

That seems to fix the issues properly. 3 decimal accuracy should be plenty.

Will make a pull request shortly.

CtlAltDel,

This is what I was referring to. Obviously the actual intersection is at 320, since it's impossible for those two lines to intersect at anything other than y=320 (since one of the lines is essentially y=320). Rounding to 3 decimals should definitely resolve the issues from using floats and horizontal/vertical lines. Thanks.

##### Share on other sites

Just tested the code and the problem is the intersection is at:

Phaser.Point {x567.9753424657532y319.99999999999994copyFrom: function, invert: function, setTo: function…}

Which is ofcourse real close to the 320. This has to do with floating point accuracy.

I added a rounding to 3 decimals in the Phaser.Line.intersectsPoints function:
`    /*    Round to 3 decimals here, due to javascript floating point is 'broken'    http://stackoverflow.com/questions/11832914/round-to-at-most-2-decimal-places-in-javascript    See workaround explanation there in accepted answer there..    */    result.x = Math.round( ((((b1 * c2) - (b2 * c1)) / denom)+0.00001)*1000 ) / 1000;    result.y = Math.round( ((((a2 * c1) - (a1 * c2)) / denom)+0.00001)*1000 ) / 1000;`

That seems to fix the issues properly. 3 decimal accuracy should be plenty.

Will make a pull request shortly.

I made this change in my copy of the code, and I noticed some false intersections started popping up. I changed it to round to the fourth decimal place and I saw far fewer false collisions (almost unnoticeable), so I'd suggest trying that or perhaps even a little bit better precision.

`result.x = Math.round( ((((b1 * c2) - (b2 * c1)) / denom)+0.000001)*10000 ) / 10000;result.y = Math.round( ((((a2 * c1) - (a1 * c2)) / denom)+0.000001)*10000 ) / 10000;`

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible. Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
• ### Recently Browsing   0 members

No registered users viewing this page.

×

• #### Activity

• Leaderboard
×
• Create New...