5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PowerShellで緯度経度と平面直角座標系を変換する。

Posted at

国土地理院のサイトで緯度経度と平面直角座標系を変換する事ができます。
業務に使う用に作ったのですがひょっとしたら需要があるかもしれないのでここに置いておきます。
平面直角座標系でつかう基準点を間違うととんでもない数値になるので注意してください。

#度分秒から10進数度単位への変換

.ps1
Function Convert-DegreesToDecimalDegrees{
  [outputtype([Double])]
  param(
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '度'
    )]
    [int]$degree,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '分'
    )]
    [ValidateRange(0,59)]
    [int]$minute,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '秒'
    )]
    [Double]$second,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'StringValue',
      helpmessage = '度分秒を文字列で'
    )]
    [string]$degreesString
  )
  begin{
    $tmp = 10000000000000000;
  }
  process{
    #パラメータセット
    switch($PsCmdlet.ParameterSetName){
      'StringValue'{
        if(
            $degreesString -match '(?<degree>\d+)°(?<minute>\d+)′(?<second>\d+[\.\d+]*)″'
        ){
            $degree = [int]$Matches.degree;
            $minute = [int]$Matches.minute;
            $second = [double]$Matches.second;
        }
        elseif(
            $degreesString -match '(?<degree>\d+)度(?<minute>\d+)分(?<second>\d+[\.\d+]*)秒' 
        ){
            $degree = [int]$Matches.degree;
            $minute = [int]$Matches.minute;
            $second = [double]$Matches.second;
        }
        else{
            throw 'not match degrees string'
        }
        break;
      }
      'NumericValue'{break}
    } 
    #微小単位が消えないよう桁あげて分秒計算
    [Double]$c = ((($minute*$tmp)+(($second*$tmp)/60))/60) / $tmp;
    [Double]$decimalDegree = $degree + $c;
    return $decimalDegree
  }
}

#10進度単位から度単位への変換

.ps1
function Convert-DecimalDegreesToDegrees{
  [outputtype([Management.Automation.PSCustomObject])]
  param($decimalDegree)
  $degSplited =  $("$decimalDegree").split('.');
  $degree     = [int]$degSplited[0] ;
  $mintmp     = [double]::Parse($('0.'+ ($degSplited[1]))) * 60;
  $minSplited = $("$mintmp").split('.');
  $minute     = [int]$minSplited[0];
  $secondtmp  = [Double]::Parse($('0.'+ ($minSplited[1]))) * 60;
  $second     = [Math]::Round($secondtmp,12);
  $obj = [pscustomobject]@{degree=$degree;minute=$minute;second=$second;decimalDegree=$decimalDegree};
  return $obj
}

#平面直角座標・緯度経度変換

.ps1
function Convert-LatLongToXY {
  [outputtype([array])]
  param(
    [parameter(
      mandatory = $false,
      helpmessage = '測地系		=1[日本測地系] =2[世界測地系]'
    )]
    $refFrame = 2,
    [parameter(
      mandatory = $true,
      ValueFromPipelineByPropertyName = $true,    
      helpmessage = '系番号(平面直角座標系)		系番号1〜19を指定する'
    )]
    [ValidateRange(1,19)]
    [int]$zone = 9,
    [parameter(
      mandatory = $true,
      ValueFromPipelineByPropertyName = $true,
      helpmessage = '緯度		degree'
    )]
    [double]$latitude = 0,
    [parameter(
      mandatory = $true,
      ValueFromPipelineByPropertyName = $true,    
      helpmessage = '経度		degree'
    )]
    [double]$longitude = 0
  )
  begin{
    $url = 'http://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2xy.pl?'
  }
  process{
    $request = "refFrame=$refFrame&zone=$zone&latitude=$latitude&longitude=$longitude&outputType=json"
    $requestURI = $url + $request  ;
    $result = Invoke-RestMethod -Uri $requestURI -DisableKeepAlive;
    if("$($result.ExportData.ErrMsg)" -ne ''){
      throw $result.ExportData.ErrMsg;
    };
    $answer = [pscustomobject]$result.OutPutData;
    $answer|Add-Member -NotePropertyName zone -NotePropertyValue $zone -PassThru;
  }
  end{
    return 
  }
}

#直角座標から緯度経度

.ps1
function Convert-XYToLatLong {
  [outputtype([pscustomobject])]
  param(
    [parameter(
      mandatory = $false,
      helpmessage = '測地系		=1[日本測地系] =2[世界測地系]'
    )]
    $refFrame = 2,
    [parameter(
      mandatory = $true,
      ValueFromPipelineByPropertyName = $true,    
      helpmessage = '系番号(平面直角座標系)		系番号1〜19を指定する'
    )]
    [ValidateRange(1,19)]
    [int]$zone = 9,
    [parameter(
      mandatory = $true,
      ValueFromPipelineByPropertyName = $true,
      helpmessage = 'X座標		小数点以下3桁まで指定可(m)'
    )]
    [double]$publicX = 0,
    [parameter(
      mandatory = $true,
      ValueFromPipelineByPropertyName = $true,    
      helpmessage = 'Y座標		小数点以下3桁まで指定可(m)'
    )]
    [double]$publicY = 0
  )
  begin{   
    $url = 'http://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/xy2bl.pl?';
  }
  process{
    $publicX = [Math]::Round($publicX,3);
    $publicY = [Math]::Round($publicY,3);
    $request = "refFrame=$refFrame&zone=$zone&publicX=$publicX&publicY=$publicY&outputType=json";
    $requestURI = $url + $request  ;
    $result = Invoke-RestMethod -Uri $requestURI -DisableKeepAlive;
    if("$($result.ExportData.ErrMsg)" -ne ''){
      throw $result.ExportData.ErrMsg;
    };
    $answer = [pscustomobject]$result.OutPutData;
    $answer|Add-Member -NotePropertyName zone -NotePropertyValue $zone -PassThru;
  }
  end{
    return 
  }
}

