ฉันจะคำนวณกล่องขอบสำหรับระยะทางและละติจูด / ลองจิจูดที่กำหนดได้อย่างไร


13

ฉันต้องสามารถคำนวณกล่องขอบเขตหรือวงกลมสำหรับละติจูด WGS84 และลองจิจูด WGS84 ที่กำหนดและระยะทางได้ แต่ไม่รู้ว่าจะเริ่มจากตรงไหน!

ระยะทางจากจุดเริ่มต้น Lat / Lon จะเป็น 10Km หรือน้อยกว่า

เป็นไปได้ไหมที่บางคนจะให้คำแนะนำ / ตัวอย่างแก่ฉันเกี่ยวกับวิธีการทำเช่นนี้


สำหรับวงการที่ไม่ครอบคลุมเสาทั้งสองคำตอบที่จะได้รับรายละเอียดที่gis.stackexchange.com/questions/19221/... แต่นี่ไม่ใช่เรื่องเต็มตามที่คำตอบปัจจุบันแนะนำ: คุณสามารถสร้างความซับซ้อนของโปรแกรมได้อย่างรวดเร็วและแม่นยำ หมายเหตุด้วยเช่นกันว่ามีปัญหา "ล้อมรอบ" ในการระบุกล่องขอบเขตเมื่อคุณทำงานใน lat-lon (ปัญหาเกิดขึ้นที่ + -180 องศาเมริเดียน) สำหรับวิธีแก้ปัญหานี้ให้ดูgis.stackexchange.com/questions/17788/...
whuber

คุณต้องการกล่องจริงหรือ 4 คะแนนใกล้จุดที่กำหนดจะเพียงพอหรือไม่ กำหนดจุด p, หาระยะทาง 4 จุด d ที่ทิศทาง NE, SW, SE และ NW จาก p
Kirk Kuykendall

@Kirk - ถ้าคุณมีพิกัดของ 4 จุดแล้วคุณมีกล่อง ...
martinstoeckli

@ Smartinstoeckli ถูกต้องฉันแค่หวังว่าจะทำให้ปัญหาง่ายขึ้นโดยไม่ต้องจินตนาการว่ากล่องที่ฉายบนทรงกลมดูเหมือนอะไร โปรดทราบว่าปัญหานี้อาจเป็นเรื่องทั่วไปที่จะทำให้ชัดเจนว่าด้านข้างของกล่องไม่จำเป็นต้องอยู่ในละติจูด / ลองจิจูดเดียวกัน (กล่องหมุนในคำอื่น ๆ )
Kirk Kuykendall

@ เคิร์ก - เอ่อถ้าคุณต้องการมันแน่นอนคุณก็พูดถูก ฉันคิดว่ากล่องนี้มีประโยชน์สำหรับการค้นหาผู้สมัครที่เป็นไปได้อย่างรวดเร็วเท่านั้น ในการตรวจสอบว่าจุดสองจุดอยู่ในระยะที่กำหนด (วงกลม) หรือไม่คุณสามารถใช้สูตรแฮเวอร์ซีนที่ซับซ้อนกว่านี้ได้
martinstoeckli

คำตอบ:


15

WGS-อะไร? WGS-84? ขึ้นอยู่กับว่าคุณต้องการความแม่นยำเพียงใดคุณอาจต้องทราบข้อมูลเพิ่มเติม - ฉันเดาว่านั่นเป็นสาเหตุที่คุณโหวตไม่ได้แม้ว่าจะไม่มีใครใส่ใจที่จะแสดงความคิดเห็นว่าทำไม

นี่คือสองวิธี:

ไม่ถูกต้อง แต่อาจ 'ดีพอ'

ละติจูดหนึ่งองศามีค่าประมาณ 1,0001.965729 / 90 กิโลเมตร (ระยะทางจากเส้นศูนย์สูตรถึงขั้วโลกหารด้วยเก้าสิบองศา) หรือ 111.113 กิโลเมตรโดยใช้ WGS-84 datum นี่คือการประมาณเนื่องจากรูปร่างของโลกและเนื่องจากระยะทางเปลี่ยนไปเมื่อคุณเข้าใกล้เสา (เหตุผลหนึ่งที่ใช้ละติจูดไม่ใช่ลองจิจูด - ในที่สุดระยะทางหนึ่งองศาของลองจิจูดนั้นเป็นศูนย์!) โลกก็ไม่สมบูรณ์แบบ รูปทรงกลม ทั้งสองสิ่งนี้เป็นเหตุผลที่ใช้วิธีการฉายภาพและข้อมูลที่ซับซ้อนยิ่งขึ้นในคำตอบที่สองของฉัน

