phpgeo icon indicating copy to clipboard operation
phpgeo copied to clipboard

Line::intersectsLine() is buggy

Open vlad-vinogradov opened this issue 2 years ago • 3 comments

Hello, Unfortunately, the Line::intersectsLine() method doesn't always work correctly. Try this test:

<?php
declare(strict_types=1);
require 'vendor/autoload.php';

use Location\Coordinate;
use Location\Line;

$line1 = new Line(
    new Coordinate(0.0, 0.0),
    new Coordinate(0.0, 2.0)
);
$line2 = new Line(
    new Coordinate(2.0, 2.0),
    new Coordinate(0.0, 10.0)
);
if ($line1->intersectsLine($line2)) {
    echo 'Line::intersectsLine() is buggy!'.PHP_EOL;
}

vlad-vinogradov avatar Sep 10 '22 17:09 vlad-vinogradov

Added a test for this issue: https://github.com/mjaschen/phpgeo/compare/master...fix/96

@nilshoerrmann It seems that there's a bug when checking for line intersection for some edge cases – do you have an idea for a fix/workaround?

mjaschen avatar Sep 12 '22 07:09 mjaschen

I'll have a look at this over the next days.

nilshoerrmann avatar Sep 12 '22 07:09 nilshoerrmann

From a quick look at the source, in intersectsLine() we have these conditions:

// the lines are collinear or touch
if (
    in_array(self::ORIENTATION_COLLINEAR, $orientation, true)
    && (new Intersection())->intersects($this, $line, false)
) {
    return true;
}

This only works if all points are collinear but fails if this is only true for three points (as in the example). So we would either have to switch to high precision for all calculations – (new Intersection())->intersects($this, $line, true) – or we would have to add a more precise condition that distinguises between three collinear points (setting precision to true) and four collinear points (settings precision to false).

nilshoerrmann avatar Sep 12 '22 07:09 nilshoerrmann