「日本で最も丸い湖」を探して - GIS, 円形度, 最急降下法
はじめに
温泉で有名な北海道の登別(のぼりべつ)には「のぼりべつクマ牧場」というものがあり、そこから隣の白老(しらおい)にある 倶多楽湖(くったらこ) という湖を望むことができます。
私はこれまで二度、クマ牧場を訪れましたが、一度目は霧で隠れており、二度目にその姿を目にすることができました。
この倶多楽湖は 日本で最も丸い と言われているそうです。
倶多楽湖は直径3キロメートル、周囲約8キロメートルの小さな丸いカルデラ湖。その丸さは日本で最も円に近いといいます。
たしかに、地図で見ると、とても丸い感じがします。
しかし、本当にこれより丸い湖はないのでしょうか?
そもそも「丸い」とは何か
札幌には地元民から「まるいさん」という愛称で親しまれている百貨店がありますが、そもそも、「丸い」とはどう定義されるのでしょうか。
真円度
まず、英語版Wikipediaにある「Roundness」という記事を参照してみましょう。
ここでは、ISOでの定義として「図形の”内接円”と”外接円”の半径の比率」というものが紹介されています。
「内接円」(inscribed circle)、つまり図形にすっぽり収まる円のうち最大のもの(その多角形の内部にあり全ての辺に接する円)、そして「外接円」(circumscribed circle)、すなわち図形をすっぽりと収めることができる円のうち最小のもの(その多角形の全ての頂点を通る円)、これらの大きさの比をもとにしています。
図: Claudio Rocchini, CC BY-SA 4.0 DEED, File:Iso roundness.svg - Wikipedia
上記の例では、左に示した「四角形」のroundnessは、
真円のとき、このroundnessは
この定義は、日本語では「真円度」と呼ばれているようです。JISB0621:1984 幾何偏差の定義及び表示を参照してみましょう:
4.3 真円度 真円度とは,円形形体の幾何学的に正しい円(以下,幾何学的円という。)からの狂いの大きさをいう。
p.2
5.3 真円度 真円度は,円形形体 (C) を二つの同心の幾何学的円で挟んだとき,同心二円の間隔が最小となる場合の,二円の半径の差 (f) で表し(図6),真円度_mm又は真円度_μmと表示する
p.4
円形度
一方で、別の尺度として「円形度」というのもあるそうです。以下のように定義されています:
円形度が1に近いほど、円らしいと言えます。
円の性質として「周長(図形の周りの長さ)が同じとき、その面積がもっとも大きくなる図形である」ということが知られています。
円の面積は、
真円度と円形度
では、真円度と円形度という二つの尺度、どちらの方が我々の目的(丸い湖を探したい)に適しているでしょうか。
次の記事では、いくつかの図形で、それぞれの真円度と円形度を算出しています:
図: 【ImageJで円形度解析】見た目の「丸さ」を表すには、「真円度」よりも「円形度」? - 60へぇ研究所 より引用
真円度を見ると、中央と一番右が同等の値となっています。
円形度では、右に行くにつれ数値が下がる、つまり円らしくない、ということになります。
どちらが正しいということはなく、それぞれの特性がある、ということが見て取れます。
ただ、今回の用途においては、時に複雑な湖の形に対し、そもそも、真円度の算出に必要な内接円と外接円が存在しないことも多いでしょう。真円度は、円形にある程度近しい、複雑ではない図形に適しているもので、それがどれくらい真円から歪んでいるかを測るための尺度なのかなと思います。
一方、円形度は、面積と周長さえ分かれば、シンプルに算出できます。
円形度で湖を見る
それではこの円形度を手がかりに、日本にある湖の丸さを調べてみましょう。
処理は全てPythonで行いました。地理空間情報を扱うライブラリGeoPandasを用いています。以下のJupyter Notebookで、手順を確認することができます:
roundest-lake/japan.ipynb at main · sorami/roundest-lake
データ
国土数値情報の「湖沼データ」を利用しました:
「数値地図25000(地名・公共施設)」に含まれる約600の湖、日本の湖沼アトラス(国土地理院技術資料D1-No,299)に含まれる58の自然湖沼、「国土数値情報・統一フォーマット(湖沼、湖岸線)」に含まれる約300湖沼について、その形状を数値地図25000(空間データ基盤)より取得し、属性情報として湖沼名を数値地図25000(地名・公共施設)の注記、国土数値情報統一フォーマット(湖沼、湖岸線)の湖沼名、「日本の湖沼アトラス」の湖沼名から付与した。さらに「日本の湖沼アトラス」に記載された自然湖沼については、最大水深・水面標高を属性として付与した。
このデータセットには556の湖沼が含まれていました。そのうち107(20%弱!)が、北海道にあるものでした。
円形度の算出
元データの座標系は「JGD2000 / (B, L)」(「B, L」 = 「地理座標系(緯度経度)」)、すなわちEPSG 4612に該当します。
これを、それぞれの面積と周囲長を算出するために、地理座標系から投影座標系へ投影変換します。今回は簡単のため全てに対し「JGD2000 / UTM zone 53N」(EPSG 3099)を用いました。
面積と周囲長は、GeoPandasの内部で用いられているライブラリShapelyが算出してくれます。
面積の最も大きく、周囲長の最も長い湖沼は、滋賀県の琵琶湖で、データ上では、面積669km², 周囲長260kmです。
面積の最も小さく、周囲長の最も短い湖沼は、青森県の青池(十二湖)で、面積429m²、周囲長92mでした。面積は琵琶湖の150万分の1です。
あとはこれらの値を、先述した円形度の式に当てはめるだけです:
gdf["円形度"] = 4 * math.pi * gdf["面積"] / (gdf["周囲長"] ** 2)
円形度による「丸い湖」
以下が、円形度の値が最も大きい湖トップ5です:
-
0.954554
- 明月湖(山形県) -
0.945450
- 倶多楽湖(北海道) -
0.920083
- 東雲湖(東小沼)(北海道) -
0.907386
- 四尾連湖(山梨県) -
0.902002
- 巣鷹湖(長野県)
... なんということでしょう、冒頭で述べた我らが倶多楽湖が、1位ではないではありませんか!
この明月湖が、日本で一番丸い湖なのでしょうか。福島県と山形県の県境に位置する吾妻山にあるものだそうです(参考: 明月湖 -日本湖沼めぐり-)。
見てみると、確かに、丸いですが、少しひしゃげているようにも思えます。
再び、倶多楽湖を見てみましょう。
なんとなく、倶多楽湖のほうが、「丸い」気がする!これは贔屓からだけではないように思えます。
そもそも、明月湖は、面積978m², 周囲長113m。倶多楽湖は、面積5km², 周囲長8kmです。
縮尺が違うため、ポリゴンの”細かさ”も違います。そのため、面積と周囲長だけをもとに算出される「円形度」という値が、単純に比較できるものではなく、小さな湖の方が有利になっているのではないでしょうか ...
「国」のかたち
ここでは話を変えて、先行事例として、国(国土)の「四角さ」「丸さ」が検討されたものを見ていきます。
国の四角さ(Barry, 2016)
David Barryによる "The rectangularness of countries" という考察では、国の「四角さ(Rectangularness)」を検討しています:
「トルコはとても四角い」と聞いたことから調べてみたそうです(結果としてトルコは15位、1位はエジプト、日本は187位)。
ここでは四角さを「”国土と同じ面積の四角形”との重なりの最大割合」と定義しています。
しかし、「同じ面積の四角形」の中から、国土との重なりが”最大”になるものはどう特定できるでしょうか。
Barryは、シンプルな最急降下法により、「重なりの割合」、つまり「四角さのスコア」が最大になる四角形を探索しています。
まず、可能なすべての「同じ面積の四角形」を、以下4つのパラメーターで表します:
- 中心点の緯度
- 中心点の経度
- 回転度
- アスペクト比
そして、現在のパラメーターを少し変更して、スコアへの影響を見る。もしスコアが上昇していたら、変更後の値を現在のパラメーターに設定する。これを、スコアが収束する(それ以上にならなくなる)か、規定の回数に達するまで繰り返します。
初期値として、中心地の経緯度には「国土ポリゴンの重心」、回転度は「0」、アスペクト比は「バウンディングボックス(ポリゴンを含む最小の四角)での比率」を設定したそうです。
以下に、本人による解説ページで紹介されている、コンゴ共和国でのパラメーター探索の様子を示します:
また、本人による解説とR言語でのコードで、詳細が述べられています。
大部分のケースでは、このシンプルな最適化手法でうまく行ったそうですが、いくつかの問題も生じたそうです。
例えば、沢山の島がある場合には、重心点が陸地から遠くなりすぎて、重なりがゼロになります。そのときには、それらを含む一番大きな四角形を手動で初期値に設定したそうです。
最急降下法では200イテレーションを行ったそうですが、うまく収束しないケース(43カ国)では、アスペクト比の更新が遅かったようです。細長い国の場合に、島があったりすると、アスペクト比の初期値が小さくなるので、最適な値までイテレーション内に到達できなかったとのこと。収束しなかった場合は、更新値を少し大きくして再度実行したそうです。
元データはNatural Earthで、これをシンプルに正距円筒図法(x=経度, y=緯度)へ投影変換して用いています(理想的には国ごとに、適した投影法が適用できると良い)。
国の丸さ(Ciruelos, 2016)
上記のBarryによる「四角い国」の考察を踏まえて、Gonzalo Ciruelosによる "What is the roundest country?" という論説では、「国の丸さ」に着目しています:
まず、「丸さ」を定義する必要があります。
円形度についての節で述べたように、円の性質として「周長(図形の周りの長さ)が同じとき、その面積がもっとも大きくなる図形である」ということが知られています。
しかし「国」の場合は、周囲(国境)が細かくギザギザとしていることが多いため、想定以上に長い周長となり、この円の性質を利用するのには向いていないでしょう。
そのためCiruelosは、任意の国(2次元空間上の図形)を
(元記事にある
ここで
分子
分母
このスコアは、0から1の間の値をとり、
丸さのスコアを得るためには、これらの比率が最大になる円のパラメーター
ここでCiruelosは、Barryが四角さを求める際にやったのと同様に、最急降下法を用いてパラメーターを求めています。
算出のためのPythonコードは、GitHub gistで公開されています:
バウンディングボックス(bbox)は、その図形を囲む最小の長方形です。それをもとに、まず初期値として、以下の二つを設定しています:
- bboxの内に収まる円のうち、面積が最大のもの(半径 = bboxの短辺 / 2)
- bboxを収める円のうち、面積が最小のもの(半径 = bboxの対角線 / 2)
def circle_inside(xmin, ymin, xmax, ymax):
center = [(xmin + xmax) / 2, (ymin + ymax) / 2]
radius = min((xmax - xmin) / 2, (ymax - ymin) / 2)
return center, radius
def circle_outside(xmin, ymin, xmax, ymax):
center = [(xmin + xmax) / 2, (ymin + ymax) / 2]
radius = math.sqrt((xmax - xmin)**2.0 + (ymax - ymin)**2.0) / 2
return center, radius
その上で、円を上下左右に移動させ、また半径を大きく・小さくすることで、重なりが大きくなるよう、パラメーターを最適化していきます。
元データはNatural Earthで、WGS84(経緯度)の形式です。これを正距円筒図法にしています。しかし、多くの国が歪んでしまうため、そこからさらに、国ごとの方位図法へ変換しています。方位図法の中心としては、その国のどこか(具体的には、その国のボーダーからランダムな2点を選び、その中間点)を設定しています。
また、このgistへのJan Freybergによるコメントも少々興味深いものでした。コメントでは、国の「丸さ」と「経度」(首都の経度の絶対値)が相関していると指摘されています。おそらく、太平洋にある島国(領土がすべて島から構成される国)が影響しているのだろうと述べられていました:
改めて、丸い湖を探す
さて、日本の湖に戻ります。
先の試行では、面積と周囲長から解析的に求める円形度を用いましたが、これは縮尺によって単純な比較ができなさそうであるという問題がありました。
では、Ciruelosによる例を参考に、湖の丸さを、数値的に見てみましょう。湖と円との重なり割合を求めます。
最急降下法による探索
以下のJupyter Notebookで、処理を見ることができます:
roundest-lake/japan_gd.ipynb at main · sorami/roundest-lake
基本的には、Ciruelosと同様の考え方で進めています。
以下のように、円が動き、大きさが変わり、スコアが上昇していきます。
北海道のシュンクシタカラ湖:
1970年代に、人工衛星によってその存在が確認された湖で、2007年現在、日本国内最後に発見された湖とされる。しかし、地元の人々はそれ以前より湖が存在することを知っており、1920年の「国土地理院5万分の1地図」にも「シュンクシタカラ沼」と表記がある[1]。
北海道のコムケ湖:
三日月湖: 初期値の調整
最初、円の初期値として、中心点は「バウンディングボックスの中心」に、半径は「湖の面積」と同じになるよう設定してみました。
しかし、多くのケースではこれでも上手くいくのですが、例えば北海道の「しのつ湖」では、スコアがゼロになってしまいます。三日月湖のような凹図形では、中心点が領域外に配置され、また半径が小さすぎて円が全く重ならないためです:
これは、初期値の半径を、湖の面積から求めるのではなく、「バウンディングボックスを囲む円」(半径 = バウンディングボックスの対角線 / 2)とすることで、局所で収束せずに、それなりの値になりました:
def get_initial_circle_params(lake):
"""
探索の初期値
中心: バウンディングボックスの中心
半径: バウンディングボックスの対角線の長さの1/2
"""
x_min, y_min, x_max, y_max = lake.bounds
center = [(x_min + x_max) / 2, (y_min + y_max) / 2]
radius = math.sqrt((x_max - x_min) ** 2 + (y_max - y_min) ** 2) / 2
return center, radius
ちなみに、しのつ湖は冬には凍って、その上でワカサギ釣りができます。私は、ここで人生初のワカサギ釣りをやりました。朝一番に4人で行って、3時間かけて、4匹しか釣れませんでした。
ダム湖: 更新幅の調整
円を「どれくらい」移動させたり、大きく・小さくさせるか。
当初は「半径の1%」をベースに、その値を足したり引いたりして、移動と拡大縮小を行っていました:
def neighbors(center, radius, delta_perc=0.01):
delta = radius * delta_perc
delta_options = [-delta, 0, delta]
for cx_delta in delta_options:
for cy_delta in delta_options:
for r_delta in delta_options:
yield ((center[0] + cx_delta, center[1] + cy_delta), radius + r_delta)
しかしこれでは、局所最適解に陥ることがありました。以下は、沖縄にある「伊集の湖」の例です:
このようなダム湖は、細々としており、円がうまく当てはまりません。そして、端の方に大きな領域がある場合、更新幅が小さすぎると、そこまで探索が辿り着かずに収束してしまいます。
そのため、大きな更新幅を用意(具体的には「半径の0.5%」に加えて「半径の10%」も考慮)することで、局所最適へ陥りづらいようにしました:
def neighbors(center, radius, delta_perc=0.005):
delta = radius * delta_perc
delta_options = [-delta * 20, -delta, 0, delta, delta * 20]
for cx_delta in delta_options:
for cy_delta in delta_options:
for r_delta in delta_options:
yield ((center[0] + cx_delta, center[1] + cy_delta), radius + r_delta)
より上手くやるには、焼きなまし法を取り入れたり色々あるでしょうが、今回は、これくらいまでで十分な結果となっているようでした。
湖中島: 穴空きポリゴン
湖ポリゴンに、穴が空いているケースがあります。湖の中に「島」(湖中島)があったりするようなケースです。
例えば北海道にある洞爺湖:
今回は、ポリゴンのexterior(外枠)とinterior(内枠 = 穴の部分)を考慮して、面積を算出しています。穴空きを気にせず、外周の形だけをもとに「丸さ」を考えるのであれば、この取り扱いをまた変える必要があるでしょう。
コード
今回利用したコードは、以下で公開しています:
また、世界の湖についても確認した結果は、以下にあります:
roundest-lake/world.ipynb at main · sorami/roundest-lake
そして、「日本で最も丸い湖」は ...
さて、新たな丸さの定義と、最急降下法により、あらためて、それぞれの湖に「丸さのスコア」が割り振られました。
円形度をみたときは、我らが倶多楽湖は、明月湖に負けてしまっていました。今回はどうでしょうか。
では、5位から1位を見てみましょう:
... なんと、倶多楽湖が1位になっています!そして、円形度で1位だった明月湖は4位になりました。
湖のかたちを見ても、なんとなく、感覚と合う感じがするのではないでしょうか。
もちろん用途によって、適切な尺度は異なるでしょう。また、今回は数値的に解いたため、これが最適解かの保証はなく、スコアは変動しえます。投影法も雑に扱っているので、その調整でまたスコアは変わるでしょう。ただ、それらを踏まえた上でも、ある程度参考となる結果になったのではないでしょうか。
全556湖の結果は、以下で見ることができます:
roundest-lake/results.md at main · sorami/roundest-lake
おわりに
ということで、「日本で最も丸い湖」は、冒頭で述べた倶多楽湖といっても差し支えはなさそうです。丸くおさりましたね。
倶多楽湖は、北海道の白老にあり、隣にある登別のクマ牧場からも望むことができます。
白老にはアイヌの歴史・文化を学び伝えるナショナルセンター「ウポポイ」があり、登別は9種もの泉質を誇り”温泉のデパート”とも呼ばれる有数の湯郷です。
もしこのあたりを訪れた際には、ぜひ、日本で最も丸い湖、倶多楽湖の丸さも見てみてください!
これにて大団円です 🙆
Discussion