init backend presensi
This commit is contained in:
96
app/Modules/Geo/Services/GeoFenceService.php
Normal file
96
app/Modules/Geo/Services/GeoFenceService.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Geo\Services;
|
||||
|
||||
/**
|
||||
* Geo Fence Service
|
||||
*
|
||||
* Handles geofencing logic using Haversine formula for distance calculation.
|
||||
*/
|
||||
class GeoFenceService
|
||||
{
|
||||
/**
|
||||
* Earth's radius in meters
|
||||
*/
|
||||
private const EARTH_RADIUS_METERS = 6371000;
|
||||
|
||||
/**
|
||||
* Check if a point (latitude, longitude) is inside a zone
|
||||
*
|
||||
* Uses Haversine formula to calculate distance between two points
|
||||
* on Earth's surface and compares it to zone radius.
|
||||
*
|
||||
* @param float $lat Latitude of the point to check
|
||||
* @param float $lng Longitude of the point to check
|
||||
* @param array $zone Zone data with 'latitude', 'longitude', and 'radius_meters'
|
||||
* @return bool True if point is inside zone, false otherwise
|
||||
*/
|
||||
public function isInsideZone(float $lat, float $lng, array $zone): bool
|
||||
{
|
||||
// Validate zone data
|
||||
if (!isset($zone['latitude']) || !isset($zone['longitude']) || !isset($zone['radius_meters'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$zoneLat = (float) $zone['latitude'];
|
||||
$zoneLng = (float) $zone['longitude'];
|
||||
$radiusMeters = (int) $zone['radius_meters'];
|
||||
|
||||
// Calculate distance using Haversine formula
|
||||
$distance = $this->calculateHaversineDistance($lat, $lng, $zoneLat, $zoneLng);
|
||||
|
||||
// Check if distance is within radius
|
||||
return $distance <= $radiusMeters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate distance between two points using Haversine formula
|
||||
*
|
||||
* Haversine formula calculates the great-circle distance between
|
||||
* two points on a sphere given their longitudes and latitudes.
|
||||
*
|
||||
* @param float $lat1 Latitude of first point
|
||||
* @param float $lng1 Longitude of first point
|
||||
* @param float $lat2 Latitude of second point
|
||||
* @param float $lng2 Longitude of second point
|
||||
* @return float Distance in meters
|
||||
*/
|
||||
private function calculateHaversineDistance(float $lat1, float $lng1, float $lat2, float $lng2): float
|
||||
{
|
||||
// Convert degrees to radians
|
||||
$lat1Rad = deg2rad($lat1);
|
||||
$lng1Rad = deg2rad($lng1);
|
||||
$lat2Rad = deg2rad($lat2);
|
||||
$lng2Rad = deg2rad($lng2);
|
||||
|
||||
// Calculate differences
|
||||
$deltaLat = $lat2Rad - $lat1Rad;
|
||||
$deltaLng = $lng2Rad - $lng1Rad;
|
||||
|
||||
// Haversine formula
|
||||
$a = sin($deltaLat / 2) * sin($deltaLat / 2) +
|
||||
cos($lat1Rad) * cos($lat2Rad) *
|
||||
sin($deltaLng / 2) * sin($deltaLng / 2);
|
||||
|
||||
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
|
||||
|
||||
// Distance in meters
|
||||
$distance = self::EARTH_RADIUS_METERS * $c;
|
||||
|
||||
return $distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate distance between two points (public helper method)
|
||||
*
|
||||
* @param float $lat1 Latitude of first point
|
||||
* @param float $lng1 Longitude of first point
|
||||
* @param float $lat2 Latitude of second point
|
||||
* @param float $lng2 Longitude of second point
|
||||
* @return float Distance in meters
|
||||
*/
|
||||
public function calculateDistance(float $lat1, float $lng1, float $lat2, float $lng2): float
|
||||
{
|
||||
return $this->calculateHaversineDistance($lat1, $lng1, $lat2, $lng2);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user