#!/usr/bin/perl -w
#
# japan1km.filled.grd -> TEM
# Nowral
# 00/4/5
#
# 内部の経緯度は全て秒単位
$0 =~ /^(.*):(.*)$/;
$cwd = $1;
&UTM::utminit();

# japan1km.filled.grdデータ諸元 > グローバル変数
$hds = 0x043C;
$npix = 2080;
$nlin = 2573;
$lat0 =  46 * 3600;
$lon0 = 122 * 3600;
$lat2 =  24 * 3600;
$lon2 = 148 * 3600;
$dlat = 30; # 0.00833333333333333 * 3600;
$dlon = 45; # 0.0125 * 3600;

$lat2 = $lat0 - $nlin*$dlat;
$lon2 = $lon0 + $npix*$dlon;
$hlat = $dlat / 2;
$hlon = $dlon / 2;

# 入力ファイルのループ
@files = sort grep {-f} @ARGV;
foreach $oldargv (@files) {
$oldargv =~ /^(.*):(.*)$/;
print "\n$2\n";

# ファイル読み込み >経緯度から標高ファイル決定
undef @ofss;
undef @hofs;
undef @hs;
$i = 0;
open(IN, $oldargv);
while(<IN>){
  next unless /^T\t/;
  @ed = split("\t");
  if($ed[9] ne "DMS") { die "Not DMS !"; }
#  die unless($ed[10]=~/WGS\s*84/i || $ed[10]=~/<NO TRANSLATION>/);

  $ed[5] =~ /(\d+)。(\d+)'(\d+\.?\d*)"/; # 緯度
  $b = $1*3600 + $2*60 + $3;
  $ed[6] =~ /(\d+)。(\d+)'(\d+\.?\d*)"/; # 経度
  $l = $1*3600 + $2*60 + $3;
# 近接三点を選択 < ロジック甘い?
  $ofs1 = &ll2ofs($b, $l);
  push(@ofss, $ofs1);
  $ofsd = &ll2ofs($b, $l-$hlon); # 左
  push(@ofss, $ofsd) unless($ofsd == $ofs1);
  $ofsd = &ll2ofs($b-$hlat, $l); # 下
  push(@ofss, $ofsd) unless($ofsd == $ofs1);
  $ofsd = &ll2ofs($b, $l+$hlon); # 右
  push(@ofss, $ofsd) unless($ofsd == $ofs1);
  $ofsd = &ll2ofs($b+$hlat, $l); # 上
  push(@ofss, $ofsd) unless($ofsd == $ofs1);
  die unless($#ofss == $i+2);

  @hs[$i .. $i+2] = ("-", "-", "-");
  $hofs{$ofss[$i]} .= " $i";
  $i++;
  $hofs{$ofss[$i]} .= " $i";
  $i++;
  $hofs{$ofss[$i]} .= " $i";
  $i++;
}
$nr = $i / 3;

# 水深読み込み <まとめて
open(IN, "$cwd:japan1km.filled.grd") || die;
foreach $ofs (sort keys %hofs) {
  seek(IN, $ofs, 0);
  read(IN, $_, 4);
  $h = unpack("f", $_);
  foreach $i (split(" ", $hofs{$ofs})) { $hs[$i] = $h; }
}

# 出力ファイル準備
$newargv = $oldargv . '.w/d';
open(OUT, ">$newargv");
MacPerl::SetFileInfo('GPSy', 'TEXT', $newargv);

# 標高補足
$i = 0;
open(IN, $oldargv);
while(<IN>){
  if(/^T\t/) {
    @ed = split("\t");
    $ed[5] =~ /(\d+)。(\d+)'(\d+\.?\d*)"/; # 緯度
    $b = $1*3600 + $2*60 + $3;
    $ed[6] =~ /(\d+)。(\d+)'(\d+\.?\d*)"/; # 経度
    $l = $1*3600 + $2*60 + $3;
# 平面で補間
    $zn = ($l/3600+180) / 6 % 60 + 1; # ゾーン < 西境界含む
    ($x, $y) = &UTM::sec2utm($b, $l, $zn);
    ($h1, $h2, $h3) = @hs[$i .. $i+2];
    ($x1, $y1) = &UTM::sec2utm(&ofs2cll($ofss[$i]), $zn);
    $i++;
    ($x2, $y2) = &UTM::sec2utm(&ofs2cll($ofss[$i]), $zn);
    $i++;
    ($x3, $y3) = &UTM::sec2utm(&ofs2cll($ofss[$i]), $zn);
    $i++;

    $d = $x1*$y2*$h3 + $x2*$y3*$h1 + $x3*$y1*$h2 - $x1*$y3*$h2 - $x2*$y1*$h3 - $x3*$y2*$h1;
    $u = $y2*$h3 + $y3*$h1 + $y1*$h2 - $y3*$h2 - $y1*$h3 - $y2*$h1;
    $v = $x1*$h3 + $x2*$h1 + $x3*$h2 - $x1*$h2 - $x2*$h3 - $x3*$h1;
    $w = $x1*$y2 + $x2*$y3 + $x3*$y1 - $x1*$y3 - $x2*$y1 - $x3*$y2;
    $h = ($d - $u*$x - $v*$y) / $w;
    $ed[8] = sprintf("%.1f", $h);
    $_ = join("\t", @ed);
  }
  else{ s/^(#\tRecords:\t)\d+/$1$nr/; } # データ数は正確に

  print OUT; # 書き出し
}
close(IN);
close(OUT);

# 1ファイル終了
print " ... done\n";
}

MacPerl::Quit(2);
die "The Unhappy End";



sub ll2ofs { # 経緯度 -> 先頭からのオフセット
  my($b, $l) =@_;
  my($x, $y);
  $x = int(($l - $lon0)/$dlon);
  $y = int(($lat0 - $b)/$dlat);
  return ($y*$npix + $x)*4 + $hds;
}

sub ofs2cll { # 先頭からのオフセット -> メッシュ中心の経緯度
  my($ofs) =@_;
  my($b, $l);
  my($x, $y);
  $ofs = ($ofs - $hds) / 4;
  $x = $ofs % $npix;
  $y = ($ofs - $x) / $npix;
  $b = $lat0 - $y * $dlat;
  $l = $lon0 + $x * $dlon;
  return ($b - $hlat, $l + $hlon);
}

package UTM; # グローバル変数隔離のため
# $pi, $rd, $a, $f, $e2, $ed2, $cad, $cbd, $ccd, $cdd, $ced

sub utminit { # グローバル変数準備
#定数
  $pi  = 4 * atan2(1, 1); # 円周率
  $rd  = $pi / 180;       # radian / degree

# 日本測地系
  $a   = 6377397.155;    # 赤道半径 (Tokyo)
  $f   = 1 / 299.152813; # 扁平率 (Tokyo)
  $e2  = 2*$f - $f*$f;   # 第1離心率
  $ed2 = $e2 / (1-$e2);  # 第2離心率

# 子午線弧長計算式係数
  my($e4, $e6, $e8);
  $e4 = $e2 * $e2;
  $e6 = $e4 * $e2;
  $e8 = $e6 * $e2;

  $cad = $a * (1-$e2) * ( 1 + 3/4*$e2 + 45/64*$e4 + 175/256*$e6 + 11025/16384*$e8 );
  $cbd = $a * (1-$e2) * (     3/4*$e2 + 15/16*$e4 + 525/512*$e6 +   2205/2048*$e8 );
  $ccd = $a * (1-$e2) * (               15/64*$e4 + 105/256*$e6 +   2205/4096*$e8 );
  $cdd = $a * (1-$e2) * (                            35/512*$e6 +    315/2048*$e8 );
  $ced = $a * (1-$e2) * (                                           315/16384*$e8 );

  return 1;
}

sub sec2utm { # 経緯度 -> UTM座標
  my($b, $l, $zn) =@_;
  my($x, $y) = &ll2xy($b/3600*$rd, ($l/3600-$zn*6+183)*$rd);
  return ($x * 0.9996, $y * 0.9996 + 500000);
}

sub ll2xy { # Gauss-Klueger
  my($b, $dl) = @_;
  my($dl2, $dl4, $sb, $cb, $cb3, $cb5, $tb2, $tb4, $eta2, $rn, $x, $y);

  $dl2 = $dl * $dl;
  $dl4 = $dl2 * $dl2;
  
  $sb = sin($b);
  $cb = cos($b);
  $cb3 = $cb * $cb * $cb;
  $cb5 = $cb3 * $cb * $cb;
  $tb2 = $sb * $sb / $cb / $cb;
  $tb4 = $tb2 * $tb2;
  
  $eta2 = $ed2 * $cb * $cb;
  $rn = $a / (1-$f) / sqrt(1+$eta2); # 卯酉線曲率半径
  
  $x = $cad*$b - $cbd/2*sin(2*$b) + $ccd/4*sin(4*$b)
    - $cdd/6*sin(6*$b) + $ced/8*sin(8*$b); # 赤道から緯度Bまでの子午線弧長
  $x += $rn/2*$sb*$cb*$dl2;
  $x += $rn/24*$sb*$cb3*(5-$tb2+9*$eta2+4*$eta2*$eta2)*$dl4;
  $x += $rn/720*$sb*$cb5*(61-58*$tb2+$tb4)*$dl4*$dl2;

  $y = $rn*$cb*$dl;
  $y += $rn/6*$cb3*(1-$tb2+$eta2)*$dl*$dl2;
  $y += $rn/120*$cb5*(5-18*$tb2+$tb4)*$dl*$dl4;

  return ($x, $y);
}