#直角座標での距離を求める

.ps1
function Get-XYLength {
  [CmdletBinding()]
  [outputtype([pscustomobject])]
  param(
    [parameter(
      ParameterSetName = 'NumericValue',
      mandatory = $false,
      helpmessage = '測地系		=1[日本測地系] =2[世界測地系]'
    )]
    [parameter(
      ParameterSetName = 'ObjectValue',
      mandatory = $false,
      helpmessage = '測地系		=1[日本測地系] =2[世界測地系]'
    )]    
    $refFrame = 2,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '系番号(平面直角座標系)		系番号1〜19を指定する'
    )]
    [ValidateRange(1,19)]
    [int]$zone = 9,
    [parameter(
      mandatory = $true,
      helpmessage = 'X座標		小数点以下3桁まで指定可(m)'
    )]
    [double]$publicX1 = 0,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = 'Y座標		小数点以下3桁まで指定可(m)'
    )]
    [double]$publicY1 = 0,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = 'X座標		小数点以下3桁まで指定可(m)'
    )]
    [double]$publicX2 = 0,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = 'Y座標		小数点以下3桁まで指定可(m)'
    )]
    [double]$publicY2 = 0,
    
    [parameter(
      mandatory = $true,
      ParameterSetName = 'ObjectValue'
    )]
    [pscustomobject]$object1,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'ObjectValue'
    )]
    [pscustomobject]$object2 
  )
  begin{
    $url = 'http://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/xy2st.pl?';
  }
  process{
    switch($PsCmdlet.ParameterSetName){
      'ObjectValue'{
        if($object1.zone -eq $object2.zone){
          $zone = $object1.zone ;
        }
        else{
          throw 'not mach Objects zone property';
        }
        $publicX1 = $object1.publicX;
        $publicY1 = $object1.publicY;     
        $publicX2 = $object2.publicX;
        $publicY2 = $object2.publicY;
        break;
      }
      'NumericValue'{break}
    }  
    $publicX1 = [Math]::Round($publicX1,3);
    $publicY1 = [Math]::Round($publicY1,3);
    $publicX2 = [Math]::Round($publicX2,3);
    $publicY2 = [Math]::Round($publicY2,3);
    $request = "refFrame=$refFrame&zone=$zone&publicX1=$publicX1&publicY1=$publicY1&publicX2=$publicX2&publicY2=$publicY2&outputType=json";
    $requestURI = $url + $request  ;
    $result = Invoke-RestMethod -Uri $requestURI -DisableKeepAlive;
    if("$($result.ExportData.ErrMsg)" -ne ''){
      throw $result.ExportData.ErrMsg;
    };
    $answer = [pscustomobject]$result.OutPutData;
    $answer
  }
  end{
    return 
  }
}

#世界測地系で直線距離

.ps1
function Get-LatLongLength {
  [CmdletBinding()]
  [outputtype([pscustomobject])]
  param(
    [parameter(
      mandatory = $false,
      ParameterSetName = 'ObjectValue',
      helpmessage = 'GRS80(世界測地系)かbessel(日本測地系)を指定。初期値は世界測地系'
    )]
    [parameter(
      mandatory = $false,
      ParameterSetName = 'NumericValue',
      helpmessage = 'GRS80(世界測地系)かbessel(日本測地系)を指定。初期値は世界測地系'
    )]
    [ValidateSet('GRS80','bessel')]
    [string]$ellipsoid = 'GRS80',
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '出発点緯度 degree'
    )]
    [double]$latitude1 = 0,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '出発点経度 degree'
    )]
    [double]$longitude1 = 0,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '到着点緯度 degree'
    )]
    [double]$latitude2 = 0,
    [parameter(
      mandatory = $true,
      ParameterSetName = 'NumericValue',
      helpmessage = '到着点経度 degree'
    )]
    [double]$longitude2 = 0,    
    [parameter(
      mandatory = $true,
      ParameterSetName = 'ObjectValue'
    )]
    [pscustomobject]$object1,
    [parameter(
      mandatory = $true,
      position = 1,
      ParameterSetName = 'ObjectValue'
    )]
    [pscustomobject]$object2 
  )
  begin{
    $url = 'http://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/bl2st_calc.pl?';
  }
  process{
    switch($PsCmdlet.ParameterSetName){
      'ObjectValue'{
        $latitude1  = $object1.latitude;
        $longitude1 = $object1.longitude;
        $latitude2  = $object2.latitude;
        $longitude2 = $object2.longitude;
        break;
      }
      'NumericValue'{break}
    }
    $request    = "ellipsoid=$ellipsoid&latitude1=$latitude1&longitude1=$longitude1&latitude2=$latitude2&longitude2=$longitude2&outputType=json";
    $requestURI = $url + $request  ;
    $result = Invoke-RestMethod -Uri $requestURI -DisableKeepAlive;
    if("$($result.ExportData.ErrMsg)" -ne ''){
      throw $result.ExportData.ErrMsg;
    };
    $answer = [pscustomobject]$result.OutPutData;
    $answer
  }
  end{
    return 
  }
}
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?