LoginSignup
4
1

More than 1 year has passed since last update.

EXCELで地図を描く

Last updated at Posted at 2020-03-29

概 要

 海岸線データをもとに地図を描画するVBA
 エクセル上に地図を描画できるが、それ以上でもそれ以下でもない。
 下の画像は国土地理院の海岸線データを基にメルカトル図法で描画した日本
 qiita06.PNG

海岸線データをエクセル上で描画する

 海岸線のデータは後述
 西経30度を端とするメルカトル図法で描画する方法です。
 GRS801回転楕円体として計算しています。
 メルカトル図法のため南北緯80度以上は計算していません。※南北端に近づくほど無限に東西に引き延ばされるため
 Minの値をいじることで縮尺を変更できます。が、エクセル上のXY座標の限界を突破した場合は描画できません

Option Explicit
Const Min = 10000 '1万分の1
Const a = 6378136.6 / Min
Const e = 8.18191910428158E-02


Function Atanh(Agmt)
    '双曲線アークタンジェント関数
    Atanh = Log((1 + Agmt) / (1 - Agmt)) / 2
End Function

Function LatCnvY(φ)
    LatCnvY = a * Atanh(Sin(φ * 4 * Atn(1) / 180)) - a * e * Atanh(e * Sin(φ * 4 * Atn(1) / 180))
'エクセル対応用
    LatCnvY = (a * Atanh(Sin(80 * 4 * Atn(1) / 180)) - a * e * Atanh(e * Sin(80 * 4 * Atn(1) / 180))) - LatCnvY
End Function

Function LonCnvX(λ)
    If λ <= -30 Then λ = λ + 360
    LonCnvX = λ * a * 4 * Atn(1) / 180
    'エクセル対応用
    LonCnvX = (30 * a * 4 * Atn(1) / 180) + LonCnvX
End Function
Sub メルカトル図法()
'***********************************************************************************************************
'メルカトル図法
'***********************************************************************************************************
'--- 記号表 ----------------------------------------------------------------------
' R:真球地球の半径
'λ:中央経線からの経度差
'中央経線:地図の中心となる線
'φ:緯度

'--- 地球の半径 ------------------------------------------------------------------
'/////////////////////////////////////////////////////////////////////////////////
'///GRS801楕円体                                                              ///
'/////////////////////////////////////////////////////////////////////////////////
'現世界の測地系で最も広く使われている
'a:長半径(赤道半径):6,378,136.6±0.1m
'b:短半径(極半径): 6356751.91548148m
'e:離心率:(√a^2-b^2)/a:0.081819191042815790
'f:扁平率:1/298.257222101
'f:扁平率:円又は球に比べどれだけつぶれているかを表す値
'/////////////////////////////////////////////////////////////////////////////////
'/// WGS84                                                                     ///
'/////////////////////////////////////////////////////////////////////////////////
'f:扁平率:1/298.257223563
'GRSとの差異は、地球の短半径(極半径)にすると約0.105mm異なるが、実用上問題はない。

'/////////////////////////////////////////////////////////////////////////////////

'--- x座標 -----------------------------------------------------------------------
'x = Rλ
'赤道を標準緯線とする接円筒図法に共通
'球、楕円体共通式
'λ = R/x

'--- y座標 -----------------------------------------------------------------------
'緯度φの緯線のy座標を表す式(球)
'y = R * log[tan{(φ/2)+(π/4)}]
'  = (R/2) * log{(1+sinφ)/(1-sinφ)}
'  = R * tanh^(-1)[sinφ]
'

'緯度φの緯線のy座標を表す式(楕円体)
'y = alog{[tan{(φ/2)+(π/4)}][(1-esinφ)/(1+sinφ)]^(e/2)}
'  = a * tanh^(-1)[sinφ] - a * e * tanh^(-1)[e * sinφ]

'***********************************************************************************************************

    'Dim b, e, f, x, y, φ, λ
    'b = 6356751.91548148
    'e = 8.18191910428158E-02
    'f = 1 / 298.257222101
    'φ = 35
    'λ = 140 - 135
    'x = a * λ
    'y = a * Atanh(Sin(φ)) - a * e * Atanh(e * Sin(φ))
    
    'Debug.Print "x:" & x & ",y:" & y

