最初のプログラムは4,5日で作成できた。国土地理院地図はダウンロードベースなので、 いとも簡単であり、2、3日で最終形に近いものが書けた。
レンダリングについては、現時点は、陸地ポリゴンだけであるが、先に進む前に、 ここで十分に時間をかけて、方針を決めたい。
現時点では、陸地ポリゴンだけであるが、シングルスレッドでの読み込み時間と処理時間は次にようになった。
最初の時間はファイル読み込みだけの時間、最後の時間は読み込み時間と処理時間を合わせた合計時間である。
何らかの処理後にはガーベージコレクションなどが働くのであろう。実行時間が大きく変動する。
ReadAllBytes 26.1588ms c:/map/data/lands_split1/1/0.dat 37,505KB 75.3065ms ReadAllBytes 6.2891ms c:/map/data/lands_split5/28/12.dat 6,418KB 12.8882ms ReadAllBytes 1.2325ms c:/map/data/lands_low1/1/0.dat 1,309KB 2.8835ms ReadAllBytes 2.0543ms c:/map/data/lands_low1/0/0.dat 1,907KB 7.6608ms ReadAllBytes 10.9436ms c:/map/data/lands_split5/27/12.dat 15,171KB 31.6195ms ReadAllBytes 40.4929ms c:/map/data/lands_split5/27/13.dat 3,351KB 43.8489ms ReadAllBytes 12.4499ms c:/map/data/lands_split5/29/10.dat 481KB 13.3242ms ReadAllBytes 5.7754ms c:/map/data/lands_split5/30/10.dat 363KB 6.5944ms ReadAllBytes 14.1663ms c:/map/data/lands_split5/27/11.dat 735KB 15.1881ms ReadAllBytes 1.8946ms c:/map/data/lands_low1/1/1.dat 673KB 5.6647ms ReadAllBytes 0.9672ms c:/map/data/lands_low1/0/1.dat 845KB 2.4662ms
処理としては、byte配列をint配列に変換しているだけであるが、時間がかかるようだ。 Java で作ったバイナリファイルはビッグエンディアンであり、一方、C#はリトルエンディアンであるから、 変換は避けられない。
int[] ia = new int[ba.Length/4]; for (int n = 0; n < ba.Length; n += 4) { ia[n/4] = (ba[n]<<24) + (ba[n+1]<<16) + (ba[n+2]<<8) + ba[n+3]; }
OSMバイナリファイルの読み込みは頻繁に起きるわけではないので、 ここでの時間はそれほど重要ではない。
getOSMs の行は最初の時間が空間検索時間、次の時間がレンダリング時間である。 ファイル読み込み直後の空間検索時間は大きいが、平均的には 1ms未満である。 一方、レンダリング時間(陸地ポリゴン塗りつぶし時間)は予想したより大きい。 平均的に 10ms前後となる。
陸地ポリゴンについては、事前に、完全に陸地かどうかを判別しておくことができ、 完全に陸地の場合には、空間検索もポリゴンの塗りつぶしも要らず、タイル全体の FillRectangle でよいので、はるかに高速に処理できる。
問題はこの先、森林や水域ポリゴンの塗りつぶしが必要となり、そこに時間がかかりそうなことである。
c:\map>map readWords: 16296618 ReadAllBytes 23.48ms c:/map/data/lands_split1/1/0.dat 37,505KB 71.81ms ReadAllBytes 4.42ms c:/map/data/lands_split5/28/12.dat 6,418KB 10.75ms ReadAllBytes 0.99ms c:/map/data/lands_low1/1/0.dat 1,309KB 2.22ms getOSMs 4/25306 records 0.44ms 7.17ms getOSMs 4/25306 records 10.00ms 14.92ms getOSMs 4/25306 records 0.74ms 9.07ms getOSMs 46/25306 records 12.45ms 23.44ms getOSMs 12/25306 records 1.76ms 44.52ms getOSMs 4/25306 records 16.52ms 44.86ms getOSMs 4/25306 records 0.50ms 47.40ms getOSMs 22/25306 records 0.56ms 14.96ms getOSMs 16/25306 records 0.47ms 11.94ms getOSMs 198/25306 records 0.51ms 18.73ms getOSMs 20/25306 records 0.55ms 19.36ms getOSMs 111/25306 records 0.60ms 37.97ms getOSMs 1501/25306 records 0.63ms 49.52ms getOSMs 229/25306 records 0.60ms 53.03ms getOSMs 5/25306 records 0.52ms 56.70ms getOSMs 152/25306 records 10.09ms 68.92ms getOSMs 2/8844 records 0.38ms 4.75ms getOSMs 2/8844 records 0.33ms 5.53ms getOSMs 50/8844 records 0.57ms 6.85ms getOSMs 9/8844 records 0.18ms 6.31ms getOSMs 8/8844 records 0.15ms 7.25ms getOSMs 3/8844 records 0.20ms 9.50ms getOSMs 4/8844 records 0.19ms 10.87ms getOSMs 20/8844 records 0.34ms 12.38ms getOSMs 2/8844 records 0.13ms 4.13ms getOSMs 1/8844 records 0.15ms 5.09ms getOSMs 5/8844 records 0.22ms 6.38ms getOSMs 35/8844 records 0.18ms 6.21ms getOSMs 1/8844 records 0.19ms 4.31ms getOSMs 3/8844 records 0.18ms 5.61ms getOSMs 8/8844 records 0.18ms 11.61ms getOSMs 141/8844 records 0.31ms 12.54ms getOSMs 1/8844 records 0.28ms 5.48ms getOSMs 41/8844 records 0.32ms 7.32ms getOSMs 21/8844 records 0.19ms 6.62ms getOSMs 17/8844 records 0.19ms 7.40ms getOSMs 44/8844 records 0.18ms 8.27ms getOSMs 214/8844 records 0.24ms 14.70ms getOSMs 64/8844 records 1.45ms 15.34ms getOSMs 363/8844 records 4.39ms 11.50ms getOSMs 11/8844 records 0.19ms 5.47ms getOSMs 21/8844 records 0.19ms 2.02ms getOSMs 1/8844 records 0.42ms 3.41ms getOSMs 1/8844 records 0.17ms 2.94ms getOSMs 1/8844 records 0.29ms 7.46ms getOSMs 46/8844 records 0.18ms 5.90ms getOSMs 17/8844 records 3.25ms 5.47ms getOSMs 55/8844 records 0.15ms 9.85ms getOSMs 674/8844 records 0.24ms 13.93ms getOSMs 553/8844 records 0.21ms 18.56ms getOSMs 73/8844 records 0.16ms 15.70ms getOSMs 819/8844 records 0.22ms 26.13ms getOSMs 39/8844 records 0.19ms 4.86ms getOSMs 19/8844 records 0.23ms 4.12ms getOSMs 1/8844 records 0.33ms 7.40ms getOSMs 73/8844 records 0.23ms 4.43ms ReadAllBytes 1.63ms c:/map/data/lands_low1/1/1.dat 673KB 3.06ms getOSMs 84/2523 records 3.07ms 1.31ms ReadAllBytes 1.94ms getOSMs 17/8844 records 3.17ms 5.40ms getOSMs 440/8844 records 3.41ms 7.78ms c:/map/data/lands_low1/0/1.dat 845KB 7.82ms getOSMs 1006/2523 records 3.50ms 10.88ms ReadAllBytes 3.57ms getOSMs 297/2264 records 14.25ms 7.27ms c:/map/data/lands_low1/0/0.dat 1,907KB 8.41ms getOSMs 20/10106 records 23.06ms 6.43ms getOSMs 120/8844 records 23.36ms 10.85ms getOSMs 554/10106 records 23.07ms 11.98ms getOSMs 2075/8844 records 7.27ms 24.84ms getOSMs 173/8844 records 0.28ms 10.28ms getOSMs 980/2523 records 0.10ms 14.21ms getOSMs 118/8844 records 0.54ms 11.74ms getOSMs 247/10106 records 0.35ms 5.54ms getOSMs 275/10106 records 0.21ms 5.75ms getOSMs 591/8844 records 0.30ms 18.32ms getOSMs 254/8844 records 0.17ms 18.27ms getOSMs 771/10106 records 0.24ms 23.99ms getOSMs 1091/8844 records 0.33ms 29.31ms getOSMs 1872/10106 records 0.33ms 36.55ms getOSMs 156/8844 records 0.20ms 4.91ms getOSMs 206/8844 records 0.24ms 5.40ms getOSMs 1/8844 records 0.19ms 6.74ms getOSMs 1/8844 records 0.13ms 4.41ms getOSMs 2/8844 records 0.14ms 5.03ms getOSMs 16/8844 records 0.18ms 5.63ms getOSMs 100/8844 records 0.32ms 7.03ms getOSMs 55/8844 records 0.18ms 10.89ms getOSMs 158/8844 records 0.18ms 15.49ms getOSMs 1/8844 records 0.16ms 4.62ms getOSMs 13/8844 records 0.25ms 5.47ms getOSMs 3/8844 records 0.17ms 6.54ms getOSMs 170/8844 records 0.18ms 6.87ms getOSMs 5/8844 records 0.18ms 7.93ms getOSMs 108/8844 records 0.19ms 13.71ms getOSMs 62/8844 records 0.28ms 15.10ms getOSMs 36/8844 records 0.17ms 11.61ms getOSMs 141/8844 records 5.39ms 10.68ms getOSMs 22/8844 records 0.44ms 4.69ms getOSMs 5/8844 records 0.15ms 7.61ms getOSMs 35/8844 records 0.21ms 3.62ms getOSMs 2/8844 records 0.32ms 5.81ms getOSMs 2/8844 records 0.33ms 5.32ms getOSMs 69/8844 records 0.26ms 10.05ms getOSMs 65/8844 records 0.18ms 8.52ms getOSMs 17/8844 records 0.19ms 10.74ms getOSMs 1/8844 records 0.25ms 5.68ms getOSMs 63/8844 records 0.18ms 9.10ms getOSMs 2/8844 records 0.12ms 11.69ms getOSMs 42/8844 records 0.18ms 14.04ms getOSMs 1/8844 records 0.18ms 6.34ms getOSMs 11/8844 records 0.19ms 2.87ms getOSMs 57/8844 records 0.20ms 8.77ms getOSMs 1/8844 records 0.24ms 5.45ms getOSMs 50/8844 records 0.24ms 9.65ms getOSMs 50/8844 records 0.27ms 8.13ms getOSMs 18/8844 records 3.39ms 8.46ms getOSMs 1/8844 records 0.13ms 6.63ms getOSMs 44/8844 records 0.18ms 7.96ms getOSMs 11/8844 records 0.13ms 10.27ms getOSMs 363/8844 records 1.98ms 9.37ms getOSMs 1/8844 records 0.16ms 11.87ms getOSMs 41/8844 records 0.14ms 12.88ms getOSMs 64/8844 records 0.21ms 14.01ms getOSMs 214/8844 records 0.27ms 18.26ms
public void FillPolygon(Graphics g, Brush br, TileToRender tile, int offset, int length) { double fact = tile.fact; double xpx = tile.xpx; double ypx = tile.ypx; int INC = (slim ? 1 : 2); int end = offset + INC * length; var list = new List<PointF>(); for (int ix = offset; ix < end; ) { float fx, fy; if (slim) { int xy = buf[ix++]; fx = (float) ((x0 + (short)(xy>>16)) * fact - xpx); fy = (float) ((y0 + (short)(xy&0xffff)) * fact - ypx); } else { fx = (float) (buf[ix++] * fact - xpx); fy = (float) (buf[ix++] * fact - ypx); } list.Add(new PointF(fx, fy)); } g.FillPolygon(br, list.ToArray()); }
データセットの時間と描画時間を分けて実測した。ノード数の小さいポリゴンが無数にあるが、 データセット時間、描画時間とも微々たるものであるため省略した。
以下の実測結果で最初の数値はノード数、次がデータセット時間、最後が描画時間である。
データセット時間より描画時間の方が5~10倍大きい。 現在のプログラムはデータセット時間短縮のために多少分かりずらくなっている。 多少データセット時間が増えるとしても分かりやすくした方がいいであろう。
c:\map>map readWords: 16296618 ReadAllBytes 24.32ms c:/map/data/lands_split1/1/0.dat 37,505KB 72.94ms ReadAllBytes 4.39ms c:/map/data/lands_split5/28/12.dat 6,418KB 11.57ms ReadAllBytes 0.93ms c:/map/data/lands_low1/1/0.dat 1,309KB 2.14ms 204 0.01ms 0.12ms 376 0.02ms 0.09ms 1021 0.05ms 0.13ms 376 0.01ms 0.09ms 231 0.02ms 0.06ms 1021 0.25ms 0.18ms 393 0.01ms 2.81ms 29911 1.67ms 8.45ms 29911 1.39ms 6.00ms 29911 0.63ms 9.44ms 29911 0.53ms 10.51ms 29911 0.62ms 5.90ms 110 0.01ms 0.04ms 29911 0.72ms 24.37ms 1021 0.15ms 3.42ms 29911 0.62ms 2.97ms 29911 0.92ms 3.61ms 1021 0.05ms 0.15ms 29911 0.46ms 2.70ms 29911 0.76ms 7.31ms 29911 0.49ms 2.15ms 29911 1.18ms 7.41ms 29911 0.87ms 8.44ms 1021 0.02ms 0.12ms 1021 0.02ms 0.17ms 204 0.00ms 0.06ms 29911 0.51ms 5.03ms 29911 0.54ms 5.56ms 393 0.01ms 0.11ms 29911 0.38ms 3.30ms 1021 0.01ms 1.70ms 29911 0.50ms 4.13ms 190 0.00ms 0.04ms 110 0.00ms 0.01ms 619 0.02ms 0.08ms 376 0.02ms 0.19ms 29911 0.77ms 4.91ms 29911 2.77ms 5.41ms 643 0.01ms 0.63ms 123 0.00ms 0.03ms 166 0.00ms 0.04ms 110 0.00ms 0.03ms 231 0.00ms 0.04ms 438 0.01ms 0.18ms 436 0.01ms 0.12ms 344 0.01ms 0.10ms 1021 0.02ms 0.09ms 125 0.00ms 0.04ms 643 0.01ms 0.09ms 29911 0.54ms 4.13ms 29911 0.67ms 4.50ms 29911 0.61ms 5.14ms 29911 0.51ms 2.95ms 29911 0.66ms 3.04ms 29911 0.48ms 3.76ms 1021 0.03ms 0.14ms 1021 0.02ms 0.17ms 1021 0.02ms 0.25ms 1021 0.02ms 0.10ms 29911 0.56ms 4.07ms 29911 0.72ms 2.96ms 1021 0.02ms 0.17ms 29911 0.53ms 5.69ms 29911 0.45ms 4.08ms 29911 0.93ms 3.44ms 29911 0.45ms 3.20ms 376 0.01ms 0.20ms 29911 0.47ms 3.32ms 231 0.00ms 0.13ms 1021 0.02ms 0.24ms 29911 0.59ms 3.26ms 1021 0.03ms 0.14ms 1021 0.02ms 0.92ms 1021 0.02ms 0.23ms 29911 1.19ms 2.21ms 1021 0.02ms 0.15ms 1021 0.02ms 0.26ms 1021 0.01ms 0.13ms 1021 0.02ms 0.19ms 29911 0.40ms 2.43ms 29911 0.37ms 3.75ms 29911 0.49ms 4.01ms 29911 0.79ms 4.38ms 29911 0.37ms 2.68ms 231 0.00ms 0.03ms 29911 0.60ms 3.61ms 1021 0.02ms 0.95ms 29911 0.56ms 2.95ms 405 0.01ms 0.06ms 1536 0.03ms 0.16ms 1125 0.02ms 0.13ms 1536 0.03ms 0.13ms 140 0.00ms 0.02ms 869 0.02ms 1.04ms 83711 4.65ms 8.17ms 56564 1.93ms 6.18ms 1125 0.02ms 1.59ms 8967 0.41ms 2.50ms 344 0.01ms 0.05ms 1536 0.03ms 0.70ms 148 0.00ms 0.03ms 886 0.01ms 0.08ms 865 0.01ms 0.12ms 865 0.02ms 1.11ms 2700 0.03ms 0.19ms 83711 3.17ms 8.67ms 6145 0.10ms 0.64ms 1911 0.03ms 0.21ms 1536 0.03ms 0.17ms 1125 0.02ms 0.11ms 1067 0.02ms 0.11ms 6145 0.11ms 2.00ms 1125 0.02ms 0.12ms 200 0.00ms 0.02ms 66736 2.72ms 6.69ms 1911 0.03ms 5.45ms 865 0.02ms 4.52ms 1536 0.03ms 0.36ms 1125 0.02ms 0.11ms 83711 2.55ms 12.63ms 66736 3.02ms 8.38ms 13937 0.35ms 3.20ms 6145 0.10ms 1.17ms 1911 0.03ms 0.56ms 8967 0.16ms 1.16ms 1536 0.03ms 0.45ms 1067 0.02ms 0.10ms 1125 0.02ms 0.17ms 869 0.02ms 0.12ms 886 0.02ms 0.08ms 66736 2.79ms 5.54ms 869 0.02ms 0.11ms 344 0.01ms 0.03ms 1536 0.02ms 0.11ms 6145 0.69ms 0.88ms 1536 0.84ms 0.22ms 1911 0.03ms 0.18ms 1125 0.02ms 0.10ms 886 0.01ms 0.11ms 865 0.01ms 0.09ms 6145 0.08ms 0.38ms 1536 0.83ms 0.12ms 6145 0.11ms 1.14ms 1125 0.02ms 0.16ms 6145 0.12ms 3.01ms 1536 0.03ms 0.13ms 1911 0.03ms 0.21ms 1911 0.03ms 0.23ms 865 0.01ms 0.62ms 1911 0.04ms 0.24ms 1536 0.03ms 0.19ms 1125 0.02ms 0.13ms 1536 0.02ms 0.14ms 1125 0.02ms 0.16ms 1536 0.02ms 0.15ms 66736 1.90ms 5.43ms 865 0.01ms 0.10ms 1125 0.02ms 0.09ms 1125 0.02ms 0.15ms 1125 0.02ms 0.09ms 66736 2.48ms 5.45ms 1536 0.02ms 0.30ms 865 0.02ms 0.23ms 1125 0.02ms 0.10ms 66736 2.46ms 4.68ms 66736 2.05ms 6.47ms 1536 0.03ms 0.69ms 1911 0.03ms 0.21ms 1125 0.03ms 0.27ms 1911 0.57ms 0.18ms 1911 0.04ms 2.19ms 1536 0.03ms 0.26ms 865 0.02ms 0.15ms 1536 0.03ms 0.13ms 1536 0.02ms 0.24ms 1536 0.02ms 0.09ms 1536 0.03ms 0.33ms 1125 0.02ms 0.30ms 1536 0.02ms 0.09ms 1125 0.02ms 0.33ms 865 0.02ms 0.22ms 1125 0.03ms 0.44ms 865 0.06ms 0.24ms 1125 0.03ms 0.26ms 1125 0.02ms 0.14ms 865 0.03ms 0.51ms 1125 0.02ms 0.47ms 886 0.02ms 0.71ms 1911 0.04ms 0.70ms 1536 0.03ms 0.31ms 1125 0.03ms 0.14ms 1911 0.03ms 0.66ms 1536 0.03ms 0.16ms 1125 0.02ms 0.11ms 1536 0.03ms 0.21ms 1125 0.02ms 1.54ms 865 0.02ms 0.05ms
陸地ポリゴンにも osm_id(8バイト)、タグ(8バイト)、wayarea(4バイト)を持たせているが、 レンダリングでは要らない。
レコードの過半数は小さな建物であるが、タグは head の数ビットで代用できる。 osm_id も wayarea もレンダリングには使わない。
境界ボックスの左上座標はブロックの左上座標との相対アドレスとすれば、大抵は2バイトで表せるだろう。
Blockには、バイナリレコードをレコード単位で管理する管理テーブルを置いてはどうか。 ファイルには境界ボックスを持たず、ブロックを読み込んだ時、算出する。 管理テーブルは小さい建物などを管理するものと、その他を管理するものに分かれていてもよい。
境界ボックスは外接矩形であるが、外接円であれば、中心座標と半径で済む。 横長、縦長については外接矩形の方が精度は高い。また、判定は円より簡単である。