Mapion マピオンラボ モバイル 独自画像をAndroid Maps APIで表示する方法(ImageMagick編)
Posted by 本城 博昭 / エンジニア Follow @honjo2
Mapion Android Maps APIで独自画像を表示する方法を紹介します。
デモアプリの「独自地図画像を指定する」の実現方法です。
今回はImageMagick編です。
前回記事の通りGMap Image Cutterを使えば簡単にタイルを作成できますが、ImageMagickを使えばもっと自由にタイルを作れます。
GMap Image Cutterの場合はググルマップに最適化されるので、タイルサイズが256x256に強制されたり、ズーム率が固定だったりします。
けれど、Maps APIはタイルサイズもズーム率も自由に設定できるので、ImageMagickを使えば元画像を最大限利用できるのです。
※独自画像を実装するためにはmaps API 2.5以上が推奨です(それ以前のVerはスクロール遅いなど問題あり)
手順
1.ImageMagickを使ってタイルを作成する
※前回記事と同じ画像を使って同じように縮尺3つ、各倍率2倍とした場合の例です
レベル3作成(画像を320x200に分割)
$ convert -crop 320x200 sa.png level3.png
レベル2作成(50%の画像を320x200に分割)
$ convert -geometry 50% sa.png level2_tmp.png
$ convert -crop 320x200 level2_tmp.png level2.png
レベル1作成(25%の画像)
$ convert -geometry 25% sa.png level1_0.png
tmpファイル削除
$ rm *_tmp.png
ファイル名内のハイフンをアンスコに変更(Androidではリソースにハイフン使えないので)
$ rename 's/-/_/' *
2.res/drawable-nodpiにタイルをコピーする

3.Mapのサブクラスを作る
可変な部分は、tileWidth(タイルの横幅), tileHeight(タイルの高さ), cols(各縮尺のタイルの横の枚数), rows(各縮尺のタイルの縦の枚数) , ratios(各縮尺の倍率)です。
package jp.co.mapion.android.mymap;
import java.lang.reflect.Field;
import java.util.HashMap;
import jp.co.mapion.android.maps.GeoPoint;
import jp.co.mapion.android.maps.Map;
import jp.co.mapion.android.maps.Tile;
import android.graphics.Point;
public class MyMap extends Map {
protected int tileWidth = 320;
protected int tileHeight = 200;
protected HashMap<Integer, Integer> cols = new HashMap<Integer, Integer>();
protected HashMap<Integer, Integer> rows = new HashMap<Integer, Integer>();
protected HashMap<Integer, Float> ratios = new HashMap<Integer, Float>();
private HashMap<String, Integer> tileNameMap = new HashMap<String, Integer>();
private String key;
private int noimage;
public MapionTownMap(String key, int noimage) {
this.key = key;
this.noimage = noimage;
init();
}
protected void init() {
cols.put(1, 1);
cols.put(2, 2);
cols.put(3, 4);
rows.put(1, 1);
rows.put(2, 2);
rows.put(3, 4);
ratios.put(1, 4.0f);
ratios.put(2, 2.0f);
ratios.put(3, 1.0f);
}
@Override
protected int getMaxZoomLevel() {
return ratios.size();
}
@Override
protected void setup() {
setCenter(new GeoPoint(0, 0));
setZoom(1);
}
@Override
protected int getTileWidth() {
return tileWidth;
}
@Override
protected int getTileHeight() {
return tileHeight;
}
@Override
protected Point geoToPixel(GeoPoint geo) {
int x = (int) (geo.getLongitudeE6() / getRatio());
int y = (int) (geo.getLatitudeE6() / getRatio());
return new Point(x, y);
}
@Override
protected GeoPoint pixelToGeo(Point pixel) {
int lat = (int) (pixel.y * getRatio());
int lon = (int) (pixel.x * getRatio());
return new GeoPoint(lat, lon);
}
@Override
protected GeoPoint getOrigin() {
double originRatio = ratios.get(1);
int centerx = tileWidth * rows.get(1) / 2;
int centery = tileHeight * cols.get(1) / 2;
int lat = (int) (centery * originRatio);
int lon = (int) (-centerx * originRatio);
return new GeoPoint(lat, lon);
}
@Override
protected String getURL(Tile tile) {
if (isOut(tile)) {
return noMap();
}
int x = (int) tile.getX();
int y = (int) tile.getY();
int tileNo = y * cols.get(getZoom()) + x;
String name = "level" + getZoom() + "_" + tileNo;
int id = getResourceInt(name);
if (id == -1) {
return noMap();
} else {
String ret = String.valueOf(id);
return ret;
}
}
@Override
protected String getKey() {
return key;
}
private double getRatio() {
return ratios.get(getZoom());
}
private int getResourceInt(String name) {
if (tileNameMap.containsKey(name)) {
return tileNameMap.get(name);
}
try {
Field field = R.drawable.class.getDeclaredField(name);
int tileId = field.getInt(R.drawable.class);
tileNameMap.put(name, tileId);
return tileId;
} catch (Exception e) {
}
return -1;
}
private String noMap() {
return String.valueOf(noimage);
}
private boolean isOut(Tile tile) {
int x = (int) tile.getX();
int y = (int) tile.getY();
if (x < 0 || y < 0) {
return true;
}
if (x >= cols.get(getZoom())) {
return true;
}
return false;
}
}
これで完成です。
APIの機能が全て使えるのでアイコンやテキストなどをOverlayしたり、回転させたりできます。
例ではローカルに画像を置いていますが、サーバに置くことも可能です。

-
この記事のトラックバックURLhttp://labs.mapion.co.jp/mtos/mt-tb.cgi/95





