Lompat ke konten
dokumentasi.id
Commit 493bd1c
v1
Star762

6

Polygon dan Boundary

/paths/{code}.json menyimpan satu polygon boundary untuk satu wilayah, dan endpoint ini berlaku untuk semua level selama berkasnya ada. Bentuk response-nya sama seperti endpoint lain: data berisi id dan path, meta berisi level dan updated_at. Contoh GET /paths/32.json mengembalikan path berupa array ring berisi pasangan [lat, lng]. README.md:447-473

Bentuk wrapper data/meta dan daftar endpoint tidak diulang di sini; lihat Format Response dan Wrapper data/meta dan Referensi Endpoint.

Cek has_path sebelum fetch

README memberi aturan tegas: cek has_path dulu, karena endpoint ini membalas 404 ketika nilainya false. README.md:447-473

Field has_path tidak ditulis manual. add-has-path memindai api/paths/*.json untuk membangun set kode yang punya polygon, lalu menempelkan "has_path": true/false ke setiap objek Place/ShortItem pada provinces, regencies, districts, dan villages. tools/add_has_path.go:6-14 Set itu dibangun oleh buildHasPathSet(pDir) dengan pDir default <out>/paths; direktori yang tidak ada dianggap set kosong, bukan error. tools/add_has_path.go:57-61 Penulisan nilainya per id: array data diiterasi item per item, objek tunggal memakai data.id dengan fallback dari nama berkas. tools/add_has_path.go:143-170

graph TD
  item["item dari /districts atau /villages"] --> hasPath{"has_path == true?"}
  hasPath -- false --> skip["tanpa polygon: render marker dari lat/lng"]
  hasPath -- true --> fetch["GET /paths/{code}.json"]
  fetch --> ok{"res.ok?"}
  ok -- "false, 404" --> skip
  ok -- true --> norm["normalizeRings(data.path)"]
  norm --> filter["buang ring dengan length <= 2"]
  filter --> lnglat["toLngLat: [lat,lng] jadi [lng,lat]"]
  lnglat --> geojson["FeatureCollection: satu Polygon per ring"]
  geojson --> layer["source wilayah-polygon + fill/line layer"]
  style hasPath fill:#f59e0b,color:#000
  style ok fill:#f59e0b,color:#000
  style skip fill:#dc2626,color:#fff
  style fetch fill:#8b5cf6,color:#fff
  style norm fill:#8b5cf6,color:#fff
  style filter fill:#8b5cf6,color:#fff
  style lnglat fill:#8b5cf6,color:#fff
  style geojson fill:#8b5cf6,color:#fff
  style layer fill:#2d7d46,color:#fff
%% fig: Alur cek has_path sampai render polygon
%% desc: Nilai has_path dan status response menentukan apakah polygon diambil, lalu ring hasil normalisasi dikonversi ke [lng,lat] dan dipasang sebagai layer MapLibre.
Fig. 1: Alur cek has_path sampai render polygonNilai has_path dan status response menentukan apakah polygon diambil, lalu ring hasil normalisasi dikonversi ke [lng,lat] dan dipasang sebagai layer MapLibre.

Playground sendiri tidak membaca has_path; ia memperlakukan res.ok === false sebagai "no path" lalu mengosongkan polygon, dan memilih kode terdalam yang tersedia lewat villCode || distCode || regCode || provCode. web/src/components/sections/PlaygroundSection.tsx:254-279 Pola itu setara dengan cek has_path untuk kasus normal, tetapi tidak mendeteksi kode yang punya berkas rusak.

path bertingkat: single, multi, sampai kedalaman 4

Kedalaman data.path tidak seragam, dan kode peta wajib menanganinya. Komentar mapUtils mencatat tiga bentuk: single ring sedalam 2, multi ring sedalam 3, dan deep nesting sedalam 4 seperti Papua Barat 92. web/src/components/playground/mapUtils.ts:1-26 Jumlah ring juga jauh berbeda antar wilayah, sementara has_path tetap true untuk semuanya: Jakarta 2 ring, Aceh 28 ring, Papua Barat 1455 ring. README.md:471-473

KedalamanBentuk data.pathContoh
2[[lat,lng], ...]single ring, wilayah pulau tunggal
3[[[lat,lng], ...], ...]Jakarta (2 ring), Aceh (28 ring)
4[[[[lat,lng]]]]Papua Barat 92 (1455 ring)

normalizeRings mengumpulkan ring secara rekursif. Sebuah node dianggap ring ketika elemen pertamanya array dan dua nilai pertamanya bertipe number; kalau bukan, setiap anak ditelusuri. Hasil akhirnya difilter ring.length > 2 supaya titik ganda atau ring kosong tidak ikut. web/src/components/playground/mapUtils.ts:1-26 README memuat versi ringkas algoritme yang sama: collect menelusuri data.path, lalu rings.filter(r => r.length > 2) diserahkan ke L.polygon. README.md:475-489

Generator ikut menambal path yang terpotong: bila jumlah [ tiga tetapi jumlah ] hanya dua, satu ] ditambahkan sebelum JSON divalidasi. Aturan itu dipakai generate-boundaries untuk kecamatan dan kelurahan. tools/generate_boundaries.go:229-252 Aturan yang sama dipakai phase B generate-static-api untuk provinsi dan kab/kota. tools/generate_static_api.go:339-352

Dua penulis berkas, dua nilai meta.level

Berkas paths/ dihasilkan dua tahap pipeline; keduanya memakai genResponse dengan level berbeda. Kedalaman pipeline lengkap ada di Pipeline Generate dengan Go Tools.

PenulisSumber pathmeta.level
generate-static-api phase Bkolom path data/wilayah_level_1_2.csvgenLevelCount(kode)+1, jadi 1 (provinsi) atau 2 (kab/kota)
generate-boundariesSQL db/kec/*.sql dan db/kel/*/*.sql3 (kecamatan) dan 4 (kelurahan)

