คำนำ
ด้วยการพัฒนาอย่างกว้างขวางของอินเทอร์เน็ตบนมือถือในปัจจุบันการพัฒนาแอพได้กลายเป็นตัวเลือกแรกสำหรับหลาย ๆ บริษัท ในการเข้าสู่อินเทอร์เน็ตบนมือถือ ผู้เขียนได้พัฒนาแอพจำนวนมากและพบว่าแอพจำนวนมากมีฟังก์ชั่นดังกล่าวนั่นคือเพื่อให้ได้ผู้คนใกล้เคียง จะรับคนใกล้เคียงได้อย่างไร? ในความเป็นจริงมันง่ายมาก มันคือการบันทึกข้อมูลพิกัดของผู้ใช้ (ละติจูดและลองจิจูด) ลงในฐานข้อมูลเสมอจากนั้นค้นหาผู้ใช้ทั้งหมดในฐานข้อมูลและตำแหน่งพิกัดปัจจุบันภายในช่วงที่กำหนดตามพิกัดของผู้ใช้ปัจจุบัน
ในความเป็นจริงสำหรับระยะห่างระหว่างสองวิชาที่ตำแหน่งทางภูมิศาสตร์ไม่เปลี่ยนแปลงมันจะเป็นการดีที่สุดที่จะคงที่ผลลัพธ์โดยตรง นั่นคือเขียนมันโดยตรงในการกำหนดค่า
ตัวอย่างเช่นค้นหาสถานีรถไฟใต้ดินใกล้บ้านของคุณ
ในกรณีนี้โดยทั่วไปการพูดเรื่องของ "บ้าน" จะไม่ "วิ่งไปรอบ ๆ " ได้อย่างง่ายดาย มันไม่สมเหตุสมผลที่จะคำนวณระยะทางทุกครั้ง เป็นการดีที่สุดที่จะคงอยู่ระยะทางและสอบถามโดยตรง
อีกกรณี:
รับสถานีรถไฟใต้ดินใกล้กับตำแหน่งของผู้ใช้แอป
ในกรณีนี้ที่ตั้งทางภูมิศาสตร์ของผู้ใช้จะเปลี่ยนไป ดังนั้นระยะทางที่แท้จริงจะต้องคำนวณแบบเรียลไทม์ทุกครั้ง
แนวคิดการใช้งาน
รักษาโลกเป็นทรงกลมมาตรฐานและใช้สูตรระยะห่างทรงกลมเพื่อคำนวณความยาวส่วนโค้งของวงกลมขนาดใหญ่ระหว่างสองจุดบนพื้นผิวทรงกลม
ระยะทรงกลม
สาธารณะคงที่ double getDistance2 (double long1, double lat1, double long2, double lat2) {lat1 = rad (lat1); lat2 = rad (lat2); double a = lat1 - lat2; double b = rad (long1 - long2); double sa2 = math.sin (a / 2.0); double sb2 = math.sin (b / 2.0); return 2 * earth_mean_radius_km * math.asin (math.sqrt (sa2 * sa2 + math.cos (lat1) * math.cos (lat2) * sb2 * sb2));}เพิ่งรู้ละติจูดและลองจิจูดระหว่างสองจุด
แน่นอนการคำนวณนี้จะต้องวางไว้ในฐานข้อมูลแล้วจัดเรียงกลับตามระยะทาง เพียงแค่นำสูตรข้างต้นเข้าสู่ SQL
ตัวอย่างของสถานีรถไฟใต้ดินใกล้เคียง
ตารางตัวอย่างสำหรับการสร้างสถานีรถไฟใต้ดิน
สร้างสถานีตาราง (ID int auto_increment คีย์หลักชื่อ varchar (20) ความคิดเห็น null 'ชื่อสถานี MRT', lng double null ความคิดเห็น 'ลองจิจูด', lat double double ความคิดเห็น 'Dimension');
ตัวอย่าง SQL
ตั้งค่า @TargetLat = 31.175702; set @targetlng = 121.519095; Select S.Id, S.Name, S.lng, S.lat, Round (6378.138 * 2 * ASIN (SQRT (POW (บาป ((@TargetLat * PI () / 180 - S.LAT @targetLat * pi () / 180) * cos (s.lat * pi () / 180) * pow (sin ((@targetlng * pi () / 180 - s.lng * pi () / 180) / 2), 2)) * 1000)
ในหมู่พวกเขา TargetLat และ Targetlng เป็นที่ตั้งทางภูมิศาสตร์ของผู้ใช้
สิ่งนี้สามารถบรรลุเป้าหมายได้อย่างแน่นอน อย่างไรก็ตามนี่คือการคำนวณระยะห่างระหว่างข้อมูลทั้งหมดและผู้ใช้ก่อนแล้วจัดเรียง
เมื่อจำนวนสถานีรถไฟใต้ดินมีขนาดใหญ่เกินไปการดำเนินการนี้จะสง่างามน้อยลง ไม่เพียง แต่จะไม่สง่างามพอ แต่ยังมีประสิทธิภาพมาก
การเพิ่มประสิทธิภาพ
ในความเป็นจริงข้อมูลจำนวนมากสามารถกรองออกก่อนคำนวณระยะทาง
ไม่จำเป็นต้องคำนวณระยะห่างระหว่างสถานีรถไฟใต้ดินของสหรัฐอเมริกาเมื่อคำนวณระยะห่างระหว่างสถานีรถไฟใต้ดินเซี่ยงไฮ้
สิ่งนี้สามารถกรองข้อมูลที่ไม่ต้องการก่อนในแอปพลิเคชันส่วนใหญ่
ตัวอย่างเช่นเมื่อข้อมูลแยกแยะเมืองคุณสามารถเปลี่ยน SQL เป็นสิ่งต่อไปนี้:
SET @TargetLat = 31.175702; set @targetlng = 121.519095; set @cityid = 605; Select S.ID, S.Name, S.lng, S.lat, Round (6378.138 * 2 * ASIN 2) + cos (@targetlat * pi () / 180) * cos (s.lat * pi () / 180) * pow (sin ((@targetlng * pi () / 180 - s.lng * pi () / 180) / 2), 2)) * 1000) 20;
การปรับปรุงข้างต้นคือการลบข้อมูลส่วนใหญ่ที่จะคำนวณก่อนคำนวณ เมื่อมองหาสถานีรถไฟใต้ดิน Changsha ไม่จำเป็นต้องค้นหาในเซี่ยงไฮ้ก่อน
แน่นอนว่าสถานการณ์นี้ค่อนข้างพิเศษเพราะคุณสามารถรู้จักเมืองที่ผู้ใช้อยู่ล่วงหน้า
การปรับปรุงอื่นคือ:
ด้วยตำแหน่งของผู้ใช้เป็นศูนย์กลางให้วาดวงกลมที่มีรัศมี R จากนั้นกลับออกช่วงละติจูดและช่วงลองจิจูดของสี่เหลี่ยมจัตุรัสด้านนอกของวงกลม ก่อนที่จะคำนวณระยะทางให้กรองข้อมูลนอกลองจิจูดและลองจิจูดของสี่เหลี่ยมจัตุรัสด้านนอก
ระบุ Radius R ในอุดมคติและกรองข้อมูลที่ไม่สามารถเป็นไปตามเกณฑ์ก่อน
ย้อนกลับช่วงสี่เหลี่ยมจัตุรัสภายนอกแบบ push-out
/*** รับละติจูดและลองจิจูดของจุดยอดทั้งสี่ของจุดที่ละติจูดและลองจิจูดที่ระบุ {@code Radius} quadrilateral ภายนอกของ km (พูดอย่างเคร่งครัดมันควรจะเป็นลูกบาศก์ภายนอก)** @param lng longitude* @param latitude latitude* @param Radius tuple4 <bould> calcboxbydistfrompt (double lng, double lat, radius คู่) {contextialcontext context = spatialContext.geo; สี่เหลี่ยมผืนผ้าสี่เหลี่ยม = context.getDistCalc () // .calcboxByDistFrompt (// context.makepoint (lng, lat), // radius * com.spatial4j.core.distance.distanceutils.km_to_deg, บริบท, null //); ส่งคืน tuple4 ใหม่ <> (rectangle.getMinx (), rectangle.getMaxx (), rectangle.getMiny (), rectangle.getMaxy ());}พิกัด Maven ที่ใช้ที่นี่มีดังนี้:
<Ederency> <sdeperency> com.spatial4j </groupId> <ratifactId> spatial4j </artifactid> <version> 0.5 </version>
ในเวลานี้ SQL สามารถเปลี่ยนเป็นสิ่งนี้ได้:
ตั้งค่า @TargetLat = 31.175702; set @targetlng = 121.519095; Select S.Id, S.Name, S.lng, S.lat, Round (6378.138 * 2 * ASIN (SQRT (POW (บาป ((@TargetLat * PI () / 180 - S.LAT @targetLat * pi () / 180) * cos (s.lat * pi () / 180) * pow (sin ((@targetlng * pi () / 180 - s.lng * pi () / 180) / 2), 2)) * 1000) $ {lat1} และ $ {lat2}) สั่งซื้อตามระยะทาง ASC, S.Idlimit 20;LNG1, LNG2, LAT1, LAT2 ข้างต้นเป็นช่วงของสี่เหลี่ยมจัตุรัสภายนอก
ข้อมูลที่อ้างถึง: http://blog.csdn.net/a364572/article/details/50483568
ซอร์สโค้ดตัวอย่าง
บริการ: https: //github.com/hylexus/bl ...
เริ่มต้นข้อมูล: https: //github.com/hylexus/bl ...
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่าเนื้อหาของบทความนี้จะมีค่าอ้างอิงบางอย่างสำหรับการศึกษาหรือที่ทำงานของทุกคน หากคุณมีคำถามใด ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร ขอบคุณสำหรับการสนับสนุน Wulin.com