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