haversine formula php / mysql - php

I'm trying to get a common database of geo points working with a radius search.
I've found several good tutorials on this topic, but I'm failing at the very end.
The main tutorial is here: http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates.
The basic formula, in the form of an SQL query, is
SELECT * FROM Places
WHERE (Lat => 1.2393 AND Lat <= 1.5532) AND (Lon >= -1.8184 AND Lon <= 0.4221)
AND acos(sin(1.3963) * sin(Lat) + cos(1.3963) * cos(Lat) * cos(Lon - (-0.6981)))
<= 0.1570;
I've implemented this in a simple PHP test page like this:
$R = 6371; // radius of Earth in KM
$lat = '46.98025235521883'; // lat of center point
$lon = '-110.390625'; // longitude of center point
$distance = 1000; // radius in KM of the circle drawn
$rad = $distance / $R; // angular radius for query
$query = '';
// rough cut to exclude results that aren't close
$max_lat = $lat + rad2deg($rad/$R);
$min_lat = $lat - rad2deg($rad/$R);
$max_lon = $lon + rad2deg($rad/$R/cos(deg2rad($lat)));
$min_lon = $lon - rad2deg($rad/$R/cos(deg2rad($lat)));
// this part works just fine!
$query .= '(latitude > ' . $min_lat . ' AND latitude < ' . $max_lat . ')';
$query .= ' AND (longitude > ' . $min_lon . ' AND longitude < ' . $max_lon . ')';
// refining query -- this part returns no results
$query .= ' AND acos(sin('.$lat.') * sin(latitude) + cos('.$lat.') * cos(latitude) *
cos(longitude - ('.$lon.'))) <= '.$rad;
Am I missing something here? I think I'm following the methodology exactly, but I cannot get the "fine tuning" query to return any results.

not sure but :
$R = 6371; // radius of Earth in KM
$lat = '46.98025235521883'; // lat of center point
$lon = '-110.390625'; // longitude of center point
$distance = 1000; // radius in KM of the circle drawn
$rad = $distance / $R; // angular radius for query
$query = '';
// rough cut to exclude results that aren't close
$radR = rad2deg($rad/$R);
$max_lat = $lat + radR;
$min_lat = $lat - radR;
$radR = rad2deg($rad/$R/cos(deg2rad($lat)));
$max_lon = $lon + radR;
$min_lon = $lon - radR;
// this part works just fine!
$query .= '(latitude > ' . $min_lat . ' AND latitude < ' . $max_lat . ')';
$query .= ' AND (longitude > ' . $min_lon . ' AND longitude < ' . $max_lon . ')';
// refining query -- this part returns no results
$query .= ' AND acos(sin('.deg2rad($lat).') * sin(radians(latitude)) + cos('.deg2rad($lat).') * cos(radians(latitude)) *
cos(radians(longitude) - ('.deg2rad($lon).'))) <= '.$rad;

Related

Issue faced while using the '< ' symbol with AND in sql query

