2010-07-28 13 views
5

से त्रिज्या उपयोगकर्ता के स्थान में स्थान प्राप्त करता है उदाहरण के लिए मेरे डेटाबेस कार घटनाओं में मेरे पास है। इन घटनाओं में अक्षांश और देशांतर है। जीपीएस का उपयोग कर मोबाइल पर, मुझे उपयोगकर्ता के स्थान को उनके निर्देशांक के साथ मिलता है। उपयोगकर्ता त्रिज्या का चयन कर सकता है कि वह जानना चाहता है कि उसके आसपास की घटनाएं हैं या नहीं। तो मान लीजिए कि वह उसके आस-पास 2 मील की घटनाओं को जानना चाहता है।PHP MySQL जीपीएस

तो मैं फ़ोन से उपयोगकर्ता की अक्षांश, देशांतर और त्रिज्या को चुनने वाली वेब सेवा में भेजता हूं। मुझे उपयोगकर्ता के चारों ओर 2 मील की घटनाओं को पाने के लिए एक SQL क्वेरी बनाने की आवश्यकता है।

क्या आपको कोई विचार है कि ऐसा कैसे करें?

उत्तर

2
function distance($lat1,$lon1,$lat2,$lon2,$unit) 
    { 
    $theta=$lon1-$lon2; 
    $dist=sin(deg2rad($lat1))*sin(deg2rad($lat2))+cos(deg2rad($lat1))*cos(deg2rad($lat2))*cos(deg2rad($theta)); 
    $dist=acos($dist); 
    $dist=rad2deg($dist); 
    $miles=$dist*60*1.1515; 
    $unit=strtoupper($unit); 
    if ($unit=="K") 
    { 
    return ($miles*1.609344); 
    } 
    else if ($unit=="N") 
    { 
    return ($miles*0.8684); 
    } 
    else 
    { 
    return $miles; 
    } 
    } // end function 

$x_lat=center_of_serach; 
$x_lon=center_of_serach; 
$_distance=some_distance_in_miles; 
$query1 = "SELECT * FROM `location_table` WHERE somefield=somefilter"; 
$result=mysql_db_query($db_conn, $query1); 
$max_rows=mysql_num_rows($result); 
if ($max_rows>0) 
    { 
while ($data1=mysql_fetch_assoc($result)) 
    { 
    if (distance($x_lat,$x_lon,$data1['lat'],$data1['lng'],'m')<$_distance) 
    { 
    //do stuff 
    } 
    } 

इसका तेजी से सभी डेटा लाने और एक समारोह के माध्यम से चलाने के लिए, के बजाय एक क्वेरी का उपयोग करता है, तो अपने डेटाबेस बहुत बड़ा नहीं है।

यह किलोस और समुद्री मील के लिए भी काम करता है। ;)

+0

एलओएल मैंने अभी आपके लिंक को देखा है .. और हाँ, यह काम करता है। ;) –

0

दो अक्षांश/लोन निर्देशांक के बीच की दूरी की गणना करने के लिए एक सूत्र है। हालांकि सावधान रहें - यह कम्प्यूटेशनल रूप से महंगा है, इसलिए यदि आपके पास बहुत सी घटनाएं हैं, तो आप इसके बारे में स्मार्ट बनना चाहेंगे। सबसे पहले, read about the maths involved

PHP कोड के लिए, एक त्वरित Google this link चालू हुआ, जो ऐसा लगता है कि यह संभवतः काम करता है। उन बिंदुओं कि सीमा के भीतर हो सकता है (उम्मीद एक छोटा सा सेट), और उन है कि आप पूरी तरह से छूट कर सकते हैं:

अब, आप शायद दो सेट में अपने घटना अंक विभाजित करने के लिए कुछ और अधिक कुशल विधि का उपयोग करना चाहते हैं। कुछ दर्जन से अधिक घटना निर्देशांक की जांच करना एक प्रदर्शन मुद्दा होने की संभावना है।

मेरे पास इसमें कोई विशेष अंतर्दृष्टि नहीं है, लेकिन अगर कोई और चालाक के साथ कोई और नहीं आता है, तो मैं बाद में कुछ समय के साथ आने की कोशिश करूंगा।

+0

मैं भी इसकी अनुशंसा करता हूं। मैं डेटा सेट पर दो पास करने पर विचार करता हूं। पहला पास सिर्फ यह जांच करेगा कि क्या घटना की रेखांश स्थान रेखांश के एक्स मील के भीतर है और यदि घटना अक्षांश स्थान अक्षांश के X मील के भीतर है। यह एक बहुत ही सरल क्वेरी है जो काम करने के लिए एक छोटा डेटा सेट वापस कर देगी। इस छोटे डेटा सेट के साथ, उपयोगकर्ता के स्थान पर घटनाओं की रैखिक दूरी निर्धारित करने के लिए कुछ ट्रिगर करना प्रारंभ करें, जिसके लिए अधिक जटिल गणित की आवश्यकता होती है लेकिन आप कम से कम एक छोटे डेटा सेट के साथ काम कर रहे हैं। –

+0

