Author Topic: Point in Polygon function  (Read 3748 times)

0 Members and 1 Guest are viewing this topic.

Offline AndyA

  • Newbie
  • Posts: 73
    • View Profile
Point in Polygon function
« on: December 02, 2019, 01:23:30 am »
Here's a nice and fast 'Point in Polygon' function.

The demo code fills a randomly generated polygon and tests each point inside of the bounding box of the polygon. Not very efficient, but demonstrates the speed of testing lots of points using this function.

I've used this function for two types of 'games', a jigsaw puzzle game in JustBasic, and in an SDL Basic hidden object game by Johnno56.

The Just Basic jigsaw puzzle DL's are still available at http://jbfilesarchive.com/phpBB3/viewtopic.php?f=4&t=2123

Of course you'll need to DL and install JustBasic to run the jigsaw puzzles. (Windows only! Sorry linux and Mac users. Though should work fine with Wine)

For the SDL Basic hidden object game, maybe Johnno56 can help me out with a link to the game and a good link for the SDL Basic install.

Another use that comes to mind is one that Qwerky/Richard Notely has already made for QB64. A shooting gallery game.

And a mirror object game.



Code: QB64: [Select]
  1. 'http://alienryderflex.com/polygon/
  2. 'QB64 version by Andy Amaya
  3.  
  4. _TITLE "Point in Polygon Function (screen 12)"
  5.  
  6.  
  7. COLOR 15, 1
  8.  
  9. WHILE again% = 0
  10.  
  11.     CLS
  12.     LINE (0, 0)-(639, 479), 1, BF
  13.     pip& = 0
  14.     minX% = 9999
  15.     maxX% = 0
  16.     minY% = 9999
  17.     maxY% = 0
  18.     numVerts% = rand(3, 4)
  19.     FOR i% = 0 TO numVerts% - 1
  20.         xp(i%) = rand(100, 540)
  21.         yp(i%) = rand(80, 440)
  22.         minX% = min(minX%, xp(i%))
  23.         maxX% = max(maxX%, xp(i%))
  24.         minY% = min(minY%, yp(i%))
  25.         maxY% = max(maxY%, yp(i%))
  26.     NEXT
  27.     COLOR 14, 1
  28.     PRINT "Number of vertices: "; numVerts%
  29.  
  30.     st = TIMER(.001)
  31.     FOR yy# = minY% TO maxY%
  32.         FOR xx# = minX% TO maxX%
  33.             test% = pointInPoly(xx#, yy#, numVerts%)
  34.             IF test% = 1 THEN
  35.                 PSET (xx#, yy#)
  36.                 pip& = pip& + 1
  37.             END IF
  38.         NEXT
  39.     NEXT
  40.     'drawPoly numVerts%, 5
  41.     et = TIMER(.001) - st
  42.  
  43.     COLOR 14, 1
  44.     PRINT "Number of points in polygon: "; pip&
  45.     total& = maxX% * maxY%
  46.     PRINT "Total number of points tested: "; total&
  47.     PRINT "Elapsed time: "; USING "###"; (et * 1000);
  48.     PRINT " milliseconds"
  49.  
  50.     SLEEP
  51.     a$ = INKEY$
  52.     IF a$ = " " THEN
  53.         again% = 0
  54.     ELSE
  55.         'a$ = ""
  56.         again% = 1
  57.     END IF
  58.  
  59.  
  60. FUNCTION pointInPoly% (x AS DOUBLE, y AS DOUBLE, verts AS INTEGER)
  61.     DIM i AS INTEGER
  62.     DIM j AS INTEGER
  63.     DIM c AS INTEGER
  64.     DIM v1 AS DOUBLE
  65.     DIM v2 AS DOUBLE
  66.     DIM v3 AS DOUBLE
  67.     DIM v4 AS DOUBLE
  68.     DIM v5 AS DOUBLE
  69.     DIM v6 AS DOUBLE
  70.     DIM v7 AS DOUBLE
  71.     c = 0
  72.     FOR i = 0 TO verts - 1
  73.         j = (i + 1) MOD verts
  74.         v1 = (yp(i) <= y)
  75.         v2 = (y < yp(j))
  76.         v3 = (yp(j) <= y)
  77.         v4 = (y < yp(i))
  78.         v5 = (xp(j) - xp(i)) * (y - yp(i))
  79.         v6 = (yp(j) - yp(i))
  80.         IF v6 = 0.0 THEN v6 = 0.000001
  81.         v7 = xp(i%)
  82.         IF (((v1 AND v2) OR (v3 AND v4)) AND (x < v5 / v6 + v7)) THEN c = 1 - c
  83.     NEXT
  84.     pointInPoly = c
  85.  
  86. SUB drawPoly (verts AS INTEGER, colr AS INTEGER)
  87.     j% = verts - 1
  88.     FOR i% = 0 TO verts - 1
  89.         LINE (xp(j%), yp(j%))-(xp(i%), yp(i%)), colr%
  90.         j% = i%
  91.     NEXT
  92.  
  93. FUNCTION rand% (low%, high%)
  94.     rand = INT(RND * (high% - low% + 1)) + low%
  95.  
  96. FUNCTION min% (flt1 AS INTEGER, flt2 AS INTEGER)
  97.     IF flt1 < flt2 THEN min = flt1 ELSE min = flt2
  98.  
  99. FUNCTION max% (flt1 AS INTEGER, flt2 AS INTEGER)
  100.     IF flt2 > flt1 THEN max = flt2 ELSE max = flt1
  101.  

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: Point in Polygon function
« Reply #1 on: December 02, 2019, 01:47:44 am »
Hi Andy,
see you already made your 2nd polygon function based on http://alienryderflex.com/. Before you go for the next one you should have a look on my DRF-Polygons library, which have some those functions ready since years. However, if it's for educational purpose, then just go ahead with your own implementations.

Just in case you wanna save yourself some work, my DRF-Polygons library is part of the QB64-Library.7z archive available in the Bonus section of the download page mentioned below in my signature. Sample programs and a nice HTML-Documentation included.

My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline AndyA

  • Newbie
  • Posts: 73
    • View Profile
Re: Point in Polygon function
« Reply #2 on: December 02, 2019, 02:02:10 am »
Hi RhoSigma,

I've been using those functions since 2011. Mostly in BlitzPlus basic and JustBasic for a jigsaw puzzle game. Also used those in SDL Basic later on.

Will look into your QB64 LIB, sounds interesting.

Cheers :)


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Point in Polygon function
« Reply #3 on: December 02, 2019, 10:27:35 am »
Hi Andy,

Seems like we are close to painting enclosed (or framed by screen) areas, an exercise we recently experimented with in the Paint Image thread. I wonder how this code compares?

Andy do you know about working images in separate destination and using as needed with _PUTIMAGE or _MAPTRIANGLE, setup a drawing area and handle& with _NEWIMAGE. Also in QB64 you can pass arrays and arrays of TYPE like points (unlike JB and SDL (actually don't remember if SDL could or couldn't)).

Offline AndyA

  • Newbie
  • Posts: 73
    • View Profile
Re: Point in Polygon function
« Reply #4 on: December 04, 2019, 11:10:40 pm »
Quote
Seems like we are close to painting enclosed (or framed by screen) areas, an exercise we recently experimented with in the Paint Image thread. I wonder how this code compares?

I would use the scan line polygon fill to accomplish filling an area when ever possible https://www.qb64.org/forum/index.php?topic=1946.0. For simple polygon shapes, polyFill is the way to go. What I mean by simple is that the number of polygon vertices should be below a threshold of 100 vertices. There is no practical limit to the number of vertices that can be processed by this algo, but the monotonous effort of converting all of the vertices of let's say of a 'perfect' maze image with an entrance and an exit to x/y coordinates would be a nightmare. You could of course use a polygon editor to plot all of those vertices to x/y coords, but it is still very tedious. (Link for JB Polygon Editor http://jbfilesarchive.com/phpBB3/download/file.php?id=1614 )

With the Scan Line Filled Polygon link above, the 62 vertices jigsaw piece shaped polygon is filled within 2ms - 3ms on my laptop. Is that fast or slow when compared to yours and Steve's method?

Quote
Andy do you know about working images in separate destination and using as needed with _PUTIMAGE or _MAPTRIANGLE, setup a drawing area and handle& with _NEWIMAGE.

I know conceptually how to do all of those things in QB64 but still am figuring out all the syntactic nuances. In BlitzPlus basic I'd use 'imagehandle% - CreateImage(width, height) just like 'imagehandle& = _NewImage(width, height, 32), easy peasy.

It's the _Source, _Dest, _PutImage while easy enough to understand the concepts, the syntax is a bit of a drain on my nerves, not that there's anything wrong with the commands, just saying...