เมื่อทำ Google Maps แล้วอยากจะเช็คว่าพิกัดนั้นๆอยู่ในพื้นที่ที่กำหนดไว้หรือป่าว?

เรื่องมีอยู๋ว่าเจ้าของบล็อกต้องการจะเช็คว่า Latitude/Longitude ที่ได้จาก Google Maps เนี่ย มันอยู่ใน Area ที่เจ้าของบล็อกต้องการหรือป่าว ก็เลยเป็นที่มาของบทความนี้นั่นเอง

ลองนึกภาพว่าผู้ที่หลงเข้ามาอ่านกำลังทำอะไรซักอย่างโดยมีการดึงตำแหน่งละติจูดและลองจิจูดมาเช็คดูว่าตำแหน่งนั้นๆอยู่ในพื้นที่ที่กำหนดไว้หรือป่าว

ถ้าพื้นที่ที่กำหนดไว้มีลักษณะเป็นวงกลมก็คงจะดีไม่น้อย เพราะว่าเจ้าของบล็อกก็สามารถคำนวณได้จากระยะห่างระหว่างจุดกึ่งกลางของวงกลมได้เลย

หรือถ้าพื้นที่ที่ว่านั้นเป็นสี่เหลี่ยมผืนผ้าหรือจัตุรัส เจ้าของบล็อกก็สามารถใช้คลาส 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]

How to determine if a point is inside a 2D convex polygon?
I have a convex polygon (typically just a rotated square), and I know all of 4 points. How do I determine if a given point (yellow/green) is inside the polygon? EDIT: For this particular project...

เมื่อทำการแปลงคำตอบที่ได้ให้อยู่ในรูปที่เหมาะสมกับ 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 ดังนั้นวิธีนี้จะให้ผลลัพธ์ที่ไวกว่าแน่นอน

จบจ้า