Log in

View Full Version : Routine to get surrounding pixels ?


lisztfr9
21st March 2013, 13:49
Hi,

This is a bit Off Topic, but i was wondering if there isn't something smarter to get coordinates of the 8 pixels around a central point, than doing something like :

SUB populate (ox, oy)

a = 1

crew(1).xx = ox + 0: crew(1).yy = oy + a

crew(2).xx = ox - a: crew(2).yy = oy + a
crew(3).xx = ox - a: crew(3).yy = oy + 0
crew(4).xx = ox - a: crew(4).yy = oy - a

crew(5).xx = ox + 0: crew(5).yy = oy - a
crew(6).xx = ox + a: crew(6).yy = oy - a

crew(7).xx = ox + a: crew(7).yy = oy + 0
crew(8).xx = ox + a: crew(8).yy = oy + a

crew(9).xx = ox: crew(9).yy = oy

END SUB

Ok that's my routine in Qb45 but there might be an error and it isn't smart ...

Thanks, L

StainlessS
21st March 2013, 15:57
"might be an error"
Looks OK to me. Whats it for ?

lisztfr9
21st March 2013, 20:15
The idea is just that i wanted to draw some circle or any other shape while only declaring the radius for example, so this 9 pixel crew should orbit around the center. On the back there is the previous drawn pixel, that can be detected with POINT, in order to not select it twice, so all pixels are tested for the distance from center, and the closest to the good distance will be the next center of the 3x3 pix... but imho here just testing, POINT seems to detect pixels where i didn't thought to been drawn. I think i draw it in 0, 100 but it's detected in -1, 100...

This sort of pixel checking could be used to discriminate between left and right, can be used for drawing.


DECLARE SUB distance (b, c, d, e, dd!)
DECLARE SUB populate (ox, oy)

TYPE surround
xx AS INTEGER
yy AS INTEGER
dd AS SINGLE
pt AS INTEGER
END TYPE

DIM SHARED crew(9) AS surround

SCREEN 12
WINDOW (-320, -240)-(320, 240)

'initialize :

oy = 100
ox = 0

CALL distance(0, 0, ox, oy, dd!)
rad = dd!

PSET (ox, oy)
'PSET (ox + 1, oy)

'start :

CALL populate(ox, oy)

' updating the pixel crew :

FOR i = 1 TO 8
d = crew(i).xx: e = crew(i).yy
CALL distance(0, 0, d, e, dd!)
crew(i).dd = ABS(dd! - rad)
crew(i).pt = POINT(crew(i).xx, crew(i).yy)
PRINT crew(i).pt; crew(i).xx; crew(i).yy
' PSET (crew(i).xx, crew(i).yy)
NEXT i



' sorting algo for the closes pixel to rad for pt = 0

a! = 2

FOR i = 1 TO 8
IF a! > crew(i).dd AND crew(i).pt = 0 THEN a! = crew(i).dd
NEXT

' PSETting the pixel, updating

FOR i = 1 TO 8
IF crew(i).dd = a! AND crew(i).pt = 0 THEN
' PSET (crew(i).xx, crew(i).yy), 4
' PRINT crew(i).xx; crew(i).yy
END IF

NEXT




END

SUB distance (b, c, d, e, dd!)

absc! = d - b
ordo! = e - c
dd! = (SQR(absc! ^ 2 + ordo! ^ 2))

END SUB

SUB populate (ox, oy)

a = 1

crew(1).xx = ox + 0: crew(1).yy = oy + a

crew(2).xx = ox - a: crew(2).yy = oy + a
crew(3).xx = ox - a: crew(3).yy = oy + 0
crew(4).xx = ox - a: crew(4).yy = oy - a

crew(5).xx = ox + 0: crew(5).yy = oy - a
crew(6).xx = ox + a: crew(6).yy = oy - a

crew(7).xx = ox + a: crew(7).yy = oy + 0
crew(8).xx = ox + a: crew(8).yy = oy + a

crew(9).xx = ox: crew(9).yy = oy

END SUB

wonkey_monkey
22nd March 2013, 00:03
Let me see if I understand correctly...

This is an algorithm for drawing a circle, centered at 0,0. First you draw the point 0,100, then you search around that point to find the neighbouring point which is closest to radius distance from 0,0, and you draw that point and then use as the next starting point. Have I got that right?

If I've understand it right, while it is an interesting solution, it's a very inefficient way to draw circles. I would guide you towards the observation that if you divide a circle into four using diagonals, and look at the North/South quadrants, you'll see that there is exactly one pixel for each horizontal coordinate. In the East or West quadrants there is exactly one pixel for each vertical coordinate. So, you can loop through those coordinates and calculate the other coordinate - for example, for the North/South quadrants, loop over x, calculate y for each x, and draw the point.

I think i draw it in 0, 100 but it's detected in -1, 100...

Don't you draw 0,100 as the starting point? So it can't be detected as the next point, since it is already drawn...

FOR i = 1 TO 8
IF a! > crew(i).dd AND crew(i).pt = 0 THEN a! = crew(i).dd
NEXT

For a general programming tip, doing something like this is better this way:


a!=2

FOR i = 1 TO 8
IF a! > crew(i).dd AND crew(i).pt = 0 THEN
a! = crew(i).dd
best = i
END IF
NEXT