@Jakobud आप उसी फ़िल्टर में उस फ़िल्टर को चला सकते हैं: 'WHERE lat <=' "। $ _ दूरी।" 'और lng <=' "। $ _ दूरी।" ''; ' –

+0

हाँ, ऐसा कुछ। कल्पना करने के लिए जैकोबुड की विधि, आप पहली बार जांच कर रहे हैं कि कोई उम्मीदवार बिंदु केंद्र में उपयोगकर्ता के निर्देशांक के साथ 4-मील वर्ग (16 वर्ग मील) क्षेत्र में है। यदि ऐसा है, तो आप यह समझने के लिए अधिक महंगा गणना करते हैं कि यह क्या है उस वर्ग के भीतर वर्णित सर्कल [http://en.wikipedia.org/wiki/Inscribed_circle] – timdev

0
SELECT 3963 * ACOS(
    SIN(RADIANS($pointAlat)) * SIN(RADIANS($pointAlat)) + COS(RADIANS($pointAlat)) * COS(RADIANS($pointBlat)) * COS(RADIANS($pointAlong) - RADIANS($pointBlong))) 
AS 
distance; 

इसके अलावा, आप एक अच्छा पढ़ा/इस पर ट्यूटोरियल के लिए देख रहे हैं .. यहाँ http://www.phpfreaks.com/forums/index.php/topic,208965.0.html

+0

उपयोगी नहीं है, क्योंकि आप WHERE खंड में उपनाम का उपयोग नहीं कर सकते हैं - जो उसे दो बार पारस्परिक कार्यों के समूह की गणना करने के लिए मजबूर करेगा। ओह। एक संभावित विशाल डेटासेट पर। डबल ओच – NullUserException

3

दूरी गिना जा रहा है की जाँच करें के रूप में अन्य लोगों ने कहा, बहुत computationally महंगा है। विशाल डेटासेट लौटाना भी एक बहुत अच्छा विचार नहीं है - खासकर PHP पर विचार करना प्रदर्शन में इतना अच्छा नहीं है।

मैं एक ह्यूरिस्टिक का उपयोग करूंगा, जैसे साधारण जोड़ और घटाव के साथ दूरी को अनुमानित करना।

1 मिनट = 1.86 किलोमीटर = 1.15 मील

बस उस सीमा (प्रभावी रूप से एक वर्ग है, बल्कि वृत के अलावा) के भीतर घटनाओं से डाटाबेस खोज, और उसके बाद आप उन पर काम कर सकते PHP के साथ।


संपादित: यहाँ एक विकल्प है, एक सन्निकटन कम रास्ता computationally महंगा है कि:

लगभग दूरी मील में: मील में

बेहतर अनुमानित दूरी:

sqrt(x * x + y * y) 

where x = 69.1 * (lat2 - lat1) 
and y = 53.0 * (lon2 - lon1) 

आप कोज्या गणित समारोह जोड़कर इस अनुमानित दूरी गणना की सटीकता में सुधार कर सकते हैं :

sqrt(x * x + y * y) 

where x = 69.1 * (lat2 - lat1) 
and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3) 

स्रोत: http://www.meridianworlddata.com/Distance-Calculation.asp


EDIT 2: मैंने यादृच्छिक रूप से जेनरेट किए गए डेटासेट के साथ परीक्षणों का एक गुच्छा भाग लिया।

  • 3 एल्गोरिदम के लिए सटीकता में अंतर विशेष रूप से कम दूरी
  • धीमी एल्गोरिथ्म (ट्रिग कार्यों के पूरे समूह के साथ एक) के अलावा अन्य दो धीमी 4x है, कम से कम है।

निश्चित रूप से इसके लायक नहीं है। बस एक अनुमान के साथ जाओ।

कोड यहाँ है: http://pastebin.org/424186

+0

एक और अच्छा ह्युरिस्टिक।सबसे छोटी संभव दूरी का उपयोग करें जो एक मिनट (या इसके प्रासंगिक उपखंड) हो सकता है, और उस मील का उपयोग किसी भी उम्मीदवार बिंदु को बाहर करने के लिए करें जो स्पष्ट रूप से दो मील दूर से अधिक है। बेशक, आप इसके बारे में बेहतर हो सकते हैं और उपयोगकर्ता की स्थिति के आधार पर विभिन्न अनुमानों का उपयोग कर सकते हैं। – timdev

0

मैं एक त्वरित खोज किया था और this blog post जो एक अच्छा विवरण और SQL किसी दिए गए त्रिज्या में रिकॉर्ड का चयन करने देता कर दिया।

टिप्पणियों में, वह सुझाव देते हैं "बड़े डेटासेट पर गति के लिए आप मूल रूप से मूल बिंदु के चारों ओर एक वर्ग ब्लॉक को पकड़ना चाहते हैं या फिर मूल के लिए लेट/लॉन दोनों से और फिर उपरोक्त का उपयोग कर बीच से काम करने के लिए एक उप-चयन "जो मुझे जाने के रास्ते की तरह लगता है।

+0

लिंक टूटा हुआ है .. – Zeus

+0

लिंक किए गए पृष्ठ को [web.archive.org] पर संग्रहीत किया गया है (https://web.archive.org/web/20121126042747/http://blog.peoplesdns.com/archives/24) – showdev