トップMy OpenStreetMap > 道路・鉄道等の描画

道路・鉄道等の描画

はじめに

道路・鉄道等の描画は難しいものではない。 ただし、種類が非常に多く、種別毎の描画時の色、幅、優先順位などを表で管理して、効率よく描画したい。

これまで使ってきた管理表を継続して使用するか、あるいはより良い管理方法があるか、再検討したい。

最初のプログラム

まず、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