/** * Returns the point which is a fraction along the line between 0 and 1. * * @param Point $point * @param float $fraction between 0 and 1 * * @throw \InvalidArgumentException * @return Point */ public function getFractionAlongLineTo(Point $point, $fraction) { if ($fraction < 0 || $fraction > 1) { throw new \InvalidArgumentException('$fraction must be between 0 and 1'); } if (function_exists('fraction_along_gc_line') && Location::$useSpatialExtension) { $result = fraction_along_gc_line($this->jsonSerialize(), $point->jsonSerialize(), $fraction); return new self($result['coordinates']); } else { $distance = Location::haversine($this, $point); $lat1 = $this->latitudeToRad(); $lat2 = $point->latitudeToRad(); $lon1 = $this->longitudeToRad(); $lon2 = $point->longitudeToRad(); $a = sin((1 - $fraction) * $distance) / sin($distance); $b = sin($fraction * $distance) / sin($distance); $x = $a * cos($lat1) * cos($lon1) + $b * cos($lat2) * cos($lon2); $y = $a * cos($lat1) * sin($lon1) + $b * cos($lat2) * sin($lon2); $z = $a * sin($lat1) + $b * sin($lat2); $res_lat = atan2($z, sqrt(pow($x, 2) + pow($y, 2))); $res_long = atan2($y, $x); return new self(rad2deg($res_lat), rad2deg($res_long)); } }
/** * Uses the haversine formula to calculate the distance between 2 points. * * @param Point $point1 * @param Point $point2 * * @return float distance in radians */ public static function haversine(Point $point1, Point $point2) { if (function_exists('haversine') && self::$useSpatialExtension) { $from = $point1->jsonSerialize(); $to = $point2->jsonSerialize(); $radDistance = haversine($from, $to, 1); } else { $lat1 = $point1->latitudeToRad(); $lon1 = $point1->longitudeToRad(); $lat2 = $point2->latitudeToRad(); $lon2 = $point2->longitudeToRad(); $distanceLat = $lat1 - $lat2; $distanceLong = $lon1 - $lon2; $radDistance = sin($distanceLat / 2) * sin($distanceLat / 2) + cos($lat1) * cos($lat2) * sin($distanceLong / 2) * sin($distanceLong / 2); $radDistance = 2 * atan2(sqrt($radDistance), sqrt(1 - $radDistance)); } return $radDistance; }