Skip to content

Instantly share code, notes, and snippets.

@mcihad
Last active December 3, 2025 20:23
Show Gist options
  • Select an option

  • Save mcihad/a32cece92e3a26833668f3f2b40543da to your computer and use it in GitHub Desktop.

Select an option

Save mcihad/a32cece92e3a26833668f3f2b40543da to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessing,
QgsProcessingAlgorithm,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterField,
QgsProcessingParameterFolderDestination,
QgsProcessingParameterBoolean,
QgsProcessingParameterCrs,
QgsFeatureRequest,
QgsCoordinateTransform,
Qgis)
import os
class AkilliSehirParselExport(QgsProcessingAlgorithm):
"""
Akıllı Şehir Müdürlüğü - Parsel Koordinat Çıkarıcı
Özellikler:
- Sadece seçili olanlar (Varsayılan)
- Hedef CRS dönüşümü (Yeni)
- MAKS klasör yapısı
"""
INPUT = 'INPUT'
ONLY_SELECTED = 'ONLY_SELECTED'
ID_FIELD = 'ID_FIELD'
TARGET_CRS = 'TARGET_CRS' # Yeni Parametre
OUTPUT_FOLDER = 'OUTPUT_FOLDER'
def tr(self, string):
return QCoreApplication.translate('Processing', string)
def createInstance(self):
return AkilliSehirParselExport()
def name(self):
return 'akillisehirparselmaks_crs'
def displayName(self):
return self.tr('Parsel Koordinat Aktarımı (Dönüşümlü & MAKS)')
def group(self):
return self.tr('Akıllı Şehir Müdürlüğü')
def groupId(self):
return 'akillisehir'
def shortHelpString(self):
return self.tr("Bu araç, seçili parselleri belirlediğiniz hedef koordinat sistemine "
"dönüştürerek 'SıraNo Y X' formatında masaüstüne çıkarır.")
def initAlgorithm(self, config=None):
# 1. Girdi Katmanı
self.addParameter(
QgsProcessingParameterVectorLayer(
self.INPUT,
self.tr('Parsel Katmanı'),
types=[QgsProcessing.TypeVectorPolygon]
)
)
# 2. Sadece Seçili Olanlar
self.addParameter(
QgsProcessingParameterBoolean(
self.ONLY_SELECTED,
self.tr('Sadece Seçili Olanları İşle'),
defaultValue=True
)
)
# 3. HEDEF KOORDİNAT SİSTEMİ (YENİ)
# Varsayılan olarak EPSG:4326 (WGS84 - Coğrafi) seçili gelir, değiştirilebilir.
self.addParameter(
QgsProcessingParameterCrs(
self.TARGET_CRS,
self.tr('Hedef Koordinat Sistemi (Çıktı Formatı)'),
defaultValue='EPSG:4326'
)
)
# 4. Dosya Adı ID
self.addParameter(
QgsProcessingParameterField(
self.ID_FIELD,
self.tr('Dosya Adı İçin ID Alanı'),
parentLayerParameterName=self.INPUT,
type=QgsProcessingParameterField.Any
)
)
# 5. Çıktı Klasörü
home = os.path.expanduser("~")
desktop = os.path.join(home, 'Masaüstü')
if not os.path.exists(desktop):
desktop = os.path.join(home, 'Desktop')
default_maks_path = os.path.join(desktop, 'MAKS')
self.addParameter(
QgsProcessingParameterFolderDestination(
self.OUTPUT_FOLDER,
self.tr('Kayıt Yeri'),
defaultValue=default_maks_path
)
)
def processAlgorithm(self, parameters, context, feedback):
layer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
only_selected = self.parameterAsBool(parameters, self.ONLY_SELECTED, context)
target_crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
id_field_name = self.parameterAsString(parameters, self.ID_FIELD, context)
output_folder = self.parameterAsString(parameters, self.OUTPUT_FOLDER, context)
if layer is None:
raise QgsProcessingException("Katman bulunamadı.")
# Klasör Kontrolü
if not os.path.exists(output_folder):
try:
os.makedirs(output_folder)
except OSError:
feedback.reportError(f"Klasör oluşturulamadı: {output_folder}", fatalError=True)
return {}
# Seçim Kontrolü
if only_selected:
selected_ids = layer.selectedFeatureIds()
if not selected_ids:
feedback.reportError("Haritada seçili parsel yok!", fatalError=True)
return {}
request = QgsFeatureRequest().setFilterFids(selected_ids)
else:
request = QgsFeatureRequest()
# --- DÖNÜŞÜM AYARLARI ---
source_crs = layer.crs()
transform = None
# Eğer kaynak ve hedef farklıysa dönüşüm nesnesi oluştur
if source_crs != target_crs:
feedback.pushInfo(f"Dönüşüm Yapılıyor: {source_crs.authid()} -> {target_crs.authid()}")
transform = QgsCoordinateTransform(source_crs, target_crs, context.transformContext())
else:
feedback.pushInfo("Dönüşüme gerek yok, kaynak ve hedef aynı.")
features = layer.getFeatures(request)
total_count = layer.selectedFeatureCount() if only_selected else layer.featureCount()
processed_count = 0
for current, feat in enumerate(features):
if feedback.isCanceled():
break
# Geometriyi al
geom = feat.geometry()
# --- DÖNÜŞÜM İŞLEMİ ---
# Eğer dönüşüm nesnesi varsa geometriyi hedef sisteme çevir
if transform:
geom.transform(transform)
# -----------------------
# ID Belirleme
try:
val = feat[id_field_name]
file_id = str(val) if val is not None else f"parsel_{feat.id()}"
except (KeyError, TypeError):
file_id = f"parsel_{feat.id()}"
safe_file_id = "".join([c for c in file_id if c.isalnum() or c in (' ', '_', '-')]).strip()
file_path = os.path.join(output_folder, f"{safe_file_id}.txt")
with open(file_path, 'w') as f:
vertices = geom.vertices()
sira_no = 1
for v in vertices:
# Y = v.y() (Latitude/Northing), X = v.x() (Longitude/Easting)
line = f"{sira_no}\t{v.y()}\t{v.x()}\n"
f.write(line)
sira_no += 1
processed_count += 1
if total_count > 0:
feedback.setProgress(int((processed_count / total_count) * 100))
return {'İşlenen': processed_count, 'Klasör': output_folder}
#actions
from qgis.utils import iface
from qgis.core import Qgis, QgsProject
import os
# --- AYARLAR ---
# Veritabanındaki parsel numarasının olduğu kolon adı:
id_kolonu_adi = 'id'
# ----------------
# 1. QGIS İfade Motoru ile ID'yi ve Katman ID'sini alıyoruz
# Köşeli parantezli kısımları QGIS, Python çalışmadan önce doldurur.
try:
secili_id = [% $id %]
layer_id = '[% @layer_id %]'
except SyntaxError:
# Eğer bu kod konsolda test edilirse hata vermemesi için sahte değer
secili_id = 0
layer_id = ''
# 2. Katmanı ve Detayı (Feature) manuel çekiyoruz (En güvenli yol)
project = QgsProject.instance()
layer = project.mapLayer(layer_id)
if not layer:
iface.messageBar().pushMessage("Hata", "Katman bulunamadı!", level=Qgis.Critical)
else:
feat = layer.getFeature(secili_id)
if feat.isValid():
geom = feat.geometry()
# 3. Klasör Yolu (Linux Masaüstü/MAKS)
home = os.path.expanduser("~")
desktop = os.path.join(home, 'Masaüstü')
if not os.path.exists(desktop):
desktop = os.path.join(home, 'Desktop')
output_folder = os.path.join(desktop, 'MAKS')
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 4. Dosya Adı Belirleme
try:
val = feat[id_kolonu_adi]
file_id = str(val) if val else f"parsel_{secili_id}"
except KeyError:
# Belirtilen kolon yoksa ID kullan
file_id = f"parsel_{secili_id}"
# Dosya adı temizliği
safe_file_id = "".join([c for c in file_id if c.isalnum() or c in (' ', '_', '-')]).strip()
file_path = os.path.join(output_folder, f"{safe_file_id}.txt")
# 5. Yazma İşlemi
try:
with open(file_path, 'w') as f:
vertices = geom.vertices()
sira_no = 1
for v in vertices:
# Format: SıraNo <TAB> Y <TAB> X
line = f"{sira_no}\t{v.y()}\t{v.x()}\n"
f.write(line)
sira_no += 1
iface.messageBar().pushMessage(
"Başarılı",
f"Kaydedildi: {safe_file_id}.txt",
level=Qgis.Success,
duration=3
)
except Exception as e:
iface.messageBar().pushMessage("Hata", str(e), level=Qgis.Critical)
else:
iface.messageBar().pushMessage("Hata", "Geçersiz Geometri veya ID", level=Qgis.Warning)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment