_TITLE "Scan Line Filled Polygon Test" 'b+ copy Andy Amaya's post 2019-12-05 ' and compare to naive poly fill that b+ would do from Paint Image Brick pattern test
'_TITLE "Brick Pattern Tile, click a spot to spray paint a brick image."
'Andy's notes
'http://alienryderflex.com/polygon_fill/
'public-domain code by Darel Rex Finley, 2007
'QB64 version by Andy Amaya
'_TITLE "Scan Line Filled Polygon"
'B+ notes of mods after adding Brick Pattern Tile code test
' change to 32 bit color graphis screen, so change Andy's colors
CONST xmax
= 800, ymax
= 600
DIM SHARED polyX#
(500), polyY#
(500), nodeX%
(500)
'Initialize maxima and minima then, find the bounding box of the polygon
minX# = 9999
maxX# = -9999
minY# = 9999
maxY# = -9999
scaleX# = 5.2 'X scaling factor
scaleY# = 4.2 'Y scaling factor
offsetX# = 80 'X and Y offsets to place polygon on screen
offsetY# = 70
numVerts% = 62
'Read the polygon vertices into polyX() and poly() arrays
'Use scaling and offsets before placing into the two arrays
FOR i%
= 0 TO numVerts%
- 1 'polygon has 62 sides (zero based counting) polyX#(i%) = zx% * scaleX# + offsetX#
polyY#(i%) = zy% * scaleY# + offsetY#
minX# = min(minX#, polyX#(i%))
maxX# = max(maxX#, polyX#(i%))
minY# = min(minY#, polyY#(i%))
maxY# = max(maxY#, polyY#(i%))
'make brick pattern B+ test for compare
DIM SHARED BC
AS _UNSIGNED LONG 'requires a unique border color for Paint Porder 1 of 16 million + colors you can find one! BC
= _RGB32(119, 17, 2) 'for PAINT fill to BCBC = &HFFFFFFFF
COLOR &HFFFFFFFF, &HFF000088 PAINT (10, 10), &HFF000088 ' <<<<<<<<< for some reason what ever goes first is really fast either Andy's polyFill or PAINT ' <<<<<<<<<<<<<< so I am making this call to PAINT first!
'draw polygon, use Andy's fixed code, missing ), and 32 bit color
drawPoly numVerts%, BC
PAINT (10 * scaleX#
+ offsetX#
, 10 * scaleY#
+ offsetY#
), BC
, BC
PRINT "Polygon with 62 vertices Andy's drawPoly and PAINT filled in: ";
USING "###";
(et
* 1000);
PRINT " milliseconds, press key for Andy's, Scan Line Fill Poly test..."
polyFill numVerts% - 1, minX#, maxX#, minY#, maxY#
PRINT "Polygon with 62 vertices using Andy's polyFill, filled in: ";
USING "###";
(et
* 1000);
PRINT " milliseconds, press key for bplus paintImage fill... "
'draw polygon, use Andy's fixed code, missing ), and 32 bit color
drawPoly numVerts%, BC
paintImage 10 * scaleX# + offsetX#, 10 * scaleY# + offsetY#, BC, 0, brickpat&
PRINT "Polygon with 62 vertices Andy's drawPoly and bplus paintImage filled in: ";
USING "###";
(et
* 1000);
PRINT " milliseconds, press key for NEW polyFillImage, bplus mod of Andy's polyFill... "
' combine Andy's polyFill with my paintImage for polyFillImage
'SUB polyFillImage (numSides%, minX#, maxX#, minY#, maxY#, imageH&)
polyFillImage numVerts% - 1, minX#, maxX#, minY#, maxY#, brickpat&
PRINT "Polygon with 62 vertices NEW polyFillImage filled in: ";
USING "###";
(et
* 1000);
PRINT " milliseconds, beats the old paintImage! End of tests... "
jigsawPiece:
DATA 4,4,7,2,27,0,36,1,35,6,32,13,32,20,36,24,45,27,61,31 DATA 61,26,57,22,57,19,60,18,75,17,89,21,87,43,85,48,88,53,97,48 DATA 99,47,106,48,107,51,109,58,106,76,103,78,99,75,95,73,93,74,92,82 DATA 93,92,95,104,76,108,69,108,67,104,67,99,70,91,70,85,59,80,47,80 DATA 45,81,46,86,48,92,42,93,22,88,20,87,16,73,15,65,14,58,15,55 DATA 20,55,25,56,30,59,30,56,27,47,25,39,22,35,15,31,9,31,3,35
SUB polyFill
(numSides%
, minX#
, maxX#
, minY#
, maxY#
) FOR pixelY%
= minY#
TO maxY#
nodes% = 0
j% = numSides% - 1
fpixY# = pixelY%
'build node list
FOR i%
= 0 TO numSides%
- 1 b1%
= ABS(polyY#
(i%
) < fpixY#
) b2%
= ABS(polyY#
(j%
) >= fpixY#
) b3%
= ABS(polyY#
(j%
) < fpixY#
) b4%
= ABS(polyY#
(i%
) >= fpixY#
) f1# = fpixY# - polyY#(i%)
f2# = polyY#(j%) - polyY#(i%)
f3# = polyX#(j%) - polyX#(i%)
nodeX%
(nodes%
) = INT(f1#
/ f2#
* f3#
+ polyX#
(i%
)) nodes% = nodes% + 1
j% = i%
'sort nodes
i% = 0
IF (nodeX%
(i%
) > nodeX%
(i%
+ 1)) THEN SWAP nodeX%
(i%
), nodeX%
(i%
+ 1) i% = i% + 1
'draw scanlines
IF (nodeX%
(i%
+ 1) > minX#
) THEN IF (nodeX%
(i%
) < minX#
) THEN nodeX%
(i%
) = minX#
IF (nodeX%
(i%
+ 1) > maxX#
) THEN nodeX%
(i%
+ 1) = maxX#
LINE (nodeX%
(i%
), pixelY%
)-(nodeX%
(i%
+ 1), pixelY%
)
SUB polyFillImage
(numSides%
, minX#
, maxX#
, minY#
, maxY#
, imageH&
) s
= _SOURCE ' <<<<<<<<<<<<<< save Source for this routine FOR pixelY%
= minY#
TO maxY#
nodes% = 0
j% = numSides% - 1
fpixY# = pixelY%
'build node list
FOR i%
= 0 TO numSides%
- 1 b1%
= ABS(polyY#
(i%
) < fpixY#
) b2%
= ABS(polyY#
(j%
) >= fpixY#
) b3%
= ABS(polyY#
(j%
) < fpixY#
) b4%
= ABS(polyY#
(i%
) >= fpixY#
) f1# = fpixY# - polyY#(i%)
f2# = polyY#(j%) - polyY#(i%)
f3# = polyX#(j%) - polyX#(i%)
nodeX%
(nodes%
) = INT(f1#
/ f2#
* f3#
+ polyX#
(i%
)) nodes% = nodes% + 1
j% = i%
'sort nodes
i% = 0
IF (nodeX%
(i%
) > nodeX%
(i%
+ 1)) THEN SWAP nodeX%
(i%
), nodeX%
(i%
+ 1) i% = i% + 1
'draw scanlines
IF (nodeX%
(i%
+ 1) > minX#
) THEN IF (nodeX%
(i%
) < minX#
) THEN nodeX%
(i%
) = minX#
IF (nodeX%
(i%
+ 1) > maxX#
) THEN nodeX%
(i%
+ 1) = maxX#
'LINE (nodeX%(i%), pixelY%)-(nodeX%(i% + 1), pixelY%) ' <<<<<<<<<<
FOR ii%
= nodeX%
(i%
) TO nodeX%
(i%
+ 1) ' <<<<<<<<<< ' _SOURCE imageH&
_SOURCE s
'<<<<<<<<<<<<< restore source
IF flt1#
< flt2#
THEN min#
= flt1#
ELSE min#
= flt2#
IF flt1#
> flt2#
THEN max#
= flt1#
ELSE max#
= flt2#
SUB paintImage
(x
, y
, Border~&
, destHandle&
, imageHandle&
) PAINT (x
, y
), BC
, Border~&
'Code to draw a polygon border
j% = verts - 1
'Point in polygon array variables for line drawing
'LINE (xp(j%), yp(j%))-(xp(i%), yp(i%)), colr%
'polyFill array variables for line drawing
LINE (polyX#
(j%
), polyY#
(j%
))-(polyX#
(i%
), polyY#
(i%
)), colr
j% = i%