创建给定行数,列数和起点的坐标网格

时间:2018-10-04 04:59:11

标签: php coordinates extrapolation

在将纬度/经度对推断到正方形网格时,我需要一些帮助。网格为200x200单元。每个单元为1NM * 1NM。起始纬度对位于网格的西南角。

例如,第0列和第0行应为前四个坐标对,以使第一个网格单元为1NM * 1NM。第0列第1列应该是接下来的四个坐标对,以使下一个网格单元格高于第一个网格单元格。 200行之后,移至下一列,依此类推。

我尝试使用以下PHP代码进行此操作,但似乎无法正确推断数据。

<?php
header('Content-Type:text/plain');

// southwest coordinate pair (starting point)
$lat = 38.883672;
$lon = -105.698848;

for($col = 0; $col < 200; $col++) {
  $startLat = $startLat2 = 0;
  $startLon = $startLon2 = 0;

  if($col > 0) {
    $lat = Extrapolate($lat, $lon, 1.0, 90)[0];
    $lon = Extrapolate($lat, $lon, 1.0, 90)[1];
  }

  $debug = sprintf("%s,%s\r\n", $lat, $lon);

  for($row = 0; $row < 200; $row++) {
    if($row == 0) {
      $startLat = Extrapolate($lat, $lon, 1.0, 360)[0];
      $startLon = Extrapolate($lat, $lon, 1.0, 360)[1];

      $startLat2 = Extrapolate($lat, $lon, 1.0, 90)[0];
      $startLon2 = Extrapolate($lat, $lon, 1.0, 90)[1];

      $nextLat = $startLat;
      $nextLon = $startLon;

      $nextLat2 = $startLat2;
      $nextLon2 = $startLon2;

      $debug .= sprintf("%s,%s\r\n", $startLat, $startLon);
      $debug .= sprintf("%s,%s\r\n", $startLat2, $startLon2);
    }
    else {
      $nextLat = Extrapolate($nextLat, $nextLon, 1.0, 360)[0];
      $nextLon = Extrapolate($nextLat, $nextLon, 1.0, 360)[1];

      $nextLat2 = Extrapolate($nextLat2, $nextLon2, 1.0, 90)[0];
      $nextLon2 = Extrapolate($nextLat2, $nextLon2, 1.0, 90)[1];

      $debug .= sprintf("%s,%s\r\n", $nextLat, $nextLon);
      $debug .= sprintf("%s,%s\r\n", $nextLat2, $nextLon2);
    }
  }

  echo $debug;
}

function Extrapolate($lat1,$long1,$d,$angle)
{
  # Earth Radious in KM
  $R = 6378.14;

  # Degree to Radian
  $latitude1 = $lat1 * (M_PI/180);
  $longitude1 = $long1 * (M_PI/180);
  $brng = $angle * (M_PI/180);

  # Distance to NM
  $d *= 1.85200;

  $latitude2 = asin(sin($latitude1)*cos($d/$R) + cos($latitude1)*sin($d/$R)*cos($brng));
  $longitude2 = $longitude1 + atan2(sin($brng)*sin($d/$R)*cos($latitude1),cos($d/$R)-sin($latitude1)*sin($latitude2));

  # back to degrees
  $latitude2 = $latitude2 * (180/M_PI);
  $longitude2 = $longitude2 * (180/M_PI);

  $lat2 = round ($latitude2,6);
  $long2 = round ($longitude2,6);

  // Push in array and get back
  $coords[0] = $lat2;
  $coords[1] = $long2;
  return $coords;
 }

1 个答案:

答案 0 :(得分:0)

有一种解决此问题的捷径,可以识别1NM“等于” 1/60度。我之所以说“等于”,是因为这是一个旧定义,虽然没有幸免于非常精确的现代测量,但仍然有用。

坐标随着N和E的移动而增加。这意味着向东移动1NM或向北移动1NM(对应于1NM网格),您只需向各自的坐标添加度数的1/60。

例如,如果您从

开始

//西南坐标对(起点)

$lat = 38.883672;
$lon = -105.698848;

向北移动1NM(1个网格正方形)

$lat[1] = 38.883672 + .016667; // 38.900339

向东移动1NM(1个网格正方形)

$lon[1] = -105.698848 + .016667; // -105.682181

因此,使用此功能,您只需增加即可轻松构建200x200的网格。

右上角的网格角将具有坐标:

向北移动200NM(200个网格正方形)

$lat[1] = 38.883672 + .016667*200; // 42.217072

向东移动200NM(200格正方形)

$lon[1] = -105.698848 + .016667*200; // -102.365448

如果您要构建网格,最好将其存储在二维数组中,如下所示:

<?php
//header('Content-Type:text/plain');

// southwest coordinate pair (starting point)
$lat = 38.883672;
$lon = -105.698848;

for ($col=0; $col< 200; $col++){
    echo PHP_EOL."Grid values for col ".$col.PHP_EOL;
    for ($row=0; $row< 200; $row++){
      $newCoords = extrapolate($lat,$lon,$row,$col);
      $coords[$col][$row]["lat"] = $newCoords["lat"];
      $coords[$col][$row]["lon"] = $newCoords["lon"];
      echo "Row ".$row." = ".$coords[$col][$row]["lat"]." , ";
      echo $coords[$col][$row]["lon"].PHP_EOL;
    }
}

function extrapolate($lat,$lon,$row,$col){
  $newCoords["lat"] = round($lat + (1/60)*$row,6);
  $newCoords["lon"] = round($lon + (1/60)*$col,6);
  return ($newCoords);
}

现在,如果您喜欢使用自己的方法来计算偏移量,则只需修改extrapolate()函数。

编辑:根据要求添加。

一旦有了上面的数组,就可以如下选择每个单元格周围的坐标。通过示例将选择底部的SW单元格。它的4个坐标对是:

// SW角

$coords[0][0]["lat"];
$coords[0][0]["lon"];

// NW角

$coords[0][1]["lat"];
$coords[0][1]["lon"];

// SE角

$coords[1][0]["lat"];
$coords[1][0]["lon"];

// NE角

$coords[1][1]["lat"];
$coords[1][1]["lon"];

通过另一个示例,将选择顶部的NE单元。它的4个坐标对是:

// SW角

$coords[198][198]["lat"];
$coords[198][198]["lon"];

// NW角

$coords[198][199]["lat"];
$coords[198][199]["lon"];

// SE角

$coords[199][198]["lat"];
$coords[199][198]["lon"];

// NE角

$coords[199][199]["lat"];
$coords[199][199]["lon"];

有帮助吗?