PSET (crew(best).xx, crew(best).yy)


That will saving having to loop through i all over again to find the point with the lowest dd.

lisztfr9
22nd March 2013, 12:42
Thanks very much for optimizing my code, Mr. davidhorman... !

Meanwhile the QB forum on network 54 solved my issue :

Works when x-axis is odd length
by lawgin (no login)

Not sure why


SCREEN 12
WINDOW (-320, -240)-(321, 240)

xo = 0
yo = 100

PSET (xo, yo)

'scan

PRINT POINT(-1, 100); POINT(0, 100); POINT(1, 100)

In fact, here for testing :

I'm using only 1 single PSET statement, and yet POINT will return 2 pixels with value = 15 :

=========================================

SCREEN 12
WINDOW (-320, -240)-(320, 240)

xo = 0
yo = 100

PSET (xo, yo)

'scan

PRINT POINT(- 1, 100); POINT(0, 100); POINT(+1, 100)

END

Didée
22nd March 2013, 19:56
Dunno if that's of any help. But, remembering the circle formula "x² + y² = r²", grabbing masktools "mt_lutspa", ...

blankclip(width=640,height=480,pixel_type="YV12")
disk = mt_lutspa(relative=false,yexpr="x 300 - 2 ^ y 200 - 2 ^ + 166 2 ^ < 255 0 ?").greyscale()
circle = mt_lutspa(relative=false,yexpr="x 300 - 2 ^ y 200 - 2 ^ + 166 2 ^ - abs 167 < 255 0 ?").greyscale()
stackvertical(disk.addborders(8,8,8,0,color=$004000),circle.addborders(8,8,8,8,color=$004000))


tadaaa ... a circle or disk, of radius 166 pixels, at center coordinates x=300, y=200.

http://thumbnails108.imagebam.com/24493/af5c10244923668.jpg (http://www.imagebam.com/image/af5c10244923668)

lisztfr9
22nd March 2013, 21:45
Very nice Didée :) i will need it soon for testing overlay.

https://fr.wikipedia.org/wiki/Fractale

I made an attempt last year to draw this little triangle fractal, it's named "von Koch", in Qbasic, using recursion. I could draw the Sierpiński fractal that way...

But it didn't work with von Koch, i need to take care of the chirality, so this is it.

lisztfr9
24th March 2013, 11:48
It is working now. And it give the circumference too, about 560 pixels (change z), not exactly 628 as it should be (2 * PI)
It is possible to draw much more than circles with this, spirals, ellipses...


*************************************

DECLARE SUB distance (b, c, d, e, dd!)
DECLARE SUB populate (ox, oy)

TYPE surround
xx AS INTEGER
yy AS INTEGER
dd AS SINGLE
pt AS INTEGER
END TYPE

DIM SHARED crew(9) AS surround

SCREEN 12
WINDOW (-320, -240)-(321, 241)

'initialize :

oy = 100
ox = 0

CALL distance(0, 0, ox, oy, dd!)
rad = dd!

PSET (ox, oy)

' ******************************

'start :

FOR z = 1 TO 560

CALL populate(ox, oy)

' updating the pixel crew :

FOR i = 1 TO 8
d = crew(i).xx: e = crew(i).yy
CALL distance(0, 0, d, e, dd!)
crew(i).dd = ABS(dd! - rad)
crew(i).pt = POINT(crew(i).xx, crew(i).yy)
' PRINT crew(i).pt; crew(i).xx; crew(i).yy
' PSET (crew(i).xx, crew(i).yy)
NEXT i


' sorting algo for the closest pixel to rad for pt = 0

a! = 2

FOR i = 1 TO 8
IF a! > crew(i).dd AND crew(i).pt = 0 THEN
a! = crew(i).dd
best = i
END IF
NEXT

' PSETting the pixel, updating

PSET (crew(best).xx, crew(best).yy)
ox = crew(best).xx
oy = crew(best).yy


NEXT z


END

SUB distance (b, c, d, e, dd!)

absc! = d - b
ordo! = e - c
dd! = (SQR(absc! ^ 2 + ordo! ^ 2))

END SUB

SUB populate (ox, oy)

a = 1

crew(1).xx = ox + 0: crew(1).yy = oy + a

crew(2).xx = ox - a: crew(2).yy = oy + a
crew(3).xx = ox - a: crew(3).yy = oy + 0
crew(4).xx = ox - a: crew(4).yy = oy - a

crew(5).xx = ox + 0: crew(5).yy = oy - a
crew(6).xx = ox + a: crew(6).yy = oy - a

crew(7).xx = ox + a: crew(7).yy = oy + 0
crew(8).xx = ox + a: crew(8).yy = oy + a

crew(9).xx = ox: crew(9).yy = oy

END SUB

wonkey_monkey
25th March 2013, 00:31
Nice to know it's working - but it is still extremely inefficient :)

It is possible to draw much more than circles with this, spirals, ellipses...

Are you sure? In the case of spirals, for example, I can imagine it reversing by accident because, as the radius decreases, the idea that previously drawn pixels will stop it going backwards will not hold:


Correct:
12-
--3

bad:

12-
3--


David