문제

이것은 명확하거나 명확하지 않을 수도 있습니다. 내가 기지에 있지 않으면 의견을 남겨 주거나 더 많은 정보가 필요합니다. 아마도 PHP에서 원하는 것에 대한 솔루션이 이미있을 것입니다.

나는 경도 또는 위도 값에서 멀리 떨어진 거리를 추가하거나 빼는 함수를 찾고 있습니다.

이유 : 모든 위도와 종단이있는 데이터베이스가 있으며 x 킬로미터 (또는 마일) 이내에 모든 도시를 추출하기위한 쿼리를 형성하고자합니다. 내 쿼리는 이렇게 보일 것입니다 ...

Select * From Cities Where (Longitude > X1 and Longitude < X2) And (Latitude > Y1 and Latitude < Y2)

 Where X1 = Longitude - (distance)
 Where X2 = Longitude + (distance)

 Where Y1 = Latitude - (distance)
 Where Y2 = Latitude + (distance)

MySQL 데이터베이스와 함께 PHP에서 일하고 있습니다.

모든 제안에도 열려! :)

도움이 되었습니까?

해결책

이것은 당신이 원하는 것을 정확하게 수행하는 MySQL 쿼리입니다. 지구가 완벽하게 구형이 아니거나 산, 언덕, 계곡 등을 고려하지 않기 때문에 이와 같은 것은 일반적으로 근사치입니다. 우리는이 코드를 사용합니다. Academichomes.com PHP와 MySQL을 사용하면 $ 반경 마일 이내 $ latitude, $ longitude의 레코드를 반환합니다.

$res = mysql_query("SELECT
    * 
FROM
    your_table
WHERE
    (
        (69.1 * (latitude - " . $latitude . ")) * 
        (69.1 * (latitude - " . $latitude . "))
    ) + ( 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3)) * 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3))
    ) < " . pow($radius, 2) . " 
ORDER BY 
    (
        (69.1 * (latitude - " . $latitude . ")) * 
        (69.1 * (latitude - " . $latitude . "))
    ) + ( 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3)) * 
        (69.1 * (longitude - " . $longitude . ") * COS(" . $latitude . " / 57.3))
    ) ASC");

다른 팁

편집 : 만약 당신이 어딘가에, 위도와 함께 세계의 모든 도시 목록이 있다면. 그리고 길다. 값, 조회를 할 수 있습니다. 이 경우 위도에서 1 개의 세로 정도의 너비를 계산하려면 아래의 첫 번째 링크를 참조하십시오. alt text :

alt text

솔직히,이 문제의 합병증은 Google지도와 같은 서비스를 사용하여 데이터를 얻는 것이 훨씬 나아질 수 있다는 것입니다. 구체적으로, 지구는 완벽한 구체가 아니며, 적도에 가까워지면서 두도 사이의 거리는 달라집니다.

보다 http://en.wikipedia.org/wiki/geographic_coordinate_system 내가 의미하는 바에 대한 예를 보려면 Google Maps API.

얼마나 많은 도시를 포함시키고 있는지에 따라 목록을 사전에 계산할 수 있습니다. 우리는 +100m의 부정확성이 우리의 설정에 비해 너무 많은 내부 응용 프로그램을 위해 여기서이 작업을 수행합니다. Location1, Location2, 거리의 두 가지 주요 테이블을 사용하여 작동합니다. 그런 다음 Location1에서 X 거리를 매우 빠르게 가져갈 수 있습니다.

또한 Calcs는 오프라인으로 수행 할 수 있으므로 시스템 실행에 영향을 미치지 않습니다. 사용자는 또한 더 빠른 결과를 얻습니다.

위의 코드를 사용해 보았고 포인트 사이의 거리가 20-30 마일 범위에있을 때 답이 너무 많이 꺼졌으며 몇 마일의 오류가 있으면 괜찮습니다. 내지도 친구와 이야기를 나누었고 우리는 대신 이것을 생각해 냈습니다. 코드는 파이썬이지만 쉽게 번역 할 수 있습니다. 라디안으로의 일정한 변환을 피하기 위해 데이터베이스를 레드/LNG 지점을도에서 라디안으로 변환했습니다. 이것에 대한 좋은 부분은 수학의 가장 큰 부분이 대부분 한 번 이루어진다는 것입니다.

ra = 3963.1906 # radius @ equator in miles, change to km  if you want distance in km
rb = 3949.90275  # radius @ poles in miles, change to km  if you want distance in km
ra2 = ra * ra
rb2 = rb * rb

phi = self.lat

big_ol_constant = (math.pow(ra2*math.cos(phi), 2) + pow(rb2*math.sin(phi), 2))/ (pow(ra*math.cos(phi), 2) + pow(rb*math.sin(phi), 2))

sqlWhere = "%(distance)g > sqrt((power(lat - %(lat)g,2) + power(lng-%(lng)g,2)) * %(big_ol_constant)g)" % {
    'big_ol_constant': big_ol_constant, 'lat': self.lat, 'lng': self.lng, 'distance': distance}

# This is the Django portion of it, where the ORM kicks in.  sqlWhere is what you would put after the WHERE part of your SQL Query.
qs = ZipData.objects.extra(where=[sqlWhere]);

거리가 떨어지면 거리가 200 마일로 자라면서 10 마일 이내에 매우 정확한 것처럼 보입니다 (물론 크로우가 날아 가면서 "포장 도로"에 문제가 있습니다).

