Bagaimana Mesin Peta alurail Direkayasa & Dibangun
Eksplorasi mendalam mengenai topologi geospasial, kinematika pergerakan dead-reckoning, penyatuan rute berantai (bundle), serta jalur kompilasi indeks spasial statis yang menggerakkan simulasi perkeretaapian real-time di Indonesia.
1. Pengolahan Geometri Jalur Rel & Ingesti Topologi Spasial
Pemetaan jaringan perkeretaapian di wilayah kepulauan Indonesia memiliki tantangan geospasial yang unik. Berbeda dengan jaringan jalan raya yang bersifat bebas arah, jalur kereta api tunduk pada batasan fisik yang ketat: radius lengkung minimum sesuai lebar sepur (1.067 mm Cape Gauge dan 1.435 mm Standard Gauge pada Whoosh), titik percabangan wesel, serta segmentasi petak jalan blok yang membatasi pergerakan armada.
Guna menyatukan ribuan segmen koordinat poliline mentah antar-stasiun menjadi satu koridor terusan yang mulus tanpa ketergantungan API pihak ketiga yang berbayar atau lambat, sistem menerapkan tahapan pra-pemrosesan bertingkat:
- Ingesti Geometri Vektor: Mengekstraksi garis vektor rel dari kontribusi OpenRailwayMap (ORM) dan OpenStreetMap secara presisi.
- Pruning Spasial Bounding Box (AABB): Memangkas segmen rel non-kandidat menggunakan batas koordinat 2D (Axis-Aligned Bounding Box) sebelum menjalankan kalkulasi trigonometri bola geodesik, mereduksi kompleksitas pencarian dari $O(N)$ menjadi $O(\log N)$.
- Penyelarasan Simpul Stasiun (Snapping): Mengoreksi koordinat geografis WGS-84 stasiun resmi ke as rel terdekat dalam toleransi radius 500 meter, memperhitungkan spoor lurus dan spoor belok emplasemen.
- Klasifikasi Lebar Sepur (Gauge): Membedakan koridor sepur sempit 1.067 mm (lintas utama Jawa-Sumatra), sepur standar 1.435 mm (KCIC Whoosh & Sulawesi), serta jalur sepur ganda gancet / dual gauge (lintas Purwosari – Solo Kota).
- Verifikasi Topologi Grafik Antar-Stasiun: Mengkompilasi jalur terpendek dan paling logis yang menghubungkan urutan stasiun persinggahan sesuai Grafik Perjalanan Kereta Api (GAPEKA 2025).
function isPointNearSegmentAABB(float $pLat, float $pLon, array $segA, array $segB, float $bufferDeg = 0.005): bool {
// Quick rectangular boundary check before executing trigonometric formulas
$minLat = min($segA[0], $segB[0]) - $bufferDeg;
$maxLat = max($segA[0], $segB[0]) + $bufferDeg;
$minLon = min($segA[1], $segB[1]) - $bufferDeg;
$maxLon = max($segA[1], $segB[1]) + $bufferDeg;
return ($pLat >= $minLat && $pLat <= $maxLat && $pLon >= $minLon && $pLon <= $maxLon);
}
function geodesicTrackSnap($nodeLat, $nodeLon, array $trackPolylinePoints, $toleranceMeters = 500.0) {
$minDistance = 1e9;
$snappedCoord = null;
for ($i = 0; $i < count($trackPolylinePoints) - 1; $i++) {
// Fast AABB pruning to bypass distant segments instantly
if (!isPointNearSegmentAABB($nodeLat, $nodeLon, $trackPolylinePoints[$i], $trackPolylinePoints[$i+1])) {
continue;
}
$dist = haversineSegmentDist($nodeLat, $nodeLon, $trackPolylinePoints[$i], $trackPolylinePoints[$i+1]);
if ($dist < $minDistance && $dist <= $toleranceMeters) {
$minDistance = $dist;
$snappedCoord = projectPointOnSegment($nodeLat, $nodeLon, $trackPolylinePoints[$i], $trackPolylinePoints[$i+1]);
}
}
return $snappedCoord ?: [$nodeLat, $nodeLon];
}
2. Kinematika Gerak Dead Reckoning & Interpolasi Spasial
Berbeda dengan pesawat terbang yang memancarkan sinyal ADS-B atau kapal laut dengan transponder AIS publik, armada kereta api penumpang belum seluruhnya menyiarkan koordinat GPS terbuka untuk konsumsi publik. Untuk menghadirkan visualisasi radar yang mencerminkan posisi fisik kereta di lintas secara realistis, sistem menerapkan model kinematika dead reckoning berbasis fisika gerak.
Setiap armada yang berdinas dievaluasi berdasarkan siklus waktu real-time:
- Sistem mendeteksi petak blok aktif perjalanan: stasiun keberangkatan awal ($t_{\text{berangkat}}$) menuju stasiun kedatangan berikutnya ($t_{\text{tiba}}$).
- Dihitung rasio progres waktu tempuh $\alpha \in [0, 1]$: $\alpha = \frac{t_{\text{sekarang}} - t_{\text{berangkat}}}{t_{\text{tiba}} - t_{\text{berangkat}}}$.
- Alih-alih menggunakan kecepatan linear datar, sistem menerapkan kurva percepatan dan perlambatan dinamis (S-curve) yang mempertimbangkan batas kecepatan lintas (TASPAT): fase akselerasi saat meninggalkan emplasemen, kecepatan konstan di petak bebas, dan fase pengereman saat memasuki stasiun berikutnya.
- Jarak tempuh akumulatif tersebut kemudian diproyeksikan ke garis vektor rel, menghasilkan titik koordinat lintang dan bujur yang presisi di atas peta.
function calculateKinematicProgress(float $tDepUnix, float $tArrUnix, float $tNowUnix): float {
if ($tNowUnix <= $tDepUnix) return 0.0;
if ($tNowUnix >= $tArrUnix) return 1.0;
// Linear time progress alpha clamped to [0.0, 1.0]
$alpha = ($tNowUnix - $tDepUnix) / ($tArrUnix - $tDepUnix);
// Cubic Hermite smoothstep polynomial (3t^2 - 2t^3) emulating train mass, acceleration, and deceleration
return $alpha * $alpha * (3.0 - 2.0 * $alpha);
}
function calculateTrackBearing(lat1, lon1, lat2, lon2) {
const toRad = Math.PI / 180;
const dLon = (lon2 - lon1) * toRad;
const phi1 = lat1 * toRad;
const phi2 = lat2 * toRad;
const y = Math.sin(dLon) * Math.cos(phi2);
const x = Math.cos(phi1) * Math.sin(phi2) - Math.sin(phi1) * Math.cos(phi2) * Math.cos(dLon);
// Normalize forward azimuth bearing to [0, 360) degrees
return (Math.atan2(y, x) * (180 / Math.PI) + 360) % 360;
}
3. Penyatuan Perjalanan Terusan Rangkaian Berantai (Bundle Trains)
Dalam operasional perkeretaapian nyata, sejumlah layanan kereta api berganti nomor dinas perjalanan di tengah rute operasionalnya karena perubahan arah lokomotif (langsir putar di stasiun percabangan) maupun regulasi izin trayek lintas Daop.
Sebagai contoh, KA Serayu melayani relasi Kroya – Pasar Senen melalui rute selatan (Bandung), berganti nomor KA secara berantai (misal 283A → 284B). Basis data relasional standar kerap memisahkan nomor KA ini sebagai perjalanan terputus, menampilkan waktu tempuh parsial yang membingungkan (hanya 5 jam untuk segmen terpendek) dan peta yang terpotong.
Sistem menyelesaikan tantangan ini melalui lapisan penyatuan armada (Train Bundling Engine):
- Penyambungan Segmen Berkelanjutan: Mengelompokkan nomor-nomor KA berantai yang berdinas menggunakan satu rangkaian fisik yang sama ke dalam satu kesatuan koridor.
- Metrik Perjalanan Riil: Menghitung total jarak kumulatif dari stasiun awal pemberangkatan hingga tujuan akhir (misal Kroya hingga Jakarta), total stasiun persinggahan, dan durasi perjalanan menyeluruh (+9 jam).
- Tampilan Peta Adaptif: Menampilkan peta menyeluruh saat pengguna membuka profil induk kereta, dan menampilkan segmen spesifik saat pengguna meninjau detail jadwal nomor KA tertentu.
class ThroughTrainCorridor {
public string $consistCode; // Physical train consist identifier
public string $masterName; // e.g. "KA Serayu"
public array $legs = []; // Sequential trip legs [ '283A' => [...], '284B' => [...] ]
public function stitchContinuousPolyline(): array {
$unifiedPolyline = [];
foreach ($this->legs as $idx => $leg) {
$coords = $leg['polyline'];
// Normalize reverse terminal switchbacks (e.g. Kroya/Kiaracondong turn-around)
if ($idx > 0 && !empty($unifiedPolyline)) {
$lastVertex = end($unifiedPolyline);
$headVertex = $coords[0];
$tailVertex = end($coords);
// If tail is closer to the previous leg endpoint than head, reverse sequence
if (haversineDistance($lastVertex, $tailVertex) < haversineDistance($lastVertex, $headVertex)) {
$coords = array_reverse($coords);
}
}
$unifiedPolyline = array_merge($unifiedPolyline, $coords);
}
return $unifiedPolyline;
}
}
4. Caching Geospasial Statis Berkecepatan Tinggi
Melayani ribuan pengguna dan komunitas yang memantau pergerakan kereta secara bersamaan—terutama pada periode angkutan puncak seperti masa Mudik Lebaran dan Libur Nataru—menuntut arsitektur yang bebas dari beban query spasial berat pada basis data relasional.
Platform mencapai keandalan dan kecepatan tinggi ini melalui strategi caching spasial berlapis:
- Pra-Kompilasi Geometri Jadwal: Setiap kali edisi GAPEKA resmi diaktifkan, seluruh koridor stasiun ke stasiun, daftar pemberhentian, dan geometri poliline rel langsung dikompilasi ke dalam struktur data statis berbobot ringan.
- Arsitektur Penyimpanan Ganda: Memori server lokal berkecepatan tinggi bertindak sebagai penyaji data primer, disinkronkan secara mulus dengan jaringan edge CDN global guna menjamin ketersediaan data secara andal.
- Manajemen Data Sisi Klien (Client Mesh): Koordinat stasiun dan ringkasan rute di-cache di sisi browser pengguna, memungkinkan filter pencarian instan pada ratusan perjalanan kereta tanpa memicu request berulang ke server.
function serveStaticSpatialPayload(string $indexKey, string $jsonPayload, int $maxAgeSeconds = 300): void {
// Non-cryptographic fast 64-bit hash for ETag validation
$etag = '"' . hash('xxh64', $jsonPayload) . '"';
header('Content-Type: application/json; charset=UTF-8');
header('ETag: ' . $etag);
header("Cache-Control: public, max-age={$maxAgeSeconds}, stale-while-revalidate=600");
// If client cache matches ETag, return 304 Not Modified immediately with 0 bytes body
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) === $etag) {
http_response_code(304);
exit;
}
echo $jsonPayload;
exit;
}
5. Arsitektur Antarmuka & Token Desain Sistem
Antarmuka pengguna {$brandName} dibangun sepenuhnya memanfaatkan standar platform web modern: HTML5 semantik, CSS custom properties dinamis, dan modul JavaScript ringan tanpa framework monolitik yang membengkak, memastikan pemuatan halaman instan serta konsumsi memori yang hemat pada ponsel pengguna.
- Token Variabel CSS Terpadu: Pengalihan tema dinamis (
--up-bg,--up-surface,--up-brand) menjaga konsistensi visual antara tema gelap dan terang di seluruh halaman platform. - Marker Berakselerasi Perangkat Keras: Marker kereta dan ikon stasiun dirender pada kanvas Leaflet dengan optimasi GPU, menjamin kelancaran interaksi zoom dan pan hingga 60fps di berbagai perangkat.
- Sistem Fallback Media Cerdas: Dokumentasi foto interior kabin dan armada sarana dilengkapi penanganan otomatis; jika foto belum tersedia, sistem secara anggun menampilkan lencana identitas resmi sarana.
function projectWGS84ToCanvasPixel(lat, lon, zoom, tileSize = 256) {
// Project geographical WGS-84 coordinate into normalized Mercator screen-space pixel coordinates
const sinLat = Math.sin(lat * (Math.PI / 180));
const scale = tileSize * Math.pow(2, zoom);
const pixelX = scale * ((lon + 180) / 360);
const pixelY = scale * (0.5 - Math.log((1 + sinLat) / (1 - sinLat)) / (4 * Math.PI));
return { x: Math.round(pixelX), y: Math.round(pixelY) };
}
6. Fondasi Perangkat Lunak Sumber Terbuka & Rekayasa Geospasial
Mesin simulasi alurail berakar kuat pada filosofi keterbukaan data dan rekayasa perangkat lunak sumber terbuka. Kami memberikan penghargaan formal serta mengintegrasikan komponen-komponen terbuka utama berikut:
- OpenStreetMap (OSM) [ODbL 1.0]: Menyediakan basis data vektor peta dunia, garis pantai, batas administratif wilayah, dan kontur geografis primer.
- OpenRailwayMap (ORM) [CC-BY-SA 2.0]: Menyediakan infrastruktur rel terperinci, wesel percabangan, klasifikasi lebar sepur (Cape Gauge 1.067 mm & Standard Gauge 1.435 mm), serta tata letak emplasemen stasiun di Indonesia.
- PostgreSQL & PostGIS [GPL-2.0+]: Basis data relasional spasial performa tinggi yang memproses topologi jalur rel, kalkulasi jarak geodesik, dan komputasi rute terpendek Dijkstra / pgRouting.
- Leaflet.js [2-Clause BSD]: Menggerakkan kanvas visualisasi peta interaktif yang ringan, proyeksi koordinat cepat, serta pergerakan marker kereta dinamis berbasis GPU.
- Pemulusan Kurva Chaikin (Corner-Cutting): Memotong sudut-sudut poliline tajam secara proporsional (25% dan 75%) dalam siklus iteratif, menghasilkan garis lengkung rel alami yang mencerminkan radius lengkung fisik jalur ($R_{\text{min}} \ge 250\text{m}$).
- Filter HMM Viterbi (Map-Matching): Memisahkan probabilitas emisi sensor ($p(z_t | x_t)$ dengan distribusi Gauss $\sigma \approx 10\text{m}$) dari probabilitas transisi topologi ($p(x_t | x_{t-1})$ yang mengukur selisih jarak jaringan rel versus jarak sensor $|\Delta d|$), menangkal lonjakan *GPS jumping* saat kereta melintasi terowongan, ngarai, maupun kawasan padat gedung.
function chaikinCurveSmoothing(array $vertices, int $refinements = 2): array {
if (count($vertices) < 3) return $vertices;
for ($it = 0; $it < $refinements; $it++) {
$refined = [$vertices[0]]; // Always preserve starting station origin
for ($i = 0; $i < count($vertices) - 1; $i++) {
$p0 = $vertices[$i];
$p1 = $vertices[$i + 1];
// Point Q: 75% P0 + 25% P1
$q = [$p0[0] * 0.75 + $p1[0] * 0.25, $p0[1] * 0.75 + $p1[1] * 0.25];
// Point R: 25% P0 + 75% P1
$r = [$p0[0] * 0.25 + $p1[0] * 0.75, $p0[1] * 0.25 + $p1[1] * 0.75];
$refined[] = $q;
$refined[] = $r;
}
$refined[] = end($vertices); // Always preserve terminal destination
$vertices = $refined;
}
return $vertices;
}
Butuh Informasi Lebih Lanjut atau Ingin Berkolaborasi?
Tim rekayasa alurail terbuka untuk kolaborasi data geospasial, riset perkeretaapian komunitas, maupun integrasi sistem telemetri. Hubungi kami langsung melalui WhatsApp resmi, email langsung, atau formulir kontak.