Vra

Dit mag of mag nie duidelik wees, laat my 'n comment as ek af basis, of jy meer inligting nodig het. Miskien is daar 'n oplossing daar buite reeds vir wat ek wil hê in PHP.

Ek is op soek na 'n funksie wat sal optel of aftrek 'n afstand van 'n lengte- of die lengte waarde.

Die rede: Ek het 'n databasis met al lengte- en breedtegrade in dit en wil 'n navraag om al die stede binne X kilometer (of myl) onttrek vorm. My vraag sou iets so lyk ...

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)

Ek werk in PHP, met 'n MySQL databasis.

oop vir enige voorstelle ook! :)

Was dit nuttig?

Oplossing

Dit is 'n MySQL navraag wat presies wat jy wil doen. Hou in gedagte dinge soos hierdie benaderings algemeen, as die aarde is nie perfek sferies en ook nie hierdie in ag neem berge, heuwels, valleie, ens .. Ons gebruik hierdie kode op AcademicHomes.com met PHP en MySQL, dit gee rekords binne $ radius myl van $ breedtegraad, $ 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");

Ander wenke

EDIT: As jy het, iewers, 'n lys van al die stede in die wêreld saam met hul lat. en 'n lang. waardes, kan jy 'n lookup doen. In hierdie geval, sien my eerste skakel hieronder vir die formule om die wydte van een longitudinale graad bereken teen breedtegraad alt text

alt text

Honestly, die komplikasies agter hierdie probleem is sodanig dat jy baie beter af met behulp van 'n diens soos Google Maps om jou data te kry sal wees. Spesifiek, die aarde is nie 'n perfekte sfeer, en die afstand tussen twee grade wissel as jy nader aan / verder van die ewenaar.

http://en.wikipedia.org/wiki/Geographic_coordinate_system vir voorbeelde van wat ek bedoel, en kyk na die Google Maps API .

Afhangende van hoeveel stede wat jy insluitende, kan jy die lys precompute. Ons doen dit hier vir 'n interne aansoek waar 'n onakkuraatheid van + 100m is te veel vir ons die opstel van. Dit werk deur 'n twee sleutel tafel van LOCATION1, LOCATION2, afstand. Ons kan dan trek terug plekke x afstand van LOCATION1 baie vinnig.

Ook sedert die calcs af gedoen kan word, is dit nie 'n impak die bedryf van die stelsel. Gebruikers ook vinniger resultate.

Ek het probeer om met behulp van die bogenoemde kode, en die antwoorde was af deur te veel wanneer die afstand tussen punte was in die 20-30 myl reeks, en ek is ok met 'n paar myl van fout. Gepraat met 'n kartering buddy van my en ons het met hierdie een plaas. Die kode is luislang, maar jy kan dit redelik maklik vertaal. Ten einde die voortdurende oorskakeling na radiale vermy, ek redid my databasis, omskakeling die lat / LNG punte van grade na radiale. Die lekker deel oor hierdie is dat die grootste deel van die wiskunde meestal een keer gedoen.

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]);

Lyk baie akkuraat te wees wanneer afstand van mekaar is klein, en binne 10 myl of so as die afstand groei tot 200 myl, (natuurlik teen daardie tyd, jy probleme het met "soos die kraai vlieg" vs "geplaveide paaie") .

Hier is die model ZipData wat ek noem hierbo.

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)

'n ekstra kennis, is dat jy kan kry baie van die geo data wat verband hou met poskodes by Geonames. org en hulle het selfs 'n paar webservice APIs jy kan net so goed gebruik.

Daar is baie (slegte opsies)

  • Bereken die afstand met behulp van die wiskundige formule (treat X1-X2 en Y1-Y2) as vektore.

  • Skep 'n lookup tafel voor die tyd met al die kombinasies en hou die afstande.

  • Oorweeg die gebruik van 'n GIS-spesifieke uitbreiding van MySQL. Hier is een artikel ek gevind hieroor .

lessthandot.com het eintlik 3 verskillende maniere om dit te doen. jy sal hê om deur die blogs 'n boekie, maar hulle is daar. http://blogs.lessthandot.com/

Die onderstaande funksie is van die nerddinner se (ASP.NET MVC monster aansoek beskikbaar op CodePlex ) databasis (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

Ek raai dit kan nuttig wees.

Jy kan Pythagoras se stelling te gebruik om die nabyheid van twee pare lat / lon punte bereken.

As jy twee plekke (Alpha en Beta) jy kan hul afstand van mekaar te bereken met:

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

Die gebruik van die opstel van die volgende URL, Ive het die onderstaande navraag. (Let wel Im met behulp van codeIgnitor om die databasis navraag)

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;
    }
}

Moenie die wiel nie weer uit te vind. Dit is 'n ruimtelike navraag. Gebruik MySQL se ingeboude ruimtelike uitbreidings te slaan die Lengte-en breedtegraad koördineer data in die moedertaal MySQL meetkunde tipe kolom . Gebruik dan die afstand funksie om navraag vir punte wat binne 'n bepaalde afstand van mekaar.

Disclaimer:. Hierdie is gebaseer op die lees van die dokumentasie, ek het nie hierdie probeer myself

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top