سؤال

قد يكون هذا واضحًا وقد لا يكون واضحًا، اترك لي تعليقًا إذا كنت خارج القاعدة، أو كنت بحاجة إلى مزيد من المعلومات.ربما يوجد حل بالفعل لما أريده في 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)

أنا أعمل في PHP، مع قاعدة بيانات MySql.

مفتوحة لأية اقتراحات أيضا!:)

هل كانت مفيدة؟

المحلول

وهذا هو استعلام الخلية من شأنها أن تفعل بالضبط ما تريد. نأخذ في الاعتبار أشياء مثل هذه تقريبية بشكل عام، حيث أن الأرض ليست كروية تماما ولا يعني هذا أن تأخذ في الاعتبار الجبال والتلال والوديان، وما إلى ذلك .. ونحن نستخدم هذا الرمز على <لأ href = "HTTP: //www.academichomes. كوم "يختلط =" noreferrer "عنوان =" AcademicHomes.com "> AcademicHomes.com باستخدام PHP و MySQL، فإنها ترجع السجلات داخل ميل $ نصف قطرها $ خطوط العرض والطول $.

$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");

نصائح أخرى

وتحرير: إذا كان لديك، في مكان ما، قائمة بجميع المدن في العالم جنبا إلى جنب مع خطوط الطول بهم. ومنذ فترة طويلة. القيم، يمكنك القيام البحث. في هذه الحالة، انظر أول ربط بلادي أدناه للحصول على صيغة لحساب عرض درجة طولية واحدة عند خط عرض :

وبصراحة، المضاعفات وراء هذه المشكلة هي تلك التي تريد ان تكون أفضل حالا بكثير باستخدام خدمة مثل خرائط Google للحصول على البيانات الخاصة بك. على وجه التحديد، والأرض ليست كرة مثالية، والمسافة بين درجتين يختلف كما كنت أقرب إلى / أبعد عن خط الاستواء.

http://en.wikipedia.org/wiki/Geographic_coordinate_system للحصول على أمثلة ل ما أعنيه، وتحقق من على خرائط جوجل API .

واعتمادا على عدد المدن التي يتم بما في ذلك، يمكنك precompute القائمة. ونحن نفعل ذلك هنا من أجل تطبيق الداخلية التي يكون فيها عدم دقة + 100M هو الكثير من أجل الإعداد لدينا. وهو يعمل عن طريق وجود جدول المفتاح اثنين من LOCATION1، LOCATION2، وبعد المسافة. نحن يمكن بعد ذلك التراجع مواقع العاشر المسافة من LOCATION1 بسرعة كبيرة.

وأيضا منذ calcs يمكن القيام به حاليا، فإنه لا يؤثر على تشغيل النظام. للمستخدمين أيضا الحصول على نتائج أسرع.

وحاولت استخدام رمز أعلاه، وكانت الإجابات من قبل كثيرا عندما كانت المسافة بين نقطة في نطاق 20-30 ميل، وأنا موافق مع بضعة أميال من الخطأ. تحدثت مع أحد الأصدقاء ورسم خرائط الألغام وتوصلنا مع هذا واحد بدلا من ذلك. هو رمز الثعبان، ولكن يمكنك ترجمتها بسهولة جدا. من أجل تجنب تحويل ثابت إلى راديان، أنا redid قاعدة البيانات الخاصة بي، وتحويل نقاط خطوط الطول / العرض للغاز الطبيعي المسال من الدرجات إلى راديان. الجزء الجميل في هذا هو أن الجزء الأكبر من الرياضيات ويتم في الغالب مرة واحدة.

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

ويبدو أن تكون دقيقة جدا عند مسافة وبصرف النظر صغير، وخلال 10 ميلا أو نحو ذلك مع نمو المسافة إلى 200 ميلا، (طبعا في ذلك الوقت، لديك مشاكل مع "زي ما تيجي" مقابل "الطرق المعبدة") .

وهنا هو النموذج 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)

ومذكرة اضافية، هو أنك تستطيع يحصل على الكثير من البيانات الجغرافية المتعلقة الرموز البريدية في GeoNames. غزاله و حتى لديهم بعض واجهات برمجة التطبيقات خدمة ويب يمكنك استخدامها أيضا.

هناك العديد من (الخيارات السيئة)

  • احسب المسافة باستخدام الصيغة الرياضية (عامل X1-X2 وY1-Y2) كمتجهات.

  • قم بإنشاء جدول بحث مسبقًا بجميع المجموعات وحافظ على المسافات.

  • فكر في استخدام ملحق خاص بـ GIS لـ MySQL.هنا مقالة واحدة لقد وجدت حول هذا.

وlessthandot.com في الواقع 3 طرق مختلفة للقيام بذلك. سيكون لديك لتمرير خلال بلوق قليلا ولكنهم هناك. http://blogs.lessthandot.com/

وظيفة أدناه هو من nerddinner الصورة (تطبيق نموذج ASP.NET MVC <لأ href = "HTTP: //nerddinner.codeplex.com/ "يختلط =" نوفولو noreferrer "> متاح في كود بلاكس ) قاعدة البيانات (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

وأنا على التخمين وهذا يمكن أن يكون مفيدا.

ويمكنك استخدام نظرية فيثاغورس "لحساب القرب من اثنين من أزواج من نقطة / خط الطول خطوط الطول.

إذا كان لديك موقعين (ألفا وبيتا) يمكنك حساب المسافة بينهما بعيدا مع:

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

ولا إعادة اختراع العجلة. هذا هو الاستعلام المكاني. استخدام الخلية ل المدمج في التمديدات المكانية للتخزين خطوط العرض وخط الطول تنسيق البيانات في في مواطن الخلية الهندسة نوع العمود . ثم استخدم في بعد وظيفة لالاستعلام عن النقاط التي تقع ضمن مسافة محددة من بعضها البعض.

تنويه: هذا يعتمد على قراءة الوثائق، لم أحاول ذلك بنفسي

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top