gpt4 book ai didi

php - 如何找到邻近的 Maidenhead 网格的定位器代码?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:45:51 26 4
gpt4 key购买 nike

我正在尝试用围绕单个 Maidenhead grid 的图 block 创建 map , 但是我不知道如何计算围绕单个 maidenhead 网格的 9 个网格。

例如,我有定位器 JO22OI60KE,我根据给定的坐标计算它,我想要其他(示例中的绿色)九个定位器围绕此网格。

Maidenhead grid

我环顾四周,但我看到的所有实现都集中在从单个纬度和经度中获取 Maidenhead。内 a extended "square"我可以计算它的邻居,但是一旦你在边缘(也就是说,接触一个新的子方 block ),它就超出了我的能力范围。

最佳答案

Cliff 的笔记:https://en.wikipedia.org/wiki/Maidenhead_Locator_System

  • MLS 坐标中的每一对字符都是网格中的一个单元格,每个后续网格都包含在前一个网格中。
  • 每对在字母和数字的碱基之间交替:18、10、24、GOTO 10 以达到您想要的精度。
  • 虽然规范大小写很重要,但实际上并不重要。

所以我们可以将JO22OI60KE分解为(J,O), (2,2), (O,I), (6,0), (K,E)(10,15), (2,2), (15,9), (6,0), (11,5)

我在 the lib I wrote [包含在下面] 中采用的方法是将坐标分解成它们的数字对,然后应用从最不重要到最重要的任何转换 [由一组偏移量表示],同时保持“进位”对.

但是,将所有内容乘以 259,200 x 259,200 [18*10*12*10*12] 网格可能会更简单,做简单的数学运算进行转换,然后使用更多数学方法重新格式化回 MLS 坐标。这也将大大简化与 lat/lng 之间的转换,因为这只是更简单的数学运算。

生活和学习。某事的第一次迭代通常只擅长教你应该如何做。 ¯\_(ツ)_/¯

代码:

包含在内是因为链接可能会消失,从而使答案变得无用。请检查 the repo 以防有 PR/更改。也列在 Packagist 上,

class Coordinate {
const ENC_FIELD = 0;
const ENC_SQUARE = 1;
const ENC_SUBSQUARE = 2;

const ENC_MAX = [
self::ENC_FIELD => 18,
self::ENC_SQUARE => 10,
self::ENC_SUBSQUARE => 24
];

const ENC_CHARS = [
self::ENC_FIELD => 'abcdefghijklmonpqr',
self::ENC_SQUARE => '0123456789',
self::ENC_SUBSQUARE => 'abcdefghijklmonpqrstuvwx'
];

// The spec only covers the first 4 pairs, the 4th pair "extended subsquare" uses the same encoding as "square"
// Non-standard extensions of the spec are to be implemented as extensions of this class.
protected static $encode_order = [ self::ENC_FIELD, self::ENC_SQUARE, self::ENC_SUBSQUARE, self::ENC_SQUARE ];

protected $pairs = [];
protected $precision;

public function __construct($pairs) {
foreach($pairs as $pair) {
$this->addPair($pair);
}
$this->precision = count($pairs);
}

public function transform($offsets) {
$offset_count = count($offsets);
$pair_count = $this->precision;
$encoding_count = count(static::$encode_order);

if( $offset_count > $pair_count ) {
throw new \Exception('Number of offsets greater than the number of coordinate pairs');
}

$carry = [0, 0];
$new_pairs = [];

// process the smallest offset first so that we don't have to specify a full array all the time
// and also so that carries can be efficiently handled
for( $o=1,$c=$pair_count; $o<=$c; $o++ ) {
$offset_index = $offset_count - $o;
$pair_index = $this->precision - $o;

$cur_pair = $this->pairs[$pair_index];
if( $offset_index < 0 ) {
$cur_offset = $carry;
} else {
$cur_offset = $offsets[$offset_index];

// apply carry
$cur_offset = [
$cur_offset[0] + $carry[0],
$cur_offset[1] + $carry[1]
];
}

$new_lat = $this->rollover($cur_pair->lat + $cur_offset[0], static::ENC_MAX[static::$encode_order[$pair_index]]);
$new_lng = $this->rollover($cur_pair->lng + $cur_offset[1], static::ENC_MAX[static::$encode_order[$pair_index]]);

$carry = [ $new_lat[1], $new_lng[1] ];
$new_pair = new Pair( $new_lat[0], $new_lng[0] );
array_unshift($new_pairs, $new_pair);
}
return new static($new_pairs);
}

public function toString() {
$output = '';
for( $i=0; $i<$this->precision; $i++ ) {
$output .= $this->encodeAs($this->pairs[$i]->lat, static::$encode_order[$i]);
$output .= $this->encodeAs($this->pairs[$i]->lng, static::$encode_order[$i]);
}
return $output;
}

public function __toString() {
return $this->toString();
}

protected function rollover($value, $base) {
if( $value < 0 ) {
$result = ($value % $base) ? $base + ($value % $base) : 0;
$carry = (int)ceil(abs($value) / $base) * -1;
} else if( $value >= $base ) {
$result = $value % $base;
$carry = (int)floor($value / $base);
} else {
$result = $value;
$carry = 0;
}

return [ $result, $carry ];
}

protected function addPair(Pair $pair) {
$this->pairs[] = $pair;
}

public static function fromString($input, $pad=true) {
$pairs = [];
$raw_pairs = array_map('str_split', str_split($input, 2));
for( $i=0,$c=count($raw_pairs); $i<$c; $i++ ) {
if( ! isset(static::$encode_order[$i]) ) {
throw new \Exception("No decoding specified for pair index $i");
}
$encoding = static::$encode_order[$i];
$pairs[] = new Pair(
self::decodeAs($raw_pairs[$i][0], $encoding),
self::decodeAs($raw_pairs[$i][1], $encoding)
);
}
if( $pad ) {
for( $c=count(static::$encode_order); $i<$c; $i++ )
$pairs[] = new Pair(0,0);
}
return new static($pairs);
}

public static function decodeAs($str, $encoding) {
$value = strpos(self::ENC_CHARS[$encoding], strtolower($str));
if( $value === false ) {
throw new \Exception("Invalid character $str for encoding $encoding");
}
return $value;
}

public static function encodeAs($int, $encoding) {
return self::ENC_CHARS[$encoding][$int];
}
}

class Pair {
protected $lat, $lng;

public function __construct($lat, $lng) {
$this->lat = $lat;
$this->lng = $lng;
}

public function __get($name) {
return $this->$name;
}

public function __set($name, $value) {
throw new Exception('Immutable');
}
}

关于php - 如何找到邻近的 Maidenhead 网格的定位器代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57420945/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com