TouchTokens

References

ACM version R. Morales Gonzalez, C. Appert, G. Bailly and E. Pietriga. (2016). TouchTokens: Guiding Multi-Touch Patterns with Passive Tokens. CHI 2016. ACM Press, pages 4189-4202.

ACM version R. Morales Gonzalez, C. Appert, G. Bailly and E. Pietriga. (2017). Passive yet Expressive TouchTokens. CHI 2017. ACM Press, pages 3741-3745.

ACM version C. Appert, E. Pietriga, E. Bartenlian and R. Morales Gonzalez. (2018). Custom-made Tangible Interfaces with TouchTokens. AVI 2017. ACM Press, pages 1–9.

Basic (rigid and flexible) TouchTokens

Fabrication

The following PDF file contains the vector shapes for the 6 tokens. Document size (for printing or laser cutting): 300 x 600mm.

If you want to use flexible tokens that can be squeezed and bent, check out the following vector descriptions: PDF file or Adobe Illustrator file.

Recognizers

Two implementations are available:

TUIO API

Test

     // e.g., with a touchpad of 105mm x 75mm with TUIO running on port 3333
     mvn clean package
     ./run.sh -tuio 3333 -inputWidth 105 -inputHeight 75
  

Use

TouchTokenListener is an interface that implements callback methods for TouchTokens events. Each callback delivers the id of the token, the touch points normalized in the input surface space ((0,0) is the top left corner and (1,1) is the bottom right corner) and the size of the input surface in millimeters.

     TokenListener listener = new TokenListener() {

        protected DecimalFormat df = new DecimalFormat("0.0000");

        public void tokenDown(TokenEvent event) {
           TouchPoint centroid = TouchTokenRecognizer.centroid(event.getPoints());
           System.out.println("+ "+event.tokenID+" ("+df.format(centroid.x)+", "+df.format(centroid.y)+")");
        }

        public void tokenMoved(TokenEvent event) {
           TouchPoint centroid = TouchTokenRecognizer.centroid(event.getPoints());
           System.out.println("~ "+event.tokenID+" ("+df.format(centroid.x)+", "+df.format(centroid.y)+")");
        }

        public void tokenUp(TokenEvent event) {
           TouchPoint centroid = TouchTokenRecognizer.centroid(event.getPoints());
           System.out.println("- "+event.tokenID+" ("+df.format(centroid.x)+", "+df.format(centroid.y)+")");
        }

     }

     ...

     TouchTokenRecognizer recognizer = new TouchTokenRecognizer(new File("templates/templates.txt"));
     TUIOManager tuioManager = new TUIOManager(recognizer, tuioPort, inputWidth, inputHeight);
     tuioManager.addTokenListener(listener);
	

Simple code examples

See classes Test, TestConsole, TestCanvas.

Android API

Test

Install TouchTokensDroid app.

Use

TouchTokenView is a subclass of android.view.View that implements callback methods for TouchTokens events. Each callback delivers the id of the token, the touch points normalized in the view space ((0,0) is the top left corner and (1,1) is the bottom right corner) and the size of the view in millimeters.

     public class TestView extends TouchTokenView {

        ...

        public void onTokenDown(String tokenID, ArrayList points, double viewWidthMm, double viewHeightMm) {
           // get the centroid of the touch points in normalized space
           TouchPoint centroid = TouchTokenRecognizer.centroid(points);
           Log.v("Token Input", ""+this.tokenID+" DOWN - centroid at "+centroid);

           // get token centroid location in pixels
           TouchPoint centroidPx = new TouchPoint(centroid.x * getWidth(), centroid.y * getHeight());
           // get token centroid location in millimeters
           TouchPoint centroidMm = new TouchPoint(centroid.x * viewWidthMm, centroid.y * viewHeightMm);
        }

        public void onTokenMoved(String tokenID, ArrayList points, double viewWidthMm, double viewHeightMm) {
           TouchPoint centroid = TouchTokenRecognizer.centroid(points);
           Log.v("Token Input", ""+this.tokenID+" MOVED - centroid at "+centroid);
        }

        public void onTokenUp(String tokenID, ArrayList points, double viewWidthMm, double viewHeightMm) {
           TouchPoint centroid = TouchTokenRecognizer.centroid(points);
           Log.v("Token Input", ""+this.tokenID+" UP - centroid at "+centroid);
        }
     }
  

Simple code examples

See class TestView.

Custom-made TouchTokens

TouchTokenBuilder

TouchTokenBuilder, is a Java application that assists interface designers in placing notches on arbitrarily-shaped vector contours using a simple direct-manipulation interface. The application outputs two files: a vector-graphics description of all tokens in the set, ready to be fabricated using, e.g., a laser cutter; and a numerical description of the geometry of each token. TouchTokenBuilder is distributed as an executable Jar file. Unzip TouchTokenBuilder.zip, and double click TouchTokensBuilder-0.0.1.jar, or execute the following command line.

