61 lines
1.7 KiB
Python
61 lines
1.7 KiB
Python
|
|
import geopandas as gpd
|
||
|
|
import fiona
|
||
|
|
import zipfile
|
||
|
|
import tempfile
|
||
|
|
import os
|
||
|
|
import shutil
|
||
|
|
from shapely.geometry import shape
|
||
|
|
|
||
|
|
def read_shp(path: str):
|
||
|
|
if not path:
|
||
|
|
raise ValueError("Path shapefile tidak boleh kosong.")
|
||
|
|
|
||
|
|
tmpdir = None
|
||
|
|
shp_path = None
|
||
|
|
|
||
|
|
if path.lower().endswith(".zip"):
|
||
|
|
tmpdir = tempfile.mkdtemp()
|
||
|
|
with zipfile.ZipFile(path, "r") as zip_ref:
|
||
|
|
zip_ref.extractall(tmpdir)
|
||
|
|
|
||
|
|
shp_files = []
|
||
|
|
for root, _, files in os.walk(tmpdir):
|
||
|
|
for f in files:
|
||
|
|
if f.lower().endswith(".shp"):
|
||
|
|
shp_files.append(os.path.join(root, f))
|
||
|
|
|
||
|
|
if not shp_files:
|
||
|
|
raise ValueError("Tidak ditemukan file .shp di dalam ZIP.")
|
||
|
|
shp_path = shp_files[0]
|
||
|
|
print(f"[DEBUG] Membaca shapefile: {os.path.basename(shp_path)}")
|
||
|
|
|
||
|
|
else:
|
||
|
|
shp_path = path
|
||
|
|
|
||
|
|
try:
|
||
|
|
gdf = gpd.read_file(shp_path)
|
||
|
|
except Exception as e:
|
||
|
|
raise ValueError(f"Gagal membaca shapefile: {e}")
|
||
|
|
|
||
|
|
if "geometry" not in gdf.columns or gdf.geometry.is_empty.all():
|
||
|
|
print("[WARN] Geometry kosong. Mencoba membangun ulang dari fitur mentah...")
|
||
|
|
|
||
|
|
with fiona.open(shp_path) as src:
|
||
|
|
features = []
|
||
|
|
for feat in src:
|
||
|
|
geom = shape(feat["geometry"]) if feat["geometry"] else None
|
||
|
|
props = feat["properties"]
|
||
|
|
props["geometry"] = geom
|
||
|
|
features.append(props)
|
||
|
|
|
||
|
|
gdf = gpd.GeoDataFrame(features, geometry="geometry", crs=src.crs)
|
||
|
|
|
||
|
|
if gdf.crs is None:
|
||
|
|
# print("[WARN] CRS tidak terdeteksi. Diasumsikan EPSG:4326")
|
||
|
|
gdf.set_crs("EPSG:4326", inplace=True)
|
||
|
|
|
||
|
|
if tmpdir and os.path.exists(tmpdir):
|
||
|
|
shutil.rmtree(tmpdir)
|
||
|
|
|
||
|
|
return gdf
|