Last active
December 3, 2025 20:23
-
-
Save mcihad/a32cece92e3a26833668f3f2b40543da to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # -*- 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