ลองนึกภาพว่าผู้ที่หลงเข้ามาอ่านกำลังทำอะไรซักอย่างโดยมีการดึงตำแหน่งละติจูดและลองจิจูดมาเช็คดูว่าตำแหน่งนั้นๆอยู่ในพื้นที่ที่กำหนดไว้หรือป่าว
ถ้าพื้นที่ที่กำหนดไว้มีลักษณะเป็นวงกลมก็คงจะดีไม่น้อย เพราะว่าเจ้าของบล็อกก็สามารถคำนวณได้จากระยะห่างระหว่างจุดกึ่งกลางของวงกลมได้เลย
หรือถ้าพื้นที่ที่ว่านั้นเป็นสี่เหลี่ยมผืนผ้าหรือจัตุรัส เจ้าของบล็อกก็สามารถใช้คลาส LatLngBound ที่อยู่ใน Google Maps API เพื่อเช็คได้เลย
เพราะคลาส LatLngBound สามารถโยนพิกัดเข้าไปได้ตามใจชอบ แล้วสามารถใช้คำสั่ง contains(...) เพื่อเช็คได้ว่าพิกัดที่เจ้าของบล็อกสงสัยนั้นอยู่ในพื้นที่ของสี่เหลียมนี้หรือป่าว
val location: LatLng = ...
val northEast = LatLng(13.71769622, 100.53270958)
val southWest = LatLng(13.70180905, 100.51446519)
val latLngBounds = LatLngBounds.Builder().apply {
include(northEast)
include(southWest)
}.build()
val isInside: Boolean = latLngBounds.contains(location)
แต่ทว่า...
ถ้าพื้นที่ตรงนี้มีรูปทรงที่ไม่แน่นอนล่ะ?
เพราะชีวิตนั้นไม่ได้เรียบง่ายเสมอไป พื้นที่ก็เช่นกัน บ่อยครั้งที่เจ้าของบล็อกจำเป็นต้องเช็คว่าพิกัดนั้นๆอยู่ในพื้นที่ที่มีหน้าตาแบบนี้...เรื่องมันเศร้าตรงนี้เจ้าของบล็อกหาใน Google Maps API ไม่เจอว่ามีคลาสไหนบ้างในนี้ที่จะช่วยให้เจ้าของบล็อกเช็คได้ว่าพิกัดอยู่ในพื้นที่หน้าตาแบบนี้หรือป่าว
ในกรณีพื้นที่ดังกล่าวเป็นตำบล, อำเภอ, จังหวัด หรือประเทศ ก็สามารถใช้ Geocoder เข้ามาช่วยได้ (ส่งพิกัดไปแล้วได้เป็นที่อยู่ของตำแหน่งนั้นๆออกมา) และข้อเสียอย่างหนึ่งก็คือต้องเชื่อมต่อกับอินเตอร์เน็ตด้วย แต่ถ้าสามารถเช็คผ่านโค้ดเลยล่ะ ขอแค่มีข้อมูลพื้นที่ดังกล่าวก็พอ มันก็ไวกว่าใช่มั้ยล่ะ? สุดท้ายก็เลยต้องเขียนเช็คเอง
ถ้าลองมองดีๆแล้วพื้นที่ดังกล่าวหรือพิกัดที่เจ้าของบล็อกต้องการเช็คนั้นก็ไม่ต่างอะไรกับ 2D Object ที่มองว่าพิกัดคือ Point ส่วนพื้นที่นั้นคือ Polygon ดังนั้นเจ้าของบล็อกจึงสามารถใช้วิธีเดียวกับการเช็คว่า Point อยู่ใน Polygon หรือไม่ จึงไปเจอคำตอบอยู่ที่ How to determine if a point is inside a 2D convex polygon? [StackOverflow]
เมื่อทำการแปลงคำตอบที่ได้ให้อยู่ในรูปที่เหมาะสมกับ Google Maps API และภาษา Kotlin ซะ ก็จะได้ออกมาหน้าตาประมาณนี้
fun isInside(area: List<LatLng>, location: LatLng): Boolean {
var x = 0
var y = area.size - 1
var result = false
while (x < area.size) {
if (area[x].longitude > location.longitude != area[y].longitude > location.longitude &&
location.latitude < (area[y].latitude - area[x].latitude) * (location.longitude - area[x].longitude) / (area[y].longitude - area[x].longitude) + area[x].latitude) {
result = !result
}
y = x++
}
return result
}
โดย area เป็น List<LatLng> ของพื้นที่ที่กำหนด และ location เป็น LatLng ของพิกัดที่ต้องการเช็ค
เพียงเท่านี้เจ้าของบล็อกก็สามารถเช็คได้ง่ายๆแล้วว่าพิกัดดังกล่าวอยู่ในพื้นที่ที่กำหนดหรือป่าว สามารถนำไปใช้กับพื้นที่แบบไหนก็ได้ขอแค่แปลงข้อมูลให้อยู่ในรูป List<LatLng> ก่อนก็พอ และที่สำคัญก็คือไม่จำเป็นต้องใช้อินเตอร์เน็ตแบบ Geocoder ดังนั้นวิธีนี้จะให้ผลลัพธ์ที่ไวกว่าแน่นอน
จบจ้า