GCDistance(38.9333,-94.3253,38.9314,-94.4876) . "
\n"; // print "GCAzimuth: " . $oGC->GCAzimuth(38.9333,-94.3253,38.9314,-94.4876) . "
\n"; // print "ApproxDistance: " . $oGC->ApproxDistance(38.9333,-94.3253,38.9314,-94.4876) . "
\n"; // print "EllipsoidDistance: " . $oGC->EllipsoidDistance(38.80126649,-94.44590241,43.3368,-96.8755) . "

\n"; // print "EllipsoidDistance In Miles: " . ConvKilometersToMiles($oGC->EllipsoidDistance(38.80126649,-94.44590241,43.3368,-96.8755)); class GeoCalc { var $PI = 3.14159265359; var $TWOPI = 6.28318530718; var $DE2RA = 0.01745329252; var $RA2DE = 57.2957795129; var $ERAD = 6378.135; var $ERADM = 6378135.0; var $AVG_ERAD = 6371.0; var $EPS = 0.000000000005; var $KM2MI = 0.621371; var $FLATTENING = 0; function GeoCalc() { $this->FLATTENING = 1.0/298.26; // Earth flattening // (WGS 1972) return; } function GCDistance($lat1, $lon1, $lat2, $lon2) { $lat1 *= $this->DE2RA; $lon1 *= $this->DE2RA; $lat2 *= $this->DE2RA; $lon2 *= $this->DE2RA; $d = sin($lat1)*sin($lat2) + cos($lat1)*cos($lat2)*cos($lon1 - $lon2); return ($this->AVG_ERAD * acos($d)); } function GCAzimuth($lat1, $lon1, $lat2, $lon2) { $result = 0.0; $ilat1 = intval(0.50 + $lat1 * 360000.0); $ilat2 = intval(0.50 + $lat2 * 360000.0); $ilon1 = intval(0.50 + $lon1 * 360000.0); $ilon2 = intval(0.50 + $lon2 * 360000.0); $lat1 *= $this->DE2RA; $lon1 *= $this->DE2RA; $lat2 *= $this->DE2RA; $lon2 *= $this->DE2RA; if (($ilat1 == $ilat2) && ($ilon1 == $ilon2)) { return $result; } else if ($ilat1 == $ilat2) { if ($ilon1 > $ilon2) $result = 90.0; else $result = 270.0; } else if ($ilon1 == $ilon2) { if ($ilat1 > $ilat2) $result = 180.0; } else { $c = acos(sin($lat2)*sin($lat1) + cos($lat2)*cos($lat1)*cos(($lon2-$lon1))); $A = asin(cos($lat2)*sin(($lon2-$lon1))/sin($c)); $result = ($A * $this->RA2DE); if (($ilat2 > $ilat1) && ($ilon2 > $ilon1)) { $result = $result; } else if (($ilat2 < $ilat1) && ($ilon2 < $ilon1)) { $result = 180.0 - $result; } else if (($ilat2 < $ilat1) && ($ilon2 > $ilon1)) { $result = 180.0 - $result; } else if (($ilat2 > $ilat1) && ($ilon2 < $ilon1)) { $result += 360.0; } } return $result; } function ApproxDistance($lat1, $lon1, $lat2, $lon2) { $lat1 = $this->DE2RA * $lat1; $lon1 = -$this->DE2RA * $lon1; $lat2 = $this->DE2RA * $lat2; $lon2 = -$this->DE2RA * $lon2; $F = ($lat1 + $lat2) / 2.0; $G = ($lat1 - $lat2) / 2.0; $L = ($lon1 - $lon2) / 2.0; $sing = sin($G); $cosl = cos($L); $cosf = cos($F); $sinl = sin($L); $sinf = sin($F); $cosg = cos($G); $S = $sing*$sing*$cosl*$cosl + $cosf*$cosf*$sinl*$sinl; $C = $cosg*$cosg*$cosl*$cosl + $sinf*$sinf*$sinl*$sinl; $W = atan2(sqrt($S),sqrt($C)); $R = sqrt(($S*$C))/$W; $H1 = (3 * $R - 1.0) / (2.0 * $C); $H2 = (3 * $R + 1.0) / (2.0 * $S); $D = 2 * $W * $this->ERAD; $return = ($D * (1 + $this->FLATTENING * $H1 * $sinf*$sinf*$cosg*$cosg - $this->FLATTENING*$H2*$cosf*$cosf*$sing*$sing)); return $return; } function EllipsoidDistance($lat1, $lon1, $lat2, $lon2) { $distance = 0.0; $faz = 0.0; $baz = 0.0; $r = 1.0 - $this->FLATTENING; $tu1 = 0.0; $tu2 = 0.0; $cu1 = 0.0; $su1 = 0.0; $cu2 = 0.0; $x = 0.0; $sx = 0.0; $cx = 0.0; $sy = 0.0; $cy = 0.0; $y = 0.0; $sa = 0.0; $c2a = 0.0; $cz = 0.0; $e = 0.0; $c = 0.0; $d = 0.0; $cosy1 = 0.0; $cosy2 = 0.0; if(($lon1 == $lon2) && ($lat1 == $lat2)) return $distance; $lon1 *= $this->DE2RA; $lon2 *= $this->DE2RA; $lat1 *= $this->DE2RA; $lat2 *= $this->DE2RA; $cosy1 = cos($lat1); $cosy2 = cos($lat2); if($cosy1 == 0.0) $cosy1 = 0.0000000001; if($cosy2 == 0.0) $cosy2 = 0.0000000001; $tu1 = $r * sin($lat1) / $cosy1; $tu2 = $r * sin($lat2) / $cosy2; $cu1 = 1.0 / sqrt($tu1 * $tu1 + 1.0); $su1 = $cu1 * $tu1; $cu2 = 1.0 / sqrt($tu2 * $tu2 + 1.0); $x = $lon2 - $lon1; $distance = $cu1 * $cu2; $baz = $distance * $tu2; $faz = $baz * $tu1; while(abs($d - $x) > $this->EPS) { $sx = sin($x); $cx = cos($x); $tu1 = $cu2 * $sx; $tu2 = $baz - $su1 * $cu2 * $cx; $sy = sqrt($tu1 * $tu1 + $tu2 * $tu2); $cy = $distance * $cx + $faz; $y = atan2($sy, $cy); $sa = $distance * $sx / $sy; $c2a = - $sa * $sa + 1.0; $cz = $faz + $faz; if($c2a > 0.0) $cz = - $cz / $c2a + $cy; $e = $cz * $cz * 2.0 - 1.0; $c = ((-3.0 * $c2a + 4.0) * $this->FLATTENING + 4.0) * $c2a * $this->FLATTENING / 16.0; $d = $x; $x = (($e * $cy * $c + $cz) * $sy * $c + $y) * $sa; $x = (1.0 - $c) * $x * $this->FLATTENING + $lon2 - $lon1; } $x = sqrt((1.0 / $r / $r - 1.0) * $c2a + 1.0) + 1.0; $x = ($x - 2.0) / $x; $c = 1.0 - $x; $c = ($x * $x / 4.0 + 1.0) / $c; $d = (0.375 * $x * $x - 1.0) * $x; $x = $e * $cy; $distance = 1.0 - $e - $e; $distance = (((($sy * $sy * 4.0 - 3.0) * $distance * $cz * $d / 6.0 - $x) * $d / 4.0 + $cz) * $sy * $d + $y) * $c * $this->ERAD * $r; return $distance; } function getKmPerLonAtLat($dLatitude) { // Thanks to Eric Iverson for this correction! Must convert degrees to radians... $dLatitude *= $this->DE2RA; return 111.321 * cos($dLatitude); } function getLonPerKmAtLat($dLatitude) { return 1 / $this->getKmPerLonAtLat($dLatitude); } function getKmPerLat() { return 111.000; } function getLatPerKm() { return 1 / $this->getKmPerLat(); } } function ConvKilometersToMiles($dValue) { return $dValue / 1.609344; } function Distance($lat1,$lon1,$lat2,$lon2) { $R = 6371; // earth's mean radius in km $dLat = $lat2 - $lat1; $dLong = $lon2 - $lon1; $a = sin($dLat/2) * sin($dLat/2) + cos($lat1) * cos($lat2) * sin($dLong/2) * sin($dLong/2); $c = 2 * atan2(sqrt($a), sqrt(1-$a)); $d = $R * $c; return $d; } function LatLongToRadian($ll){ return $ll * Pi() / 180; // signed decimal degrees without NSEW } function DegreToDecimal($deg,$min,$sec,$sens){ $d=$deg+($min / 60) +($sec / 3600); if($sens=='W' || $sens=='S') $d=-$d; return $d; } /* GEOCALC-PHP Geographic Distance and Azimuth Calculations in PHP Version 1.2 ABOUT THIS LIBRARY This code was "ported" to PHP from Visual C++ by Steven Brendtro of www.imaginerc.com. The original article and source code, written by andyf4i can be found on CodeGuru.com at the following address: http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115/ VERSION HISTORY Version 1.0 - Initial release Version 1.1 - Bug in getKMPerLonAtLat() fixed. Thanks to Eric Iverson for finding it. Version 1.2 - Bug in getLonPerKMAtLat() fixed. FILES INCLUDED IN THIS RELEASE GeoCalc.class.php - The actual PHP class README - This file ADDITIONAL PACKAGES Also available on SourceForge.net under the GEOCALC-PHP project, you can find a ZIP Code database (for FREE!) that you can use for distance calculations between ZIP Codes. For increased speed when performing distance calculations using MySQL, be sure to check out GEOCALC-UDF at SourceForge.net. This UDF (User Defined Function) is designed for MySQL and has been known to reduce query time up to 1000%! METHODS # Basic Methods: GeoCalc(); # Default Constructor GCDistance($lat1, $lon1, $lat2, $lon2); # Using the Great Circle formula, calculate # the distance in kilometers between # Latitude/Longitude 1 and Latitude/Longitude 2 GCAzimuth($lat1, $lon1, $lat2, $lon2); # Using the Great Circle formula, calculate the # azimuth between Latitude/Longitude 1 and # Latitude/Longitude 2 ApproxDistance($lat1, $lon1, $lat2, $lon2); # Using the Ellipsoidal Approximation formula, # calculate the distance in kilometers between # Latitude/Longitude 1 and Latitude/Longitude 2 EllipsoidDistance($lat1, $lon1, $lat2, $lon2); # Using the Ellipsoidal Distance formula, calculate # the distance in kilometers between Latitude/Longitude 1 # and Latitude/Longitude 2. This formula is the most # accurate of the formulas. # Helper Methods getKmPerLonAtLat($dLatitude); # Get the number of Kilometers per degree longitude # at the given latitude. getLonPerKmAtLat($dLatitude); # Get the number of degrees longitude per kilometer at the # given latitude. getKmPerLat(); # Get the number of kilometers per degree latitude (average # of 111.0 kilometers per degree) getLatPerKm(); # Get the number of degrees latitude per kilometer (average # of 1/111 degrees per kilometer) # Helper Function (not a method in the class, but a function) ConvKilometersToMiles($dValue); # Convert a distance from kilometers to miles # (km / 1.609344 = miles). EXAMPLES Here are some example uses for this class: include_once("GeoCalc.class.php"); $oGC = new GeoCalc(); // Great Circle Distance $dDist = $oGC->GCDistance(38.9333,-94.3253,38.9314,-94.4876); // Great Circle Azimuth $dDist = $oGC->GCAzimuth(38.9333,-94.3253,38.9314,-94.4876); // Approximate Ellipsoid Distance $dDist = $oGC->ApproxDistance(38.9333,-94.3253,38.9314,-94.4876); // Accurate Ellipsoid Distance $dDist = $oGC->EllipsoidDistance(38.9333,-94.3253,38.9314,-94.4876); // Convert distance from kilometers to miles $dDistMiles = ConvKilometersToMiles($dDist); // Advanced Calculation: // The following will search for ZIP codes // within a radius (roughly calculated) // Define the center of the search bounds... $dLongitude = -94.44590241; $dLatitude = 38.7996; // Define the maximum search distance $dRadius = 100.00; // in kilometers // Calculate the boundary distance in degrees longitude / latitude $dAddLat = $oGC->getLatPerKm() * $dRadius; $dAddLon = $oGC->getLonPerKmAtLat($dLatitude) * $dRadius; // Calculate the boundaries $dNorthBounds = $dLatitude + $dAddLat; $dSouthBounds = $dLatitude - $dAddLat; $dWestBounds = $dLongitude - $dAddLon; $dEastBounds = $dLongitude + $dAddLon; print "Center Longitude: $dLongitude\n"; print "Center Latitude: $dLatitude\n"; print "Radius: $dRadius kilometers\n"; print "North Bounds: $dNorthBounds\n"; print "South Bounds: $dSouthBounds\n"; print "East Bounds: $dEastBounds\n"; print "West Bounds: $dWestBounds\n"; // Sample SQL query stament based on above boundaries: $strQuery = "SELECT * FROM PostalCodes " . "WHERE Latitude > $dSouthBounds " . "AND Latitude < $dNorthBounds " . "AND Longitude > $dWestBounds " . "AND Longitude < $dEastBounds"; */ 3669 HORLOGE PARLANTE © Décalage horaire Nova Prata Brésil FR