Hand Part Tutorial

<< Back to the TouchID Toolkit page


In this tutorial you learn how to use different hand parts in an application.

Therefore, we will implement a finger painting application together. Each finger will paint in its own color and thickness. Each knuckle is an eraser in the same thickness as its corresponding finger paints.

Table 1 shows the color and thickness for each finger.

FingerColorThickness
ThumbPink35px
Index fingerYellow25px
Middle fingerBlue20px
Ring fingerGreen15px
PinkieRed10px

Prerequisite 1: At least one glove configuration has been created

Glove configurations can be conveniently created with the GloveConfigurator which stores the glove configuration files also directly in the glove repository (My Documents/GroupLab/TouchID Toolkit/Gloves) right away. If you have glove configuration files in a different folder and want them to work with this example, copy them into the glove repository.

Step 1: Creating a new TouchID Application

For detailed information, please read: How to start a new TouchID Application

The TouchID Application template creates the following code skeleton for you:

public partial class Window1 : TouchIDWindow{
  public Window1(){
    InitializeComponent();

    //Creates a glove for every glove model in the glove repository
    this.LoadHands();

    //Alternatively you can also instantiate glove by glove;
    //Hand hand = new Hand(this, "Hand1");

    //Creates posture recognizer and loads all postures from the posture repository into the recognition engine
    this.PostureRecognizer = new PostureRecognizer(this);
    this.PostureRecognizer.LoadPostures(PostureRepository);

    //Creates gesture recognizer and loads all gesture from the gesture repository into the recognition engine
    this.GestureRecognizer = new GestureRecognizer();
    this.GestureRecognizer.LoadGestures(GestureRepository);

    this.HandpartDown += new EventHandler<TouchEventArgs>(Window1_HandpartDown);
  }

  void Window1_HandpartDown(object sender, TouchEventArgs e){
    Console.WriteLine(e.Glove.Hand + " " + e.Handpart.Identifier);
  }
}

Step 2: Replacing the HandpartDown event with FingerDown and KnuckleDown event

Since we know that we would like to handle fingers and knuckles separately, it makes sense to access them not via the general HandpartDown event but the specialized events FingerDown and KnuckleDown. Even though we have to check for hand parts in these vents, too, splitting up the two groups in two events improves the code clearness.

this.HandpartDown += new EventHandler<TouchEventArgs>(Window1_HandpartDown);
this.FingerDown += new EventHandler<TouchEventArgs>(Window1_FingerDown);
this.KnuckleDown += new EventHandler<TouchEventArgs>(Window1_KnuckleDown);

Step 3: Adjusting the callback methods for the FingerDown and KnuckleDown event

The fingers should start painting we they are placed down. The knuckles should erase when they are placed down. Therefor, we adjust the callback methods for each event accordingly:

void Window1_FingerDown(object sender, TouchEventArgs e)
{
  if(e.Handpart.Identifier.Thumb)
  {
    Paint(e.Handpart.Position, Brushes.Pink, 35.0);
  }
  else if(e.Handpart.Identifier.IndexFinger)
  {
    Paint(e.Handpart.Position, Brushes.Yellow, 25.0);
  }
  else if(e.Handpart.Identifier.MiddleFinger)
  {
    Paint(e.Handpart.Position, Brushes.Blue, 20.0);
  }
  else if(e.Handpart.Identifier.RingFinger)
  {
    Paint(e.Handpart.Position, Brushes.Green, 15.0);
  }
  else if(e.Handpart.Identifier.Pinkie)
  {
    Paint(e.Handpart.Position, Brushes.Red, 10.0);
  }
}
void Window1_KnuckleDown(object sender, TouchEventArgs e)
{
  if(e.Handpart.Identifier.ThumbKnuckle)
  {
    Erase(e.Handpart.Position, 35.0);
  }
  else if(e.Handpart.Identifier.IndexKnuckle)
  {
    Erase(e.Handpart.Position, 25.0);
  }
  else if(e.Handpart.Identifier.MiddleKnuckle)
  {
    Erase(e.Handpart.Position, 20.0);
  }
  else if(e.Handpart.Identifier.RingKnuckle)
  {
    Erase(e.Handpart.Position, 15.0);
  }
  else if(e.Handpart.Identifier.PinkieKnuckle)
  {
    Erase(e.Handpart.Position, 10.0);
  }
}

