Text on curves
From Processing
| Versions: | 0095+ |
| Contributors: | Chris Hoge |
| Started: | 2006-02-07 20:20 |
A quick and dirty way to write text on a curve. I have some supporting classes to make this a little more reusable, but for those interested in how this gets done take a look at the draw() method for the TextCurve class. To draw text on a curve the steps are:
- Compute the x and y location of the letter
- Compute the tangent on the curve (the dx and dy values in the code)
- Compute the rotation of the letter
- Translate and rotate the drawing space ( after a pushMatrix() )
- Draw the letter
- Restore the original drawing space ( by calling popMatrix() )
Source Code
/** textoncurves taken from http://processinghacks.com/hacks:textoncurves @author Chris Hoge */ PFont font; Identity identity; Sine sine; Cosine cosine; TextCurve textCurve; String s; float t; // press c for a circle // press w for a sine wave void keyPressed() { if ( key == 'c' ) { textCurve.m_xfunction = cosine; } else if ( key == 'w' ) { textCurve.m_xfunction = identity; } } void setup() { size( 400, 400 ); font = loadFont( "Courier-48.vlw" ); textFont( font, 48 ); // The functions we want to draw a curve against identity = new Identity(); sine = new Sine( height/4, 0.01, height/2 ); cosine = new Cosine( height/4, 0.01, height/2 ); // The string to place on the curve s = new String("I love Penny"); textCurve = new TextCurve( cosine, sine ); t = 0; background(0); } void draw() { //background(0); fill( 0, 50 ); rect( 0, 0, width, height ); fill( 255 ); // draw the text on the curve textCurve.draw( s, 20, 25 ); // update the functions for the animation sine.m_d = t; cosine.m_d = t; t += 1; } class TextCurve { Function m_xfunction; Function m_yfunction; String m_nextChar; // Text curve uses parametric functions, so y and x are functions of t TextCurve( Function xfunction, Function yfunction ) { m_xfunction = xfunction; m_yfunction = yfunction; } void draw( String value, float t, float spacing ) { float x; float y; float dx; float dy; float theta; for ( int i = 0; i < value.length(); ++i ) { // compute the location x = m_xfunction.f( t ); y = m_yfunction.f( t ); // compute the tangent line dx = m_xfunction.f( t + 0.01 ) - x; dy = m_yfunction.f( t + 0.01 ) - y; // compute the letter rotation theta = atan2( dy, dx ); // move the location to draw the letter to the origin // then rotate the letter by the proper amount pushMatrix(); translate( x, y ); rotate( theta ); // draw the text text( value.substring( i, i+1 ), 0, 0 ); // return to our original canvas popMatrix(); t += spacing; } } } // an interface for a parametrix function interface Function { float f( float t ); } class Identity implements Function { Identity() {} float f( float t ) { return t; } } // wrapper for sin class Sine implements Function { float m_a; float m_b; float m_c; float m_d; Sine( float a, float b, float c) { m_a = a; m_b = b; m_c = c; m_d = 0; } float f( float t ) { return m_a*sin( m_b*(t +m_d) ) + m_c; } } // wrapper for cos class Cosine implements Function { float m_a; float m_b; float m_c; float m_d; Cosine( float a, float b, float c) { m_a = a; m_b = b; m_c = c; m_d = 0; } float f( float t ) { return m_a*cos( m_b*(t +m_d) ) + m_c; } }