Search code examples
phpalgorithmsortingcoordinatescoordinate-systems

I have coordinates pool with x,y combniation I need to match nearest match of given x,y


Example

1   8.919280,45.622651  
2   8.910296,45.626021  
3   8.914084,45.627028  
4   8.913913,45.62941  

I have to match x,y not sum of x and y but closest of x and y. not closest of (x+y) or ((x1-x)+(y1-y)) both are wrong I need perfect match.

8.912680,45.629392

foreach($pair_coordinates as $pair_coordinate)
                    {
                    sscanf((string)$pair_coordinate, '%f,%f',$longitude, $latitude);
                        $data[$move]['lng'] = $longitude;
                        $data[$move]['lat'] = $latitude;
                        $data[$move]['longitude'] = ($longitude-$_POST['k_lng']);
                        $data[$move]['latitude'] = ($latitude-$_POST['k_lat']);

                        $data[$move]['diff'] = $data[$move]['longitude'] + $data[$move]['latitude'];

                        $data[$move]['diff'] = abs($data[$move]['diff']);

                        $sort[$move] = $data[$move]['diff'];
                        $sort_old[$move] = $data[$move]['diff'];

                        $data[$move]['zona'] = (string)$placemarker->ExtendedData->Data[2]->value;
                        $data[$move]['codcom'] = (string)$placemarker->ExtendedData->Data[1]->value;
                        $data[$move]['markername'] = (string)$placemarker->name;
                        if($data[$move]['longitude'] < 0 || $data[$move]['latitude'] < 0)
                        {
                            unset($sort[$move]);
                        }


                        $move++;
                    }







                    asort($sort);

Solution

  • Maybe this will help you get on track:

    <?php
    
    $coords = array(
        array("lng" => 8.919280, "lat" => 45.622651),
        array("lng" => 8.910296, "lat" => 45.626021),
        array("lng" => 8.914084, "lat" => 45.627028),
        array("lng" => 8.913913, "lat" => 45.62941)
    );
    
    $find = array("lng" => 8.912680, "lat" => 45.629392);
    
    $idx = null;
    $shortest = null;
    
    foreach($coords as $k => $v)
    {
        // I know the abs() calls are optional, but this allows for some other logic to be used on the individual distances aswell.
        $dLng = abs($find["lng"] - $v["lng"]); 
        $dLat = abs($find["lat"] - $v["lat"]);
    
        $distance = sqrt($dLng * $dLng + $dLat * $dLat);
    
        if (!$shortest || $distance < $shortest)
        {
            $shortest = $distance;
            $idx = $k;
        }
    }
    
    if ($idx)
    {
        echo "Found:\n";
        print_r($coords[$idx]);
    } else {
        echo "Nothing found.";
    }
    

    Output:

    Found:
    Array
    (
        [lng] => 8.913913
        [lat] => 45.62941
    )
    

    Another solution using array_reduce:

    <?php
    
    $coords = array(
        array("lng" => 8.919280, "lat" => 45.622651),
        array("lng" => 8.910296, "lat" => 45.626021),
        array("lng" => 8.914084, "lat" => 45.627028),
        array("lng" => 8.913913, "lat" => 45.62941)
    );
    
    $find = array("lng" => 8.912680, "lat" => 45.629392);
    
    function distance($a, $b)
    {
        $dLng = abs($a["lng"] - $b["lng"]);
        $dLat = abs($a["lat"] - $b["lat"]);
    
        $distance = sqrt($dLng * $dLng + $dLat * $dLat);
    
        return $distance;
    }
    
    
    $nearest = array_reduce($coords, function($carry, $item) use ($find)
    {
        if (!$carry)
            return $item;
    
        $dCarry = distance($find, $carry);
        $dItem = distance($find, $item);
    
        return $dCarry < $dItem ? $carry : $item;
    }, null);
    
    print_r($nearest);
    

    Output:

    Array
    (
        [lng] => 8.913913
        [lat] => 45.62941
    )