I'm getting issue when I try to use < symbol with AND condition in sql query.
WHERE (latitude - 0.009 < AND latitude + 0.00 >)
AND (longitude - 0.009 <
AND longitude + 0.009 > )
Here is my code in CorePHP:
<?php
ini_set("display_errors", 0);
$lat = $_REQUEST['latit'];
$long = $_REQUEST['longit'];
include ("commanvar.php");
include ("class.db.php");
$coordinates_ = '';
// function to calculate distance between two latitudes and longitudes
function distance($lat1, $lng1, $lat2, $lng2, $miles = true)
{
$pi80 = M_PI / 180;
$lat1 *= $pi80;
$lng1 *= $pi80;
$lat2 *= $pi80;
$lng2 *= $pi80;
$r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1;
$dlng = $lng2 - $lng1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
return ($miles ? $km * 0.621371192 : $km);
}
$obj = new db_connect();
// added by pramod
$sql = "SELECT name,
latitude,
longitude,
TYPE
FROM (SELECT name,
TO_BINARY_FLOAT(latitude) latitude,
TO_BINARY_FLOAT(longitude) longitude,
TYPE
FROM (SELECT name,
latitude,
longitude,
TYPE,
is_number (latitude) latisnum,
is_number (longitude) longisnum
FROM (SELECT name,
REGEXP_SUBSTR (latlon,
'[^,]+',
1,
1)
latitude,
REGEXP_SUBSTR (latlon,
'[^,]+',
1,
2)
longitude,
TYPE
FROM (SELECT olt.name,
olt_details.latlon,
'olt' AS TYPE
FROM ftth.olt, ftth.olt_details
WHERE olt_id = id
UNION
SELECT name, latlon, TYPE FROM ftth.splitters
))
WHERE latitude IS NOT NULL AND longitude IS NOT NULL)
WHERE latisnum = 1 AND longisnum = 1)
WHERE (latitude - 0.009 < $lat
AND latitude + 0.00 > $lat)
AND (longitude - 0.009 < $long
AND longitude + 0.009 > $long)";
//die();
$obj->db_query($sql);
// echo $sql;
// echo $lat . ',' . $long;
// define json array coordinates and prepare it's elements for returning via AJAX
$coordinates = '{
"coordinates": [';
while ($result = $obj->db_fetch_array(1)) {
$latitude = $result['LATITUDE'];
$longitude = $result['LONGITUDE'];
$name = $result['NAME'];
$type = $result['TYPE'];
$latlon_fiber = $result['LATITUDE'] . ", " . $result['LONGITUDE'];
$distance_fromswitch = distance($lat, $long, $latitude, $longitude, FALSE);
$distance_fromswitch = floor($distance_fromswitch * 1000);
$coordinates_ .= '{ "distance":"' . $distance_fromswitch . '" ,"site_name":"' . $name . '" , "latitude":"' . $latitude . '" , "longitude":"' . $longitude . '" , "device_type":"' . $type . '" },';
}
$coordinates .= rtrim($coordinates_, ',');
$coordinates .= "]}";
echo $coordinates;
$obj->free();
?>
I'm getting the following error due to this part < AND on line WHERE (latitude - 0.009 < AND latitude + 0.00 >)
ORA-00936: missing expression
00936. 00000 - "missing expression"
I think I've used some improper syntax while using < with AND on line WHERE (latitude - 0.009 < AND latitude + 0.00 >)
What can be the correction that need to be done here?
Think of it! The error message is self-explanatory.
You're trying to compare the result of subtraction to nothing. To correct this, you have to change it to:
WHERE (latitude - 0.009 < SomeValueHere AND latitude + 0.00 > SomeValueHere)
For further details, please see: ORA-00936 missing expression
[EDIT]
As to changes made in the question...
You're asking for help in debugging (inspect) your code. Let me quote the comment to your comment:
probably the variables do not have any values and passing empty
strings into your query.. – skybunk
Thank you, #skybunk!

Getting error on Trying to get property of non-object [duplicate]

This question already has answers here:
What is the difference between single-quoted and double-quoted strings in PHP?
(7 answers)
Closed 5 years ago.
I want to display the nearest location around me by the following code
<?php
$lat = "27.7350758";
$long = "85.3102946";
$result = $conn->query( 'SELECT * , (3956 * 2 * ASIN(SQRT( POWER(SIN(( $lat - college_lat) * pi()/180 / 2), 2) +COS( $lat * pi()/180) * COS(college_lat * pi()/180) * POWER(SIN(( $long - college_lon) * pi()/180 / 2), 2) ))) as distance from colleges having distance <= 10 order by distance' );
if ( $result->num_rows>0 ) {
// output data of each row
while( $row = $result->fetch_assoc() ) {
echo '<div class="category"><div class="cover" style="background-image: url(img/animation.jpg);"><div>'; ?>
<td><?php echo $row[ "college_name" ]; ?></td>
<?php
echo '</div></div><span class="counter ">Courses : <span>' . $row[ "college_courses" ] . '</span></span>';
echo '<span class="counter "> Distance : <span>' . $row[ "college_address" ] . '</span></span>';
echo '<span class="near-you"> <p>'. substr( $row[ "college_desc" ], 0 , 100) . '</p> </span></div>'; ?>
Read More...
<?php
}
} else {
echo "Colleges Not Found Please add";
}
?>
When i run this code following error will display
Notice: Trying to get property of non-object in C:\xampp\htdocs\college\index.php on line 56
Colleges Not Found Please add
If I remove $lat and $long, then keep the value on query it works.
What is my mistake please suggest me. Thank you
change your query as below. change ' to " otherwise value will not interpreted:
$result = $conn->query( "SELECT * , (3956 * 2 * ASIN(SQRT( POWER(SIN(( $lat - college_lat) * pi()/180 / 2), 2) +COS( $lat * pi()/180) * COS(college_lat * pi()/180) * POWER(SIN(( $long - college_lon) * pi()/180 / 2), 2) ))) as distance from colleges having distance <= 10 order by distance" );
What is the difference between single-quoted and double-quoted strings in PHP?
I think, that is because, value $lat and $long is treated as string. You could better use prepared statement and bind these variables.
$stmt = $mysqli->prepare("SELECT * , (3956 * 2 * ASIN(SQRT(POWER(SIN((? - college_lat) * pi()/180 / 2), 2) + COS(? * pi()/180) * COS(college_lat * pi()/180) * POWER(SIN(( ? - college_lon) * pi()/180 / 2), 2) ))) as distance from colleges having distance <= 10 order by distance");
$stmt->bind_param('ddd', $lat, $lat, $long);

Select and insert in one query SQL

I have a web page where a user clicks on a map, the latitute and longitude are passed to text fields, and along with some other details the data is submitted to the database. I have a formula for calculating the nearest town, and I have a little sample table of towns with their latitudes and logitudes.
At the moment I can display the nearest town and distance, but I can't get it to send to the database. I think I need to put the two queries together but I don't know how. Please be kind, I know my code is terrible and I have lots of security issues which I'm going to try to address later. Thank you!
<?php
$conn = Connect();
/**
* Use the Haversine Formula to display the 100 closest matches to $origLat, $origLon
* Only search the MySQL table $tableName for matches within a 10 mile ($dist) radius.
*/
$origLat = $conn->real_escape_string($_POST['lat']);
$origLon = $conn->real_escape_string($_POST['lng']);
// This is the maximum distance (in miles) away from $origLat, $origLon in which to search
$dist = 50;
$query = "SELECT Townland, lat, lng, 3956 * 2 *
ASIN(SQRT( POWER(SIN(($origLat - lat)*pi()/180/2),2)
+COS($origLat*pi()/180 )*COS(lat*pi()/180)
*POWER(SIN(($origLon-lng)*pi()/180/2),2)))
as distance FROM townland WHERE
lng between ($origLon-$dist/cos(radians($origLat))*69)
and ($origLon+$dist/cos(radians($origLat))*69)
and lat between ($origLat-($dist/69))
and ($origLat+($dist/69))
having distance < $dist ORDER BY distance limit 1";
$result = mysqli_query($conn, $query) or die(mysql_error());
while($row = mysqli_fetch_assoc($result)) {
echo $row['Townland']." > ".$row['distance']."<BR>";
}
$User_ID = $conn->real_escape_string($_POST['User_ID']);
$Species_Name = $conn->real_escape_string($_POST['Species_Name']);
$No_Of_Birds = $conn->real_escape_string($_POST['No_Of_Birds']);
$newdate = $conn->real_escape_string($_POST['Sighting_Date']);
//Converts date to 'yyyy-mm-dd' acceptable to mysql
$newdate=date('Y-m-d',strtotime($newdate));
$Sighting_Details = $conn->real_escape_string($_POST['Sighting_Details']);
$lat = $conn->real_escape_string($_POST['lat']);
$lng = $conn->real_escape_string($_POST['lng']);
$townland = $row['Townland'];
$query = "INSERT into sighting
(User_ID, Species_Name, No_Of_Birds,
Sighting_Date, Sighting_Details,
lat, lng, Townland)
VALUES('" . $User_ID . "','" . $Species_Name . "','" . $No_Of_Birds . "','"
. $newdate . "','" . $Sighting_Details . "','"
. $lat . "','" . $lng . "','" . $townland . "')";
$success = $conn->query($query);
if (!$success) {
die("Couldn't enter data: ".$conn->error);
}
header("Location: ../View/thankYouSubmitSighting.php");
$conn->close();
exit();
while($row = mysqli_fetch_assoc($result)) {
echo $row['Townland']." > ".$row['distance']."<BR>";
}
mysqli_close($conn);
?>
If you need insert the result from query in a table eg: my_table
could be you need an insert select query ( a single sql command composed by two part )
"INSERT into my_table (Townland, lat, lng, distance)
SELECT Townland, lat, lng, 3956 * 2 *
ASIN(SQRT( POWER(SIN(($origLat - lat)*pi()/180/2),2)
+COS($origLat*pi()/180 )*COS(lat*pi()/180)
*POWER(SIN(($origLon-lng)*pi()/180/2),2)))
as distance FROM townland WHERE
lng between ($origLon-$dist/cos(radians($origLat))*69)
and ($origLon+$dist/cos(radians($origLat))*69)
and lat between ($origLat-($dist/69))
and ($origLat+($dist/69))
having distance < $dist ORDER BY distance limit 1";

Extend WP Query & return output in $post

I'm trying to create an event site. Users at the moment can search for events within a specified radius of their chosen search location (using Google Geocode).
I have a custom DB Query, which works fine, except I want the distance of the event to display on the front end of the site also, so users know how far away each event is from them.
Here's the custom query function I have at the moment:
function location_posts_where( $where ) {
// if user has input a location
if( isset($_POST['where']) != '' ) :
// check the geo locaton of user
$geoURL = "http://freegeoip.net/json/". $_SERVER['REMOTE_ADDR'] .'';
$geo = json_decode(file_get_contents($geoURL), true);
// Geocode input value + users country code
$url = "https://maps.googleapis.com/maps/api/geocode/json?address=".urlencode($_POST['where'])."+".$geo[country_code]."&sensor=false";
$location = json_decode(file_get_contents($url), true);
// store lat and long of searched location
$Slat = $location[results][0][geometry][location][lat];
$Slng = $location[results][0][geometry][location][lng];
// if use hasn't unput a location
else :
// get location of user
$url = "http://freegeoip.net/json/". $_SERVER['REMOTE_ADDR'] .'';
$geo = json_decode(file_get_contents($url), true);
// store lat and long of user location
$Slat = $geo[latitude];
$Slng = $geo[longitude];
endif;
// Specify the co-ordinates that will form
// the centre of our search
$lat = $Slat;
$lng = $Slng;
$radius = $_POST['distance']; // (in miles)
// Append our radius calculation to the WHERE
$where .= " AND wp_posts.ID IN (SELECT post_id FROM lat_lng_post WHERE
( 3959 * acos( cos( radians(" . $lat . ") )
* cos( radians( lat ) )
* cos( radians( lng )
- radians(" . $lng . ") )
+ sin( radians(" . $lat . ") )
* sin( radians( lat ) ) ) ) <= " . $radius . ")";
// Return the updated WHERE part of the query
return $where;
}
This code works fine, however, I've used the wp_geo_posts plugin before, and that lets you output onto the screen the distance each event is from the users location using <?php echo $post->distance; ?>
With this code, there is no 'distance' output to the $post variable. Is there a way of getting this to output to $post so it can be displayed on the front end?

Mysql Result Return Problem

I'm creating a project in FuelPHP, with php + mysql.
I have this database query (I'm not using their built in query builder because its just a pain in the ass for complex queries).
$sql = DB::query('
SELECT game_id, lati, longi,
acos(sin (' . $lat . ')
* sin (radians( lati ))
+ cos (' . $lat . ')
* cos (radians(lati))
* cos (radians(longi) - ' . $lon . '))
*' . $R . ' AS D
FROM (
SELECT game_id, lati, longi
FROM games
WHERE lati > ' . $minLat .
' AND lati <' . $maxLat .
' AND longi > ' . $minLon .
' AND longi < ' . $maxLon .
') AS firstcut
WHERE
acos(sin (' . $lat . ')
* sin (radians( lati ))
+ cos (' . $lat . ')
* cos (radians(lati))
* cos (radians(longi) - ' . $lon . '))
*' . $R . '<' . $rad .
' ORDER BY D');
If I execute this and print_r(result) the number of rows is displayed i.e 2.
However I cant treat, or convert this result into an array, so I cant
foreach($result as $row) { echo $row['id'] . ' + ' . $row['D']}
Or something similar.
If I paste this code and replace the php variables with real values into phpmyadmin, I get the green 'The query was executed successfully' message but no rows are returned (two rows should be returned, there is not even a 'This query returned zero rows' message).
I dont have much experience with this kind of nested/complex sql queries, so any help would be appreciated.
Thanks.
You need to pass DB::SELECT as the second param for DB::query().
You might want to use the as_array method from the database result. Or take a look here: http://fuelphp.com/docs/classes/database/usage.html#results

Categories