'***********************************************************************************************************
'地図の描画
'***********************************************************************************************************
'CSVファイルの読み取り
   Dim Path, CsvFile
   Dim Area(), Cnt
   Dim Lat, Lon
   
   Path = Application.GetOpenFilename("CSVファイル,*.csv?")
 
   Open Path For Input As #1
   Do Until EOF(1)
      Line Input #1, CsvFile
   Loop
   Close #1
   
   Cnt = 0
   Do Until Not InStr(1, CsvFile, "_") <> 0
      ReDim Preserve Area(Cnt)
      Area(Cnt) = Mid(CsvFile, 1, InStr(1, CsvFile, "_") - 1)
      CsvFile = Mid(CsvFile, InStr(1, CsvFile, "_") + 1)
      Cnt = Cnt + 1
   Loop
   
   Cnt = Cnt - 1
   
'地図の描画
   Do Until Cnt = 0
      '経度
      Lon = Mid(Area(Cnt), 1, InStr(1, Area(Cnt), ",") - 1)
      Lon = LonCnvX(Lon)
      Area(Cnt) = Mid(Area(Cnt), InStr(1, Area(Cnt), ",") + 1)
      '緯度
      Lat = Mid(Area(Cnt), 1, InStr(1, Area(Cnt), ",") - 1)
      If Lat > 80 Then Lat = 80
      Lat = LatCnvY(Lat)
      Area(Cnt) = Mid(Area(Cnt), InStr(1, Area(Cnt), ",") + 1)
      
      With ActiveSheet.Shapes.BuildFreeform(msoEditingAuto, Lon, Lat)
           Do Until Area(Cnt) = ""
              '経度
              Lon = Mid(Area(Cnt), 1, InStr(1, Area(Cnt), ",") - 1)
              Lon = LonCnvX(Lon)
              Area(Cnt) = Mid(Area(Cnt), InStr(1, Area(Cnt), ",") + 1)
              '緯度
              If InStr(1, Area(Cnt), ",") <> 0 Then
                 Lat = Mid(Area(Cnt), 1, InStr(1, Area(Cnt), ",") - 1)
              Else
                 Lat = Area(Cnt)
                 Area(Cnt) = ""
              End If
              If Lat > 80 Then Lat = 80
              Lat = LatCnvY(Lat)
              '描画
              Area(Cnt) = Mid(Area(Cnt), InStr(1, Area(Cnt), ",") + 1)
              .AddNodes msoSegmentLine, msoEditingAuto, Lon, Lat
           Loop
           .ConvertToShape.Select
      End With
      
      Cnt = Cnt - 1
   Loop
'***********************************************************************************************************
End Sub

図形の描画に関しては以下の通り
With ActiveSheet.Shapes.BuildFreeform(msoEditingAuto, X座標, Y座標)で指定する部分が始点
With中の.AddNodes 部分が中点~終点で、複数設定すると頂点を増やせる。
繰り返し処理でも頂点は増やすことが可能
始点と終点を同じにすると自動で閉じた図形に。

      With ActiveSheet.Shapes.BuildFreeform(msoEditingAuto, X座標, Y座標)
           .AddNodes msoSegmentLine, msoEditingAuto, X座標, Y座標
           .AddNodes msoSegmentLine, msoEditingAuto, X座標, Y座標
           .ConvertToShape.Select
      End With

緯度経度をエクセル上のXY座標に変換する式については、コメントアウトしている部分とfunctionのとおり
エクセル上のXY座標の確認についてはこちらの記事を参考程度にどうぞ

海岸線データダウンロード

 こちらのページから全レイヤをダウンロードする。
※下図赤枠
qiita01.PNG

海岸線データをCSVへ変換

解凍したデータの中のcoastl_jpn.shpをQGISに取り込む。
qiita02.PNG
レイヤ上で右クリックし名前を付けて保存を選択
qiita07.PNG
形式はCSVを選択し、下図のように設定する。※WGS84を選択
保存場所と保存名はなんでもいい。
qiita03.PNG

データの編集

作成したデータをメモ帳で開く。
qiita04.PNG
「一行目」と「"LINESTRING (」を削除
「半角スペース」を「,(カンマ)」に変換
「)",BA010,1,1,JPN」と「)",BA010,3,1,JPN」を「 _ 」に変換
一番最後の「 _ 」を削除
し上書き保存します。
※1:「 _ 」の空白部分は含めない。
※2:「 _ 」ごとに一つの図形として取り扱います。地理院のデータは本州や九州、北海道など一本の線で描かれていません。
次に改行コードを置換できるソフトで開き、改行コードを削除する。
ここではAtomを使用
Atomの場合、「 * 」を選択し、「\r\n」を検索窓に入れると置換できる。
これで読み込みデータは完成。
qiita05.PNG

さいごに

 図形を描けるが現在のところそれ以上の応用は難しそう。
 エクセル上のXY座標を取得する関数でもあれば違うのだろうが……

参 考

地図投影法――地理空間情報の技法 著者:政春 尋志(国土地理院基本図情報部長)

4
1
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
4
1