generate-boundaries hanya menulis berkas ketika it.Path tidak kosong dan json.Valid menerima hasil pembulatan; berkas yang ditulis dihitung sebagai totalPathsWritten. tools/generate_boundaries.go:229-252

Dari [lat,lng] ke layer peta

⚠️ Koordinat API memakai urutan [lat, lng], sedangkan GeoJSON dan MapLibre menuntut [lng, lat]. Melewatkan konversi ini menaruh polygon di belahan bumi yang salah.

toLngLat melakukan pembalikan per titik. web/src/components/playground/mapUtils.ts:28-31 ringsToGeoJSON membungkus setiap ring menjadi Feature bertipe Polygon dengan coordinates: [ring] di dalam satu FeatureCollection. web/src/components/playground/mapUtils.ts:33-45 Komponen MapLibre membangun GeoJSON yang sama secara inline, lalu menambah source wilayah-polygon dengan layer wilayah-polygon-fill (fill-color #10b981, fill-opacity 0.18) dan wilayah-polygon-line (line-color #059669, line-width 2). web/src/components/playground/MapLibreIndonesiaMap.tsx:308-344

Simplifikasi 6 desimal

roundPathCoords membulatkan setiap float pada string JSON koordinat memakai coordFloatRe (-?\d+\.\d+), lalu math.Round(f*1e6)/1e6 dan strconv.FormatFloat(rounded, 'f', 6, 64). Komentarnya menyebut presisi ~11 cm, cukup untuk render boundary administratif, dan efek utamanya memperkecil ukuran berkas. tools/generate_static_api.go:650-665 README menyebut hal yang sama untuk sisi pemakaian: 6 desimal, sudah di-simplify, dan pembaca yang butuh resolusi tinggi diminta mengambil langsung dari cahyadsn/wilayah_boundaries. README.md:471-473

Pembulatan terjadi di dalam generator, bukan saat request. Phase B memanggilnya tepat sebelum validasi JSON dan penulisan berkas. tools/generate_static_api.go:339-352 generate-boundaries memanggilnya pada tiap it.Path sebelum menulis paths/{kode}.json. tools/generate_boundaries.go:229-252

⚠️ has_path: false bukan bug render. Wilayah itu memang belum punya polygon, dan daftar lengkapnya tersedia di Kelengkapan Data dan missings.json. Untuk mencoba interaksi peta secara langsung, lihat Website dan Playground.