10001.965729km = 90 degrees
1km = 90/10001.965729 degrees = 0.0089982311916 degrees
10km = 0.089982311915998 degrees

นี่ใช้องศาทศนิยมไม่ใช่องศา / นาที / วินาที

ดังนั้นขอบเขตของกล่องจะเป็นจุดบวกและลบ 0.08999 องศา หรือคุณสามารถใช้หมายเลขนี้เป็นรัศมีให้คุณมีวงกลมล้อมรอบ

บุคคล GIS ที่อ่านข้อความนี้จะสั่น มันจะถูกต้องส่วนใหญ่ขึ้นอยู่กับว่าคุณอยู่ที่ไหนในโลก สำหรับรัศมี 10km มันควรจะดี

ถูกต้องมากขึ้น แต่รหัสเพิ่มเติม

ใช้ห้องสมุดฉายและระบุข้อมูลของคุณ ฯลฯ ฉันขอแนะนำ Proj4; มันใช้กันอย่างแพร่หลายเพื่อให้ Google ส่งกลับกองของผลการค้นหาสำหรับคำถามเกี่ยวกับเรื่องนี้และมีDelphi ห่อ หากคุณมีปัญหาในการใช้โพสต์คำถามอื่นที่นี่ใน SO - มันเกินขอบเขตสำหรับคำถามนี้ เว็บไซต์ Proj4 มีตัวอย่างการใช้ API พื้นฐานและแม้ว่าสิ่งเหล่านี้จะอยู่ใน C มันควรจะแปลได้ค่อนข้างง่าย ของพวกเขาอ้างอิง APIเป็นสถานที่ที่ดีที่สุดที่จะเริ่มต้นตามด้วยคำถามที่พบบ่อย

ฉันจะใช้ WGS-84 เป็นฐานข้อมูลพื้นฐาน (เป็นตัวแทนของโลก) เว้นแต่คุณจะรู้ว่าคุณต้องการใช้เฉพาะหรือใช้เพื่อสร้างพิกัดของคุณ มันใช้กันทั่วไปและค่อนข้างแม่นยำ

หากตำแหน่งของคุณมาจาก Google Maps (ตัวอย่าง) ให้ระบุการฉายภาพของ Mercator คุณอาจต้องการใช้การฉายภาพอื่นหรือใช้พูดพิกัด UTMแทนละติจูดและลองจิจูดขึ้นอยู่กับแหล่งข้อมูลของคุณและหากคุณต้องการความแม่นยำสูงสำหรับพื้นที่ขนาดเล็ก (UTM มีหลายโซนซึ่งทั้งหมดนี้เปลี่ยนการบิดเบือนเพื่อให้อยู่ในโซนนั้นมันมีความแม่นยำสูงถ้าคุณใช้โซนสำหรับพิกัดด้านนอกการบิดเบือนจะเพิ่มขึ้นอย่างมากเมื่อคุณย้ายออกไปถ้าคุณดูทั้งโลกที่ฉายจาก โซนอาจไม่สามารถจดจำได้ แต่ภายในโซนการแปล UTM จะดีเท่าที่คุณจะได้รับพิกัดโดยทั่วไปจะระบุเป็นเมตรไม่ใช่เป็นองศาดังนั้นมันอาจมีประโยชน์มากกว่าสำหรับคุณเนื่องจากคุณต้องการ 10km รัศมี 10km อยู่ในโซนเดียวได้อย่างง่ายดายคุณเพียงแค่ต้องเลือกโซนที่เหมาะสมตามพิกัดศูนย์กลางของคุณบิตเล่ห์เหลี่ยมเพียงอย่างเดียวคือเมื่อคุณเข้าใกล้ชายแดน: เป็นสถานการณ์ทั่วไปและมันก็ดีที่สอดคล้องกันในวิธีการที่คุณเลือกหนึ่งที่คุณใช้ Proj4 จะให้คุณแปลการฉายเพื่อให้คุณสามารถไปจาก Mercator WGS-84 lat / long ของคุณไปยัง UTM zone n , ตัวอย่างเช่น, หรือไปยังและจากทั้งสองโซน UTM)


