How to calculate good-looking bezier control points in 3D?

I’d like to draw Bezier curves algorithmically, i.e. I’d like the control points to be functions of two data points. Assuming the following Bezier curve:


I imagine P0, P1, and P2 form an obtuse triangle where the angle at P1, say β, is somewhere around 115 degrees. How do I find point P1 given that points P0 and P2 are determined by my data?

Do you really mean 3D?

This assume your plane / floor is in x/z and height is y

P1.x = (P0.x + P2.x) / 2;  
P1.y =  P0.y - 140; 
P1.z = (P0.z + P2.z) / 2;
1 Like

Yeah, I mean 3D. I know my drawing is 2D but that’s just for simplicity.

Your points work in principle but depending on how far apart the points are, I sometimes get a very heavy curvature and sometimes almost no curvature at all. Is there a way to make point P1 to be a function of the distance of P0 and P2? This way, I hope, the angle/curvature will be maintained.

unfortunately the angle is not sufficient to determine the position of P1 even in 2D

so you need to set more constraints. for example, P0P1 == P1P2. But again this is not sufficient in 3D. To deal with these situations, for example, Catmull-Rom uses adjacent points as control points (implemented as curveVertex in processing)

1 Like

Ah perfect, thanks! This is closer to what I’m looking for. Taking my 2D example from above, how could one create a line that just curves ever-so-slightly from a straight line between P0 and P2?

I have tried the following:

curveVertex(P0.x, P0.y, P0.z);
curveVertex(P2.x, P2.y, P2.z);

I get curved lines from point P0 to P2 but they are bent very strongly and I’m wondering how I can tune down the curvature a bit, again not using a constant but by imputing a helpful in-between point (e.g. P1) that reduces the curvature.

I haven’t tried but curveTightness might do the job:

1 Like

I came across it in this exact moment. It does do the job! Apparently, the apparent tightness depends on how far the points are apart. So I’m experimenting with 1/distanceBetweenPoints, 1/distanceBetweenPoints^2, etc. It seems to be working well.