Обекти в близост - каква заявка трябва...

Msecurity

Registered
Здравей колеги и колежки :D
Имам малко тегав въпрос...
Имам база данни с добавени обекти,координати към тях и точен адрес, ето пример:
GPS: 42.697155,23.317985,
Адрес: България, Варна, бул. Сливница 192 ...
До тук всичко е ОК, но да речем че мойте координати са 40.697155,23.317945 и как мога да отсея всички обекти който са в радиус от 10км примерно ... без да се налага да извикам всички обекти от базата данни, и т.н ... а само тези който отговорят на критерия?
 
https://coderwall.com/p/fodzrw/calculate-distance-between-two-coordinates-in-php-javascript-and-mysql

Този урок няма ли да ти свърши работа?

PHP:
<?php

class GPS
{
	public function calculateDistance($ini, $fin) 
	{
		$r = 6371; // km
		$dLat = deg2rad($fin[0]-$ini[0]);
		$dLon = deg2rad($fin[1]-$ini[1]);
		$a = sin($dLat/2) * sin($dLat/2) + cos(deg2rad($ini[0])) * cos(deg2rad($fin[0])) * sin($dLon/2) * sin($dLon/2);
		$c = 2 * atan2(sqrt($a), sqrt(1-$a));
		$d = $r * $c;
		return $d;
	}
}

$gps = new GPS;
print $distance = $gps->calculateDistance([43.703373,22.177048],[43.697708,22.321868]);

if ($distance <= 15) {
	print '<br> В радиус от 15 км е!';
}

[sql]CREATE FUNCTION `calc_distance` (lat1 DECIMAL(10,6), long1 DECIMAL(10,6), lat2 DECIMAL(10,6), long2 DECIMAL(10,6))
RETURNS DECIMAL(10,6)
RETURN (6353 * 2 * ASIN(SQRT( POWER(SIN((lat1 - abs(lat2)) * pi()/180 / 2),2) + COS(lat1 * pi()/180 ) * COS( abs(lat2) * pi()/180) * POWER(SIN((long1 - long2) * pi()/180 / 2), 2) )))[/sql]

Естествено ще трябва само да добавиш условието <=10 км и си ти:
 
Разгледай това четиво - http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates
Много добре е обяснено + SQL заявки + програмен код на няколко езика, вкл. PHP - https://github.com/anthonymartin/GeoLocation.php/blob/master/src/AnthonyMartin/GeoLocation/GeoLocation.php

Логическата верига е следната:
Имаш координати [X;Y]
Определяш граничните координати (координатите до които би достигнал при придвижване с определеното разстояние само по паралела или само по меридиана във всяка от посоките), т.е:
При движение 10км на север достигаш координати [X1;Y]
При движение 10км на юг достигаш координати [X2;Y]
При движение 10 км на изток достигаш координати [X;Y1]
При движение 10км на запад достигаш координати [X;Y2]
(Сведено до равнина - все едно чертаеш квадрат около окръжност)

Взимаш всички обекти отговарящи на условието:
Latitude BETWEEN X1 AND X2
AND
Longitude BETWEEN Y1 AND Y2

Това филтриране значително ще намали броя на резултатите, но все още ще има такива извън посочения радиус.
След това филтрираш повторно, като изключваш резултатите на разстояние по-голямо от зададеното.
Това може да стане с 1 array_filter и малка модификация на класа, който ти е дал @dakata__92 (инциализираш с началната точка и радиуса, а за callback на array_filter ползваш метод на класа който приема втора точка и връща true/false според това дали точката в зададения радиус).
Авторът на публикацията използва същия подход, но в самата SQL заявка и работи директно с радиани вместо с километри. Предимството е, че изчисляваш веднъж параметрите на база на входните данни и ги включваш в заявката, а изчисленията и филтрирането се извършват от SQL сървъра.
 

Горе