Step 4: Adding the Paint and Erase method

In order to keep this tutorial as simple as possible both functions will just draw an ellipse in the defined thickness and color (white for erasing) at the given position. It works better and looks nicer when you use a path instead but it also makes the tutorial unnecessarily complicated.

private void Paint(Point position, Brush brush, double thickness)
{
  Ellipse ellipse = new Ellipse();

  // Setting the thickness.
  ellipse.Width = thickness;
  ellipse.Height = thickness;

  // Setting the color.
  ellipse.Fill = brush;

  // Translating ellipse to designated position.
  ellipse.RenderTransform = new TranslateTransform(this.position.X-thickness/2.0, this.position.Y-thickness/2.0);
  this.Canvas.Children.Add(ellipse);
}
private void Erase(Point position, double thickness)
{
  // Erasing is done by painting a white ellipse in the given thickness and at the designated position.
  this.Paint(position, Brushes.White, thickness);
}

Step 5: Subscribing to FingerChanged and KnuckleChanged events

When you run the application at this point, you will notice that we've implemented a stamping and not a painting application so far. In order to change this, we subscribe to the FingerChanged and KnuckleChanged events. These events are raised when the hand parts change their position or orientation. By calling the Paint and Erase methods in the callback method for the FingerChanged event and KnuckleChanged event, respectively, the fingers and knuckles will not only paint and erase when placed down on the surface, but also when moved over it.

this.FingerChanged += new EventHandler<TouchEventArgs>(Window1_FingerChanged);
this.KnuckleChanged += new EventHandler<TouchEventArgs>(Window1_KnuckleChanged);

Step 6: Adjusting the callback methods for the FingerChanged and KnuckleChanged event

The bodies of the two callback methods are the same as their counterparts for the FingerDown and KnuckleDown events.

void Window1_FingerChanged(object sender, TouchEventArgs e)
{
  if(e.Handpart.Identifier.Thumb)
  {
    Paint(e.Handpart.Position, Brushes.Pink, 35.0);
  }
  else if(e.Handpart.Identifier.IndexFinger)
  {
    Paint(e.Handpart.Position, Brushes.Yellow, 25.0);
  }
  else if(e.Handpart.Identifier.MiddleFinger)
  {
    Paint(e.Handpart.Position, Brushes.Blue, 20.0);
  }
  else if(e.Handpart.Identifier.RingFinger)
  {
    Paint(e.Handpart.Position, Brushes.Green, 15.0);
  }
  else if(e.Handpart.Identifier.Pinkie)
  {
    Paint(e.Handpart.Position, Brushes.Red, 10.0);
  }
}
void Window1_KnuckleChanged(object sender, TouchEventArgs e)
{
  if(e.Handpart.Identifier.ThumbKnuckle)
  {
    Erase(e.Handpart.Position, 35.0);
  }
  else if(e.Handpart.Identifier.IndexKnuckle)
  {
    Erase(e.Handpart.Position, 25.0);
  }
  else if(e.Handpart.Identifier.MiddleKnuckle)
  {
    Erase(e.Handpart.Position, 20.0);
  }
  else if(e.Handpart.Identifier.RingKnuckle)
  {
    Erase(e.Handpart.Position, 15.0);
  }
  else if(e.Handpart.Identifier.PinkieKnuckle)
  {
    Erase(e.Handpart.Position, 10.0);
  }
}

This is where the hand part tutorial ends. You've learned how to differentiate between hand parts and assign separate functions to them.