diff --git a/app/__pycache__/apiController.cpython-313.pyc b/app/__pycache__/apiController.cpython-313.pyc index d7d30f6..dac7bd8 100644 Binary files a/app/__pycache__/apiController.cpython-313.pyc and b/app/__pycache__/apiController.cpython-313.pyc differ diff --git a/app/__pycache__/mapController.cpython-313.pyc b/app/__pycache__/mapController.cpython-313.pyc index 41df45f..abe74f7 100644 Binary files a/app/__pycache__/mapController.cpython-313.pyc and b/app/__pycache__/mapController.cpython-313.pyc differ diff --git a/app/apiController.py b/app/apiController.py index 63e4220..e6022b3 100644 --- a/app/apiController.py +++ b/app/apiController.py @@ -394,9 +394,26 @@ class apiController: cur.execute(""" SELECT id, kode, nama, null as lat, null as lng, koordinat as path FROM wil_provinsi """) elif level == 'kabupaten': - cur.execute("SELECT id, kode, nama, null as lat, null as lng, koordinat as path FROM wil_kabupatenkota WHERE provinsi_id = %s", (parent_code,)) + cur.execute(""" + SELECT + id, kode, nama, null as lat, null as lng, + CONCAT( + REPEAT('[', 4 - (LENGTH(path) - LENGTH(REPLACE(path, '[', '')))), + path, + REPEAT(']', 4 - (LENGTH(path) - LENGTH(REPLACE(path, ']', '')))) + ) AS path + FROM wil_kabupatenkota WHERE provinsi_id = %s""", (parent_code,)) elif level == 'kecamatan': - cur.execute("SELECT id, kode, nama, null as lat, null as lng, koordinat as path FROM wil_kecamatan WHERE kabupaten_kota_id = %s", (parent_code,)) + cur.execute(""" + SELECT + id, kode, nama, null as lat, null as lng, + CONCAT( + REPEAT('[', 4 - (LENGTH(path) - LENGTH(REPLACE(path, '[', '')))), + path, + REPEAT(']', 4 - (LENGTH(path) - LENGTH(REPLACE(path, ']', '')))) + ) AS path FROM wil_kecamatan WHERE + kabupaten_kota_id = %s + """, (parent_code,)) elif level == 'desa': # cur.execute("SELECT id, kode, nama, null as lat, null as lng,path FROM wil_desa WHERE kecamatan_id = %s", (parent_code,)) cur.execute((""" @@ -433,8 +450,8 @@ class apiController: continue geometry = { - "type": "MultiPolygon", # karena bentuk datamu seperti itu - "coordinates": corrected_path + "type": "MultiPolygon", + "coordinates": parsed_path } feature = { diff --git a/app/mapController.py b/app/mapController.py index 855db90..d93d84f 100644 --- a/app/mapController.py +++ b/app/mapController.py @@ -9,21 +9,79 @@ def swap_latlon(coords): # [ [lon, lat] for lat, lon in ring ] # for ring in coords # ] - return coords + return [ - [ # Polygon - [ # Ring + [ + [ [lon, lat] for lat, lon in ring ] for ring in polygon ] for polygon in coords ] +def swap_latlon2(coords): + try: + sample = coords[0][0][0] + if not (-180 <= sample[0] <= 180 and -90 <= sample[1] <= 90): + return [ + [ + [ + [lon, lat] for lat, lon in ring + ] for ring in polygon + ] for polygon in coords + ] + else: + # Sudah benar [lon, lat] + return coords + except Exception as e: + print(f"[swap_latlon] Error during coordinate swap: {e}") + return None + +def normalize_to_multipolygon(coords): + if isinstance(coords, list): + if ( + isinstance(coords[0], list) + and isinstance(coords[0][0], list) + and isinstance(coords[0][0][0], list) + and isinstance(coords[0][0][0][0], (int, float)) + ): + return coords # Sudah valid + else: + # Kurang dimensi → bungkus + return [[[coord for coord in ring] for ring in coords]] + return coords + +def audit_geojson_paths(conn, table): + cur = conn.cursor() + cur.execute(f"SELECT id, path FROM {table}") + errors = [] + for row in cur.fetchall(): + try: + coords = json.loads(row[1]) + sample_point = coords[0][0][0] + if not (-180 <= sample_point[0] <= 180 and -90 <= sample_point[1] <= 90): + errors.append(row[0]) + except Exception as e: + errors.append(row[0]) + print(f"[AUDIT] Invalid GeoJSON paths found in {table}: {errors}") + return errors #MAP DATA #========================================================= def fetch_geojson(conn, level, parent_code=None): - # cur = conn.cursor() - # cur.execute(f"SELECT id, kode, nama, lat, lng, path, iso FROM {table_name} WHERE id = 1 LIMIT 1") + + table_name = { + 'provinsi': 'wil_provinsi', + 'kabupaten': 'wil_kabupatenkota', + 'kecamatan': 'wil_kecamatan', + 'desa': 'wil_desa' + }.get(level) + + if not table_name: + return {"type": "FeatureCollection", "features": []} + + # Jalankan audit + invalid_ids = audit_geojson_paths(conn, table_name) + cur = conn.cursor() if level == 'provinsi': old_sql = """ @@ -68,27 +126,22 @@ def fetch_geojson(conn, level, parent_code=None): for row in cur.fetchall(): path = row[5] - # path = swap_latlon(path) - # if not path: - # continue - # geometry = { - # "type": "Polygon", - # "coordinates": json.loads(path) - # } - + #Multi poligons try: parsed_path = json.loads(path) - corrected_path = swap_latlon(parsed_path) + normalized = normalize_to_multipolygon(parsed_path) + corrected_path = swap_latlon2(normalized) + except Exception as e: print(f"Error parsing path for row {row[0]}: {e}") continue if not corrected_path: continue - + geometry = { - "type": "MultiPolygon", # karena bentuk datamu seperti itu + "type": "MultiPolygon", "coordinates": corrected_path }