KnuckleCracker / CW4-bug-tracker

The gathering point for bugs and supporting information, or suggestions about additional features.
Creative Commons Attribution Share Alike 4.0 International
13 stars 1 forks source link

[4RPL Addition] IsPointInPolygon() function #831

Closed zer0ner closed 1 year ago

zer0ner commented 3 years ago

Is your feature request related to a problem? Please describe. Related to #822, determining if a specific X/Z cell position or a generic point is in a polygon does not have a simple 4RPL function available.

Describe the solution you'd like An easy way to pass in a specific X/Z cell position (or a V2()) and a list of X/Z cell positions representing a polygon and get back a boolean value if the specified position is inside the polygon.

Although the inputs will probably be map-related, the input coordinates don't need to be related to the actual map.

Describe alternatives you've considered A pure 4RPL script-level implementation is possible. Just not as convenient/performant as a globally-available function would be.

zer0ner commented 3 years ago

I ended up writing my own 4RPL implementation based on a function from StackOverflow for map 1161 (The Aquarium):

# IsPointInPoly(point polyList)
:IsPointInPoly
    ->ipip_polyList
    ->ipip_point

    false ->ipip_retval
    GetListCount(<-ipip_polyList) 1 - ->ipip_prev
    <-ipip_polyList 0 do
        <-ipip_polyList[I] ->ipip_linept1
        <-ipip_polyList[<-ipip_prev] ->ipip_linept2

        if (<-ipip_linept1.y <-ipip_point.y gt <-ipip_linept2.y <-ipip_point.y gt neq)
            <-ipip_linept2.x <-ipip_linept1.x - <-ipip_point.y <-ipip_linept1.y - * ->ipip_tempval
            <-ipip_tempval <-ipip_linept2.y <-ipip_linept1.y - / ->ipip_tempval
            <-ipip_tempval <-ipip_linept1.x + ->ipip_tempval

            if (<-ipip_point.x <-ipip_tempval lt)
                <-ipip_retval ! ->ipip_retval
            endif
        endif

        I ->ipip_prev
    loop

    <-ipip_retval

This isn't the best nor most performant point in polygon function but it is able to be understood fairly easily. It doesn't work correctly if the polygon has holes and there are a few (literal) edge cases where it will fail as well. But it does work well enough for most concave/convex polygons, which is all I needed for my map.

Karsten75 commented 3 years ago

You can contribute 4RPL code snippets to the wiki where it might be picked up by other 4RPL coders.

I already pointed you to this page and suggested you could start a new section there:

https://knucklecracker.com/wiki/doku.php?id=cw4:4rpl_tools