brick / geo

GIS geometry library for PHP
MIT License
221 stars 31 forks source link

Is the order important when we call distance function ? #39

Closed fabrice-dresscodes closed 4 months ago

fabrice-dresscodes commented 2 years ago

Hi,

Context : POSTGIS function - PHP7.4 - Wood cutting project

I've noticed when I call this function that way :

        $distance = $existingCut->getGISForme()->distance($new_cut->getGISForme() );

or that whay :

        $distance = $new_cut->getGISForme()->distance($existingCut->getGISForme() );

I don't have the same result.

With the first row, I sometime get a distance between my curvepolygon (circle) equals to 0 ( WITH no intersections with intersect function). How is that possible ? How can I get no intersections between curve-polygons but with zero distance ?

I'v changed my code for the second row but I would prefer to understand the difference.

Thanks,

BenMorel commented 2 years ago

Hi, AFAIK, there should not be any difference. Could you please share the WKT of the 2 geometries, so that I can try to reproduce it locally?

nono303 commented 2 years ago

Hi @BenMorel @fabrice-dresscodes, FYI I just checked with my distance functions (4326 corrds) ; order doesn't matter. results:

>>>>>> testDistance(45.832615, 6.865129,44.922525, 6.359967))
-----------------------------------------------------
* 1 iterations                 | ms       | m or °
-----------------------------------------------------
distanceGeod (1 iter)          | 57.511   | 108609.97
haversineGreatCircleDistance   | 0        | 108738.41
vincentyGreatCircleDistance    | 0        | 108738.41
phpGeosDistanceLatLon          | 9.502    | 1.04
phpGeosHausdorffDistanceLatLon | 0.5      | 1.04
brickGeosDistanceLatLon        | 8.002    | 1.04
brickMySQLDistanceLatLon       | 4.001    | 108610.81
MySQLDistanceLatLon            | 0        | 108610.81
-----------------------------------------------------
>>>>>> testDistance(44.922525, 6.359967,45.832615, 6.865129))
-----------------------------------------------------
* 1 iterations                 | ms       | m or °
-----------------------------------------------------
distanceGeod (1 iter)          | 25.505   | 108609.97
haversineGreatCircleDistance   | 0        | 108738.41
vincentyGreatCircleDistance    | 0        | 108738.41
phpGeosDistanceLatLon          | 0        | 1.04
phpGeosHausdorffDistanceLatLon | 0.5      | 1.04
brickGeosDistanceLatLon        | 0        | 1.04
brickMySQLDistanceLatLon       | 0.5      | 108610.81
MySQLDistanceLatLon            | 0        | 108610.81
-----------------------------------------------------

code:

    public static function haversineGreatCircleDistance($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = EARTHRADIUS){
        $latFrom = deg2rad($latitudeFrom);
        $lonFrom = deg2rad($longitudeFrom);
        $latTo = deg2rad($latitudeTo);
        $lonTo = deg2rad($longitudeTo);

        $latDelta = $latTo - $latFrom;
        $lonDelta = $lonTo - $lonFrom;

        $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
            cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
        return $angle * $earthRadius;
    }

    public static function brickGeosDistanceLatLon($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
        GeometryEngineRegistry::set(new GEOSEngine());
        return  (Point::xy($latitudeFrom, $longitudeFrom, 4326))->distance(Point::xy($latitudeTo, $longitudeTo, 4326));
    }

    public static function brickMySQLDistanceLatLon($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
        global $pdo;
        if(is_null($pdo)) $pdo = new PDO('mysql:host='.PDO_HOST, PDO_LOGIN, PDO_PASS);
        GeometryEngineRegistry::set(new PDOEngine($pdo));
        return  (Point::xy($latitudeFrom, $longitudeFrom, 4326))->distance(Point::xy($latitudeTo, $longitudeTo, 4326));
    }

    public static function phpGeosDistanceLatLon($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
        $a = geoPHP::load('SRID=4326;POINT ('.$latitudeFrom.' '.$longitudeFrom.')',"wkt");
        $b = geoPHP::load('SRID=4326;POINT ('.$latitudeTo.' '.$longitudeTo.')',"wkt");
        return $a->distance($b);
    }

    public static function phpGeosHausdorffDistanceLatLon($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
        $a = geoPHP::load('SRID=4326;POINT ('.$latitudeFrom.' '.$longitudeFrom.')',"wkt");
        $b = geoPHP::load('SRID=4326;POINT ('.$latitudeTo.' '.$longitudeTo.')',"wkt");
        return $a->hausdorffDistance($b);
    }

    public static function MySQLDistanceLatLon($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo){
        global $pdo;
        if(is_null($pdo)) $pdo = new PDO('mysql:host='.PDO_HOST, PDO_LOGIN, PDO_PASS);
        return $pdo->query("SELECT ST_Distance(ST_GeomFromText('POINT(".$latitudeFrom.' '.$longitudeFrom.")', 4326), ST_GeomFromText('POINT(".$latitudeTo.' '.$longitudeTo.")', 4326))")->fetchAll()[0][0];
    }
BenMorel commented 2 years ago

Thanks for your feedback, @nono303. @fabrice-dresscodes, looking forward to your reproduce code!

BenMorel commented 4 months ago

Closing due to lack of feedback.