This is the second part in an endless series of tutorials dealing with Multi-Touch Development in Python. If you have not read the first one yet, it can be found here.

In the last tutorial we made a really useless example, where every time each TUIO event happened, it would print out “Something left the table”, “Something moved on the table”, or “Something was placed on the table”. We are going to further extend this program to print out where it happened.

So, get started by firing up your editor and opening hellomt.py. If you are particularly fond of your first program, you can copy it and name it hellomt2.py, or whatever you want for that matter. No explanation of this program is needed, because you wrote it:)

If you noticed, common between all three callbacks is an argument that gets passed call blobID. blobID itself in an integer, which contains the blobID of the blob the callback is referring too. On every print line you wrote in the last tutorial, add this to the end:

+ str(blobID)

Now cd into the directory where the program lies, and run the program:

python ./hellomt.py

Now when you touch the surface it should print “Something was placed on the surface 1”. And every time you touch that number should increase. The blobID is the index of a list called blobs. You access blobs through the Observer. In this program the Observer is instantiated as ‘t’, so you would access it as t.blobs. t.blobs is a list of TUIO2DCursor Objects. If you were to print t.blobs, each entry would look something like this:

<touch.Tuio2DCursor object at 0x823f36c>

If we poke around TouchPy a bit(or just pass t.blobs[blobID] through the dir() function, we can figure out that it has the following attributes:

[‘Height’, ‘Width’, ‘__class__’, ‘__delattr__’, ‘__dict__’, ‘__doc__’, ‘__getattribute__’, ‘__hash__’, ‘__init__’, ‘__module__’, ‘__new__’, ‘__reduce__’, ‘__reduce_ex__’, ‘__repr__’, ‘__setattr__’, ‘__str__’, ‘__weakref__’, ‘_event_stack’, ‘_get_handlers’, ‘_raise_dispatch_exception’, ‘blobID’, ‘dispatch_event’, ‘event’, ‘mot_accel’, ‘move’, ‘oxpos’, ‘oypos’, ‘pop_handlers’, ‘push_handlers’, ‘register_event_type’, ‘remove_handler’, ‘remove_handlers’, ‘set_handler’, ‘set_handlers’, ‘xmot’, ‘xpos’, ‘ymot’, ‘ypos’]

The only ones we really care about right now are xpos and ypos. In other tutorials we will get to more of them, such as Height, Width, xmot, ymot, and probably others as well. So, how do we get the x and y position of a blob? Like this:

x = t.blobs[blobID].xpos

y = t.blobs[blobID].ypos

If you understand this line then skip this paragraph. Otherwise, if you are still unclear(like I always was when I started Python), read on. This line accesses the List “blobs”(which is a list of TUIO2DCursor Objects, or pretty much its a list of blobs), that is inside the observer(named ‘t’). Because its a list, it has an index, and the index of the blob we want is blobID. That returns a TUIO2DCursor Object, which we take the xpos attribute of.

So, to print the x and y position of each blob, lets do this:

Replace your print line in touch_up with:

x = t.blobs[blobID].xpos

y = t.blobs[blobID].ypos

print ‘Touch Up at ‘ + str(x) + ‘ , ‘ + str(y)

Replace the print line in touch_move with:

x = t.blobs[blobID].xpos

y = t.blobs[blobID].ypos

print ‘Touch Up at ‘ + str(x) + ‘ , ‘ + str(y)

You should be able to figure out how to do the last one(touch_down).

When you run this program, each line should look like this, substituting Touch Up for the right event:

Touch Up at 0.478175550699 , 0.86176776886

If you look at those coordinates, evidently they are not pixel locations. To get decimal coordinates, multiply each x coordinate by the width of the screen, and each y coordinate by the height of the screen. Because I am anticipating people reading this guide will be running many different Operating Systems, I will not show any specific way to get the screen resolution, and have people hard code their screen resolution into the program. Make a global constant-tuple at the top of your program(anywhere before the callbacks is fine) with your screen dimensions. Mine looks like this:

screen_dimensions = (1280, 800)

Then in your callbacks on the lines that you calculate the X value, add this to the end:

*screen_dimensions[0]

Which is simply, multiply by the screens X dimensions. Do the same for the Y calculations, except multiply by the Height of the screen. Run your program, and observe the output.

Each line should look like this, substituting the correct event:

Touch Up at 832.000045776 , 49.9999940395

Now you have More accurate pixel coordinates, but you can’t really put a dot half-way through a Pixel. Solve this by int-rounding each calculation. int-rounding is the name I made up for the process of rounding to the nearest whole floating number, then making this an integer. You do this by passing your calculation through int(round()). The X calculation would look like this:

x = int(round(t.blobs[blobID].xpos*screen_dimensions[0]))

Do this to all of the calculations, both x and y. Now running your program should yield results similar to these, substituting the correct event:

Touch Up at 922 , 492

Congratulations! You can now get X and Y position of events! In the next tutorial we will write a small program using Clutter to draw circles over all the blobs.