๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ‘จ‍๐Ÿ’ป web.dev/fe

point-in-polygon ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๊ตญ๋‚ด์™ธ ํŒ๋‹จํ•˜๊ธฐ

by HandHand 2024. 1. 30.

 

 

ํŠธ๋ฆฌํ”Œ ์›น ์ผ์ •ํŒ์„ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ํŠน์ • ์œ„๊ฒฝ๋„ ์ขŒํ‘œ ์ง€์ ์ด ๊ตญ๋‚ด์ธ์ง€ ํ•ด์™ธ์ธ์ง€ ํŒ๋‹จํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๊ธ€ ์ง€๋„ API์—์„œ ์ œ๊ณตํ•˜๋Š” reverse geocoding๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ถ”๊ฐ€์ ์ธ API ์‚ฌ์šฉ์„ ์œ„ํ•ด ๋น„์šฉ์„ ์ง€๋ถˆํ•˜๋Š” ๋Œ€์‹  ์ˆ˜ํ•™์ ์œผ๋กœ ๊ฐ€๋ณ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋ดค์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ Point-In-Polygon ์•Œ๊ณ ๋ฆฌ์ฆ˜

๋‹ค๊ฐํ˜•์˜ ๊ต์ ์„ ์ด์šฉํ•ด์„œ ํŒ๋‹จํ•˜๊ธฐ

 

 

์œ„์™€ ๊ฐ™์€ ๋‹ค๊ฐํ˜•์—์„œ ๋ถ‰์€ ์ ์„ A ๋ผ๊ณ  ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋•Œ ์ขŒํ‘œ A ๊ฐ€ ๋‹ค๊ฐํ˜• ์•ˆ์— ์กด์žฌํ•˜๋Š”์ง€ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ•ด๋‹น ์ง€์ ์„ ๊ธฐ์ค€์œผ๋กœ ์ˆ˜ํ‰์„ ์„ ๊ทธ์–ด์„œ ๊ต์ฐจ๋˜๋Š” ๋ณ€์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ธ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/

 

๋ฐฉํ–ฅ์€ ์ƒ๊ด€์—†๊ณ , ํ•œ์ชฝ์œผ๋กœ๋งŒ ๊ทธ์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ๊ต์ฐจ๋˜๋Š” ์ง€์ ์„ node ๋ผ๊ณ  ํ‘œํ˜„ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋งŒ์•ฝ node ์˜ ๊ฐœ์ˆ˜๊ฐ€ ํ™€์ˆ˜๋ผ๋ฉด ๋‹ค๊ฐํ˜•์˜ ๋‚ด๋ถ€์—, ์ง์ˆ˜๋ผ๋ฉด ์™ธ๋ถ€์— ์กด์žฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

node๊ฐ€ ๊ผญ์ง“์ ์— ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ

node ๊ฐ€ ๊ผญ์ง“์ ์— ์žˆ๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

 

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ํ•œ ๋ณ€์— ๋Œ€ํ•ด์„œ ์ˆ˜ํ‰ ์ง์„ ์˜ ๊ต์ฐจ ์กฐ๊ฑด์„ ์„ค์ •ํ•ด ์ฃผ๋ฉด ์ค‘๋ณต๋˜๋Š” node ๋ฅผ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์ฒซ ๋ฒˆ์งธ ๋‹ค๊ฐํ˜•์—์„œ ๋ณ€ a ๊ฐ€ ๋‘ ์ •์  a'1 ๊ณผ a'2 ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค๊ณ  ํ•  ๋•Œ, a'1 <= X < a'2 ์— ํฌํ•จ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๊ต์ ์œผ๋กœ ํŒ๋‹จํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

node์˜ X์ถ• ์ขŒํ‘œ๊ฐ’ ๊ตฌํ•˜๊ธฐ

๊ต์ ์˜ Y ์ถ• ์ขŒํ‘œ๋Š” ๊ธฐ์ค€์ ๊ณผ ๋™์ผํ•œ๋ฐ, ๊ทธ๋Ÿฌ๋ฉด X ์ถ• ์ขŒํ‘œ๊ฐ’์€ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ์š”?

์ด๋•Œ 2์ฐจ์› ์ง์„ ์˜ ๋ฐฉ์ •์‹ ์„ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

https://www.sarthaks.com/223593/derive-the-equation-the-straight-line-passing-through-the-point-x1-y1-and-having-the-slope

 

m (๊ธฐ์šธ๊ธฐ) : (y - y1) / (x - x1)

x = (y - y1) / m + x1

 

์ฝ”๋“œ๋กœ ์˜ฎ๊ฒจ๋ณด์ž

์œ„ ๋‚ด์šฉ๋“ค์„ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const GEO_POLYGON = [
    // ...
]

const SIZE = GEO_POLYGON.length

export function isPointInPolygon(point) {
  const target = getLatLng(point)

  let end = SIZE - 1
  let isInside = false

  for (let start = 0; start < SIZE; start += 1) {
    const { lat: slat, lng: slng } = getLatLng(GEO_POLYGON[start])
    const { lat: elat, lng: elng } = getLatLng(GEO_POLYGON[end])

        // โœ… Y ์ถ• ์ขŒํ‘œ๊ฐ€ (start, end) ๋กœ ์ด๋ฃจ์–ด์ง„ ๋ณ€์— ํฌํ•จ๋˜๋Š”์ง€ ํŒ๋‹จํ•ฉ๋‹ˆ๋‹ค.
    const isYIntersect =
      (slat < target.lat && target.lat <= elat) ||
      (elat < target.lat && target.lat <= slat)

    if (isYIntersect) {
            // โœ… ์ง์„ ์˜ ๋ฐฉ์ •์‹์œผ๋กœ ๊ต์ ์˜ X ์ขŒํ‘œ๋ฅผ ๊ตฌํ•ฉ๋‹ˆ๋‹ค.
      const gradient = (elat - slat) / (elng - slng)
      const x = slng + (target.lat - slat) / gradient

            // โœ… ๊ธฐ์ค€ ์ขŒํ‘œ๋ณด๋‹ค ์™ผ์ชฝ์— ์œ„์น˜ํ•˜๋Š” ๊ต์ ๋งŒ ํฌํ•จ์‹œํ‚ต๋‹ˆ๋‹ค.
      if (x < target.lng) {
        isInside = !isInside
      }
    }

    end = start
  }

  return isInside
}

 

๐Ÿ“Œ ์ฃผ์˜์‚ฌํ•ญ

Point-In-Polygon ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ 2์ฐจ์› ํ‰๋ฉด์„ ๊ฐ€์ •ํ•˜๊ณ  ์ •์˜๋œ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ ์œ„๊ฒฝ๋„ ์ขŒํ‘œ๊ณ„์— ๋Œ€์ž…ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ์ง€๊ตฌ์˜ ๊ณก๋ฅ  ๋•Œ๋ฌธ์— ์˜ค์ฐจ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋งŒ ๋Œ€ํ•œ๋ฏผ๊ตญ์˜ ๊ฒฝ์šฐ ๋Œ€๋ฅ™์˜ ๋ฉด์ ์ด ์ด ์˜ค์ฐจ์˜ ์˜ํ–ฅ์„ ๋ฐ›์„ ๋งŒํผ ํฌ์ง€๋Š” ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•ด์„œ ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ์ฐธ๊ณ ์ž๋ฃŒ

Determining Whether A Point Is Inside A Complex Polygon

๋ฐ˜์‘ํ˜•

๐Ÿ’ฌ ๋Œ“๊ธ€