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.
R. Morales Gonzalez, C. Appert, G. Bailly and E. Pietriga. (2017). Passive yet Expressive TouchTokens. CHI 2017. ACM Press, pages 3741-3745.
C. Appert, E. Pietriga, E. Bartenlian and R. Morales Gonzalez. (2018). Custom-made Tangible Interfaces with TouchTokens. AVI 2017. ACM Press, pages 1–9.
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.
Two implementations are available:
// 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
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);
See classes Test
, TestConsole
, TestCanvas
.
Install TouchTokensDroid app.
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, ArrayListpoints, 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); } }
See class TestView
.
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.
java -jar TouchTokensBuilder-0.0.1.jar <path_to_folder_SVG_pictures> <nb_columns_in_ui>
TouchTokenTracker is a library that takes as input the numerical description produced by TouchTokenBuilder.
Two implementations are available:
// 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
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()); ... } ...
See classes Test
, TestConsole
, TestCanvas
.
Install TouchTokensDroid app.
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 ArrayListtouchPoints; 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); ... } }
See class TestView
. Tokens recognized in TestView
are defined in app/src/main/assets/templates.txt.