fix jitter and mouse cursor accuracy

This commit is contained in:
visionmercer 2026-05-27 11:03:51 +02:00
commit e3054bdb79
3 changed files with 257 additions and 300 deletions

View file

@ -4,7 +4,7 @@ type statetype
bcolor as long bcolor as long
offsetx as long offsetx as long
offsety as long offsety as long
zoom as single zoom as long
brushsize as integer brushsize as integer
startx as long startx as long
starty as long starty as long
@ -55,7 +55,7 @@ for y=0 to _height-16 step 16
next next
_dest 0 _dest 0
state.tool=1 state.tool=1
state.zoom=1.0 state.zoom=1
state.offsetx=70+20 state.offsetx=70+20
state.offsety=20 state.offsety=20
state. brushsize=1 state. brushsize=1
@ -66,8 +66,8 @@ addcommand"bcolor ("+hex$(state.bcolor)+")"
dim lastmx,lastmy dim lastmx,lastmy
dim keyin as string dim keyin as string
dim mouseworldy as integer dim mouseworldy as long
dim mouseworldx as integer dim mouseworldx as long
dim diffx as integer dim diffx as integer
dim diffy as integer dim diffy as integer
@ -76,6 +76,7 @@ dim oldheight as integer
oldwidth=_width oldwidth=_width
oldheight=_height oldheight=_height
do do
' 1. Check for window resizing first
if checkresize(_source)=-1 then if checkresize(_source)=-1 then
diffx=_width-oldwidth diffx=_width-oldwidth
diffy=_height-oldheight diffy=_height-oldheight
@ -85,12 +86,10 @@ do
oldheight=_height oldheight=_height
end if end if
canvas ' 2. Clear the screen BEFORE drawing anything for this frame
if showtoolbox then toolbox line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
if showcolorpicker then colorpicker
if showcommands then commandlist
'Mouse Handling ' 3. Process all inputs and update offsets FIRST
while _mouseinput:mw=mw+_mousewheel:wend while _mouseinput:mw=mw+_mousewheel:wend
mouseclicked=0 mouseclicked=0
rmouseclicked=0 rmouseclicked=0
@ -101,63 +100,43 @@ do
' Panning (Middle Mouse) ' Panning (Middle Mouse)
if _mousebutton(3) then if _mousebutton(3) then
state.offsetx=int(state.offsetx+(_mousex-lastmx)) state.offsetx=state.offsetx+(_mousex-lastmx)
state.offsety=int(state.offsety+(_mousey-lastmy)) state.offsety=state.offsety+(_mousey-lastmy)
end if end if
lastmx=_mousex:lastmy=_mousey lastmx=_mousex:lastmy=_mousey
' Zooming ' Zooming
if mw<>0 then if mw<>0 then
' 1. Capture current world position
mouseworldx=(_mousex-state.offsetx)/state.zoom mouseworldx=(_mousex-state.offsetx)/state.zoom
mouseworldy=(_mousey-state.offsety)/state.zoom mouseworldy=(_mousey-state.offsety)/state.zoom
if mw>0 then state.zoom=state.zoom+1 else state.zoom=state.zoom-1
' 2. Calculate the new zoom level (Snap to whole numbers)
if mw>0 then
state.zoom=state.zoom+1
else
state.zoom=state.zoom-1
end if
' 3. Constrain zoom (Min 1, Max 20)
if state.zoom<1 then state.zoom=1 if state.zoom<1 then state.zoom=1
if state.zoom>20 then state.zoom=20 if state.zoom>20 then state.zoom=20
' 4. Adjust offsets
state.offsetx=_mousex-(mouseworldx*state.zoom) state.offsetx=_mousex-(mouseworldx*state.zoom)
state.offsety=_mousey-(mouseworldy*state.zoom) state.offsety=_mousey-(mouseworldy*state.zoom)
mw=0 mw=0
end if end if
' Keyboarding ' Keyboarding
keyin=inkey$ keyin=inkey$
select case keyin select case keyin
case "+" case "+": state.brushsize=state.brushsize+1: addcommand"brushsize ("+tst(state.brushsize)+")"
state.brushsize=state.brushsize+1 case "-": if state.brushsize>1 then state.brushsize=state.brushsize-1: addcommand"brushsize ("+tst(state.brushsize)+")"
addcommand"brushsize ("+tst(state.brushsize)+")" case "h": state.zoom=1: state.offsetx=(_width/2)-(_width(layers(0).ihandle)/2): state.offsety=(_height/2)-(_height(layers(0).ihandle)/2)
case "-" case "t": showtoolbox=not showtoolbox
if state.brushsize>1 then state.brushsize=state.brushsize-1 case "c": showcolorpicker=not showcolorpicker
addcommand"brushsize ("+tst(state.brushsize)+")" case "l": showcommands=not showcommands
case chr$(19) ' ctrl+s
'TODO: save logic
case chr$(27) ' esc
menu
case "h"
state.zoom=1.0
state.offsetx=(_width/2)-(_width(layers(0).ihandle)/2)
state.offsety=(_height/2)-(_height(layers(0).ihandle)/2)
case "t"
showtoolbox=not showtoolbox
case "c"
showcolorpicker=not showcolorpicker
case "l"
showcommands=not showcommands
end select end select
' 4. Draw everything using the freshly updated math
canvas
if showtoolbox then toolbox
if showcolorpicker then colorpicker
if showcommands then commandlist
' 5. Flip the buffer to the monitor cleanly
_limit 30 _limit 30
_display _display
line (0,0)-(_width-1,_height-1),backgroundcolor1,bf
loop loop
sub commandlist sub commandlist
@ -366,50 +345,30 @@ sub canvas
if showcolorpicker then viewy2=_height-20 else viewy2=_height-1 if showcolorpicker then viewy2=_height-20 else viewy2=_height-1
_dest 0 _dest 0
' 2. Render Layers with Clipping ' 2. Render Layers (Let QB64 handle the viewport clipping natively)
dim srcx1 as long dim i as integer
dim srcy1 as long for i = 0 to ubound(layers)
dim srcx2 as long dim img as long: img = layers(i).ihandle
dim srcy2 as long dim imgw as integer: imgw = _width(img)
dim drawx1 as long dim imgh as integer: imgh = _height(img)
dim drawy1 as long
dim drawx2 as long
dim drawy2 as long
dim i as integer ' Calculate the absolute unclipped destination positions
for i=0 to ubound(layers) drawx1 = state.offsetx
dim img as long:img=layers(i).ihandle drawy1 = state.offsety
dim imgw as integer:imgw=_width(img) drawx2 = state.offsetx + (imgw * state.zoom)
dim imgh as integer:imgh=_height(img) drawy2 = state.offsety + (imgh * state.zoom)
' Current scaled dimensions ' Direct 1:1 mapping of the entire source asset
dim fullscaledw as single:fullscaledw=imgw*state.zoom srcx1 = 0
dim fullscaledh as single:fullscaledh=imgh*state.zoom srcy1 = 0
srcx2 = imgw
srcy2 = imgh
' Calculate visible area in screen coordinates (Overlap of image and viewport) ' Only draw if the asset is within the general view window range
drawx1=state.offsetx if drawx2 > viewx1 and drawx1 < viewx2 and drawy2 > viewy1 and drawy1 < viewy2 then
drawy1=state.offsety _putimage (drawx1, drawy1)-(drawx2, drawy2), img, 0, (srcx1, srcy1)-(srcx2, srcy2)
drawx2=state.offsetx+fullscaledw end if
drawy2=state.offsety+fullscaledh next
' Clip the destination to the Viewport
if drawx1<viewx1 then drawx1=viewx1
if drawy1<viewy1 then drawy1=viewy1
if drawx2>viewx2 then drawx2=viewx2
if drawy2>viewy2 then drawy2=viewy2
' Only draw if the image is actually inside the viewport
if drawx2>drawx1 and drawy2>drawy1 then
' Map screen-clipped coordinates back to the source image coordinates
srcx1=int((drawx1-state.offsetx)/state.zoom)
srcy1=int((drawy1-state.offsety)/state.zoom)
srcx2=int((drawx2-state.offsetx)/state.zoom)
srcy2=int((drawy2-state.offsety)/state.zoom)
' Syntax: _PUTIMAGE (destX1, destY1)-(destX2, destY2), sourceHandle, 0, (srcX1, srcY1)-(srcX2, srcY2)
_putimage (drawx1,drawy1)-(drawx2,drawy2),img,0,(srcx1,srcy1)-(srcx2,srcy2)
end if
next
_dest layers(2).ihandle:cls,0:_dest 0 _dest layers(2).ihandle:cls,0:_dest 0
' 2.5 if the mouse is in ui thats all we need ' 2.5 if the mouse is in ui thats all we need
if showtoolbox then if showtoolbox then
@ -428,11 +387,13 @@ sub canvas
end if end if
end if end if
' 3. Calculate Canvas Coordinates ' 3. Calculate Canvas Coordinates (Center-aligned to the zoom block)
dim canx as long dim canx as long
dim cany as long dim cany as long
canx=int((_mousex-state.offsetx)/state.zoom)
cany=int((_mousey-state.offsety)/state.zoom) ' Add half a zoomed pixel block to align the mouse tip to the block center
canx = int((_mousex - state.offsetx + (state.zoom \ 2)) / state.zoom)
cany = int((_mousey - state.offsety + (state.zoom \ 2)) / state.zoom)
static drawcol static drawcol
if _mousebutton(1) then drawcol=state.fcolor if _mousebutton(1) then drawcol=state.fcolor

