Moore Neighborhood tracing help needed

Monkey Forums/Monkey Programming/Moore Neighborhood tracing help needed

GC-Martijn(Posted 2015) [#1]
I have made an PNG outline tracer a week ago, but that was not good enough for what I want to do with it.

Now I'm trying for more then a week to get the coordinates clockwise and I know how.
But I can't create the correct monkey code for it :(

Its this solution
http://en.wikipedia.org/wiki/Moore_neighborhood

http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/moore.html

What I have
- does check if the next pixel is not alpha 0

What I don't have
- loop needs to stop when its find the first pixel again
- find the whole outline

Thanks very much :)


Strict

Import mojo
Import opengl.gles11

Function Main:Int()
	New MyApp()
	Return 0
End

Class MyApp Extends App
	Field thing:Sprite
		
	Method OnCreate:Int()			
		SetUpdateRate(60)
		thing = New Sprite()
		Return 0
	End
	
	Method OnUpdate:Int()
		thing.Update()
		Return 0
	End
	
	Method OnRender:Int()
		Cls(255,255,255)

		thing.Draw()
		Return 0
	End
End


Class PNGTracer
	Field startX:Int = 93
	Field startY:Int = 0
	Field size:Int[2]
	Field _w:Int
	Field _h:Int
	Field db:DataBuffer
	Field xy:Stack<Point> = New Stack<Point>()
	Field data:Int[]

	Function Get:Int[] (_db:DataBuffer,_w:Int,_h:Int)
		Local data:Int[_w * _h]
		For Local y:Int = 0 Until _h
			For Local x:Int = 0 Until _w
				Local j:Int = _db.PeekInt( ( y * _w +  x) * 4)
				data[y * _w + x] = (j & $ff000000) | ( (j & $00ff0000) Shr 16) | (j & $0000ff00) | ( (j & $000000ff) Shl 16)
			Next
		Next		
		Return data
	End Function

	Method neighbor:Void(_x:Int,_y:Int)

	''	Print _data.Length()
		Print "Start:"+_x+","+_y

		Local check:Bool[8]
		Local calc:Point[8]


		check[0] = (_y-1)*_w+(_x-1)>=0 And (data[(_y-1)*_w+(_x-1)] shr 24) & $FF
		calc[0]	= New Point(_x-1,_y-1)

		check[1] = (_y-1)*_w+_x>=0 And (data[(_y-1)*_w+_x] shr 24) & $FF
		calc[1]	= New Point(_x,_y-1)

		check[2] = (_y-1)*_w+(_x+1)>=0 And (data[(_y-1)*_w+(_x+1)] shr 24) & $FF
		calc[2]	= New Point(_x+1,_y-1)

		check[3] = _y*_w+(_x+1)>=0 And (data[_y*_w+(_x+1)] shr 24) & $FF
		calc[3]	= New Point(_x+1,_y)

		check[4] = (_y+1)*_w+(_x+1)>=0 And (data[(_y+1)*_w+(_x+1)] shr 24) & $FF
		calc[4]	= New Point(_x+1,_y+1)

		check[5] = (_y+1)*_w+_x>=0 And (data[(_y+1)*_w+_x] shr 24) & $FF
		calc[5]	= New Point(_x,_y+1)

		check[6] = (_y+1)*_w+(_x-1)>=0 And (data[(_y+1)*_w+(_x-1)] shr 24) & $FF
		calc[6]	= New Point(_x-1,_y+1)

		check[7] = _y*_w+(_x-1)>=0 And (data[_y*_w+(_x-1)] shr 24) & $FF
		calc[7]	= New Point(_x-1,_y)

		Local index:Int = 0
		For Local hit:Bool = Eachin check
			If hit Then
				' FOUND THE NEXT GOOD PIXEL !

				Print "hit:"+index
				Print "add:"+calc[index].x+","+calc[index].y
				xy.Push(New Point(calc[index].x,calc[index].y))

			''	neighbor(calc[index].x,calc[index].y)
			' uncomment and there is a crash
				Exit
			End
			index+=1
		Next
	End

	Method Trace:Stack<Point>(_img:String)
		db = LoadImageData(_img, size)
		data = Get(db,size[0],size[1])
		_w = size[0] 'helper var
		_h = size[1] 'helper var
		neighbor(startX,startY)
		Return xy
	End

	Function toPolyData:Float[](_data:Stack<Point>)
		Local verts:Float[_data.Length*2]
		Local tmpI:Int = 0

		For Local point:Point = Eachin _data
			verts[tmpI] = point.x
			tmpI=tmpI+1
			verts[tmpI] = point.y
			tmpI=tmpI+1
		Next

		Return verts
	End

End


Class Point
	Field x:Int
	Field y:Int

	Method New(_x:Int,_y:Int)
		x=_x
		y=_y
	End
End



Class Sprite
	Field image:Image
	Field tmp:Image
	Field outline_xy:Stack<Point> = New Stack<Point>()
	Field verts:Float[]

	Method New()
		Local PNGTrace:PNGTracer = New PNGTracer()
		outline_xy = PNGTrace.Trace("monkey://data/test-thing2.png")
	''	verts = PNGTracer.toPolyData(outline_xy)
	End
	
	Method Draw:Void()
		SetColor(255,0,0)
		For Local point:Point = Eachin outline_xy
			DrawPoint(point.x,point.y)
		Next

	''	DrawPoly(verts)
	End
	
	Method Update:Void()
	''	If PointInPoly(MouseX(),MouseY(),verts) Then
		''		Print "Hit"
	''		Else
		''		Print "no"
	''		End
	End

	

	Function PointInPoly:Bool(x:Float, y:Float, poly:Float[])
		Local i:Int, j:Int, c:Bool
		Local v1:Bool, v2:Bool, v3:Bool, v4:Bool, v5#, v6#, v7#
		c = False
		Local p_count% = (poly.Length() / 2)
		
		For i = 0 To p_count-1
			j = (i+1) Mod p_count
			v1 = (poly[i*2+1] <= y)
			v2 = (y < poly[j*2+1])
			v3 = (poly[j*2+1] <= y)
			v4 = (y < poly[i*2+1])
			v5 = (poly[j*2]-poly[i*2]) * (y-poly[i*2+1])
			v6 = (poly[j*2+1]-poly[i*2+1])
			If v6 = 0.0 Then v6 = 0.0001
			v7 = poly[i*2]
			If (((v1 And v2) Or (v3 And v4)) And (x < v5 / v6 + v7)) Then c = Not c
		Next
		Return c
	End
End


Still using this image: