トップ地図アプリMap > タイルの管理

タイルの管理

タイル地図

自作地図アプリMapは Google Mapを元祖とするタイル画像データによる地図の表示を行う。

zoom 0 では世界地図が1枚のタイルで表される。アドレス zoom/x/y は 0/0/0 となる。

zoom 1 は zoom 0 を縦横2分割したものであり、アドレスは 1/0/0、1/0/1、1/1/0、1/1/1 となる。

以下同様に zoom 2、3、4、... となる。

国土地理院の地図はネットからダウンロードしたタイル画像となり、 OSM(OpenStreetMap)のタイル画像データは、プログラムで作成する。 いずれも、class Tile で管理する。

class Tile

以下に class Tile の主内容を示す。一部は省略している。

初期化で 64タイル分のインスタンス(タイル・キャッシュ)を生成しておき、これを使いまわす。 最初は空き状態(free)であり、地図を表示しようとすると、リクエストが生まれる(waiting)。

リクエストはマルチスレッドで処理する。あるスレッドが処理を始めたら、 状態は waiting から busy に変わる。この処理が終わり、 Bitmap bmp にタイル画像データがセットされたら、状態は ready に変わる。

タイルキャッシュやリクエストには高度な HashMapやキューなどは一切使用せず、順次検索とする。 その理由は独自の状態管理が必要であり、汎用的な HashMap や List では実現が難しいからである。

public class Tile {
  final static int PX = 256;
  enum Status { free, waiting, busy, ready }
  enum Source { gsi, ort, osm, plateau, japan, kanto, hot }

  final static Tile[] cache = new Tile[64];
  static int ixEntry = 0;

  static void initialize() {
    for (int i = 0; i < cache.length; i++) {
      cache[i] = new Tile();
      cache[i].ixCache = i;
      cache[i].status = Status.free;
    }
  }

  int ixCache;      // cacheのインデックス
  Status status;
  Bitmap bmp;       // 256x256画素
  Canvas canvas;
  Source src;       // 地図のソース
  int zoom, x, y;   // タイルアドレス
  String url, dir, path;
  long key;

  public Tile() {
    this.bmp = Bitmap.createBitmap(PX, PX, Bitmap.Config.ARGB_8888);
    this.canvas = new Canvas(bmp);
  }

  void set(Source src, int zoom, int x, int y, long key) {
    this.src = src;
    this.zoom = zoom;
    this.x = x;
    this.y = y;
    this.key = key;   // ユニーク

    // その他の設定省略
  }

  // サイクリックに使用
  static Tile alloc(Source src, int zoom, int x, int y, long key) {
    synchronized (cache) {
      for (Tile tile : cache) {
        if (tile.status == Status.free) {
          tile.set(src, zoom, x, y, key);
          tile.status = Status.waiting;
          return tile;
        }
      }
      while (true) {
        Tile tile = cache[ixEntry];
        ixEntry = (ixEntry + 1) & 0x3f;   // キャッシュサイズ=64
        tile.set(src, zoom, x, y, key);
        if (tile.status != Status.busy && tile.status != Status.waiting) {
          tile.status = Status.waiting;
          return tile;
        }
      }
    }
  }


  static Tile get(long key) {
    synchronized(cache) {
      for (Tile tile : cache) {
        if (tile.key == key) {
          return tile;
        }
      }
      return null;
    }
  }

}
【プログラム・ソースコード】 Map.java  Tile.java

リファレンス