위에서 언급 한 모델 zipdata는 다음과 같습니다.

class ZipData(models.Model):
    zipcode = ZipCodeField(null=False, blank=False, verbose_name="ZipCode", primary_key=True)
    city = models.CharField(max_length=32, null=False, blank=False)
    state = models.CharField(max_length=2)
    lat = models.FloatField(null=False, blank=False)
    lng = models.FloatField(null=False, blank=False)

추가 메모는 우편 번호와 관련된 많은 GEO 데이터를 얻을 수 있다는 것입니다. geonames.org 그리고 그들은 당신이 사용할 수있는 웹 서비스 API도 있습니다.

많은 사람들이 있습니다 (나쁜 옵션)

  • 수학 공식 (X1-X2 및 Y1-Y2를 처리)을 벡터로 사용하여 거리를 계산하십시오.

  • 모든 조합으로 조회 테이블을 미리 만들고 거리를 유지하십시오.

  • MySQL의 GIS 특이 적 확장을 고려하십시오. 여기에 있습니다 하나의 기사 나는 이것에 대해 찾았다.

Lessthandot.com은 실제로이 작업을 수행하는 3 가지 방법이 있습니다. 블로그를 조금 스크롤해야하지만 거기에 있습니다.http://blogs.lessthandot.com/

아래 기능은 Nerddinner(ASP.NET MVC 샘플 응용 프로그램 CodePlex에서 사용할 수 있습니다) 데이터베이스 (MSSQL).

ALTER FUNCTION [dbo].[DistanceBetween] (@Lat1 as real,
                @Long1 as real, @Lat2 as real, @Long2 as real)
RETURNS real
AS
BEGIN

DECLARE @dLat1InRad as float(53);
SET @dLat1InRad = @Lat1 * (PI()/180.0);
DECLARE @dLong1InRad as float(53);
SET @dLong1InRad = @Long1 * (PI()/180.0);
DECLARE @dLat2InRad as float(53);
SET @dLat2InRad = @Lat2 * (PI()/180.0);
DECLARE @dLong2InRad as float(53);
SET @dLong2InRad = @Long2 * (PI()/180.0);

DECLARE @dLongitude as float(53);
SET @dLongitude = @dLong2InRad - @dLong1InRad;
DECLARE @dLatitude as float(53);
SET @dLatitude = @dLat2InRad - @dLat1InRad;
/* Intermediate result a. */
DECLARE @a as float(53);
SET @a = SQUARE (SIN (@dLatitude / 2.0)) + COS (@dLat1InRad)
                 * COS (@dLat2InRad)
                 * SQUARE(SIN (@dLongitude / 2.0));
/* Intermediate result c (great circle distance in Radians). */
DECLARE @c as real;
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a));
DECLARE @kEarthRadius as real;
/* SET kEarthRadius = 3956.0 miles */
SET @kEarthRadius = 6376.5;        /* kms */

DECLARE @dDistance as real;
SET @dDistance = @kEarthRadius * @c;
return (@dDistance);
END

나는 이것이 도움이 될 수 있다고 생각합니다.

피타고라스의 정리를 사용하여 두 쌍의 LAT/LON 포인트의 근접성을 계산할 수 있습니다.

두 위치 (알파 및 베타)가있는 경우 다음과 같이 거리를 계산할 수 있습니다.

SQRT( POW(Alpha_lat - Beta_lat,2) + POW(Alpha_lon - Beta_lon,2) )

다음 URL의 설정을 사용하여 아래 쿼리를 구축했습니다. (데이터베이스를 쿼리하기 위해 Codeignitor를 사용하여 메모하십시오)

http://howto-use-mysql-spatial-ext.blogspot.com/2007/11/using-circular-area-selection.html

function getRadius($point="POINT(-29.8368 30.9096)", $radius=2)
{
    $km = 0.009;
    $center = "GeomFromText('$point')";
    $radius = $radius*$km;
    $bbox = "CONCAT('POLYGON((',
        X($center) - $radius, ' ', Y($center) - $radius, ',',
        X($center) + $radius, ' ', Y($center) - $radius, ',',
        X($center) + $radius, ' ', Y($center) + $radius, ',',
        X($center) - $radius, ' ', Y($center) + $radius, ',',
        X($center) - $radius, ' ', Y($center) - $radius, '
    ))')";

    $query = $this->db->query("
    SELECT id, AsText(latLng) AS latLng, (SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )))/0.009 AS distance
    FROM crime_listing
    WHERE Intersects( latLng, GeomFromText($bbox) )
    AND SQRT(POW( ABS( X(latLng) - X({$center})), 2) + POW( ABS(Y(latLng) - Y({$center})), 2 )) < $radius
    ORDER BY distance
        ");

    if($query->num_rows()>0){
        return($query->result());
    }else{
        return false;
    }
}

바퀴를 재발 명하지 마십시오. 이것은 공간 쿼리입니다. 사용 MySQL의 내장 공간 확장 위도-단위 좌표 데이터를 저장합니다 기본 MySQL 지오메트리 열 유형. 그런 다음 사용하십시오 거리 서로 지정된 거리 내에있는 점에 대한 쿼리 기능.

면책 조항 : 이것은 문서를 읽는 것을 기반으로합니다. 나는 이것을 직접 시도하지 않았습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top