View file

@ -1,4 +0,0 @@
canvas (1024,780)
fcolor (FF0D2B45)
bcolor (FFFFECD6)
gradient (85,74,200,137)

View file

@ -1,6 +1,6 @@
$console $console
_screenhide _screenhide
if command$=""then _echo"please specify image file to process":system 1 if command$="" then _echo "🫥 please specify image file to process": system 1
_screenshow _screenshow
type point2d type point2d
@ -24,101 +24,110 @@ dim shared done as _byte
dim shared mouseclicked as _byte dim shared mouseclicked as _byte
dim shared mbd as _byte dim shared mbd as _byte
' Global polygon trace registers ' Global polygon trace registers declared as dynamic
redim shared contour(4999) as point2d redim shared contour(4999) as point2d
dim shared totalpoints as long dim shared totalpoints as long
if _fileexists(command$) then file=command$ if _fileexists(command$) then file = command$
state.orgimg=_loadimage(file,32) state.orgimg = _loadimage(file, 32)
state.handle=_copyimage(state.orgimg) state.handle = _copyimage(state.orgimg)
state.overlay=_newimage(_width(state.orgimg),_height(state.orgimg),32) state.overlay = _newimage(_width(state.orgimg), _height(state.orgimg), 32)
state.levels=10 state.levels = 10
state.threshold=127 state.threshold = 127
updateimage updateimage
screen _newimage(_width(state.orgimg)+200,_height(state.orgimg)+200,32) screen _newimage(_width(state.orgimg) + 200, _height(state.orgimg) + 200, 32)
do until done do until done
cls cls
while _mouseinput:wend while _mouseinput: wend
mouseclicked=not _mousebutton(1) and mbd mouseclicked = not _mousebutton(1) and mbd
mbd=_mousebutton(1) mbd = _mousebutton(1)
if state.change then if state.change then
updateimage updateimage
state.change=0 state.change = 0
end if end if
' Render quantized base image ' Render quantized base image
_putimage (0,0),state.handle _putimage (0, 0), state.handle
' Render the vector transparent overlay shapes on top ' Render the vector transparent overlay shapes on top
_putimage (0,0),state.overlay _putimage (0, 0), state.overlay
' Process interactive trace when clicking inside image viewport ' Process interactive trace when clicking inside image viewport
if mouseclicked then if mouseclicked then
dim clickx as long,clicky as long dim clickx as long, clicky as long
clickx=_mousex clickx = _mousex
clicky=_mousey clicky = _mousey
' Verify click coordinates are safely within the source image canvas bounding box ' Verify click coordinates are safely within the source image canvas bounding box
if clickx>=0 and clickx<_width(state.orgimg) and clicky>=0 and clicky<_height(state.orgimg) then if clickx >= 0 and clickx < _width(state.orgimg) and clicky >= 0 and clicky < _height(state.orgimg) then
dim targetcolor as _unsigned long dim targetcolor as _unsigned long
' Fetch look-up color index from the generated active handle ' Fetch look-up color index from the generated active handle
_source state.handle _source state.handle
targetcolor=point(clickx,clicky) targetcolor = point(clickx, clicky)
_source 0 ' Restore background source monitor pointer _source 0
' SAFEGUARD 1: Do not attempt to parse pure black background/borders ' FIX 1: Clear out the old polygon completely by resetting the transparent overlay canvas
if targetcolor<>_rgb32(0,0,0) and targetcolor<>_rgba32(0,0,0,0) then dim prevdest as long
totalpoints=0 prevdest = _dest
tracecontour targetcolor,clickx,clicky _dest state.overlay
cls ,_rgb32(0,0,0,0) ' Wipes the canvas clean
_dest prevdest
if totalpoints>=3 and totalpoints<(_width(state.orgimg)*_height(state.orgimg)) then ' FIX 2: Reset the dynamic buffer array to its clean baseline size right here in the main module
redim _preserve contour(totalpoints-1) as point2d redim shared contour(4999) as point2d
simplifypolygon totalpoints = 0
if totalpoints>=3 then ' Pass the shared dynamic array directly into the tracing routine
' Build flat 1D coordinate matrix map array (X1, Y1, X2, Y2...) tracecontour contour(), targetcolor, clickx, clicky
dim polypoints(0 to (totalpoints*2)-1) as long
dim i as long
dim clipstr as string
clipstr="fpolygon(" if totalpoints >= 3 and totalpoints < (_width(state.orgimg) * _height(state.orgimg)) then
for i=0 to totalpoints-1 redim _preserve contour(totalpoints - 1) as point2d
polypoints(i*2)=contour(i).x
polypoints(i*2+1)=contour(i).y
clipstr=clipstr+ltrim$(str$(contour(i).x))+","+ltrim$(str$(contour(i).y)) ' Pass the dynamic array directly into the simplification routine
if i<totalpoints-1 then clipstr=clipstr+"," simplifypolygon contour()
next i
clipstr=clipstr+")"
' Send string array payload safely to system clipboard hardware if totalpoints >= 3 then
_clipboard$=clipstr ' Build flat 1D coordinate matrix map array (X1, Y1, X2, Y2...)
redim polypoints(0 to (totalpoints * 2) - 1) as long
dim i as long
dim clipstr as string
' Render transparent vector overlay on overlay handler sheet clipstr = "fpolygon("
dim olddest as long for i = 0 to totalpoints - 1
olddest=_dest polypoints(i * 2) = contour(i).x
_dest state.overlay polypoints(i * 2 + 1) = contour(i).y
' Render with a semi-transparent green color (Alpha = 100) clipstr = clipstr + ltrim$(str$(contour(i).x)) + "," + ltrim$(str$(contour(i).y))
filledpolygon polypoints(),_rgba32(0,255,0,100) if i < totalpoints - 1 then clipstr = clipstr + ","
next i
clipstr = clipstr + ")"
_dest olddest ' Send string array payload safely to system clipboard hardware
end if _clipboard$ = clipstr
' Render transparent vector overlay on overlay handler sheet
dim olddest as long
olddest = _dest
_dest state.overlay
' Render with a semi-transparent green color (Alpha = 100)
filledpolygon polypoints(), _rgba32(0, 255, 0, 100)
_dest olddest
end if end if
end if end if
end if end if
mouseclicked=0
end if end if
ol=state.levels ol = state.levels
ot=state.threshold ot = state.threshold
interface interface
if ol<>state.levels then state.change=-1 if ol <> state.levels then state.change = -1
if ot<>state.threshold then state.change=-1 if ot <> state.threshold then state.change = -1
_limit 30 _limit 30
_display _display
@ -127,54 +136,54 @@ system
'$include: '../include/ui.bm' '$include: '../include/ui.bm'
sub interface sub interface
if button(10,_height-34,60,23,"exit") then done=-1 if button(10, _height - 34, 60, 23, "exit") then done = -1
color highlightcolor color highlightcolor
_printstring (10,_height(state.handle)+10),"levels" _printstring (10, _height(state.handle) + 10), "levels"
state.levels=slider(10,_height(state.handle)+28,100,state.levels*10)/10 state.levels = slider(10, _height(state.handle) + 28, 100, state.levels * 10) / 10
color highlightcolor color highlightcolor
_printstring (118,_height(state.handle)+28),str$(state.levels) _printstring (118, _height(state.handle) + 28), str$(state.levels)
_printstring (10,_height(state.handle)+40),"threshold" _printstring (10, _height(state.handle) + 40), "threshold"
state.threshold=slider(10,_height(state.handle)+58,100,state.threshold/255*100)/100*255 state.threshold = slider(10, _height(state.handle) + 58, 100, state.threshold / 255 * 100) / 100 * 255
color highlightcolor color highlightcolor
_printstring (118,_height(state.handle)+58),str$(state.threshold) _printstring (118, _height(state.handle) + 58), str$(state.threshold)
end sub end sub
sub updateimage sub updateimage
dim odest as long dim odest as long
dim osource as long dim osource as long
odest=_dest odest = _dest
osource=_source osource = _source
_source state.orgimg _source state.orgimg
_dest state.handle _dest state.handle
dim x as long,y as long,l as integer dim x as long, y as long, l as integer
dim numsteps as integer dim numsteps as integer
if state.levels<2 then state.levels=2 if state.levels < 2 then state.levels = 2
numsteps=state.levels-1 numsteps = state.levels - 1
for y=0 to _height-1 for y = 0 to _height - 1
for x=0 to _width-1 for x = 0 to _width - 1
l=luma(point(x,y)) l = luma(point(x, y))
dim adjustedl as single dim adjustedl as single
if state.threshold=0 or state.threshold=255 then if state.threshold = 0 or state.threshold = 255 then
adjustedl=l adjustedl = l
elseif l<=state.threshold then elseif l <= state.threshold then
adjustedl=(l/state.threshold)*127.5 adjustedl = (l / state.threshold) * 127.5
else else
adjustedl=127.5+((l-state.threshold)/(255-state.threshold))*127.5 adjustedl = 127.5 + ((l - state.threshold) / (255 - state.threshold)) * 127.5
end if end if
dim currentstep as integer dim currentstep as integer
currentstep=int((adjustedl/256)*state.levels) currentstep = int((adjustedl / 256) * state.levels)
if currentstep<0 then currentstep=0 if currentstep < 0 then currentstep = 0
if currentstep>numsteps then currentstep=numsteps if currentstep > numsteps then currentstep = numsteps
l=int(currentstep*(255/numsteps)) l = int(currentstep * (255 / numsteps))
pset (x,y),_rgb32(l) pset (x, y), _rgb32(l)
next x next x
next y next y
@ -183,207 +192,198 @@ sub updateimage
end sub end sub
function luma (col as _unsigned long) function luma (col as _unsigned long)
luma=0.21*_red(col)+0.72*_green(col)+0.07*_blue(col) luma = 0.21 * _red(col) + 0.72 * _green(col) + 0.07 * _blue(col)
end function end function
' ========================================================================= sub filledpolygon (points() as long, col as long)
' SUBROUTINE: Solid Filled Scanning Polygon Vector Renderer dim i as integer, j as integer
' ========================================================================= dim x1 as single, y1 as single, x2 as single, y2 as single
sub filledpolygon (points() as long,col as long)
dim i as integer,j as integer
dim x1 as single,y1 as single,x2 as single,y2 as single
dim intersectx as single dim intersectx as single
dim numpoints as integer dim numpoints as integer
numpoints=(ubound(points)+1) \ 2 numpoints = (ubound(points) + 1) \ 2
dim intersections(4999) as single ' SAFEGUARD 2: Larger intersection limit dim intersections(4999) as single
dim numintersections as integer dim numintersections as integer
dim y as long dim y as long
for y=0 to _height-1 for y = 0 to _height - 1
numintersections=0 numintersections = 0
for i=0 to numpoints-1 for i = 0 to numpoints - 1
x1=points(i*2) x1 = points(i * 2)
y1=points(i*2+1) y1 = points(i * 2 + 1)
x2=points(((i+1) mod numpoints)*2) x2 = points(((i + 1) mod numpoints) * 2)
y2=points(((i+1) mod numpoints)*2+1) y2 = points(((i + 1) mod numpoints) * 2 + 1)
if ((y1>y and y2<=y) or (y2>y and y1<=y)) then if ((y1 > y and y2 <= y) or (y2 > y and y1 <= y)) then
if y2-y1<>0 then if y2 - y1 <> 0 then
intersectx=x1+(y-y1)*(x2-x1)/(y2-y1) intersectx = x1 + (y - y1) * (x2 - x1) / (y2 - y1)
' SAFEGUARD 3: Array bounds protection if numintersections <= ubound(intersections) then
if numintersections<=ubound(intersections) then intersections(numintersections) = intersectx
intersections(numintersections)=intersectx numintersections = numintersections + 1
numintersections=numintersections+1
end if end if
end if end if
end if end if
next i next i
for i=0 to numintersections-1 for i = 0 to numintersections - 1
for j=i+1 to numintersections-1 for j = i + 1 to numintersections - 1
if intersections(i)>intersections(j) then if intersections(i) > intersections(j) then
swap intersections(i),intersections(j) swap intersections(i), intersections(j)
end if end if
next j next j
next i next i
for i=0 to numintersections-1 step 2 for i = 0 to numintersections - 1 step 2
if i+1<numintersections then if i + 1 < numintersections then
line (intersections(i),y)-(intersections(i+1),y),col line (intersections(i), y)-(intersections(i + 1), y), col
end if end if
next i next i
next y next y
end sub end sub
' ========================================================================= ' FIX 3: Adjusted signature to cleanly receive the dynamic array as a parameter
' SUBROUTINE: Moore-Neighbor Contour Tracer sub tracecontour (poly() as point2d, targcolor as _unsigned long, mx as long, my as long)
' ========================================================================= dim startx as long, starty as long
sub tracecontour (targcolor as _unsigned long,mx as long,my as long)
dim startx as long,starty as long
dim foundstart as _byte dim foundstart as _byte
dim oldsource as long dim oldsource as long
oldsource=_source oldsource = _source
_source state.handle _source state.handle
dim y& dim y&
for y&=my to 0 step -1 for y& = my to 0 step -1
if point(mx,y&)<>targcolor then if point(mx, y&) <> targcolor then
startx=mx startx = mx
starty=y&+1 starty = y& + 1
foundstart=-1 foundstart = -1
exit for exit for
end if end if
next y& next y&
if not foundstart then if not foundstart then
startx=mx:starty=my startx = mx: starty = my
end if end if
dim dx(0 to 7) as integer dim dx(0 to 7) as integer
dim dy(0 to 7) as integer dim dy(0 to 7) as integer
dx(0)=-1:dx(1)=0:dx(2)=1:dx(3)=1:dx(4)=1:dx(5)=0:dx(6)=-1:dx(7)=-1 dx(0) = -1: dx(1) = 0: dx(2) = 1: dx(3) = 1: dx(4) = 1: dx(5) = 0: dx(6) = -1: dx(7) = -1
dy(0)=-1:dy(1)=-1:dy(2)=-1:dy(3)=0:dy(4)=1:dy(5)=1:dy(6)=1:dy(7)=0 dy(0) = -1: dy(1) = -1: dy(2) = -1: dy(3) = 0: dy(4) = 1: dy(5) = 1: dy(6) = 1: dy(7) = 0
dim currentx as long,currenty as long dim currentx as long, currenty as long
dim backtrackdir as integer,checkdir as integer dim backtrackdir as integer, checkdir as integer
dim startbacktrackdir as integer dim startbacktrackdir as integer
currentx=startx currentx = startx
currenty=starty currenty = starty
totalpoints=0 totalpoints = 0
backtrackdir=1 backtrackdir = 1
startbacktrackdir=1 startbacktrackdir = 1
dim firststep as _byte dim firststep as _byte
firststep=-1 firststep = -1
' Calculate absolute ceiling area parameter to handle escape routes
dim maxallowedpoints as long dim maxallowedpoints as long
maxallowedpoints=_width(state.handle)*_height(state.handle) maxallowedpoints = _width(state.handle) * _height(state.handle)
do do
contour(totalpoints).x=currentx poly(totalpoints).x = currentx
contour(totalpoints).y=currenty poly(totalpoints).y = currenty
totalpoints=totalpoints+1 totalpoints = totalpoints + 1
' SAFEGUARD 4: Break if loop gets stuck spinning in empty coordinates if totalpoints >= maxallowedpoints then
if totalpoints>=maxallowedpoints then totalpoints = 0
totalpoints=0
exit do exit do
end if end if
if totalpoints>=ubound(contour) then if totalpoints >= ubound(poly) then
redim _preserve contour(ubound(contour)+1000) as point2d ' Safely scales the array parameter reference across scopes
redim _preserve poly(ubound(poly) + 1000) as point2d
end if end if
checkdir=(backtrackdir+1) mod 8 checkdir = (backtrackdir + 1) mod 8
dim steps as integer dim steps as integer
steps=0 steps = 0
do while steps<8 do while steps < 8
dim nx as long,ny as long dim nx as long, ny as long
nx=currentx+dx(checkdir) nx = currentx + dx(checkdir)
ny=currenty+dy(checkdir) ny = currenty + dy(checkdir)
if nx>=0 and nx<_width(state.handle) and ny>=0 and ny<_height(state.handle) then if nx >= 0 and nx < _width(state.handle) and ny >= 0 and ny < _height(state.handle) then
if point(nx,ny)=targcolor then if point(nx, ny) = targcolor then
backtrackdir=(checkdir+4) mod 8 backtrackdir = (checkdir + 4) mod 8
currentx=nx currentx = nx
currenty=ny currenty = ny
if firststep then if firststep then
startbacktrackdir=backtrackdir startbacktrackdir = backtrackdir
firststep=0 firststep = 0
end if end if
exit do exit do
end if end if
end if end if
checkdir=(checkdir+1) mod 8 checkdir = (checkdir + 1) mod 8
steps=steps+1 steps = steps + 1
loop loop
if steps=8 then exit do if steps = 8 then exit do
loop until (currentx=startx and currenty=starty and backtrackdir=startbacktrackdir) loop until (currentx = startx and currenty = starty and backtrackdir = startbacktrackdir)
_source oldsource _source oldsource
end sub end sub
' ========================================================================= ' FIX 4: Adjusted signature to cleanly receive the dynamic array as a parameter
' SUBROUTINE: SimplifyPolygon sub simplifypolygon (poly() as point2d)
' =========================================================================
sub simplifypolygon
dim numpoints as long dim numpoints as long
numpoints=totalpoints numpoints = totalpoints
if numpoints>2 then if numpoints > 2 then
if contour(numpoints-1).x=contour(0).x and contour(numpoints-1).y=contour(0).y then if poly(numpoints - 1).x = poly(0).x and poly(numpoints - 1).y = poly(0).y then
numpoints=numpoints-1 numpoints = numpoints - 1
end if end if
end if end if
if numpoints<3 then exit sub if numpoints < 3 then exit sub
dim temp(0 to numpoints-1) as point2d dim temp(0 to numpoints - 1) as point2d
dim keepcount as long dim keepcount as long
temp(0)=contour(0) temp(0) = poly(0)
keepcount=1 keepcount = 1
dim i as long dim i as long
for i=1 to numpoints-1 for i = 1 to numpoints - 1
dim previdx as long:previdx=i-1 dim previdx as long: previdx = i - 1
dim nextidx as long:nextidx=i+1 dim nextidx as long: nextidx = i + 1
if nextidx>numpoints-1 then nextidx=0 if nextidx > numpoints - 1 then nextidx = 0
dim dx1 as single:dx1=contour(i).x-contour(previdx).x dim dx1 as single: dx1 = poly(i).x - poly(previdx).x
dim dy1 as single:dy1=contour(i).y-contour(previdx).y dim dy1 as single: dy1 = poly(i).y - poly(previdx).y
dim dx2 as single:dx2=contour(nextidx).x-contour(i).x dim dx2 as single: dx2 = poly(nextidx).x - poly(i).x
dim dy2 as single:dy2=contour(nextidx).y-contour(i).y dim dy2 as single: dy2 = poly(nextidx).y - poly(i).y
dim crossproduct as single dim crossproduct as single
crossproduct=(dx1*dy2)-(dy1*dx2) crossproduct = (dx1 * dy2) - (dy1 * dx2)
if abs(crossproduct)>0.05 then if abs(crossproduct) > 0.05 then
temp(keepcount)=contour(i) temp(keepcount) = poly(i)
keepcount=keepcount+1 keepcount = keepcount + 1
end if end if
next i next i
if keepcount>=3 then if keepcount >= 3 then
redim contour(keepcount-1) as point2d redim poly(keepcount - 1) as point2d
for i=0 to keepcount-1 for i = 0 to keepcount - 1
contour(i)=temp(i) poly(i) = temp(i)
next i next i
totalpoints=keepcount totalpoints = keepcount
else else
redim contour(numpoints-1) as point2d redim poly(numpoints - 1) as point2d
for i=0 to numpoints-1 for i = 0 to numpoints - 1
contour(i)=temp(i) poly(i) = temp(i)
next i next i
totalpoints=numpoints totalpoints = numpoints
end if end if
end sub end sub