交番、郵便局、病院、バス停、トイレ、ベンチといった多くの地物にはそれを特徴づける シンボルマーク(アイコン)を描画する。名称があるものはそれも併記するが、 一般には、シンボルマークを優先する。ズームを上げれば名称も表示されるようにする。
交番、郵便局、病院アイコンなどは重なると見栄えが悪くなるため、重なりを回避する仕組みが必要となる。 一方、高圧線の鉄塔、踏切などもアイコン扱いであるが、これらは道路などと同じで、 その上に別のアイコンや文字が描かれて、一部が見えなくなっても差支えがない。
初代の地図システムのプログラムは結構複雑になった。 二代目のスマホ版地図アプリでは大幅に簡素化した。今回はそれを更にスリム化したい。
最初のプログラムを下に示す。
例えば amenity=hospitalのアイコンファイルはディレクトリ c:/map/img/amenity/ に置かれた hospital.png である。 このように、大抵のアイコンは主タグのキー名を持つサブディレクトリにあり、その名前はタグの値となっている。
バス停などでは zoom によってアイコンを変えている。例えば bus_stop_small.png といった補正名を使う。
宗教施設は amenity=place_of_worship であるが、 religion=buddhist(寺院)、religion=shinto(神社)といったサブタグreligionの値に従うアイコンを表示する。
単なる●や■のアイコンも使う。この場合もアイコンファイルを作ればプログラム的には簡単であるが、 これまでは、プログラムでこのイメージデータを生成している。今回は、これを避け、pngファイルのみとしたい。 プログラムで作成した場合、pngファイルとして出力して、それを使う。
static Dictionary dicIcon = new Dictionary();
public void DrawIcon(Graphics g, Key key, Val val, TileToRender tile) {
long kv = ((long)key << 32) + (int)val;
Image img = null;
lock(dicIcon) {
if (!dicIcon.ContainsKey(kv)) {
string path = "c:/map/img/" + key.ToString() + "/" + val.ToString() + ".png";
if (!File.Exists(path)) return;
img = Image.FromFile(path);
} else {
img = dicIcon[kv];
}
}
float x = (float) (xc * tile.fact - tile.xpx); // 中心X座標
float y = (float) (yc * tile.fact - tile.ypx); // 中心Y座標
g.DrawImage(img, x - img.Width/2, y - img.Height/2, img.Width, img.Height);
}