Mapsforge, OSM Bazlı Harita Tabanından Harita Görüntüsü Almak
Açık harita veri tabanı OSM bazlı bir diğer haritalama tabanı ve kodlama altyapısı mapsforge. Eğer kendi diskimizdeki bir dosyadan harita alıp basmak istiyorsak, en basit kod alttaki gibi
import org.mapsforge.core.graphics.GraphicFactory;
import org.mapsforge.core.graphics.TileBitmap;
import org.mapsforge.core.model.Tile;
import org.mapsforge.core.util.MercatorProjection;
import org.mapsforge.map.awt.graphics.AwtGraphicFactory;
import org.mapsforge.map.datastore.MapDataStore;
import org.mapsforge.map.layer.cache.FileSystemTileCache;
import org.mapsforge.map.layer.labels.TileBasedLabelStore;
import org.mapsforge.map.layer.renderer.DatabaseRenderer;
import org.mapsforge.map.layer.renderer.RendererJob;
import org.mapsforge.map.model.DisplayModel;
import org.mapsforge.map.model.FixedTileSizeDisplayModel;
import org.mapsforge.map.reader.MapFile;
import org.mapsforge.map.rendertheme.InternalRenderTheme;
import org.mapsforge.map.rendertheme.XmlRenderTheme;
import org.mapsforge.map.rendertheme.rule.RenderThemeFuture;
import java.io.File;
import java.io.IOException;
public class SaveTiles {
private static final String SAVE_PATH = "/tmp/";
private static final File DEFAULT_MAP_PATH = new File("[DIZIN]/kosovo.map");
// Kosovoda herhangi bir nokta
private static final double LAT = 42.470369;
private static final double LNG = 20.838044;
private static final byte ZOOM = 14;
public static void main(String[] args) throws IOException {
MapDataStore mapData = new MapFile(DEFAULT_MAP_PATH);
final int ty = MercatorProjection.latitudeToTileY(LAT, ZOOM);
final int tx = MercatorProjection.longitudeToTileX(LNG, ZOOM);
Tile tile = new Tile(tx, ty, ZOOM, 800);
GraphicFactory gf = AwtGraphicFactory.INSTANCE;
XmlRenderTheme theme = InternalRenderTheme.OSMARENDER;
DisplayModel dm = new FixedTileSizeDisplayModel(256);
RenderThemeFuture rtf = new RenderThemeFuture(gf, theme, dm);
RendererJob theJob = new RendererJob(tile, mapData, rtf, dm, 1.0f, false, false);
File cacheDir = new File("/tmp", "tmp");
FileSystemTileCache tileCache = new FileSystemTileCache(10, cacheDir, gf, false);
TileBasedLabelStore tileBasedLabelStore = new TileBasedLabelStore(tileCache.getCapacityFirstLevel());
DatabaseRenderer renderer = new DatabaseRenderer(mapData, gf, tileCache, tileBasedLabelStore, true, true, null);
Thread t = new Thread(rtf);
t.start();
TileBitmap tb = renderer.executeJob(theJob);
tileCache.put(theJob, tb);
mapData.close();
System.out.printf("Tile has been saved at %s/%d/%d/%d.tile.\n", cacheDir.getPath(), ZOOM, tx, ty);
}
}
Bu kod için gereken jar dosyaları,
https://mvnrepository.com/artifact/net.sf.kxml/kxml2/2.3.0
https://mvnrepository.com/artifact/org.mapsforge/mapsforge-core/0.12.0
https://mvnrepository.com/artifact/org.mapsforge/mapsforge-core/0.12.0
https://mvnrepository.com/artifact/org.mapsforge/mapsforge-map-awt/0.12.0
https://mvnrepository.com/artifact/org.mapsforge/mapsforge-map-reader/0.12.0
https://mvnrepository.com/artifact/org.mapsforge/mapsforge-themes/0.12.0
https://mvnrepository.com/artifact/com.kitfox.svg/svg-salamander/1.0
Kodu derlemek icin gerekli iskelet dizi, Ant yapisi icin
https://github.com/burakbayramli/kod/tree/master/sk/2019/12/staticmap
Mapsforge tabanları pek çok ülke için bulunabilir, mesela Kosova için
(ufak olduğu için oraya gittik), kosovo.map
indirilir,
http://download.mapsforge.org/maps/v5/europe/
istenilen dizine konup ona göre kod ayarlanınca, ant run
ile
işletiriz, ve sonuç bir tile
dosyası oluyor, alttaki gibi çıkacak,
Dikkat: enlem/boylam verip bir statik elde ettiğimizde bu harita verilen enlem/boylam merkezli ortalanmış olmayabiliyor. Haritanın ortasının hangi kordinatlara sahip olduğunu bulmak için
double centerlon = tile.getBoundingBox().getCenterPoint().getLongitude();
double centerlat = tile.getBoundingBox().getCenterPoint().getLatitude();
işletilebilir.
Python
Eğer Python üzerinden Java çağırmak istiyorsak, şu şekilde bir değişiklik yapabiliriz,
...
import org.mapsforge.core.model.LatLong;
import org.mapsforge.core.model.Point;
public class SaveTiles {
private static final String SAVE_PATH = "/tmp/";
private static File DEFAULT_MAP_PATH;
private static byte ZOOM;
public static void main(String[] args) throws IOException {
DEFAULT_MAP_PATH = new File(args[2]);
ZOOM = (byte)Integer.parseInt(args[3]);
String [] tokens = args[0].split(",");
double LAT = Double.parseDouble(tokens[0].split(";")[0]);
double LNG = Double.parseDouble(tokens[0].split(";")[1]);
MapDataStore mapData = new MapFile(DEFAULT_MAP_PATH);
final int ty = MercatorProjection.latitudeToTileY(LAT, ZOOM);
final int tx = MercatorProjection.longitudeToTileX(LNG, ZOOM);
Tile tile = new Tile(tx, ty, ZOOM, 800);
System.out.print("{\"pixels\":[");
for (int i=0;i<tokens.length;i++){
double currlat = Double.parseDouble(tokens[i].split(";")[0]);
double currlng = Double.parseDouble(tokens[i].split(";")[1]);
Point pix = MercatorProjection.getPixelRelativeToTile(new LatLong(currlat,currlng), tile);
System.out.print("[" + pix.x + ","+pix.y+"]");
if (i<tokens.length-1) {
System.out.print(",");
}
}
System.out.print("]");
GraphicFactory gf = AwtGraphicFactory.INSTANCE;
XmlRenderTheme theme = InternalRenderTheme.OSMARENDER;
DisplayModel dm = new FixedTileSizeDisplayModel(256);
RenderThemeFuture rtf = new RenderThemeFuture(gf, theme, dm);
RendererJob theJob = new RendererJob(tile, mapData, rtf, dm, 1.0f, false, false);
File cacheDir = new File(args[1], "");
FileSystemTileCache tileCache = new FileSystemTileCache(10, cacheDir, gf, false);
TileBasedLabelStore tileBasedLabelStore = new TileBasedLabelStore(tileCache.getCapacityFirstLevel());
DatabaseRenderer renderer = new DatabaseRenderer(mapData, gf, tileCache, tileBasedLabelStore, true, true, null);
Thread t = new Thread(rtf);
t.start();
TileBitmap tb = renderer.executeJob(theJob);
tileCache.put(theJob, tb);
mapData.close();
System.out.printf(",\"file\": \"%s/%d/%d/%d.tile\"", cacheDir.getPath(), ZOOM, tx, ty);
System.out.print("}");
}
}
Bu koda bir kordinat listesi verebiliyoruz, ve cevap olarak bir sözlük içinde piksel olarak o kordinatların yerleri, ve imaj dosyası yeri raporlanıyor.
Altta Python'dan Java çağrısının nasıl yapıldığını, girdi ve çıktı
işleme görülüyor. Çağrıyı aslında komut satırı ile yapıyoruz,
subprocess
paketi ile, bir anlamda bir süreç başlatıp Java'yı orada
işletiyoruz, ve sonucu alıp Python'dan devam ediyoruz.
import numpy as np, json
import matplotlib.pyplot as plt
from PIL import Image
import subprocess, os, json
def plot(points,outfile,pixel=False,bp=True):
plt.figure()
res = load_map(pts)
pixels = res['pixels']
found_file = res['file']
im = Image.open(found_file)
nim = np.array(im)
plt.axis('off')
fig=plt.imshow(im)
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.imshow(im)
for i,[xx,yy] in enumerate(pixels):
if xx > nim.shape[0] or yy > nim.shape[1] or xx<0 or yy<0: continue
if i==0:
if bp: plt.plot(xx,yy,'rx')
else: plt.plot(xx,yy,'r,')
else:
if pixel:
plt.plot(xx,yy,'r,')
else:
plt.plot(xx,yy,'r.')
plt.savefig(outfile, bbox_inches='tight', pad_inches = 0, dpi = 300)
def load_map(pts):
spts = str([str(pt[0]) + ";" + str(pt[1]) for pt in pts])
spts = spts.replace('[','').replace(']','')
spts = spts.replace("'","").replace(" ","")
cmd = ['/bin/sh',os.environ['HOME']+'/Documents/kod/nomadicterrain/map/staticmap/run.sh', spts,'/tmp','/home/burak/Downloads/turkey.map','14']
result = subprocess.run(cmd, stdout=subprocess.PIPE)
res = json.loads(result.stdout.decode('utf-8'))
return res
lat1,lon1=40.970041,29.170311
lat2,lon2=40.971041,29.171311
lat3,lon3=40.971041,29.172311
pts = [[lat1,lon1],[lat2,lon2],[lat3,lon3]]
plot(points=pts, outfile="/tmp/out.png")
Ayrıca run.sh
lazım,
DIR=$HOME/Documents/kod/nomadicterrain/map/staticmap
java -cp $DIR/build:$DIR/lib/kxml2-2.3.0.jar:$DIR/lib/mapsforge-core-0.12.0.jar:\
$DIR/lib/mapsforge-map-0.12.0.jar:$DIR/lib/mapsforge-map-awt-0.12.0.jar:\
$DIR/lib/mapsforge-map-reader-0.12.0.jar:$DIR/lib/mapsforge-themes-0.12.0.jar:\
$DIR/lib/svg-salamander-1.0.jar \
SaveTiles $1 $2 $3 $4
Üç tane nokta bastık, sonucu altta görüyoruz,
Yukarı