Etapa 1 - Gere N + 1 pontos interpolando a curva em incrementos de 1 / N. N deve ser grande o suficiente para obter bons resultados visuais, mas pequeno o suficiente para ser facilmente calculado. Um valor de 50 deve ser bom para a maioria das situações, mas deve ser ajustado para o seu caso específico. Vou chamar isso de "pontos interpolados".
Como alternativa, você pode gerar uma lista curta de segmentos e interromper recursivamente cada segmento maior que o comprimento máximo desejado do segmento (inicialmente você deve gerar pelo menos quatro segmentos para contabilizar as curvas S, onde o início está muito próximo do fim).
Etapa 2 - "Ande na linha" usando os pontos interpolados e o espaçamento desejado entre cada ponto.
Vou deixar aqui meu código do Unity:
public static Vector2[] InterpolateBezier(Vector2 start, Vector2 startControlPoint,
Vector2 end, Vector2 endControlPoint, int segments)
{
Vector2[] interpolated = new Vector2[segments + 1];
interpolated[0] = start;
interpolated[segments] = end;
float step = 1f / segments;
for (int i = 1; i < segments; i++)
{
interpolated[i] = GetBezierPosition(start, startControlPoint, end,
endControlPoint, i * step);
}
return interpolated;
}
public static Vector2 GetBezierPosition(Vector2 start, Vector2 startControlPoint,
Vector2 end, Vector2 endControlPoint, float t)
{
float omt = 1f - t;
float omt2 = omt * omt;
float t2 = t * t;
return
start * (omt2 * omt) +
startControlPoint * (3f * omt2 * t) +
endControlPoint * (3f * omt * t2) +
end * (t2 * t);
}
public static List<Vector2> WalkLine(Vector2[] points, float spacing, float offset = 0)
{
List<Vector2> result = new List<Vector2>();
spacing = spacing > 0.00001f ? spacing : 0.00001f;
float distanceNeeded = offset;
while (distanceNeeded < 0)
{
distanceNeeded += spacing;
}
Vector2 current = points[0];
Vector2 next = points[1];
int i = 1;
int last = points.Length - 1;
while (true)
{
Vector2 diff = next - current;
float dist = diff.magnitude;
if (dist >= distanceNeeded)
{
current += diff * (distanceNeeded / dist);
result.Add(current);
distanceNeeded = spacing;
}
else if (i != last)
{
distanceNeeded -= dist;
current = next;
next = points[++i];
}
else
{
break;
}
}
return result;
}
t
, digamos, 100 passos e meça as distâncias entre os pontos resultantes. Em seguida, interpole ao longo dessa polilinha, conforme desejado.