How to build an interactive plotter with a polygon

Start to build our stack

1) Create a table named "MyTable" and fill it with some numerical data (only positive values for our lesson.)

2) Create a button named "Draw".

3) Create a rectangle named "destRect", and put it where you want your graph to be drawn.

4) Create a polygon and keep its original name "Polygon". You can draw a few points, but don't worry about the size and the position of it.

This Polygon will be our graph result afterwards and will be automatically redrawn by our Card Script.

If you have questions at this point, you might want to read this lesson first: "How to make a simple line graph".

Look in our Project Browser

We can see our 4 cards objects with their respectives names, and we have only 2 scripts. One script in our "Draw" button, and our main script in the card. We will explore them now.

Script our "Draw" button

We are calling our card handlerDrawGraph, passing 3 parameters, well, self-explained.

Sleeves up ! our plotter script

(1) We split our original list of lines of points into 2 lists; one for the X, the second for the Y axis, respectively listTableX and listTableY.

(2) We are calculating the rectangle including all our original points.

(3) We have the rectangle where all the final points will fit into.

(4) We set the ratios for our X and Y values.

(5) For each item (actually a point) in our list we transform the original point to a new value. Points in a polygon are integers, that's why we use the round() function. The last line of the repeat will build our new list of points in a format understandable by our polygon (each point is on a separate line)

(6) We update our polygon with our calculated points.... That's it!

If you have questions at this point about the details of calculation, you might want to read this lesson first: "How to make a simple line graph".

You can copy and paste the entire script here:

on Drawgraph tableName, destRectName, graphicId

  -- get the values from our table

  -- split them into 2 lists: X and Y values

  repeat for each line thisLine in the text of field tableName

     put word 1 of thisLine & comma after listTableX

     put word 2 of thisLine & comma after listTableY

  end repeat

  delete last char of lisTableX -- get rid of last comma

  delete last char of lisTableY -- get rid of last comma

 

  -- these next 4 values give us the rectangle aread of our original values

  put min(listTableX) into minTableX

  put 0 into minTableY

  put max(listTableX) into maxTableX

  put max(listTableY) into maxTableY

 

  -- the rect of the destination area

  put the rect of control destRectName into destRect

 

  --ratios

  put (item 3 of destRect - item 1 of destRect) / (maxTableX - minTableX) into deltaX

  put (item 4 of destRect - item 2 of destRect) / (maxTableY - minTableY) into deltaY

 

  --shifts

  put item 1 of destRect into shiftX

  put item 4 of destRect into shiftY

 

  --  Now we have to do a transformation to every point to fit in our destRect

 

  --build a new list to display our polygon

  put empty into listP

  put empty into listP2

  put the number of items in listTableX into Nitems

  repeat with i=1 to Nitems

     put round(deltaX * (item i of listTableX - minTableX) + shiftX) into x

     put round(-deltaY * (item i of listTableY - minTableY) + shiftY) into Y

     -- ste our list of points

     put x & comma & y & cr after listP

  end repeat  

  -- update our polygon

  set the points of graphic id graphicId to listP

end Drawgraph

Make the plotter real...

Hmmm, it works, but I don't like these black lines.

Ok, we can change this behavior easily. See next section...

Make the plotter real. Second version

Above, we see the last lines of our card script, with 2 little changes from the previous script.

(1) We add a cr (return) character after each point. Doing so, the polygon sees all our points as split, and it will not draw the lines any more. Easy, no?

(2) We have to suppress the last cr of our list ( if not, we will have an extra point with value 0,0 )

And then....

Our new plotter.

Now we would like to add some extra information as a line for the X axis, another one for the Y axis, and maybe 4 fields in each corner of our plotter (the blue rectangle) filled with the 4 values we calculated at the beginning of our script.

But in this case we are not really using the best of LiveCode.

Why not do a minimalist interaction with our plotter?

For instance, bringing the cursor close to a red point, will highlight the original corresponding value, which means the corresponding line in our Table.

For this , we add 2 handlers in our card script...

Add handlers for user interaction

The script displayed above completes our script. See the section "Sleeves up !.." for the first part.

(1) We had a list variable listP2. It will contains our list of points. Almost the same as listP, except for the extra cr after each point.

(2) We fill our list for each iteration of the repeat loop.