Run

     java -jar TouchTokensBuilder-0.0.1.jar <path_to_folder_SVG_pictures> <nb_columns_in_ui>
  

TouchTokenTracker

TouchTokenTracker is a library that takes as input the numerical description produced by TouchTokenBuilder.

Two implementations are available:

TUIO API

Test

     // e.g., with a touchpad of 105mm x 75mm with TUIO running on port 3333
     mvn clean package
     ./run.sh -tuio 3333 -inputWidth 105 -inputHeight 75
  

Use

TouchTokenListener is an interface that implements callback methods for TouchTokens events. Each callback delivers an object of type TokenEvent that allows developers to get the following information: token id, touch points normalized in the input surface space ((0,0) is top left corner and (1,1) is bottom right corner), notch points normalized in the same space, token center location, token orientation (in radians) and the token contour shape.


     public class PaintTokenOutline implements TouchTokenListener {

        protected TokenEvent event;

        public PaintTokenOutline(int tuioPort, int inputWidth, int inputHeight) {
          TouchTokenRecognizer recognizer = new TouchTokenRecognizer(new File("templates/templates.txt"));
          TUIOManager tuioManager = new TUIOManager(recognizer, tuioPort, inputWidth, inputHeight);
          tuioManager.addTokenListener(this);

        }
        public void tokenDown(TokenEvent event) { this.event = event; }

        public void tokenMoved(TokenEvent event) { this.event = event; }

        public void tokenUp(TokenEvent event) { this.event = event; }

        ...

        protected void paintComponent(Graphics g) {
          Graphics2D g2d = (Graphics2D) g;
          ...
          // TOKEN OUTLINE
          TouchPoint tokenCenter = event.getTokenCenter();
          double tokenRelOrientation = event.getTokenRelOrientation();
          double tokenAbsOrientation = event.getTokenInitOrientation() + tokenRelOrientation;
          g2d.setColor(Color.LIGHT_GRAY);
          AffineTransform xForm = new AffineTransform();
          xForm.translate((int)(tokenCenter.x * getWidth()), (int)(tokenCenter.y * getHeight()));
          xForm.rotate(-tokenAbsOrientation);
          // take the screen resolution into account to display the token at its actual physical size
          xForm.scale(SCREEN_RES, SCREEN_RES); // SCREEN_RES is the screen resolution in px.mm-1
          g2d.setStroke(new BasicStroke((float)(outlineStroke/SCREEN_RES)));
          g2d.setTransform(xForm);
          g2d.draw(event.getUntransformedTemplate().getContourShape());
          ...
     }

     ...


	

Simple code examples

See classes Test, TestConsole, TestCanvas.

Android API

Test

Install TouchTokensDroid app.

Use

TouchTokenView is a subclass of android.view.View that implements callback methods for TouchTokens events. Each callback delivers the id of the token, the touch points normalized in the input surface space ((0,0) is the top left corner and (1,1) is the bottom right corner), the notch points normalized in the same space, the token center location, the token orientation (in radians) and the token contour shape.

     public class TestView extends TouchTokenView {

        ...
        protected ArrayList touchPoints;
        protected ArrayList notchPoints;
        protected TokenTemplate transformedTemplate;

        public void onTokenDown(String tokenID, ArrayList points, double viewWidthMm, double viewHeightMm) {
          this.touchPoints = touchPoints;
          this.notchPoints = notchPoints;
          this.transformedTemplate = transformedTemplate;
        }

        public void onTokenMoved(String tokenID, ArrayList points, double viewWidthMm, double viewHeightMm) {
          this.touchPoints = touchPoints;
          this.notchPoints = notchPoints;
          this.transformedTemplate = transformedTemplate;
        }

        public void onTokenUp(String tokenID, ArrayList points, double viewWidthMm, double viewHeightMm) {
          this.touchPoints = touchPoints;
          this.notchPoints = notchPoints;
          this.transformedTemplate = transformedTemplate;
        }

        protected void onDraw(Canvas canvas) {
          ...
          TouchPoint tokenCenter = getTokenCenter(transformedTemplate, notchPoints);
          double tokenRelOrientation = getTokenRelOrientation(transformedTemplate, notchPoints);
          double tokenAbsOrientation = getTokenInitOrientation(transformedTemplate) + tokenRelOrientation;
          canvas.save();
          canvas.drawCircle(
                  (int) (tokenCenter.x * getWidth()),
                  (int) (tokenCenter.y * getHeight()),
                  40, tokenCenterPaint);
          canvas.translate((float) (tokenCenter.x * getWidth()), (float) (tokenCenter.y * getHeight()));
          canvas.rotate(-(float) (tokenAbsOrientation * 180 / Math.PI));
          canvas.drawPath(transformedTemplate.getOriginalGeometryTemplate().getContourShape(), tokenOutlinePaint);
          ...
        }
     }
  

Simple code examples

See class TestView. Tokens recognized in TestView are defined in app/src/main/assets/templates.txt.