From b4fa7e123b38965082f45a2e703a3aa072c0e951 Mon Sep 17 00:00:00 2001 From: DmsAnhr Date: Mon, 22 Dec 2025 15:24:15 +0700 Subject: [PATCH] update main file --- main.py | 132 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 16 deletions(-) diff --git a/main.py b/main.py index a629226..9c3af26 100644 --- a/main.py +++ b/main.py @@ -10,7 +10,9 @@ from qgis.core import ( QgsVectorLayerExporter, QgsDataSourceUri, QgsProviderRegistry, - QgsCoordinateReferenceSystem + QgsCoordinateReferenceSystem, + QgsWkbTypes, + QgsGeometry ) from qgis.PyQt.QtCore import QByteArray from config import HOST,PORT,DB,USER,PWD,SCHEMA,GEOM_COL @@ -43,17 +45,38 @@ def clean_table(table_name: str): } +from pydantic import BaseModel -@app.post("/process/{table_name}") -def process_table(table_name: str, background: BackgroundTasks): - job_id = uuid4().hex - background.add_task(run_clean_table, table_name, job_id) +class ProcessRequest(BaseModel): + table_name: str + job_id: str + +@app.post("/process") +def process_table( + payload: ProcessRequest, + background: BackgroundTasks +): + background.add_task( + run_clean_table, + payload.table_name, + payload.job_id + ) return { "status": "ACCEPTED", - "job_id": job_id, - "table": table_name + "job_id": payload.job_id, + "table": payload.table_name } +# @app.post("/process/{table_name}") +# def process_table(table_name: str, background: BackgroundTasks): +# job_id = uuid4().hex +# background.add_task(run_clean_table, table_name, job_id) +# return { +# "status": "ACCEPTED", +# "job_id": job_id, +# "table": table_name +# } + def run_clean_table(table_name: str, job_id: str): @@ -80,7 +103,7 @@ def run_clean_table(table_name: str, job_id: str): } requests.post( - "http://localhost:8000/jobs/callback", + "http://localhost:8000/dataset/jobs/callback", json=callback_payload ) @@ -102,6 +125,81 @@ def to_python(v): # Fallback return v + +# def get_postgis_geom_type(layer): +# for f in layer.getFeatures(): +# g = f.geometry() +# if g.isMultipart(): +# return QgsWkbTypes.displayString(g.wkbType()).upper() +# else: +# base = QgsWkbTypes.displayString(g.wkbType()).upper() +# if "POINT" in base: +# return "MULTIPOINT" +# if "LINESTRING" in base: +# return "MULTILINESTRING" +# if "POLYGON" in base: +# return "MULTIPOLYGON" +# return "GEOMETRY" + +def get_postgis_geom_type(layer): + has_z = False + has_m = False + base_type = None # polygon / linestring / point + is_multi = False + + for f in layer.getFeatures(): + g = f.geometry() + if g.isEmpty(): + continue + + wkb = g.wkbType() + + # Detect Z & M + if QgsWkbTypes.hasZ(wkb): + has_z = True + if QgsWkbTypes.hasM(wkb): + has_m = True + + # Detect MULTI + if QgsWkbTypes.isMultiType(wkb): + is_multi = True + + # Detect base type (polygon / line / point) + geom_type = QgsWkbTypes.geometryType(wkb) + base_type = geom_type # polygon=2, line=1, point=0 + + if base_type is None: + return "GEOMETRY" + + # Convert base_type to PostGIS string + if base_type == QgsWkbTypes.PointGeometry: + base = "POINT" + elif base_type == QgsWkbTypes.LineGeometry: + base = "LINESTRING" + elif base_type == QgsWkbTypes.PolygonGeometry: + base = "POLYGON" + else: + base = "GEOMETRY" + + # Force MULTI + if base != "GEOMETRY": + base = "MULTI" + base + + # Add dimensionality + if has_z and has_m: + base += "ZM" + elif has_z: + base += "Z" + elif has_m: + base += "M" + + return base + + + + + + def save_to_postgis(layer, table_name): host = HOST port = PORT @@ -126,14 +224,13 @@ def save_to_postgis(layer, table_name): # DROP TABLE cur.execute(f'DROP TABLE IF EXISTS "{schema}"."{table_name}" CASCADE') - - # CREATE TABLE + print(f'Drop table {table_name}') + field_defs = [] for f in fields: if f.name() == geom_col: continue - # type mapping t = f.typeName().lower() if "int" in t: pg_type = "INTEGER" @@ -145,12 +242,15 @@ def save_to_postgis(layer, table_name): col = f.name().replace(" ", "_") field_defs.append(f'"{col}" {pg_type}') - # geometry column - field_defs.append(f'"{geom_col}" geometry(MultiPolygon,{srid})') - + # AUTODETECT 2D/3D geometry + pg_geom_type = get_postgis_geom_type(layer) + print("get type") + field_defs.append(f'"{geom_col}" geometry({pg_geom_type},{srid})') create_sql = f'CREATE TABLE "{schema}"."{table_name}" ({",".join(field_defs)});' cur.execute(create_sql) + + # Prepare INSERT attribute_columns = [ f'"{f.name().replace(" ", "_")}"' @@ -177,6 +277,8 @@ def save_to_postgis(layer, table_name): geom = feat.geometry() wkb_bytes = geom.asWkb() + # geom_2d = QgsGeometry.fromWkt(geom.asWkt()) + # wkb_bytes = geom_2d.asWkb() if isinstance(wkb_bytes, QByteArray): wkb_bytes = bytes(wkb_bytes) @@ -190,5 +292,3 @@ def save_to_postgis(layer, table_name): print(f"[DB] Inserted features: {count}") - -