Geo Utils — Fonksiyon Referansı
mapindata.core.geo_utils modülü, coğrafi hesaplama için saf Python fonksiyonları içerir.
Harici bağımlılık gerektirmez; pointInPolygon için shapely opsiyonel olarak kullanılır.
haversineDistance
İki koordinat arasındaki yüzey mesafesini metre cinsinden hesaplar.
Haversine formülünü kullanır — kısa ve orta mesafelerde yüksek doğruluk sağlar.
Parametre sırası: (lat, lon) — GeoJSON'daki (lon, lat) sırasının tersidir.
| Parametre | Tip | Açıklama |
|---|---|---|
lat1 |
float | Birinci noktanın enlemi (derece) |
lon1 |
float | Birinci noktanın boylamı (derece) |
lat2 |
float | İkinci noktanın enlemi (derece) |
lon2 |
float | İkinci noktanın boylamı (derece) |
Döndürür: float — iki nokta arası mesafe (metre)
Örnek:
from mapindata.core import haversineDistance
dist = haversineDistance(41.01, 28.97, 39.92, 32.85)
# → ~350 000 metre (İstanbul–Ankara)
Formül:
$$ a = \sin^2!\left(\frac{\Delta\phi}{2}\right) + \cos\phi_1 \cdot \cos\phi_2 \cdot \sin^2!\left(\frac{\Delta\lambda}{2}\right) $$ $$ d = 2R \cdot \arctan2!\left(\sqrt{a},\,\sqrt{1-a}\right) \quad R = 6\,371\,000 \text{ m} $$
pointInPolygon
Bir koordinatın GeoJSON polygon içinde olup olmadığını kontrol eder.
İçeride shapely.geometry.shape kullanılır.
| Parametre | Tip | Açıklama |
|---|---|---|
lat |
float | Noktanın enlemi |
lon |
float | Noktanın boylamı |
polygonCoords |
list | GeoJSON Polygon.coordinates dizisi — [[[lon, lat], ...]] |
Döndürür: bool — True nokta içinde, False dışında ya da hatalı girdi
Not: GeoJSON koordinat sırası
[lon, lat]'tır (boylam önce). Bu fonksiyon bu dönüşümü dahili olarak yapar.
Örnek:
from mapindata.core import pointInPolygon
polygon = [[[28.97, 41.03], [28.98, 41.03], [28.98, 41.04], [28.97, 41.04], [28.97, 41.03]]]
result = pointInPolygon(41.035, 28.975, polygon)
# → True
boundingBox
Koordinat listesinden minimum sınırlayıcı dikdörtgeni hesaplar.
Girdi formatı: [[lat, lon], [lat, lon], ...]
Döndürür:
Kullanım amacı: Büyük veri kümelerini bounding box ile ön filtrelemek — örn. S3'ten okunurken gereksiz kayıtları erken elemek.
centroid
Koordinat listesinin aritmetik merkezini hesaplar.
Girdi formatı: [[lat, lon], [lat, lon], ...]
Döndürür: {"lat": float, "lon": float}
Neden Haversine? Neden Polygon?
| Durum | Önerilen Yöntem |
|---|---|
| Mağaza/POI ziyareti (giriş noktası) | Haversine + küçük yarıçap (15–50 m) |
| AVM, park, büyük yapı | Polygon (şekil düzensiz, alan büyük) |
| Semt / ilçe analizi | Polygon (idari sınır verisi) |
| Hızlı ön filtresi | Bounding Box → ardından Polygon |
Daha fazla bilgi için bkz. kodlama-standartlari.md
S3Client ile Büyük Veri Akışı
S3'ten okunan mobil veri FootfallEngine'in Spark metodlarıyla birleştirilerek
tam analiz yapılır. Tipik iş akışı:
S3Client.loadMobilityData() → Spark DataFrame
└─▶ boundingBox() → ön filtre koordinatları
└─▶ FootfallEngine.*Spark() → polygon / radius filtresi
└─▶ unique device sayısı veya DataFrame
from mapindata.core.config import ConfigManager
from mapindata.core.geo_utils import boundingBox
from mapindata.data.duckdb_client import DuckDBClient
from mapindata.mobility.footfall_engine import FootfallEngine
cfg = ConfigManager()
duck = DuckDBClient(cfg)
# Engine DuckDB motoru ile başlat (varsayılan, ~70× hızlı)
engine = FootfallEngine(con=duck.connect(), s3Path=duck.s3Path("istanbul"))
polygon = [[[28.97, 41.03], [29.01, 41.03], [29.01, 41.07], [28.97, 41.07], [28.97, 41.03]]]
count = engine.getCountByPolygon(polygon)
print(f"Footfall: {count:,} unique device")
duck.close()
Spark motoru da desteklenir:
FootfallEngine(df=spark_df)→engine.getCountByPolygon(polygon, engine="spark")
Spark konfigürasyonu için bkz. Proje Geçmişi — S3 ve EC2 Ortamı
polygonAreaM2
GeoJSON polygon alanını metre kare cinsinden hesaplar.
Shoelace (Gauss alan) formülünü kullanır; sonucu derece² → m² katsayısıyla çarpar.
Küçük polygon / büyük polygon karar eşiğinde (_SMALL_POLYGON_AREA_M2 = 100 000 m²) kullanılır.
| Parametre | Tip | Açıklama |
|---|---|---|
polygonCoords |
list | GeoJSON Polygon.coordinates — [[[lon, lat], ...]] |
Döndürür: float — alan (m²)
Örnek:
from mapindata.core.geo_utils import polygonAreaM2
polygon = [[[28.972, 41.018], [28.978, 41.018], [28.978, 41.022], [28.972, 41.022], [28.972, 41.018]]]
area = polygonAreaM2(polygon)
# → ~300 000 m² (yaklaşık 0.3 km²)
h3CentroidCell
Koordinatın H3 hücresini INT64 olarak döndürür.
Parquet dosyalarında h3_res9_id sütunu INT64 olarak saklandığından bu çıktı
doğrudan Spark filter ifadelerinde kullanılabilir.
| Parametre | Tip | Açıklama |
|---|---|---|
lat |
float | Enlem |
lon |
float | Boylam |
res |
int | H3 çözünürlük (varsayılan 9) |
Döndürür: int — H3 hücre indeksi (64-bit)
Örnek:
from mapindata.core.geo_utils import h3CentroidCell
cell = h3CentroidCell(41.0370, 28.9850)
# → 613146799897739263 (Taksim Meydanı H3 res9 hücresi)
h3PolygonCells
GeoJSON polygon için H3 hücrelerini INT64 listesi olarak döndürür.
h3shape_to_cells polyfill uygular; ardından sınır hücrelerine grid_disk(bufferK) tamponu ekler.
Büyük / orta polygonlar (alan ≥ 100 000 m²) için uygundur.
Polyfill boş dönerse (< 1 H3 hücresi) boş liste döner — bu durumda h3CentroidCell + autoKringK kullanın.
| Parametre | Tip | Açıklama |
|---|---|---|
polygonCoords |
list | GeoJSON Polygon.coordinates — [[[lon, lat], ...]] |
res |
int | H3 çözünürlük (varsayılan 9) |
bufferK |
int | Kenar tamponu halka sayısı (varsayılan 1) |
Döndürür: list[int] — H3 hücre INT64 listesi
Örnek:
from mapindata.core.geo_utils import h3PolygonCells
polygon = [[[28.820, 41.050], [28.880, 41.050], [28.880, 41.080], [28.820, 41.080], [28.820, 41.050]]]
cells = h3PolygonCells(polygon)
# → [613146..., 613147..., ...] (Bağcılar bölgesi H3 hücreleri)
autoKringK
Polygon kenar uzunluğuna göre H3 kring yarıçapını (0 veya 1) otomatik seçer.
Karar kriteri: en kısa polygon kenarı H3 res9 çapından (≈ 174 m) büyükse k=0 (sadece centroid),
küçükse k=1 (centroid + 1 halka çevre hücreler).
FootfallEngine._filterByPolygonSpark tarafından küçük polygon yolunda kullanılır.
| Parametre | Tip | Açıklama |
|---|---|---|
polygonCoords |
list | GeoJSON Polygon.coordinates — [[[lon, lat], ...]] |
res |
int | Şu an yalnızca res=9 desteklenir |
Döndürür: int — 0 veya 1
H3 res9 referans değerleri:
| Değer | Ölçüm |
|---|---|
| Hücre kenarı | ≈ 87 m |
| Hücre çapı (köşe–köşe) | ≈ 174 m |
| Kapsama alanı | ≈ 0.105 km² |
Örnek:
from mapindata.core.geo_utils import autoKringK
small = [[[28.972, 41.018], [28.974, 41.018], [28.974, 41.020], [28.972, 41.020], [28.972, 41.018]]]
print(autoKringK(small)) # → 1 (kenar < 174 m)
large = [[[28.820, 41.050], [28.880, 41.050], [28.880, 41.080], [28.820, 41.080], [28.820, 41.050]]]
print(autoKringK(large)) # → 0 (kenar >> 174 m)
Katkıda Bulunanlar
| Ad | Rol |
|---|---|
| Kaan Gümele | SDK Geliştirici |