Getting all vertex lat, long coordinates every 1 meter between two known points using PHP?
This is quick and dirty. Most of this was adapted from the following website:
http://www.movable-type.co.uk/scripts/latlong.html
I haven't tested this too much but it seemed to work after initial testing. It will return a list of lat, long coordinate pairs along a line at a specified interval. I wrote it in python since I don't know php very well.
from math import cos, sin, atan2, sqrt, radians, degrees, asin, modf
def getPathLength(lat1,lng1,lat2,lng2):
'''calculates the distance between two lat, long coordinate pairs'''
R = 6371000 # radius of earth in m
lat1rads = radians(lat1)
lat2rads = radians(lat2)
deltaLat = radians((lat2-lat1))
deltaLng = radians((lng2-lng1))
a = sin(deltaLat/2) * sin(deltaLat/2) + cos(lat1rads) *
cos(lat2rads) * sin(deltaLng/2) * sin(deltaLng/2)
c = 2 * atan2(sqrt(a), sqrt(1-a))
d = R * c
return d
def getDestinationLatLong(lat,lng,azimuth,distance):
'''returns the lat an long of destination point
given the start lat, long, aziuth, and distance'''
R = 6378.1 #Radius of the Earth in km
brng = radians(azimuth) #Bearing is degrees converted to radians.
d = distance/1000 #Distance m converted to km
lat1 = radians(lat) #Current dd lat point converted to radians
lon1 = radians(lng) #Current dd long point converted to radians
lat2 = asin( sin(lat1) * cos(d/R) + cos(lat1)* sin(d/R)* cos(brng))
lon2 = lon1 + atan2(sin(brng) * sin(d/R)* cos(lat1),
cos(d/R)- sin(lat1)* sin(lat2))
#convert back to degrees
lat2 = degrees(lat2)
lon2 = degrees(lon2)
return[lat2, lon2]
def main(interval,azimuth,lat1,lng1,lat2,lng2):
'''returns every coordinate pair inbetween two coordinate
pairs given the desired interval'''
coords = []
d = getPathLength(lat1,lng1,lat2,lng2)
remainder, dist = modf((d / interval))
counter = 1.0
coords.append([lat1,lng1])
for distance in xrange(1,int(dist)):
c = getDestinationLatLong(lat1,lng1,azimuth,counter)
counter += 1.0
coords.append(c)
counter +=1
coords.append([lat2,lng2])
return coords
if __name__ == "__main__":
#point interval in meters
interval = 1
#direction of line in degrees
azimuth = 279.91
#start point
lat1 = 41.97809
lng1 = -91.65573
#end point
lat2 = 41.97834
lng2 = -91.65767
coords = main(interval,azimuth,lat1,lng1,lat2,lng2)
print coords
I hope this helps. sorry if not. :)
Ok, I added the ability for it to calculate the azimuth for you. I tested with the same location you were using and it turned out perfectly.http://www.darrinward.com/lat-long/?id=705140
import math
def getPathLength(lat1,lng1,lat2,lng2):
'''calculates the distance between two lat, long coordinate pairs'''
R = 6371000 # radius of earth in m
lat1rads = math.radians(lat1)
lat2rads = math.radians(lat2)
deltaLat = math.radians((lat2-lat1))
deltaLng = math.radians((lng2-lng1))
a = math.sin(deltaLat/2) * math.sin(deltaLat/2) + math.cos(lat1rads) * math.cos(lat2rads) * math.sin(deltaLng/2) * math.sin(deltaLng/2)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
d = R * c
return d
def getDestinationLatLong(lat,lng,azimuth,distance):
'''returns the lat an long of destination point
given the start lat, long, aziuth, and distance'''
R = 6378.1 #Radius of the Earth in km
brng = math.radians(azimuth) #Bearing is degrees converted to radians.
d = distance/1000 #Distance m converted to km
lat1 = math.radians(lat) #Current dd lat point converted to radians
lon1 = math.radians(lng) #Current dd long point converted to radians
lat2 = math.asin(math.sin(lat1) * math.cos(d/R) + math.cos(lat1)* math.sin(d/R)* math.cos(brng))
lon2 = lon1 + math.atan2(math.sin(brng) * math.sin(d/R)* math.cos(lat1), math.cos(d/R)- math.sin(lat1)* math.sin(lat2))
#convert back to degrees
lat2 = math.degrees(lat2)
lon2 = math.degrees(lon2)
return[lat2, lon2]
def calculateBearing(lat1,lng1,lat2,lng2):
'''calculates the azimuth in degrees from start point to end point'''
startLat = math.radians(lat1)
startLong = math.radians(lng1)
endLat = math.radians(lat2)
endLong = math.radians(lng2)
dLong = endLong - startLong
dPhi = math.log(math.tan(endLat/2.0+math.pi/4.0)/math.tan(startLat/2.0+math.pi/4.0))
if abs(dLong) > math.pi:
if dLong > 0.0:
dLong = -(2.0 * math.pi - dLong)
else:
dLong = (2.0 * math.pi + dLong)
bearing = (math.degrees(math.atan2(dLong, dPhi)) + 360.0) % 360.0;
return bearing
def main(interval,azimuth,lat1,lng1,lat2,lng2):
'''returns every coordinate pair inbetween two coordinate
pairs given the desired interval'''
d = getPathLength(lat1,lng1,lat2,lng2)
remainder, dist = math.modf((d / interval))
counter = float(interval)
coords = []
coords.append([lat1,lng1])
for distance in xrange(0,int(dist)):
coord = getDestinationLatLong(lat1,lng1,azimuth,counter)
counter = counter + float(interval)
coords.append(coord)
coords.append([lat2,lng2])
return coords
if __name__ == "__main__":
#point interval in meters
interval = 1.0
#direction of line in degrees
#start point
lat1 = 43.97076
lng1 = 12.72543
#end point
lat2 = 43.969730
lng2 = 12.728294
azimuth = calculateBearing(lat1,lng1,lat2,lng2)
print azimuth
coords = main(interval,azimuth,lat1,lng1,lat2,lng2)
print coords
I think I have fixed the bugs from the original and it should work (including change the interval). Let me know how it turns out.
I did port the Python code to php:
<?php
function parseFloat($ptString) {
if (strlen($ptString) == 0) {
return false;
}
$pString = str_replace(" ", "", $ptString);
if (substr_count($pString, ",") > 1)
$pString = str_replace(",", "", $pString);
if (substr_count($pString, ".") > 1)
$pString = str_replace(".", "", $pString);
$pregResult = array();
$commaset = strpos($pString,',');
if ($commaset === false) {$commaset = -1;}
$pointset = strpos($pString,'.');
if ($pointset === false) {$pointset = -1;}
$pregResultA = array();
$pregResultB = array();
if ($pointset < $commaset) {
preg_match('#(([-]?[0-9]+(\.[0-9])?)+(,[0-9]+)?)#', $pString, $pregResultA);
}
preg_match('#(([-]?[0-9]+(,[0-9])?)+(\.[0-9]+)?)#', $pString, $pregResultB);
if ((isset($pregResultA[0]) && (!isset($pregResultB[0])
|| strstr($preResultA[0],$pregResultB[0]) == 0
|| !$pointset))) {
$numberString = $pregResultA[0];
$numberString = str_replace('.','',$numberString);
$numberString = str_replace(',','.',$numberString);
}
elseif (isset($pregResultB[0]) && (!isset($pregResultA[0])
|| strstr($pregResultB[0],$preResultA[0]) == 0
|| !$commaset)) {
$numberString = $pregResultB[0];
$numberString = str_replace(',','',$numberString);
}
else {
return false;
}
$result = (float)$numberString;
return $result;
}
function xrange($start, $limit, $step = 1) {
if ($start < $limit) {
if ($step <= 0) {
throw new LogicException('Step must be +ve');
}
for ($i = $start; $i <= $limit; $i += $step) {
yield $i;
}
} else {
if ($step >= 0) {
throw new LogicException('Step must be -ve');
}
for ($i = $start; $i >= $limit; $i += $step) {
yield $i;
}
}
}
function modf($x) {
$m = fmod($x, 1);
return [$m, $x - $m];
}
function getPathLength($lat1,$lng1,$lat2,$lng2)
{
$R = '6371000'; //# radius of earth in m
$lat1rads = deg2rad($lat1);
$lat2rads = deg2rad($lat2);
$deltaLat = deg2rad(($lat2 - $lat1));
$deltaLng = deg2rad(($lng2 - $lng1));
$a = sin($deltaLat/2) * sin($deltaLat/2) + cos($lat1rads) * cos($lat2rads) * sin($deltaLng/2) * sin($deltaLng/2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$d = $R * $c;
return $d;
}
function getDestinationLatLong($lat,$lng,$azimuth,$distance){
$R = 6378.1; //#Radius of the Earth in km
$brng = deg2rad($azimuth); #Bearing is degrees converted to radians.
$d = $distance / 1000; #Distance m converted to km
$lat1 = deg2rad($lat); #Current dd lat point converted to radians
$lon1 = deg2rad($lng); #Current dd long point converted to radians
$lat2 = asin(sin($lat1) * cos($d/$R) + cos($lat1)* sin($d/$R)* cos($brng));
$lon2 = $lon1 + atan2(sin($brng) * sin($d/$R)* cos($lat1), cos($d/$R)- sin($lat1)* sin($lat2));
#convert back to degrees
$lat2 = rad2deg($lat2);
$lon2 = rad2deg($lon2);
return [$lat2, $lon2];
}
function calculateBearing($lat1,$lng1,$lat2,$lng2){
// '''calculates the azimuth in degrees from start point to end point'''
$startLat = deg2rad($lat1);
$startLong = deg2rad($lng1);
$endLat = deg2rad($lat2);
$endLong = deg2rad($lng2);
$dLong = $endLong - $startLong;
$dPhi = log(tan($endLat / 2 + pi() / 4) / tan($startLat / 2 + pi() / 4));
if (abs($dLong) > pi()) {
if ($dLong > 0) {
$dLong = -(2 * pi() - $dLong);
} else {
$dLong = 2 * pi() + $dLong;
}
}
$bearing = (rad2deg(atan2($dLong, $dPhi)) + 360) % 360;
return $bearing;
}
function main($interval, $azimuth, $lat1, $lng1, $lat2, $lng2)
{
$d = getPathLength($lat1, $lng1, $lat2, $lng2);
$rapydUnpack = modf($d / $interval);
$remainder = $rapydUnpack[0];
$dist = $rapydUnpack[1];
$counter = parseFloat($interval);
$coords = [];
array_push($coords, [ $lat1, $lng1 ]);
$xRange = xrange(0, intval($dist));
foreach ($xRange as $rapydIndex => $value)
{
//print $value;
$distance =$value;
$coord = getDestinationLatLong($lat1, $lng1, $azimuth, $counter);
$counter = $counter + parseFloat($interval);
array_push($coords, $coord);
}
array_push($coords, [ $lat2, $lng2]);
return $coords;
}
#point interval in meters
$interval = 10;
#direction of line in degrees
#start point
$lat1 = 43.97076;
$lng1 = 12.72543;
#end point
$lat2 = 43.969730;
$lng2 = 12.728294;
$azimuth = calculateBearing($lat1,$lng1,$lat2,$lng2);
//print $azimuth;
$coords = main($interval,$azimuth,$lat1,$lng1,$lat2,$lng2);
print_r($coords);
?>