道路・鉄道等の描画は難しいものではない。 ただし、種類が非常に多く、種別毎の描画時の色、幅、優先順位などを表で管理して、効率よく描画したい。
これまで使ってきた管理表を継続して使用するか、あるいはより良い管理方法があるか、再検討したい。
まず、zoom 12以下の道路、鉄道等の描画プログラムを示す。
下記のプログラムで、先頭の4行の表は zoom 13 以上で使うもので、後程説明する。 その下の static { ... } で、道路鉄道種別毎の Id, zorder, 幅倍率, 色 を示す。
定義方法については改善の余地がある。
実際の描画は以下のように簡単なプログラムによっている。 道路鉄道の幅 width と 色 color が種別 wid により異なる。
if (width > 0 && (zoom <= 12 || (wid==9 || wid==10))) { int color = 0xff000000 | wayInfo[wid][4]; paintRoads.setColor(color); paintRoads.setStrokeWidth(width); osm.drawLine(cv, paintRoads, tile); }
public class RenderRoads extends SuperRenderer { // zoom 13 14 15 16 17 18 19 20 21 22 float[] caseMajor = { 2, 3, 4, 5.6f, 9, 11.3f, 16, 25, 40, 74 }; float[] fillMajor = { 1.7f, 2.4f, 3.2f, 4.7f, 8f, 10, 14, 22, 36, 68 }; float[] caseMinor = { 0, 2.1f, 3.6f, 4.8f, 7, 9, 15, 23, 34, 48 }; float[] fillMinor = { 0, 1.7f, 3.0f, 4, 6.1f, 8.0f, 14.0f, 21.8f, 32.2f, 45 }; public static Map<String, int[]> map = new HashMap<>(); public static int[][] wayInfo = new int[50][]; // 通し番号からアクセスするための配列 // 文字列はコメント的な役割のみ static { map.put("motorway", new int[] { 1, 38, 100, 0xdc2a67, 0xe892a2, 0xf0bcc5 }); map.put("motorway_link", new int[] { 2, 24, 60, 0xdc2a67, 0xe892a2, 0xf0bcc5 }); map.put("trunk", new int[] { 3, 37, 100, 0xc84e2f, 0xf9b29c, 0xfbd6cb }); map.put("trunk_link", new int[] { 4, 23, 60, 0xc84e2f, 0xf9b29c, 0xfbd6cb }); map.put("primary", new int[] { 5, 36, 100, 0xa06b00, 0xfcd6a4, 0xfdecd4 }); map.put("primary_link", new int[] { 6, 22, 60, 0xa06b00, 0xfcd6a4, 0xfdecd4 }); map.put("secondary", new int[] { 7, 35, 90, 0x939c40, 0xf7fabf, 0xf9fcd6 }); map.put("secondary_link",new int[] { 8, 21, 60, 0x939c40, 0xf7fabf, 0xf9fcd6 }); map.put("tertiary", new int[] { 9, 34, 80, 0x999999, 0xffffff, 0xffffff }); map.put("tertiary_link", new int[] {10, 20, 50, 0x999999, 0xffffff, 0xffffff }); map.put("raceway", new int[] {11, 30, 70, 0xff5675, 0xffc0cb, 0xffe5ea }); map.put("residential", new int[] {12, 33, 80, 0x999999, 0xffffff, 0xffffff }); map.put("unclassified", new int[] {13, 33, 80, 0x999999, 0xffffff, 0xffffff }); map.put("living_street", new int[] {14, 32, 80, 0x999999, 0xffffff, 0xffffff }); map.put("road", new int[] {15, 9, 50, 0x999999, 0xdddddd, 0xdddddd }); map.put("service", new int[] {16, 15, 60, 0x999999, 0xffffff, 0xffffff }); map.put("service_alley", new int[] {17, 15, 40, 0x999999, 0xffffff, 0xffffff }); map.put("pedestrian", new int[] {18, 13, 60, 0x777777, 0xdddde8, 0xf8f8fa }); map.put("pedestrian_wide",new int[]{19, 13, 100, 0x777777, 0xdddde8, 0xf8f8fa }); map.put("pedestrian_alley",new int[]{20, 13, 40, 0x777777, 0xdddde8, 0xf8f8fa }); map.put("track1", new int[]{21, 11, 60, 0xB8A669, 0xF7F5ED, 0xF7F5ED }); map.put("track2", new int[]{22, 11, 60, 0xB8A669, 0xF6F4EA, 0xF6F4EA }); map.put("track", new int[]{23, 11, 60, 0xB8A669, 0xF4F1E6, 0xF4F1E6 }); map.put("path", new int[]{24, 10, 80, 0, 0x999999, 0 }); map.put("footway", new int[]{25, 10, 60, 0, 0x999999, 0 }); map.put("cycleway", new int[]{26, 10, 100, 0, 0x7876f5, 0 }); map.put("bridleway", new int[]{27, 10, 100, 0, 0x70b971, 0 }); map.put("steps", new int[]{28, 9 }); map.put("platform", new int[]{29, 49 }); map.put("construction", new int[]{30, 1 }); // railway // platform は highway と共通 map.put("rail", new int[]{ 31, 44, 100, 0x555555, 0x555555, 0}); map.put("subway", new int[]{ 32, 42 }); map.put("narrow_gauge", new int[]{ 33, 42 }); map.put("light_rail", new int[]{ 34, 42 }); map.put("funicular", new int[]{ 35, 42 }); map.put("preserved", new int[]{ 36, 42 }); map.put("monorail", new int[]{ 37, 42 }); map.put("miniature", new int[]{ 38, 42 }); map.put("turntable", new int[]{ 39, 42 }); map.put("tram", new int[]{ 40, 41 }); map.put("disused", new int[]{ 41, 40 }); // aeroway map.put("runway", new int[]{ 42, 6 }); map.put("taxiway", new int[]{ 43, 5 }); for (int[] val : map.values()) { wayInfo[val[0]] = val; } } Paint paintBridge = getPaintFill(colorBridge); Paint paintPedestrian = getPaintFill(colorPedestrian); Paint paintPlatformHw = getPaintFill(colorPlatformHw); Paint paintPlatformRw = getPaintFill(colorPlatformRw); Paint paintWhite = getPaintFill(0xffffffff); // zoom <= 12 Paint paintRoads = getPaintLine(0, 0, null, 7); public void renderRoads(Canvas cv, TileToRender tile, OSM[] osms, int fromIndex, int toIndex) { int zoom = tile.zoom; for (int n = fromIndex; n < toIndex; n++) { OSM osm = osms[n]; int wid = osm.wid; if (osm.type != 1 || wid == 0 || (wid >= 11 && wid != 31)) continue; float width = 0; switch (wid) { case 1: case 2: // motorway width = zoom == 5 ? 0.5f : zoom <= 7 ? 1.2f : zoom <= 10 ? 1.5f : zoom == 11 ? 2.5f : 3.0f; break; case 3: case 4: // trunk width = zoom == 6 ? 0.5f : zoom <= 7 ? 0.9f : zoom <= 10 ? 1 : zoom == 11 ? 2 : 2.5f; break; case 5: case 6: // primary width = zoom <= 7 ? 0 : zoom == 8 ? 0.8f : zoom == 9 ? 1.2f : zoom <= 12 ? 2 : 2.5f; break; case 7: case 8: // secondary width = zoom <= 9 ? 0 : zoom <= 10 ? 0.8f : zoom <= 12 ? 1.8f : 2; break; case 9: case 10: // secondary width = zoom <= 12 ? 0 : 2; break; case 31: if (zoom >= 7 && (osm.tag_flags & bitService) == 0) { // railway=rail width = zoom <= 7 ? 0.2f : zoom == 8 ? 0.9f : zoom <= 12 ? 1.2f : 2; } break; } if (width > 0 && (zoom <= 12 || (wid==9 || wid==10))) { int color = 0xff000000 | wayInfo[wid][4]; paintRoads.setColor(color); paintRoads.setStrokeWidth(width); osm.drawLine(cv, paintRoads, tile); } } } }
この段階での画面当たりのレンダリング&描画時間を下に示す。
ズーム 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 平均 郊 外 220 213 140 256 169 122 71 111 60 60 42 56 58 46 51 112ms 東 京 208 228 148 219 188 110 92 90 79 56 75 60 56 62 42 114ms