2
สำหรับที่ที่เราอาศัยอยู่นักสำรวจได้บอกฉันว่าเขาใช้ 1 องศาประมาณ 108 กม. สำหรับการคำนวณทางจิตของเขา ทางจิตใจ 10 กม. อยู่ที่ประมาณ 0.1 องศา เนื่องจากสิ่งเหล่านี้เป็นการประมาณคร่าวๆที่ดีที่สุดในการรักษาความถูกต้องของตัวเลข 1 หลัก (อย่างน้อย 2 หรือ 3 หลัก) มากกว่า 0.089982311915998 เนื่องจากมีความแม่นยำระดับหนึ่ง
Stephen Quan

1
เป็นการยากที่จะคำนวณองศาที่แม่นยำยิ่งขึ้นโดยคำนึงถึงละติจูด เนื่องจากคอมพิวเตอร์ทำการคำนวณจึงไม่มีอะไรได้มาจากการประมาณ (ดูฟังก์ชั่นแรกในตัวอย่างของฉัน)
martinstoeckli

3

สมมติว่าคุณต้องการสร้างแบบสอบถามในฐานข้อมูลคุณอาจต้องการทำการค้นหาที่รวดเร็ว (ไม่ถูกต้อง) และหลังจากนั้นคำนวณระยะทางสำหรับสถานที่ที่เกิดขึ้นอย่างแน่นอน นั่นคือสถานการณ์ของคุณหรือไม่

ฟังก์ชั่นต่อไปนี้ (ใน PHP, ขอโทษ) จะประมาณความแตกต่างในละติจูดและลองจิจูด ความแตกต่างนี้ขึ้นอยู่กับละติจูดของจุดค้นหาของคุณ ใช้พวกเขา (ด้วยความอดทนเล็กน้อย) เพื่อทำการค้นหาอย่างรวดเร็วในฐานข้อมูล กล่องสามารถคำนวณได้อย่างง่ายดายด้วยละติจูด + -deltaLatitude และลองจิจูด + -deltaLongitude

deltaLatitude[rad] = distance[m] / earthRadius[m]
deltaLongitude[rad] = distance[m] / (cos(latitude[rad]) * $earthRadius[m])

/**
 * Calculates the deltas in latitude and longitude to use, for a db search
 * around a location in the database.
 * @param float $distance Radius to use for the search [m]
 * @param float $latitude Latitude of the location, we need the angle deltas for [deg decimal]
 * @param float $deltaLatitude Calculated delta in latitude [deg]
 * @param float $deltaLongitude Calculated delta in longitude [deg]
 * @param float $earthRadius Mean earth radius in [m]
 */
public static function angleFromSphericDistance($distance, $latitude,
  &$deltaLatitude, &$deltaLongitude, $earthRadius = 6371000)
{
  $lat = deg2rad($latitude);

  $radiusOnLatitude = cos($lat) * $earthRadius;
  $deltaLatitude = $distance / $earthRadius;
  $deltaLongitude = $distance / $radiusOnLatitude;

  $deltaLatitude = rad2deg($deltaLatitude);
  $deltaLongitude = rad2deg($deltaLongitude);
}

ด้วยสูตรแฮเวอรีนคุณสามารถคำนวณระยะทางบนทรงกลม ใช้สำหรับแต่ละสถานที่ที่พบเพื่อให้ได้ระยะทาง "ที่แน่นอน" วิธีนี้คุณสามารถทดสอบได้หากสถานที่ทั้งสองอยู่ภายในรัศมีที่แน่นอน (วงกลมแทนกล่อง)

/**
 * Calculates the great-circle distance between two points, with
 * the Haversine formula.
 * @param float $latitudeFrom Latitude of start point in [deg decimal]
 * @param float $longitudeFrom Longitude of start point in [deg decimal]
 * @param float $latitudeTo Latitude of target point in [deg decimal]
 * @param float $longitudeTo Longitude of target point in [deg decimal]
 * @param float $earthRadius Mean earth radius in [m]
 * @return float Distance between points in [m] (same as earthRadius)
 */
