最初のプログラムは4,5日で作成できた。国土地理院地図はダウンロードベースなので、 いとも簡単であり、2、3日で最終形に近いものが書けた。
レンダリングについては、現時点は、陸地ポリゴンだけであるが、先に進む前に、 ここで十分に時間をかけて、方針を決めたい。
パフォーマンスについてはこれまでに十分に高速化を達成できたので、現状維持でよい。 プログラムのスリム化、分かりやすさを目指す。
表示の滑らかさを目指す。一挙に画面を書き換えず、新しいタイル画像ができるまでは、 旧タイルを表示して、新しいタイルができたところから順に書き換えていく。
C# としては メンバー変数を public とはせず、プロパティを使ってカプセル化するのが望ましいが、 この地図プログラムは個人利用であり、コードをなるべくスリムにするため、 public メンバー変数で済ませているところが大半である。
詳細は前ページに記載したので、ここでは省略する。
レンダリングは陸地ポリゴンしか終わっていないが、陸地ポリゴンのレンダリング自体に一番時間がかかっている。 その意味では大きな改善の余地は少ない。プログラムをスリムにして分かりやすくすること、無駄なデータを省いて OSMバイナリレコードファイルのサイズやメモリ使用量を削減することに重点を置きたい。
差分コードの基準を境界ボックスの左上に戻した。差分化できるレコードは少し減少すると思うが、 プログラムは分かりやすくなる。
マルチポリゴンについては num_nodes 配列は必須であるが、ラインやポリゴンについては要らない。 形式を合わせるために導入していたが、以前に戻して、これを省く。 全体のファイルサイズとしては数%程度の削減となろう。
widは主に道路描画の簡単化のために導入したものであるが、陸地ポリゴン、簡単な建物にも広げる。
OSMデータはレコード数としては小さな建物が全体の過半数を占める。 タグ、osm_id、way_area (計20バイト)は省く。 全体のファイルサイズとしては5%以上の削減となろう。
その他の改善を含めて精々10%程度の縮小であろう。 パソコンの場合、メモリに余裕があるため、有難みは皆無であるが、 スマホでは、アプリのメモリ使用量が 512MB に制限されているため、 メモリ使用量削減は安心感につながる。
多くのOSMバイナリレコードのブロックファイルをメモリにキャッシュするほどパフォーマンスは良くなる。
前地図アプリGISとは少し変更した。フラグなどの head と レコード長length を分離した。 レコード長の単位はこれまでと同じバイトとする。
osm_id は long、way_area は float、他は int である。
num_nodes は multipolygon の場合、先頭は outer polygon のノード数、 以降は inner polygon のノード数である。 line と polygon の場合は1要素で、ノード数となる。
head, length, x0, y0, x1, y1, rec_id, osm_id, [way_area,] [xc, yc,] {key, val,}+ {num_nodes,}* {x, y,}* head: 第0,1bit 0: point、1: line、2: polygon、3: multipolygon 第4bit(0x10) xc, yc, 1:有り 0:無し
head, length, x0, y0, x1, y1, [osm_id,] [way_area,]
[xc, yc,] [num_tags,] {key, val,}* [multi,] {x, y,}*
head:
第0,1bit(0x03) 0: point、1: line、2: polygon、3: multipolygon
第4bit(0x10) xc, yc, 1:有り 0:無し
第5bit(0x20) osm_id 1:有り 0:無し
第6bit(0x40) 1: polygon分割データ 0: 分割されたものではない 廃止予定
第7bit(0x80) 1: 差分座標、0: 絶対座標
第11~20bit(11) zorder(-500~599)
第21~26bit(6) wid LandPolygon, building=yes なども含む
第27~31bit(5) minzoom
num_tags はタグ(key, valペア)数、陸地ポリゴン、小建物などでは存在しない。
multi は multipolygon管理配列、先頭は polygonn数、次は outer ノード数、以降は inner ノード数(1つ以上)である。
bit割り当てで負の値を扱うのは面倒なため、zorderの値は +500 して 0~1099 の値を送り、 読み込みプログラムで -500 するように変更した(2023.3.20)。
データ圧縮効果は大きいが、空間検索か初めて座標値を使うときに復号化しないとメモリ使用量削減にならないため、 スマホではこの復号化に時間がかかる。
2バイト単位であれば処理時間的に可能かもしれないが、現在の差分コードに比べて大きなメモリ使用量削減は期待できない。
ラインもポリゴンも描画には座標変換を伴うから、復号化も座標変換以下の処理時間ならば許容される。
Blockキャッシュは頻繁な入れ替えがないことと、サイズが大きく異なることから、再利用はしていない。
Tileキャッシュはサイズが同じため、再利用している。
空間検索結果(OSM配列)のレコード数は大きく変動するが、最大レコード数分の配列を確保して、再利用している。
座標値列データは Blockデータに置いたままである。 空間検索結果の後処理として、座標値変換を行えば、プログラムは分かりやすくなり、特に、 道路レンダリングでは、多少、パフォーマンス向上も期待される。
ただし、メモリ使用量は増える。80MB程度の増加かと思っていたが、実際に試したところ、 アプリ起動時のメモリ使用量は 600MB 程度になる。
やはり、現在の形(下記)をベースとして、少し、見直す程度がベストのようである。
public class OSM { public short head, type; // typeはhead の一部であるが、使用頻度が高いため、部分コピーをおく public short blk; // block番号 0, 1, 2, ... , MaxBlock-1 public int pos; // blockの int配列上のレコードの始まり public int bgnTag; public int bgnMulti; public int bgnData, endData; // blockの int配列上の座標値列データの始まりと終わり public short layer, zorder; public short wid; // highway, railway, aeroway用の identifier public float way_area; public long tag_flags; public int x0, y0; // 境界ボックスの左上座標 public int xc, yc; public bool slim; // 差分コード public int nodes; public int[] buf; public int iname = int.MinValue; // nameタグのコード }
下のように変更する。
public class OSM { public short head, type; // typeはheadの一部であるが、使用頻度が高いため、部分コピーをおく public short layer, zorder; public short wid; // highway, railway, aeroway用の identifier public float way_area; public int x0, y0; // 境界ボックスの左上座標 public int xc, yc; // 中心座標 public bool slim; public long tag_flags; public int iname=int.MinValue; // nameタグのコード, string nameとの比較を行う public int[] buff; // ブロックバッファの先頭 public int pos; // レコードの先頭 public short ixOsm_id; // osm_id のレコード先頭からの位置 public short num_tags; public short ixTags; // タグ配列の先頭位置 public short num_polys; // マルチポリゴンのポリゴン数 public short ixMulti; // マルチポリゴンのノード数配列の先頭位置 public short ixData; // ノード座標値列データの先頭位置 public int num_nodes; // ノード数 }
パソコンの場合、メモリに余裕があるせいか、スマホよりメモリ使用量が大きくなりやすいようだ。 パソコンで 500MB以下に抑えれば大丈夫であろう。
道路は非常に多くの種類に分けており、幅、色を変えている。zoom 13以上では、幅のある道路は単純な実線ではなく、 最初に全道路を太い実線で描画し、その後、やや細い実線で描画することにより、道路の見栄えを良くしたり、 立体交差を実現している。
道路種別毎のプログラムにすると、行数が膨大になるため、道路幅(の倍率)や色をテーブル(配列)で定義している。 地図アプリGISでは、幅のある道路を大きくは二つに分けていたが、これを一本化してさらにプログラムをスリムにする。
また、道路幅や色の管理は地図アプリGISに比べて、より単純な配列管理とする。