Jump to content

Phaser.Line.intersects does not work for floats


xzereus
 Share

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?

 

Link to comment
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.

Link to comment
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.

Link to comment
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;
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...