Tracer Library - Cannot Composite Smooth Path

Hi there, I am working on an art project and trying to create a path made of Bezier curves and then mapping text on it.

The path is like this:

  bezier1a = new CubicBezier (1400, 179, 1150, 50 , 810, 140, 700, 190);
  bezier1b = new CubicBezier (700 , 190, 580 , 290, 360, 300, 0  , 180);
  path1 = new Composite (bezier1a, bezier1b);

I basically just edited a little of the map_text_to_path example from the Tracer Library so far:

import tracer.*;
import tracer.paths.*;

int fgColor = #FFFFFF; //foreground color
int bgColor = #222222; //background color

String text = "One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.";
float startu; //1D position where text starts
float dstartu = 0.00005; //1D text speed per millisecond

//Lissajous path;

CubicBezier bezier1;
CubicBezier bezier2;
Composite path;

float dphi = 0.0005; //change in phi per millisecond

int d;
int k;

int prevt; //the previous time in milliseconds

void setup() {
  size(1280, 720, P2D);
  //create lissajous path
  //int freqX = 3;
  //int freqY = 2;
  //int radius = 125;
  //float phi = HALF_PI;
  //new Lissajous(width/2, height/2, radius, radius, freqX, freqY, phi);

  bezier1 = new CubicBezier (0, 180, 360, 300, 580, 290, 700, 190);
  bezier2 = new CubicBezier (700, 190, 810, 120, 1150, 50, 1400, 170);
  path = new Composite (bezier1, bezier2);

  prevt = millis();

void draw() {
  //update change in time
  int dt = millis() - prevt;
  prevt = millis();
  //animate path
 // path.setPhi(path.getPhi() + dphi * dt); //change phi angle
  startu += dstartu * dt; //shift 1D position where the text starts
  //draw background
  //draw text
  for (int k=0; k<1; k++){  
    String string = text;
  embedText(path, string);

void embedText(Path path, String string) {
  //create memory to store traced points (to limit the number of new points that have to be allocated)
  Point a = new Point(0, 0);
  Point b = new Point(0, 0);
  float textWidthAcc = 0; //the accumulated width of the text from the start of the loop to the end of the loop
  float textWidthTotal = textWidth(text); //the total width of the text
  for (int i=0; i<string.length(); i++) {
    char c = string.charAt(i);
    //update text width accumulator
    textWidthAcc += 0.5 * textWidth(c);
    //compute 1D coordinate of text character
    float u = (startu + map(textWidthAcc, 0, textWidthTotal, 0, 1)) % 1;
    //compute 2D coordinate of text character
    path.trace(a, u);
    //compute angle of rotation
    path.trace(b, (u + 0.000001) % 1.0);
    float angleOfRotation = atan2(b.y - a.y, b.x - a.x);
    //draw character
    drawChar(string.charAt(i), a.x, a.y, angleOfRotation);
    //update text width accumulator
    textWidthAcc += 0.5 * textWidth(c);

void drawChar(char c, float x, float y, float angle) {
  textAlign(CENTER, CENTER);
  translate(x, y);
  text(c, 0, 0);

I expected the path automatically to be smooth since the bezier1a and 1b both have the (700, 190) vertex, but the text does not flow smoothly through the connecting point.

How can I make the path smooth? Or is there other ways to add Bezier curves into a path? I see BEZIER_VERTEX in the Path class’s inherit fields but dunno how to use it…

Hi ychen53,

The first thing you can do to improve the render is to change the coordinates of the first control points of the second bezier curves. You want to avoid straight angle so you want this point to be aligned with the last 2 points of the first bezier curves so both tangents are the same.

Here what I mean in picture:

The new values are then like this:

bezier1 = new CubicBezier (0, 180, 360, 300, 580, 290, 700, 190);
bezier2 = new CubicBezier (700, 190, 820, 90, 1150, 50, 1400, 170);

Then render is a bit better but there is still another problem: the letters are quite close to each other. Sadly I don’t think there is much to do about it. I’ve never used tracer before so what I’ll say is just a guess on how it seems to work.

When you want to draw a new letter, you “move by a tiny time” dt. By moving by dt, you can compute the next point on the curve and if you look how bezier curves are drawn you’ll see that they are also construct with the same principle.

Now, because of the way they are construct, the small change in dt will not always move the point on the curve by the same distance. For that problem, maybe you can find a solution on google to see how you can go through a bezier curves at a constant speed.

1 Like

Thank you jb4x!! That’s really helpful XD