diff --git a/app/Models/Tracks.php b/app/Models/Tracks.php index f96429b..05d2601 100755 --- a/app/Models/Tracks.php +++ b/app/Models/Tracks.php @@ -357,23 +357,86 @@ class Tracks extends Model // Filter loncatan $filtered = self::filterJumps($rawTracks, 1000, 5, 300); - // return $filtered; - return array_reverse($filtered); + return $filtered; + // return array_reverse($filtered); } - public static function filterJumps($points, $maxDistance = 1000, $maxTimeGap = 5, $maxSpeed = 300) + // public static function filterJumps($points, $maxDistance = 1000, $maxTimeGap = 5, $maxSpeed = 300) + // { + // $filtered = []; + // $last = null; + + // foreach ($points as $p) { + // // 🛡️ 1. Validasi data koordinat + // if (!is_numeric($p->latitude) || !is_numeric($p->longitude)) { + // continue; + // } + + // if (strlen((string) abs($p->latitude)) < 8 || strlen((string) abs($p->longitude)) < 8) { + // // Buang lat/lon kurang dari 8 digit desimal (umumnya noise) + // continue; + // } + + // if (!$last) { + // $filtered[] = $p; + // $last = $p; + // continue; + // } + + // // 2. Hitung jarak dan waktu + // $distance = self::haversineDistance( + // $last->latitude, + // $last->longitude, + // $p->latitude, + // $p->longitude + // ); + // $timeGap = $p->lst_loc_crt - $last->lst_loc_crt; + + // if ($timeGap <= 0) { + // continue; + // } + + // $speed = ($distance / $timeGap) * 3.6; // m/s to km/h + + // // 🧠 3. Validasi kombinasi logis + // if ($speed <= $maxSpeed && ($distance <= $maxDistance || $timeGap >= $maxTimeGap)) { + // $filtered[] = $p; + // $last = $p; + // } else { + // // Optional debug: + // // Log::info("LONCAT: speed={$speed}, dist={$distance}, timeGap={$timeGap}, pointID={$p->master_id}"); + // } + // } + + // // ⏳ Tambahkan titik terakhir jika tidak masuk + // if (!empty($points)) { + // $lastPoint = end($points); + // if (empty($filtered) || end($filtered)->lst_loc_crt !== $lastPoint->lst_loc_crt) { + // $filtered[] = $lastPoint; + // } + // } + + // return $filtered; + // } + + public static function filterJumps($points, $maxDistance = 2000, $maxTimeGap = 5, $maxSpeed = 150) { $filtered = []; $last = null; + // Sort dari terbaru ke terlama (pastikan sesuai kebutuhan) + usort($points, fn($a, $b) => $b->lst_loc_crt <=> $a->lst_loc_crt); + foreach ($points as $p) { - // 🛡️ 1. Validasi data koordinat + // 1. Validasi koordinat if (!is_numeric($p->latitude) || !is_numeric($p->longitude)) { continue; } - if (strlen((string) abs($p->latitude)) < 8 || strlen((string) abs($p->longitude)) < 8) { - // Buang lat/lon kurang dari 8 digit desimal (umumnya noise) + if ( + strlen(explode(".", $p->latitude)[1] ?? "") < 6 || + strlen(explode(".", $p->longitude)[1] ?? "") < 6 + ) { continue; } @@ -383,14 +446,14 @@ class Tracks extends Model continue; } - // 2. Hitung jarak dan waktu + // 2. Jarak & waktu $distance = self::haversineDistance( $last->latitude, $last->longitude, $p->latitude, $p->longitude ); - $timeGap = $p->lst_loc_crt - $last->lst_loc_crt; + $timeGap = $last->lst_loc_crt - $p->lst_loc_crt; if ($timeGap <= 0) { continue; @@ -398,22 +461,16 @@ class Tracks extends Model $speed = ($distance / $timeGap) * 3.6; // m/s to km/h - // 🧠 3. Validasi kombinasi logis - if ($speed <= $maxSpeed && ($distance <= $maxDistance || $timeGap >= $maxTimeGap)) { + // 3. Filter logis + if ($speed <= $maxSpeed || $distance <= $maxDistance) { $filtered[] = $p; $last = $p; - } else { - // Optional debug: - // Log::info("LONCAT: speed={$speed}, dist={$distance}, timeGap={$timeGap}, pointID={$p->master_id}"); } } - // ⏳ Tambahkan titik terakhir jika tidak masuk - if (!empty($points)) { - $lastPoint = end($points); - if (empty($filtered) || end($filtered)->lst_loc_crt !== $lastPoint->lst_loc_crt) { - $filtered[] = $lastPoint; - } + // 4. Pastikan hasil minimal N + if (count($filtered) < 500 && count($points) > 500) { + return array_slice($points, 0, 500); // fallback ke raw jika terlalu sedikit } return $filtered;