public static function haversineGreatCircleDistance(
  $latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
{
  // convert from degrees to radians
  $latFrom = deg2rad($latitudeFrom);
  $lonFrom = deg2rad($longitudeFrom);
  $latTo = deg2rad($latitudeTo);
  $lonTo = deg2rad($longitudeTo);

  $latDelta = $latTo - $latFrom;
  $lonDelta = $lonTo - $lonFrom;

  $angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
    cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
  return $angle * $earthRadius;
}

3

ในการทดสอบว่า lat / lon อยู่ภายในหรือภายนอกวงกลมที่มีขอบเขตคุณจะต้องคำนวณระยะทางจาก lat / lon อ้างอิงของคุณไปยังจุด lat / lon ที่คุณต้องการทดสอบ เนื่องจากระยะทางของคุณอยู่ที่ 10km หรือน้อยกว่าฉันจะลองใช้ Equirectangular Approximation เพื่อให้ได้ระยะทางมากกว่า Haversine เพราะความเรียบง่าย ในการรับระยะทางเป็นกม.:

x = (lonRef - lon) * cos ( latRef )
y = latRef - lat
distance = EarthRadius * sqrt( x*x + y*y )

หมายเหตุสำคัญ: lat / lon ในสูตรเหล่านี้เป็นเรเดียนไม่ใช่องศา ค่าทั่วไปของ EarthRadius คือ 6371 กม. ซึ่งจะส่งคืนระยะทางเป็นหน่วยกิโลเมตร ตอนนี้เป็นการทดสอบง่ายๆว่าระยะทางของคุณอยู่ในหรือนอกวงกลม ถ้าวงกลมล้อมรอบทำงานฉันจะไปกับมัน

สำหรับสี่เหลี่ยมผืนผ้าที่มีขอบเขตฉันจะสมมติว่าคุณต้องการสี่เหลี่ยมที่กำหนดโดยการขนานกับเส้นศูนย์สูตร ฉันจะคำนวณมุมของกล่องขอบโดยใช้การคำนวณช่วง / แบริ่ง (แบริ่งเป็น 45 องศา, 135 องศา, 225 องศาและ 315 องศา) จากตรงนั้นฉันจะถือว่าคุณไม่ได้อยู่ที่เสาและใช้จุดทดสอบรูปหลายเหลี่ยม


2

ด้านล่างเป็นรหัส T-SQL ที่ฉันใช้สำหรับสร้างกล่องขอบเขตใน SQL-Server 2012 ในกรณีของฉันฉันได้รับค่าทศนิยมสำหรับ Lat, Long ฉันใช้สิ่งนี้เพื่อ จำกัด จำนวนแถวอย่างรวดเร็วก่อนที่ฉันจะใช้STDistanceฟังก์ชันSQL เพื่อตรวจสอบว่าผลลัพธ์นั้นอยู่ในระยะทางที่เฉพาะเจาะจงหรือไม่ ฟังก์ชั่นทางภูมิศาสตร์นั้นมีค่าใช้จ่ายสูงใน SQL Server ดังนั้นด้วยการสร้างกล่องขอบเขตฉันสามารถลดจำนวนครั้งที่ต้องดำเนินการอย่างมาก

DECLARE @Lat DECIMAL(20, 13) = 35.7862
   ,@Long DECIMAL(20, 13) = -80.3095
   ,@Radius DECIMAL(7, 2) = 5
   ,@Distance DECIMAL(10, 2)
   ,@Earth_Radius INT = 6371000;

SET @Distance = @Radius * 1609.344;

DECLARE @NorthLat DECIMAL(20, 13) = @Lat + DEGREES(@distance / @Earth_Radius)
   ,@SouthLat DECIMAL(20, 13) = @Lat - DEGREES(@distance / @Earth_Radius)
   ,@EastLong DECIMAL(20, 13) = @Long + DEGREES(@distance / @Earth_Radius / COS(RADIANS(@Lat)))
   ,@WestLong DECIMAL(20, 13) = @Long - DEGREES(@distance / @Earth_Radius / COS(RADIANS(@Lat)));

SELECT *
    FROM CustomerPosition AS cp
    WHERE (
            cp.Lat >= @SouthLat
            AND cp.Lat <= @NorthLat )
        AND (
              cp.Long >= @WestLong
              AND cp.Long <= @EastLong )
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.