xzereus

Phaser.Line.intersects does not work for floats

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 this post


Link to post
Share on other sites

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 this post


Link to post
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 this post


Link to post
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;

Share this post


Link to post
Share on other sites

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.

Guest
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.