import json from app.apiController import apiController def swap_latlon(coords): # return [[lon, lat] for lat, lon in coords] # print(coords) # return [ # [ [lon, lat] for lat, lon in ring ] # for ring in coords # ] return [ [ [ [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): 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 = """ SELECT id, kode, nama, lat, lng, CONCAT( REPEAT('[', 4 - (LENGTH(path) - LENGTH(REPLACE(path, '[', '')))), path, REPEAT(']', 4 - (LENGTH(path) - LENGTH(REPLACE(path, ']', '')))) ) AS path FROM wil_provinsi """ cur.execute(old_sql) elif level == 'kabupaten': cur.execute(""" SELECT id, kode, nama,lat,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,lat,lng, CONCAT( REPEAT('[', 4 - (LENGTH(path) - LENGTH(REPLACE(path, '[', '')))), path, REPEAT(']', 4 - (LENGTH(path) - LENGTH(REPLACE(path, ']', '')))) ) AS path FROM wil_kecamatan WHERE kabupatenkota_id = %s""", (parent_code,)) elif level == 'desa': 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_desa WHERE kecamatan_id = %s""", (parent_code,)) else: return {"type": "FeatureCollection", "features": []} features = [] for row in cur.fetchall(): path = row[5] #Multi poligons try: parsed_path = json.loads(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", "coordinates": corrected_path } feature = { "type": "Feature", "geometry": geometry, "properties": { "id": row[0], "kode": row[1], "nama": row[2], "lat": row[3], "lng": row[4] } } features.append(feature) return { "type": "FeatureCollection", "features": features }