Life cycle of a stroke:

In class Tablet:


0) Read points using the mouseDragged( MouseEvent e ) method.

1 )When the mouse button is released, check if the stroke was a line or
not using test_line(). test_line() integrates the length of the stroke and
compares it to the actual distance between the end points. If the
integrated length is a small percentage above the actual distance, the
stroke is interpreted as a line and we are done with this stroke.

2) If the stroke was not classified as a line, using the speed
information:

* Find the vertices of a polygon that we would obtain if the stroke was
indeed a polygon. This is done in two steps. First an estimate for the
number of vertices is obtained by taking half the number of times the
speed function intersects the horizontal line with the equation
y=avg*scale where avg is the average speed of the line and scale is a
conveniently chosen scaling factor. Using the estimate for the number of
vertices (call it n), find the actual vertices. This is done by finding
the minimum of the speed function between two indices where it just
crosses the y=avg*scale line with a negative slope and the one that it
crosses the same line with a positive slope. This gives us a possible
polygonal approximation to the stroke.

* Calculate the major and semi-major axis lengths and the (x, y) position
of the ellipse that is fully contained in the rectangular bounding box of
the input stroke. This gives us a possible elliptical approximation to
the stroke.

Find the LSQ errors that are obtained by matching the original stroke to
the polygonal and elliptical approximations found above. Go with the
interpretation that gives us the smallest error. 

3) If we have a polygon, simplify it by removing consecutive edges that
are sufficiently parallel. This is where direction information is used.

4) If we recognized a polygon, combine the end points if they are
sufficiently close to each other. 

5) Add the recognized object to the Object Manager module along with the
timing information that we stored and the original data points (for future 
use). 

6) Reset the data structures used in the recognition process and go to 0.



Strategies tried before (at least the ones that come to my mind now):

1) Looking at acceleration information: This information is too noisy and
deviations are large. 

2) Direction information: Testing for changes in the direction doesn't
seem to work well. I believe the main problem is the low resolution that
we have. In order to have useful direction information, the distance
between the points should be large. There are only a limited set of angles
that we can have between any two points inside an NxN grid. Unless N is
large (perhaps larger than 4 or 5) we can't extract enough direction
information. On the other hand having a large N requires us to work with a
sequence of points where the Manhattan distance between two consecutive
points is more than 2*N. If we don't use points that are closer than what
this measure requires, we end up loosing information. (I think the Napkin
people also had the same problem, and they decided to discard points less
than sqrt(18) pixel apart for N=3). There is one strategy that I didn't
try for this part. Perhaps by unzipping (as in lists in list) the data
points into separate arrays, we can do direction analysis on each one
separately and then combine the results.

3) Change in direction: Not reliable due to the reasons described above. 

I believe increasing the sampling rate will lead to much better results
for all of the methods described above. Also since the resolution is
limited by hardware it limits the performance of all of these methods. 
