Why is my ofPath.courveTo making stright lines

Quick question, I was reading the following post and, while quite clear, left me puzzled as to the result of my code. I have 4 points in my code, and by having my ofPath curve from the first one to the last one, i was expecting a curve between points 2 and 3. I do have said curve… and I also have a straight line between points 1 and 2… why?

void ofApp::setup(){
    curve1.setFilled(false);
    curve1.setStrokeWidth(10);
    curve1.setStrokeColor(0);
    curve1.curveTo(50, 250);
    curve1.curveTo(150, 50);
    curve1.curveTo(250, 250);
    curve1.curveTo(350, 50);
}
void ofApp::draw(){
    curve1.draw();
    ofFill();
    ofSetColor(0);
    ofEllipse(50, 250, 10, 10);
    ofEllipse(150, 50, 10, 10);
    ofEllipse(250, 250, 10, 10);
    ofEllipse(350, 50, 10, 10);
}

Result:

I believe, based on the example, that that’s right, is it not? Why do I have a straight line?

Hi, the curveTo algorithm expects to have at least one point before the one from where it starts, and also have one after the one where it ends. 
What you are getting is correct.

to fix this duplicate the first and last curveTo commands.
void ofApp::setup(){
    curve1.setFilled(false);
    curve1.setStrokeWidth(1);
    curve1.setStrokeColor(0);
    curve1.curveTo(50, 250);
    curve1.curveTo(50, 250);
    curve1.curveTo(150, 50);
    curve1.curveTo(250, 250);
    curve1.curveTo(350, 50);
    curve1.curveTo(350, 50);
}

I think that there might be a more elegant solution but I cant recall in this moment.

Best

It works, so thanks. However, did I misunderstood the post that I linked in my original post? My understanding was that the first and last points are just there for the reference needed to make the curve calculations, thus, I should be able to have an invisible 1st point detached from the first point of the drawn curve, and that invisible 1st point is going to affect how the first segment of the curve gets drawn. Currently, I’m just coupling the first reference point with the first point of the drawn curve.

Ohh right. To be honest I didn’t click on the link to the other post. Your understanding is correct.
###Explanation

The problem is that ofPath uses by default the COMMANDS mode. This is that it just stores the command given, then when you call draw() all the commands are calculated into the points through which the path will pass. On the opposite mode, POLYLINES, whenever you call curveTo(...), lineTo(...), bezierTo(...), quadBezierTo(...), arc(...) or arcNegative(...) the points through which the path will pass are calculated immediately.
The problem is that when you add the first curveTo(...) in COMMANDS mode, it will automatically add a moveTo(...) command using the arguments you originally passed to the curveTo(...) method and it will also add the curveTo(...) command.
Check the following.

void ofPath::curveTo(const ofPoint & p){
    if(mode==COMMANDS){
        addCommand(Command(Command::curveTo,p));
    }else{
        lastPolyline().curveTo(p,curveResolution);
    }
    flagShapeChanged();
}

//------------------------------------------------------

void ofPath::addCommand(const ofPath::Command & command){
    if((commands.empty() || commands.back().type==Command::close) && command.type!=Command::moveTo){
        commands.push_back(Command(Command::moveTo,command.to));
    }
    commands.push_back(command);
}

This means that you will get the straight line that you are getting and also your curve will be calculated correctly.
###Solution(s)

  • The easiest is just to switch the ofPath to POLYLINES mode.
    add the following line to the the code you posted originally before the curveTo(....) lines.
    curve1.setMode(ofPath::POLYLINES);
  • Another solution, without changing to POLYLINES mode is to add a moveTo(...) command before the curveTo(...) using the same parameters you pass to the SECOND curveTo(...)

  • And last, just use an ofPolyline instead of an ofPath.

Hope it helps!

Best