Access user drawed objects by programming code

Hello everyone,

i want to use Igor to analize some structures in an image. Therefore i am drawing some lines (more than 100 lines) onto a drawing layer with the line-drawing tool. Now i want to do some statistics on the lines for example calculate the length of the lines, crossing points, etc. Sadly i can't find any example how to do that and if it is even possible to for example to generate a wave which contains all coordinates of the user drawed lines so that i could analize the properties of each line in a loop.

Does anyone know how this can be done?

Best,

flashbanger
I can suggest a general approach which may be cumbersome to implement, depending on how automated you want the process to be.
In your image graph, first specify the drawing coordinates to be the left (y) and bottom (x) axes, with whatever line appearance you wish.
Draw all your lines.
Exit drawing mode, and create the graph recreation macro. In that macro each line drawing command will look like:
 DrawLine -0.778770949720671,-0.385988483685221,0.489385474860335,0.550671785028791

Save the macro in a Notebook, and then save the Notebook as a text file.
Load and parse the text file to extract the numerical data following each "DrawLine" string, converting each pair vertex string into two numerical N=2 x-waves and y-waves (or use a multidimensional wave to accumulate all the data). (You may also try to parse and extract the data directly from the Notebook, without saving an external file.)

The main idea is to use the recreation macro to access the drawing data. Subsequent processing will be your burden. I hope someone else may suggest an easier approach.
flashbanger wrote: Therefore i am drawing some lines (more than 100 lines) onto a drawing layer with the line-drawing tool.


Drawing that many lines using drawing tools can get old pretty quickly and the result is not ideal for further processing. On the other hand, if you use a pair of waves say YYY plotted vs. XXX and edit these curves (possibly adding NaNs where you want to end a segment), leaves you with numeric representation in a coordinate system that matches the image. You can also pre-populate the wave programmatically (especially the NaNs). To find out more about this execute

DisplayHelpTopic GraphWaveEdit


I hope this helps,

A.G.
WaveMetrics, Inc.
Perhaps you might also find the following example code helpful for tracing and storing XY coordinates.

•make/o/n=(1000,1000) img //this will be the traced image
•img=enoise(1) //just fill it with some values to look at
•newimage/k=1/N=clickWin img 
•disp_storeClickLocs("clickWin","top","left","clickLocs",1) //allows tracing by mouse clicks with the control key down



//run this function to get started with tracing an image in a window called winN
function disp_storeClickLocs(winN,horizAxName,vertAxName,mouseLocWvRef,showOverlay)
	String winN		//name of window
	String horizAxName,vertAxName		//name of horizontal and vertical axes for coordinate plane
	String mouseLocWvRef			//name of a wave to store the horizontal and vertical coordinates in (created if it does not exist)
	Variable showOverlay		//pass true to overlay click points on window
	
	setwindow $winN userdata(mouseLocWvRef)=mouseLocWvRef
	setwindow $winN userdata(horizAxName)=horizAxName
	setwindow $winN userdata(vertAxName)=vertAxName
	setwindow $winN userdata(showOverlay)=num2str(showOverlay)

	setwindow $winN hook(disp_storeClickHook)=disp_storeClickHook
end

//main hook function to track when (ctrl) clicks occur and store their location
function disp_storeClickHook(s)		//main 
	STRUCT WMWinHookStruct &s
	
	Variable mouseUp = s.eventcode == 5
	Variable ctrlClick = s.eventmod & 2^3
	
	if (!mouseUp || !ctrlClick)
		return 0		//ignore all other events 
	endif
	
	String mouseLocWvRef = GetUserData(s.winname, "", "mouseLocWvRef" )
	String horizAxName = GetUserData(s.winname, "", "horizAxName" )
	String vertAxName = GetUserData(s.winname, "", "vertAxName" )
	Variable showOverlay = str2num(GetUserData(s.winname, "", "showOverlay" ))
	
	Variable row
	if (!WaveExists($mouseLocWvRef))
		make/o/d/n=(1,2) $mouseLocWvRef/wave=mouseLocWv
		row=0
		
		SetDimLabel 1,0,$horizAxName,mouseLocWv 
		setdimlabel 1,1,$vertAxName,mouseLocWv
	else
		WAVE mouseLocWv=$mouseLocWvRef
		row=dimsizE(mouseLocWv,0)
		redimension/n=(row+1,-1) mouseLocWv
	endif
	
	mouseLocWv[row][0] = disp_getMouseLoc(s,horizAxName)
	mouseLocWv[row][1] = disp_getMouseLoc(s,vertAxName)
		
	//check that mouseLocWv is plotted if it should be
	if (showOverlay && !itemsinlist(WaveList(mouseLocWvRef, ";", "WIN:"+s.winname)))
		String horAxisType = StringByKey("AXTYPE", AxisInfo(s.winName, horizAxName))
		String vertAxisType = StringByKey("AXTYPE", AxisInfo(s.winName, vertAxName))
		
		if (stringmatch(horAxisType,"right") && stringmatch(vertAxisType,"bottom"))
			appendtograph/R $mouseLocWvref[][1] vs $mouseLocWvref[][0]
		elseif (stringmatch(horAxisType,"left") && stringmatch(vertAxisType,"bottom"))
			appendtograph $mouseLocWvref[][1] vs $mouseLocWvref[][0]
		elseif (stringmatch(horAxisType,"right") && stringmatch(vertAxisType,"top"))
			appendtograph/R/T $mouseLocWvref[][1] vs $mouseLocWvref[][0]
		else		//last combination is left top
			appendtograph/T $mouseLocWvref[][1] vs $mouseLocWvref[][0]
		endif
	endif
end

//helper function to get mouse click locations
function disp_getMouseLoc(s, axisNameStr)
	STRUCT WMWinHookStruct &s
	String axisNameStr		//name of axis of interest	
	
	String axisType = StringByKey("AXTYPE", AxisInfo(s.winName, axisNameStr))
	
	//determine if vertical, return y position if so, x position if not
	Variable isVert = stringmatch(axisType, "left") || stringmatch(axisType, "right")
	
	//find proportion along vert or horiz
	Variable prop; getWindow $s.winName, psizeDC
	if (isVert)
		prop = (s.mouseLoc.v - V_top) / (V_bottom - V_top)	
	else
		prop = (s.mouseLoc.h - V_left) / (V_right - V_left)	
	endif
	
	//find start and end values of axis as shown
	GetAxis/Q $axisNameStr; Variable shownRange, rangeStart, relPos
	if (V_max > V_min)			//standard direction axis, low to high ordering
		shownRange = V_max - V_min
		rangeStart = V_min
	else	
		shownRange = V_min - V_max
		rangeStart = V_max
	endif
	
	if (shownRange == 0)
		relPos = nan 
	else
		relPos = rangeStart + prop*shownRange
	endif
	
	return relPos
end