(3) We need to declare listP2 as local, so to be shared between handlers. ( Please, put this line on top of the script )

(4) We calculate all the distances from our cursor position and each point. It returns the index of the closest point or 0 if the distance is more than minDistance.

(5) For each move of our cursor, we pass here, call TheClosestPoint() function and highlight the corresponding line. Highlighting a field with empty or 0 will reset the previous highlighted line.

 

local listP2 -- put it on top of this script

on Drawgraph tableName, destRectName, graphicId

  -- get the values from our table

  -- split them into 2 lists: X and Y values

  repeat for each line thisLine in the text of field tableName

     put word 1 of thisLine & comma after listTableX

     put word 2 of thisLine & comma after listTableY

  end repeat

  delete last char of listTableX -- get rid of last comma

  delete last char of listTableY -- get rid of last comma

 

  -- these next 4 values give us the rectangle aread of our original values

  put min(listTableX) into minTableX

  put 0 into minTableY

  put max(listTableX) into maxTableX

  put max(listTableY) into maxTableY

 

  -- the rect of the destination area

  put the rect of control destRectName into destRect

 

  --ratios

  put (item 3 of destRect - item 1 of destRect) / (maxTableX - minTableX) into deltaX

  put (item 4 of destRect - item 2 of destRect) / (maxTableY - minTableY) into deltaY

 

  --shifts

  put item 1 of destRect into shiftX

  put item 4 of destRect into shiftY

 

  --  Now we have to do a transformation to every point to fit in our destRect

 

  --build a new list to display our polygon

  put empty into listP

  put empty into listP2

  put the number of items in listTableX into Nitems

  repeat with i=1 to Nitems

     put round(deltaX * (item i of listTableX - minTableX) + shiftX) into x

     put round(-deltaY * (item i of listTableY - minTableY) + shiftY) into Y

     -- set our list of points

     put x & comma & y & cr &cr after listP

     put x & comma & y & cr after listP2

  end repeat      

  delete last char of listP

  -- update our polygon

  set the points of graphic id graphicId to listP

end Drawgraph

function TheClosestPoint x, y

  put the number of lines of listP2 into Npoints

  put 1600 into minDistance -- 40 pixels threshold

  put 0 into closestPoint

  repeat with i=1 to Npoints

     put item 1 of line i of listP2 into x1

     put item 2 of line i of listP2 into y1

     get (x1 - x)^2 + (y1 - y)^2

     if it < minDistance then

        put it into minDistance

        put i into closestPoint

     end if

  end repeat

  return closestPoint

end TheClosestPoint

on mouseMove

  if the mouseLoc is within the rect of graphic "destRect" then

     get TheClosestPoint(the mouseH, the mouseV)

     set the hilitedLine of field "MyTable" to it

  else

     set the hilitedline of field "MyTable" to empty

  end if

end mouseMove

Final screen

Our cursor is positioned around the fifth point, and the fifth line is highlighted.

How do we make our spots square and red

Select our Polygon, open the Property Inspector.

(1) Choose the Basic tab.

(2) Select the Draw shape at vertices option.

(3) Choose the size of the line.

(4) Draw your marker with this list of points. In our example, we have drawn a square of 2 pixels

For setting the red color, in (1) Select "Colors" and choose the color of the Marker Border Fill.

2 Comments

John Tripp

why does the programme not compile?
repeat for each line thisLine in the text of field tableName
put word 1 of thisLine & comma after listTableX
put word 2 of thisLine & comma after listTableY
end repeat
the program says chink: can't create a variable with that name (explicitVariables?() near listTableX, char 38 for line
put word 1 of thisLine & comma after listTableX
it appears to be an exact copy of the code in the help page but this error is poping up more and more often and I cannot find any reference to what it means or how to adjust - why d you have code in the help file that does not work?

Hanson Schmidt-Cornelius

Hi John,

the reason you are getting this is because you probably have variable checking switched on and you are not declaring the variables.

Variable checking is a good thing, as it encourages good development practices. You can switch it off by clicking the script editor and then selecting: "Edit -> Variable Checking."

If you want to keep this feature on (recommended), then add: "local listTableX, listTableY" before you use these variables.

Kind Regards,

Hanson

Add your comment

E-Mail me when someone replies to this comment