地名描画メソッドはシンプルなものであるが、その裏に苦労が隠されている。 下の図では、地名間は適当な間隔があいているが、これは事前に間引き処理を行っているからである。 都会には地名がびっしりあり、とても描ききれない。
間引き自体はさほど難しくないが、描画がタイル毎に行われることに難しさがある。 タイルをまたがる地名は無数に存在するため、タイル単位の間引きが難しい。
タイルAとタイルBにまたがる地名があったとする。 もし、タイルAで間引いたとすればタイルBでも間引かねばならない。 タイルAで描画したのであればタイルBでも描画しなければならない。 タイルA、タイルBのどちらが先に描画されるかは決まっていない。
このような状況で矛盾なく地名を描画するのは実際上不可能に近い。 このため、現在は地名に限り、日本全体を対象に描画するかしないかを事前に決定している。 zoom毎に異なり、OSMバイナリレコードにそのデータを含めている。
できれば事前処理の要らない方法を考えたい。
public class RenderPlacename extends SuperRenderer {
Paint paProvince, paCity, paTown, paSuburb, paQuarter, paNeighbourhood, paHamlet, paLocality;
public RenderPlacename() {
paProvince = getPaint(0xff917296, 17);
paCity = getPaint(0xff4c4c4c, 15);
paTown = getPaint(0xff3c3c3c, 13);
paSuburb = getPaint(0xff555555, 12);
paQuarter = getPaint(0xff777777, 11);
paNeighbourhood = getPaint(0xff777777, 11);
paHamlet = getPaint(0xff777777, 11);
paLocality = getPaint(0xff777777, 11);
} // GIS起動時に一度だけ実行する
void render(Canvas cv, TileToRender tile, OSM[] osms, int fromIndex, int toIndex) {
final int zoom = tile.zoom;
for (int n = fromIndex; n < toIndex; n++) {
OSM osm = osms[n];
if (osm.type != 0 || (osm.tag_flags&bitPlace)==0 || (osm.tag_flags&bitName)==0) {
continue;
}
Tag.Val place = osm.getVal(Tag.Key.place);
switch (place) {
case province:
if (zoom >= 5) osm.drawPlacename(cv, paProvince, tile, 0, 0);
break;
case city:
if (zoom >= 7) osm.drawPlacename(cv, paCity, tile, 0, 1);
break;
case suburb:
osm.drawSurburbname(cv, paSuburb, tile, 0, 1);
break;
case town:
if (zoom >= 9) osm.drawPlacename(cv, paTown, tile, 0, 1);
break;
case village:
if (zoom >= 10) osm.drawPlacename(cv, paTown, tile, 0, 1);
break;
case quarter:
if (zoom >= 14) osm.drawPlacename(cv, paQuarter, tile, 0, 1.5f);
break;
case neighbourhood:
if (zoom >= 15) osm.drawPlacename(cv, paNeighbourhood, tile, 0, 1.5f);
break;
case hamlet:
if (zoom >= 15) osm.drawPlacename(cv, paHamlet, tile, 0, 1.5f);
break;
case locality:
if (zoom >= 18) osm.drawPlacename(cv, paLocality, tile, 0, 1.5f);
break;
}
}
}
}