Thursday, December 1, 2016

Islenmis OSM Verisi Yerel Diskte, osm2pgsql

Daha once OSRM projesi ile OSM verisi uzerinden nasil servis sunabilir, bunu gorduk. Peki ya ham veriyi almak istiyorsak ne yapariz?

osm2pgsql adli arac apt-get ile kurulabiliyor, yerel diskteki osm.bz2 tipindeki dosyalari isleyip direk Postgresql tabanina veriyi yazabiliyor. PG kurmayi hatirlayalim (lokasyon ekleri ile, PG'nin lokasyon verisinin islenmesini saglayan ozel fonksiyonlari var),

sudo apt-get install postgresql make cmake g++ libboost-dev libboost-system-dev   libboost-filesystem-dev libexpat1-dev zlib1g-dev   libbz2-dev libpq-dev libgeos-dev libgeos++-dev libproj-dev lua5.2   liblua5.2-dev osm2pgsql

Baslamak, durdurmak icin sudo service postgresql stop ya da start. Kurulus sirasinda mevcut kullanicinizin direk erisebilecegi postgres adli bir kullanici yaratilmis olmali.

sudo -u postgres createdb gis

ile taban yaratilir.

sudo -i -u postgres

ile oteki kullaniciya girilir,

psql -d gis -c 'CREATE EXTENSION postgis; CREATE EXTENSION hstore;'

Simdi

osm2pgsql berlin-latest.osm.bz2 --slim

Tabana bakariz, psql -d gis, komut satirinda \dt

planet_osm_line
planet_osm_nodes
planet_osm_point
planet_osm_polygon
planet_osm_rels
planet_osm_roads
planet_osm_ways

tablolarini gormemiz lazim. Artik gereken ham veri bu tablolar icinde. Eger veriyi disari cikartmak istiyorsak, mesela tabandaki tum caddeler,

psql -d gis -t -A -F";" -c \
     "SELECT  osm_id,name,highway,\
     st_asText(st_startpoint(st_transform(way, 4326))), \
     st_asText(st_endpoint(st_transform(way, 4326))) \
     FROM planet_osm_line " > output.csv

Not: Ayni cadde ismi ustteki sorgu sonucu birden fazla satirda ve baslangic / bitis noktasi ile gozukebilir. Bu durumda buyuk cogunlukla ayni caddeyi parcalar haline goruyoruz demektir.

osm2po

Alttaki Java bazli bir proje (kapali kod ne yazik ki), Geofabrik sitesinden gerekli veriyi alip bir Postgresql tabani uzerinde isletilebilecek SQL dosyasi uretiyor.

http://osm2po.de

java -Xmx1g -jar osm2po-core-5.1.0-signed.jar prefix=tr tileSize=x http://download.geofabrik.de/europe/turkey-latest.osm.pbf postp.0.class=de.cm.osm2po.plugins.postp.PgRoutingWriter

cagrisi yeterli. Gerekli dosya tr altdizini icinde olacak. Fakat bu kutuphanenin bazi verileri disarida biraktigini gorduk.

osm2pgrouting

Ham OSM verisinin Postgresql tabana yazabilen bir proje

https://github.com/pgRouting/osm2pgrouting.

Derlemek gerekli.. Ayrica tabani pgrouting icin hazirlamak lazim, bazi create extension komutlari gerekiyor. Ustteki README icinde bunlar var.

Bu kodun bir problemi eger yeterince hafiza yoksa (2 GB bile yetmeyebilir) tek bir bolge verisi uzerinde bile program cokebiliyor.

Wednesday, November 30, 2016

Python ve OSRM

OSRM harita servisi JSON ile bilgi gonderir; bu bilgiyi dekode etmek icin Python araclari var. Once,

apt-get install binutils libproj-dev gdal-bin python-gdal

sudo pip install geopandas polyline Fiona 

Su alttaki GH adresindeki Python kodlari fena degil, fakat tek script icinden pat diye isletebilmek icin biraz basitlestirme gerekti. Bu kod direk localhost:5000 uzerinde isleyen servise baglanir ve bilgiyi alir.

https://github.com/ustroetz/python-osrm

Alttaki kod yol bulma (route)  icin yeterli

import numpy as np
from pandas import DataFrame
from urllib2 import urlopen
from polyline import encode as polyline_encode
from ogr import Geometry
from polyline.codec import PolylineCodec
import json

def _chain(*lists):
    for li in lists:
        for elem in li: yield elem

class DefaultRequestConfig:
    def __init__(self):
        self.host = "http://localhost:5000"
        self.profile = "driving"
        self.version = "v1"

    def __str__(self):
        return("/".join([self.host, '*', self.version, self.profile]))

    def __repr__(self):
        return("/".join([self.host, '*', self.version, self.profile]))

    @staticmethod
    def __call__(addr=None):
        if not addr:
            return DefaultRequestConfig()
        else:
            tmp = addr.split('/')
            cla = DefaultRequestConfig()
            cla.host = tmp[0]
            i = len(tmp)
            cla.version = tmp[i-2]
            cla.profile = tmp[i-1]
            return cla

RequestConfig = DefaultRequestConfig()

def check_host(host):
    """ Helper function to get the hostname in desired format """
    if not ('http' in host and '//' in host) and host[len(host)-1] == '/':
        return ''.join(['http://', host[:len(host)-1]])
    elif not ('http' in host and '//' in host):
        return ''.join(['http://', host])
    elif host[len(host)-1] == '/':
        return host[:len(host)-1]
    else:
        return host

def decode_geom(encoded_polyline):
    ma_ligne = Geometry(2)
    lineAddPts = ma_ligne.AddPoint_2D
    for coord in PolylineCodec().decode(encoded_polyline):
        lineAddPts(coord[1], coord[0])
    return ma_ligne

def simple_route(coord_origin_old, coord_dest_old, coord_intermediate=None,
                 alternatives=False, steps=False, output="full",
                 geometry='polyline', overview="simplified",
                 url_config=RequestConfig, send_as_polyline=True):
    if geometry.lower() not in ('wkt', 'well-known-text', 'text', 'polyline',
                                'wkb', 'well-known-binary', 'geojson'):
        raise ValueError("Invalid output format")
    else:
        geom_request = "geojson" if "geojson" in geometry.lower() \
            else "polyline"

    coord_origin = tuple(reversed(coord_origin_old))
    coord_dest = tuple(reversed(coord_dest_old))

    host = check_host(url_config.host)

    if not send_as_polyline:
        url = [host, "/route/", url_config.version, "/", url_config.profile,
               "/", "{},{}".format(coord_origin[0], coord_origin[1]), ';']

        if coord_intermediate:
            url.append(";".join(
                [','.join([str(i), str(j)]) for i, j in coord_intermediate]))

        url.extend([
            '{},{}'.format(coord_dest[0], coord_dest[1]),
            "?overview={}&steps={}&alternatives={}&geometries={}".format(
                 overview, str(steps).lower(),
                 str(alternatives).lower(), geom_request)
            ])
    else:
        coords = [
            pt[::-1] for pt in _chain(
                        [coord_origin],
                        coord_intermediate if coord_intermediate else [],
                        [coord_dest])
            ]
        url = [
            host, "/route/", url_config.version, "/", url_config.profile, "/",
            "polyline(", polyline_encode(coords), ")",
            "?overview={}&steps={}&alternatives={}&geometries={}".format(
                 overview, str(steps).lower(),
                 str(alternatives).lower(), geom_request)
            ]
    rep = urlopen(''.join(url))
    parsed_json = json.loads(rep.read().decode('utf-8'))

    if "Ok" in parsed_json['code']:
        if geometry in ("polyline", "geojson") and output == "full":
            return parsed_json
        elif geometry in ("polyline", "geojson") and output == "routes":
            return parsed_json["routes"]
        else:
            if geometry == "wkb":
                func = Geometry.ExportToWkb
            elif geometry == "wkt":
                func = Geometry.ExportToWkt

            for route in parsed_json["routes"]:
                route["geometry"] = func(decode_geom(route["geometry"]))

        return parsed_json if output == "full" else parsed_json["routes"]

    else:
        raise ValueError(
            'Error - OSRM status : {} \n Full json reponse : {}'.format(
                parsed_json['code'], parsed_json))

# test
result1 = simple_route((40.987659,29.036428), (40.992186,29.039228),
                       output="routes",
                       geometry="wkt",
                       send_as_polyline=True, steps=True)
print result1

Bu arada ciktilarda enlem, boylam degerleri yer degisikligine ugramis, OSRM her nedense boyle yapiyor, biz sadece girdide sirayi degistirdik.

Tuesday, November 29, 2016

Yol Tarifi, Harita Bilgisi: osrm-backend

Verili herhangi bir enlem / boylam kordinatina en yakin sokak, yol isimlerini, yerlerini bulabilen, hatta bir noktadan digerine nasil gidilecegini veren bir veri tabani ve program OSRM. Aslinda bu arkadaslar OpenStreetMap adli projenin veri tabanini daha iyi erisilebilir hale getirmisler.

https://github.com/Project-OSRM

Proje C++ bazli, hizli isliyor. Icinde OSM projesinin dosyalarini alip onlari daha ufaltan, ve bir servis ve API uzerinden dis erisime hazir hale getiren kodlar var. Bu servisin nasil isledigini gostermek icin kendileri bir bedava servis isletiyorlar,

http://router.project-osrm.org

Mesela alttaki kordinata en yakin cadde hangisidir

http://router.project-osrm.org/nearest/v1/foot/29.036428,40.987659

ile bulunabiliyor, cikti JSON formatinda. Iki nokta arasinda nasil gidilir, hangi caddeler kullanilir,

http://router.project-osrm.org/route/v1/foot/29.036428,40.987659;29.039228,40.992186

URL icinde v1 ardindan gidis sekli verilmeli, araba icin car, bisiklet icin bicycle; ustteki yuruyerek.

Istenen her  turden veri ustteki bedava servisten alinabilir, ama baskasinin servisini fazla yormamak (!) icin (ve yerel bazli erisim daha hizli olur tabii) kendi servisimizi olusturabiliriz.

Kod Github'dan indirilir, ve apt-get install alttakiler uzerinde isletilir,

cmake libtbb-dev lua5.2 libboost-all-dev liblua52 libluabind-dev liblua5.2-dev libluabind-dev libstxxl-dev libxml2 libxml2-dev libosmpbf-dev libbz2-dev libprotobuf-dev

Simdi proje dizinine girilip

mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
sudo cmake --build . --target install

isletilir. Ayrica ayni dizinde hangi ulasim sekli var ise, onun lua dosyasina Unix sembolik baglanti kurulmali, mesela araba yontemi icin

ln -s profiles/car.lua .

Kurulum bitti, simdi veri lazim, mesela Turkiye icin

http://download.geofabrik.de/europe/turkey.html turkey-latest.osm.bz2

Tum veri icin http://download.geofabrik.de

Bu dosya acilir, simdi dosya uzerinde

osrm-extract turkey-latest.osm

ve

osrm-contract turkey-latest.osrm

Dikkat bu komutlari lua linki neredeyse oradan isletmek lazim. O zaman osrm dosya referansina dizin ismi eklemek gerekebilir.

Bu son komut uzun surecek, 30-40 dakika gibi.. Bittikten sonra artik veri hazir, veri dizininde

osrm-routed map.osrm

isletilir. Bu komut 5000 port'unu dinleyen bir servis baslatir. Artik ustteki turunden tum komutlarda http://router.project-osrm.org yerine http://localhost:5000 kullanilabilir.

Baglantilar

https://www.digitalocean.com/community/tutorials/how-to-set-up-an-osrm-server-on-ubuntu-14-04

https://github.com/Project-OSRM/osrm-backend/wiki/Running-OSRM

https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md

Harita Uygulamasi, GPS, Android

Cep telefonunda nerede oldugumuzu harita uzerinde bulmak icin bir uygulama.

https://github.com/burakbayramli/kod/tree/master/mycamera2

Ayrica kamera goruntuleri, yon algilayicisi, GPS verilerini kaydetme ozelligi var. Ben bu uygulamayi baska bir proje icin veri kaydi, test etme ve sonradan analiz amacli yazdim, baslangic noktasi olarak baskalari icin faydali olabilir.

Harita gosteren kodun zoom ozelligi var, haritada ayrica saga, sola, yukari, asagi kaydirma hareketi ile dogu, bati, vs. yonundeki diger haritalari da gormek mumkun.

Uygulama tum bir sehrin haritasini tek bir zip dosyasinda tutuyor, baska hicbir veriye, ya da Google Maps baglantisina ihtiyac yok. Haritalama uygulamasi boyle calismali; Internet baglantisi olmayinca harita calismazsa bu iyi olmaz, turist, gezgin yolda kalir. "Merkezle" fazla baglanti iyi bir sey degil, saglam bilgi islem sistemleri de bu mantikla kurulur.

Derlemek icin ant yeterli, ant debug, ant installd, ya da ant release ile apk yaratilir.

Istanbul haritasi

https://dl.dropboxusercontent.com/u/1570604/data/istanbul.zip

Tuesday, November 22, 2016

Android'i Konusturmak, Metinden Konusma (Text-to-Speech)

Android uygulamasi icinde cep telefonunu konusturmak icin arayuz var. Herhangi bir Activity icinde

import android.speech.tts.TextToSpeech;

public class MyActivity extends Activity
{
    ...

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        ...
        t1=new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
                @Override
                public void onInit(int status) {
                    if(status != TextToSpeech.ERROR) {
                        t1.setLanguage(Locale.UK);
                    }
                }
            });
     }
}

Ustteki onInit konusturma yapmadan once islemis olmali. Simdi herhangi bir metni okutmak icin

String toSpeak = "How much wood could a woodchuck chuck";
t1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);