Curvas de Bézier Grupo 2
| Trabajo realizado por estudiantes | |
|---|---|
| Título | Curvas de Bézier (Grupo 2) |
| Asignatura | Teoría de Campos |
| Curso | 2024-25 |
| Autores | Marta Escaso Camacho Maximiliano Rodríguez Ruiz Beatrice Laval González Alejandro Villaverde Carrascosa Daniel Pérez Cámara |
| Este artículo ha sido escrito por estudiantes como parte de su evaluación en la asignatura | |
Las curvas de Bézier son un sistema que se desarrolló sobre 1960 para el diseño aeronáutico, el trazado de dibujos técnicos y el diseño de automóviles. Fueron ideadas por el ingeniero francés Pierre Bézier y posteriormente desarrolladas por Paul de Casteljau. Hoy en día, estas curvas se han convertido en un estándar en la industria de la gráfica por computadora, el diseño industrial y la ingeniería, permitiendo crear formas fluidas y precisas. Las curvas de Bézier de orden [math]n[/math] están definidas por los puntos de control [math]P_0,P_1,...,P_n[/math] y se pueden expresar mediante la siguiente fórmula:
donde \(B_{i,n}(t)\) son los polinomios de Bernstein, dados por:
para \(t \in [0, 1]\), y donde \(\binom{n}{i}\) es el coeficiente binomial.
Contenido
- 1 Representación de la curva de Bézier cúbica para [math]n=3[/math], junto con la curva poligonal que conecta cuatro puntos de control coplanarios.
- 2 Representación del campo tangente [math]T(t)[/math] y del campo normal [math]N(t)[/math] en varios puntos de la curva.
- 3 Representación de la curvatura de la curva en función del parámetro [math]t[/math].
- 4 Animación del vector tangente, el vector normal y la circunferencia osculatriz asociados a cada punto de la curva de Bézier.
- 5 Representación de la curva de Bézier tridimensional, junto con la curva poligonal que conecta los cuatro puntos que están en el espacio tridimensional y no pertenecen al mismo plano.
- 6 Representación de los gráficos de la curvatura y de la torsión como funciones del parámetro [math]t[/math].
- 7 Animación que representa el triedro de Frenet que se mueve a lo largo de la curva.
- 8 Aplicación de una curva de Bézier al tramo de un circuito de [math]F_1[/math].
- 9 Aplicaciones de las curvas de Bézier en la ingeniería.
1 Representación de la curva de Bézier cúbica para [math]n=3[/math], junto con la curva poligonal que conecta cuatro puntos de control coplanarios.
En primer lugar seleccionamos cuatro puntos de control coplanarios ([math]P_0,P_1,P_2,P_3[/math]):
[math] \;\left\{\begin{matrix}P_0=(0,0) \\ P_1=(4,2) \\ P_2=(0,2) \\ P_3=(4,4) \end{matrix}\right.[/math]
Para calcular los puntos de la curva se utilizan los polinomios de Bernstein para cada valor de [math]n[/math]:
[math] B_0=(1-t)^3 [/math]
[math] B_1=3(1-t)^2·t [/math]
[math] B_2=3(1-t)·t^2 [/math]
[math] B_3=t^3 [/math]
Se calcula la posición del punto en la curva mediante una combinación lineal de los puntos de control ponderados por los polinomios de Bernstein.
La imagen representa la gráfica de la curva de Bézier y la poligonal de control. Se puede observar cómo los puntos de control influyen en la forma de la curva, lo que nos permite adaptarla a distintas aplicaciones.
% Selección de puntos de control coplanarios
P0 = [0, 0, 0];
P1 = [4, 2, 0];
P2 = [0, 2, 0];
P3 = [4, 4, 0];
n = 3; % Orden de la curva de Bézier
% Puntos para la curva de Bézier
numPuntos = 100;
% Valores de t entre 0 y 1
t = linspace(0, 1, numPuntos);
% Inicializar los puntos de la curva Bézier
puntosCurva = zeros(numPuntos, n);
% Calcular los puntos de Bézier
for i = 1:numPuntos
% Polinomio de Bernstein
B0 = (1-t(i))^n;
B1 = n * (1-t(i))^2 * t(i);
B2 = n * (1-t(i)) * t(i)^2;
B3 = t(i)^n;
puntosCurva(i,:) = B0*P0 + B1*P1 + B2*P2 + B3*P3;
end
% Graficar la curva y la poligonal de control
figure;
hold on;
% Poligonal de control
plot3([ P0(1), P1(1), P2(1), P3(1) ], [ P0(2), P1(2), P2(2), P3(2) ], ...
[ P0(3), P1(3), P2(3), P3(3) ], 'bo--', 'LineWidth', 1.5);
% Curva de Bézier
plot3(puntosCurva(:,1), puntosCurva(:,2), puntosCurva(:,3), 'r-', 'LineWidth', 2.5);
% Se pone título a la gráfica
title('Curva de Bézier cúbica');
% Se pone nombre a los ejes
xlabel('Eje x');
ylabel('Eje y');
legend('Poligonal de control', 'Curva Bézier');
grid on;
hold off;
2 Representación del campo tangente [math]T(t)[/math] y del campo normal [math]N(t)[/math] en varios puntos de la curva.
- Cálculo del Vector Tangente [math]T(t)[/math]:
El vector tangente [math]T(t)[/math] es la derivada de la curva \(B(t)\) respecto al parámetro [math]t[/math]:
donde la derivada del polinomio de Bernstein es:
El vector tangente se obtiene normalizando la derivada:
donde [math]||B'(t)||=\sqrt{(B'_x(t))^2 + (B'_y(t))^2} [/math]
- Cálculo del Vector Normal [math]N(t)[/math]:
Como el vector normal es ortogonal al vector tangente, lo calculamos haciendo uso del tensor rotación [math]R[/math] con eje unitario y ángulo 90º ([math]\frac{\pi}{2}[/math] radianes).
La fórmula general para una rotación alrededor de un eje [math]e[/math] unitario con un ángulo [math]θ[/math] es:
Particularizando para [math] e_z=\begin{pmatrix} 0 \\ 0 \\ 1 \end{pmatrix} [/math]:
Para rotaciones en el plano XY, es decir, 2D:
% Vector de puntos de control coplanarios
P = [0, 0; 4, 2; 0, 2; 4, 4];
n = 3; % Orden de la curva de Bézier
% Puntos para la curva de Bézier
numPuntos = 100;
t = linspace(0, 1, numPuntos); % Valores de t entre 0 y 1
B = zeros(numPuntos, 2); % Inicializar B con la matriz nula
dB = zeros(numPuntos, 2); % Derivada de la curva
% Cálculo de la curva y derivada
for i = 0:n
coefBin = nchoosek(n, i); % Coeficiente binomial
Bernstein = coefBin * (t.^i) .* ((1-t).^(n-i)); % Polinomio de Bernstein
BernsteinDerivada = coefBin * (i * t.^(i-1) .* (1-t).^(n-i) - (n-i) * t.^i .* (1-t).^(n-i-1)); % Derivada
B = B + Bernstein' * P(i+1, :); % Curva de Bézier
dB = dB + BernsteinDerivada' * P(i+1, :); % Derivada
end
% Obtenemos el vector tangente
T = dB ./ vecnorm(dB, 2, 2);
% Definimos la matriz de rotación para 90º alrededor del eje Z
R = [0 -1; 1 0];
% Cálculo del vector normal usando R
N = (R * T')';
% Puntos de la curva para dibujar vectores tangentes y normales
puntos = round(linspace(1, numPuntos, 12)); % Seleccionamos 12 puntos
% Graficar la curva y la poligonal de control
figure;
hold on;
plot(P(:, 1), P(:, 2), 'bo--', 'LineWidth', 1.5); % Poligonal de control
plot(B(:, 1), B(:, 2), 'r-', 'LineWidth', 2.5); % Curva Bézier
% Graficar vectores tangentes y normales
quiver(B(puntos, 1), B(puntos, 2), T(puntos, 1), T(puntos, 2), 0.3, 'g', 'LineWidth', 1); % Tangentes (en verde)
quiver(B(puntos, 1), B(puntos, 2), N(puntos, 1), N(puntos, 2), 0.3, 'm', 'LineWidth', 1); % Normales (en magenta)
title('Campos tangente y normal');
xlabel('Eje x');
ylabel('Eje y');
legend('Poligonal de control', 'Curva Bézier', 'Tangentes', 'Normales');
grid on;
hold off;
3 Representación de la curvatura de la curva en función del parámetro [math]t[/math].
La curvatura de una curva describe cuánto y cómo cambia la dirección de la tangente de la curva en cada punto. Esta propiedad se puede expresar como una función del parámetro "t", que generalmente parametriza la curva. En este apartado representaremos el gráfico de la curvatura de la curva en función del parámetro [math]t[/math].
Definimos la curva [math] B(t) = (x(t), y(t)) [/math]. Para calcular la curvatura de una curva se utiliza la siguiente ecuación:
% Selección de puntos de control coplanarios
P0 = [0, 0, 0];
P1 = [4, 2, 0];
P2 = [0, 2, 0];
P3 = [4, 4, 0];
n = 3; % Orden de la curva de Bézier
% Puntos para la curva de Bézier
numPuntos = 100;
% Valores de t entre 0 y 1
t = linspace(0, 1, numPuntos);
% Inicializar los puntos de la curva Bézier
puntosCurva = zeros(numPuntos, n);
% Calcular los puntos de Bézier
for i = 1:numPuntos
% Polinomio de Bernstein
B0 = (1-t(i))^n;
B1 = n * (1-t(i))^2 * t(i);
B2 = n * (1-t(i)) * t(i)^2;
B3 = t(i)^n;
puntosCurva(i,:) = B0*P0 + B1*P1 + B2*P2 + B3*P3;
end
% Derivar las coordenadas de la curva con respecto a t
% Aproximación por diferencias finitas
dx = gradient(puntosCurva(:, 1), t); % Primera derivada de x
dy = gradient(puntosCurva(:, 2), t); % Primera derivada de y
d2x = gradient(dx, t); % Segunda derivada de x
d2y = gradient(dy, t); % Segunda derivada de y
% Calcular la curvatura usando la fórmula
curvatura = abs(dx .* d2y - dy .* d2x) ./ ((dx.^2 + dy.^2).^(3/2));
% Graficar la curvatura en función del parámetro t
plot(t, curvatura, 'r-', 'LineWidth', 2);
title('Curvatura de la curva de Bézier en función de t');
xlabel('Eje x');
ylabel('Eje y');
4 Animación del vector tangente, el vector normal y la circunferencia osculatriz asociados a cada punto de la curva de Bézier.
% Puntos de control coplanares
P0 = [0, 0,0];
P1 = [4, 2,0];
P2 = [0, 2,0];
P3 = [4, 4,0];
% Parámetro t (de 0 a 1)
t = linspace(0, 1, 100);
% Polinomios de Bernstein
B0 = (1 - t).^3;
B1 = 3 * t .* (1 - t).^2;
B2 = 3 * t.^2 .* (1 - t);
B3 = t.^3;
% Coordenadas de la curva de Bézier
x = B0 * P0(1) + B1 * P1(1) + B2 * P2(1) + B3 * P3(1);
y = B0 * P0(2) + B1 * P1(2) + B2 * P2(2) + B3 * P3(2);
% Derivadas de la curva de Bézier
dx = gradient(x, t);
dy = gradient(y, t);
% Vectores tangentes normalizados
T = [dx; dy] ./ sqrt(dx.^2 + dy.^2);
% Vectores normales (perpendiculares al tangente)
N = [-T(2, :); T(1, :)];
% Segunda derivada de la curva
d2x = gradient(dx, t);
d2y = gradient(dy, t);
% Curvatura
curvatura = abs(dx .* d2y - dy .* d2x) ./ (dx.^2 + dy.^2).^(3/2);
% Radio de curvatura
R = 1 ./ curvatura;
% Animación
figure;
for i = 1:length(t)
clf;
plot(x, y, 'b-', 'LineWidth', 2); hold on;
quiver(x(i), y(i), T(1, i), T(2, i), 0.5, 'r', 'LineWidth', 1.5); % Tangente
quiver(x(i), y(i), N(1, i), N(2, i), 0.5, 'g', 'LineWidth', 1.5); % Normal
% Circunferencia osculatriz
center = [x(i), y(i)] + R(i) * N(:, i)';
theta = linspace(0, 2*pi, 100);
circle_x = center(1) + R(i) * cos(theta);
circle_y = center(2) + R(i) * sin(theta);
plot(circle_x, circle_y, 'm--');
title('Animación: Vectores y Circunferencia Osculatriz');
xlabel('x'); ylabel('y');
axis equal; grid on;
pause(0.1);
end
5 Representación de la curva de Bézier tridimensional, junto con la curva poligonal que conecta los cuatro puntos que están en el espacio tridimensional y no pertenecen al mismo plano.
% Curva de Bézier Cúbica en 3D
% Demuestra una curva de Bézier con puntos de control no coplanares
% Definición de puntos de control en el espacio 3D
% Elegimos puntos que claramente no están en el mismo plano
P0 = [0, 0, 0]; % Origen
P1 = [2, 3, 1]; % Primer punto de control con elevación
P2 = [4, 1, 3]; % Segundo punto de control con diferente elevación
P3 = [6, 4, 0]; % Punto final con variación en z
% Matriz de puntos de control
controlPoints = [P0; P1; P2; P3];
% Función para calcular punto de Bézier
function P = bezierPoint(controlPoints, t)
n = size(controlPoints, 1) - 1;
P = zeros(1, 3);
for i = 0:n
b = nchoosek(n, i) * (t^i) * ((1-t)^(n-i));
P = P + b * controlPoints(i+1, :);
end
end
% Generar puntos de la curva
numPoints = 100;
t = linspace(0, 1, numPoints);
curvePoints = zeros(numPoints, 3);
for i = 1:numPoints
curvePoints(i, :) = bezierPoint(controlPoints, t(i));
end
% Configuración de la visualización
figure;
hold on;
grid on;
axis equal;
% Graficar la curva de Bézier
plot3(curvePoints(:,1), curvePoints(:,2), curvePoints(:,3), 'b-', 'LineWidth', 2);
% Graficar la curva poligonal (polígono de control)
plot3(controlPoints(:,1), controlPoints(:,2), controlPoints(:,3), 'ro-', 'LineWidth', 1.5);
% Decorar los puntos de control
scatter3(controlPoints(:,1), controlPoints(:,2), controlPoints(:,3), 100, 'r', 'filled');
% Etiquetar los puntos de control
labels = {'P0', 'P1', 'P2', 'P3'};
for i = 1:length(labels)
text(controlPoints(i,1), controlPoints(i,2), controlPoints(i,3), ...
labels{i}, 'FontSize', 10, 'FontWeight', 'bold');
end
% Configuraciones finales de la figura
title('Curva de Bézier Cúbica en 3D');
xlabel('Eje X');
ylabel('Eje Y');
zlabel('Eje Z');
view(45, 30); % Ángulo de vista para mejor perspectiva 3D
legend('Curva de Bézier', 'Polígono de Control');
hold off;
% Información adicional sobre los puntos de control
disp('Puntos de Control:');
for i = 1:size(controlPoints, 1)
fprintf('P%d: [%.2f, %.2f, %.2f]\n', i-1, controlPoints(i,:));
end
% Verificación de que los puntos no son coplanares
% Calculamos el volumen del tetraedro formado por los puntos
function vol = tetrahedronVolume(A, B, C, D)
% Matriz de vectores
M = [B-A; C-A; D-A];
% Volumen =
6 Representación de los gráficos de la curvatura y de la torsión como funciones del parámetro [math]t[/math].
Una vez la curva de Bézier tridimensional junto a su curva poligonal han sido representadas, se continuará con la representación de la curvatura y la torsión como funciones del parámetro [math]t[/math].
Empezando por la curvatura ([math]\kappa(t)[/math]), que marca cuanto se desvía la recta tangente a lo largo de la curva, que en otros palabras sería cuánto cambia la curvatura en el plano, y se calcula en función de la siguiente expresión:
Siendo [math] \mathbf{B}'(t) [/math] la primera derivada de la curva en función de [math]t[/math], y [math] \mathbf{B}''(t) [/math] la segunda derivada en funcón de [math] t [/math].
Por tanto , [math] \|\mathbf{B}'(t) \times \mathbf{B}''(t)\| [/math] equivale a la norma del producto mixto de la primera y la segunda derivada de la curva [math] \mathbf{B}(t) [/math].
Por otro lado, encontramos la torsión([math] \tau(t)[/math]) que mide cuánto cambia la orientación del plano tangente a lo largo de la curva, y sigue la siguiente expresión:
Dónde [math] \mathbf{B}'(t) [/math] vuelve a ser la primera derivada de la curva en función de [math]t[/math], y [math] \mathbf{B}''(t) [/math] la segunda derivada de la curva en funcón de [math] t [/math], además, aparec también [math] \mathbf{B}'''(t) [/math] que sería la tercera derivada de la curva.
También como se puede observar en la expresión, hay un producto vectorial por un producto escalar, eso se convierte en un producto mixto y se resuelve como el determinante de las tres derivadas de la curva en este caso como se ve en el desarrollo de la expresión.
Para la representación, se ha utilizado el siguiente código:
% Visualización de la curva de Bézier 3D
% Puntos de control en el espacio tridimensional (no coplanarios)
P = [0 0 0; 2 3 1; 4 1 3; 6 4 0];
% Número de puntos para la curva
n = 100;
t = linspace(0, 1, n);
% Función para trabajar con el polinomio de Bernstein
function b = bernstein(i, n, t)
b = nchoosek(n, i) * (t.^i) .* ((1-t).^(n-i));
end
% Inicializamos la curva de Bézier
curve = zeros(n, 3);
% Calculamos los puntos de la curva de Bézier
for i = 1:size(P, 1)
curve = curve + bernstein(i-1, size(P, 1)-1, t)' .* P(i, :);
end
% Primera derivada
d1 = zeros(n, 3);
for i = 1:size(P, 1)-1
d1 = d1 + (size(P, 1)-1) * bernstein(i-1, size(P, 1)-2, t)' .* (P(i+1, :) - P(i, :));
end
% Segunda derivada
d2 = zeros(n, 3);
for i = 1:size(P, 1)-2
d2 = d2 + (size(P, 1)-1)*(size(P, 1)-2) * bernstein(i-1, size(P, 1)-3, t)' .* ...
(P(i+2, :) - 2*P(i+1, :) + P(i, :));
end
% Tercera derivada (para calcular la torsión)
d3 = zeros(n, 3);
for i = 1:size(P, 1)-3
d3 = d3 + (size(P, 1)-1)*(size(P, 1)-2)*(size(P, 1)-3) * bernstein(i-1, size(P, 1)-4, t)' .* ...
(P(i+3, :) - 3*P(i+2, :) + 3*P(i+1, :) - P(i, :));
end
% Calculamos la curvatura
tangent = d1 ./ vecnorm(d1, 2, 2);
curvature = vecnorm(cross(d1, d2), 2, 2) ./ (vecnorm(d1, 2, 2).^3);
% Calculamos la torsión
torsion = zeros(n, 1);
for i = 1:n
torsion(i) = dot(cross(d1(i,:), d2(i,:)), d3(i,:)) / norm(cross(d1(i,:), d2(i,:)))^2;
end
% Trazamos la gráfica
figure('Position', [100, 100, 1200, 800]);
% Curva 3D con polígono de control
subplot(2, 2, [1 3]);
% Curva de Bézier
plot3(curve(:,1), curve(:,2), curve(:,3), 'b-', 'LineWidth', 2);
hold on;
% Polígono de control
plot3(P(:,1), P(:,2), P(:,3), 'ro-', 'MarkerFaceColor', 'r');
title('Curva de Bézier');
xlabel('X'); ylabel('Y'); zlabel('Z');
grid on;
view(45, 30);
% Gráfico de curvatura
subplot(2, 2, 2);
plot(t, curvature, 'b-', 'LineWidth', 2);
title('Curvatura');
xlabel('t'); ylabel('Curvatura');
grid on;
% Gráfico de torsión
subplot(2, 2, 4);
plot(t, torsion, 'r-', 'LineWidth', 2);
title('Torsión');
xlabel('t'); ylabel('Torsión');
grid on;
sgtitle('Curvatura y torsión en función de t');
7 Animación que representa el triedro de Frenet que se mueve a lo largo de la curva.
Tras haber representado la curva, pasamos al triedro de Frenet que es un conjunto de tres vectores que se utilizan para describir el comportamiento geométrico de una curva en el espacio tridimensional. Estas vectores son:
el vector [math] \overrightarrow{T} [/math] que hace referencia al vector tangente a lo largo de la curva [math] \mathbf{B}(t) [/math]
el vector [math] \overrightarrow{n} [/math] que es el vector normal que esta orientado a la dirección en la que está curvando cada punto de la curva [math] \mathbf{B}(t) [/math]
y por último, el vector [math] \overrightarrow{BN} [/math] que es es vector binormal y es perpendicular a [math] \overrightarrow{T} [/math] y [math] \overrightarrow{N} [/math], y se calcula tal que : [math] \overrightarrow{BN} = {\overrightarrow{T} \times \overrightarrow{N}} [/math]
Una vez definido lo que es y los vectores que lo componen, se representa, gracias al programa MATLAB, una animación del Triedro de Frenet a lo largo de la curva, dónde se utilizó el siguiente código para su realización:
% Frenet Trihedral Animation for 3D Bézier Curve
% Control points in 3D space (non-coplanar)
P = [0 0 0; 1 2 1; 3 1 2; 4 3 3];
% Number of points for smooth curve
n = 100;
t = linspace(0, 1, n);
% Function to compute binomial coefficient
function b = binomial_coef(n, k)
b = factorial(n) / (factorial(k) * factorial(n-k));
end
% Function to compute Bernstein polynomial
function b = bernstein(i, n, t)
b = binomial_coef(n, i) * (t.^i) .* ((1-t).^(n-i));
end
% Compute Bézier curve points
curve = zeros(n, 3);
for i = 1:size(P, 1)
curve = curve + bernstein(i-1, size(P, 1)-1, t)' .* P(i, :);
end
% First derivative
d1 = zeros(n, 3);
for i = 1:size(P, 1)-1
d1 = d1 + (size(P, 1)-1) * bernstein(i-1, size(P, 1)-2, t)' .* (P(i+1, :) - P(i, :));
end
% Second derivative
d2 = zeros(n, 3);
for i = 1:size(P, 1)-2
d2 = d2 + (size(P, 1)-1)*(size(P, 1)-2) * bernstein(i-1, size(P, 1)-3, t)' .* ...
(P(i+2, :) - 2*P(i+1, :) + P(i, :));
end
% Compute Frenet frame
tangent = d1 ./ vecnorm(d1, 2, 2);
normal = cross(d2, d1) ./ (vecnorm(d1, 2, 2).^2);
binormal = cross(tangent, normal);
% Normalize vectors
normal = normal ./ vecnorm(normal, 2, 2);
binormal = binormal ./ vecnorm(binormal, 2, 2);
% Prepare animation
figure('Position', [100, 100, 1000, 800]);
axis equal;
hold on;
grid on;
% Plot Bézier curve
plot3(curve(:,1), curve(:,2), curve(:,3), 'b-', 'LineWidth', 2);
plot3(P(:,1), P(:,2), P(:,3), 'ro-', 'MarkerFaceColor', 'r');
% Animation of Frenet trihedral
title('Animación Triedro de Frenet');
xlabel('X'); ylabel('Y'); zlabel('Z');
% Vector length for visualization
vector_length = 0.3;
% Create lines for vectors
tangent_line = line([0 0], [0 0], [0 0], 'Color', 'r', 'LineWidth', 2);
normal_line = line([0 0], [0 0], [0 0], 'Color', 'g', 'LineWidth', 2);
binormal_line = line([0 0], [0 0], [0 0], 'Color', 'm', 'LineWidth', 2);
% Animation
view(80, 60);
for i = 1:n
% Update vector lines
set(tangent_line, 'XData', [curve(i,1), curve(i,1) + vector_length*tangent(i,1)], ...
'YData', [curve(i,2), curve(i,2) + vector_length*tangent(i,2)], ...
'ZData', [curve(i,3), curve(i,3) + vector_length*tangent(i,3)]);
set(normal_line, 'XData', [curve(i,1), curve(i,1) + vector_length*normal(i,1)], ...
'YData', [curve(i,2), curve(i,2) + vector_length*normal(i,2)], ...
'ZData', [curve(i,3), curve(i,3) + vector_length*normal(i,3)]);
set(binormal_line, 'XData', [curve(i,1), curve(i,1) + vector_length*binormal(i,1)], ...
'YData', [curve(i,2), curve(i,2) + vector_length*binormal(i,2)], ...
'ZData', [curve(i,3), curve(i,3) + vector_length*binormal(i,3)]);
drawnow;
pause(0.05);
end
8 Aplicación de una curva de Bézier al tramo de un circuito de [math]F_1[/math].
La velocidad escalar constante [math]ν_0[/math] que debe mantener un Ferrari F2004 para no salirse de la pista en ningún punto de un circuito con el trazado de una curva de Bézier, debe ser tal que la fuerza centrípeta [math]F_c=mκν^2[/math] no exceda la fuerza máxima de fricción [math]F_{\text{fricción}}=μmg[/math].
Siendo [math]m[/math] la masa del Ferrari, [math]κ[/math] la curvatura de la pista, [math]g[/math] la aceleración de la gravedad y [math]μ[/math] el coeficiente de fricción entre los neumáticos y la pista (se asume igual a 1.5).
Esto implica que [math]F_c≤F_{\text{fricción}}→κν^2≤μg[/math]
Para que la velocidad sea constante y segura se tomará el valor máximo de [math]κ(t)[/math] a lo largo del intervalo [math]t∈[0,1][/math]. Así pues: [math]ν_0≤\sqrt{\frac{μg}{κ_{\text{máx}}}}[/math]
Como ya se ha mencionado en apartados anteriores, para calcular la curvatura [math]κ(t)[/math] se necesitan la primera y la segunda derivada de [math]B[/math]: [math] \kappa(t) = \frac{\|\mathbf{B}'(t) \times \mathbf{B}''(t)\|}{\|\mathbf{B}'(t)\|^3} [/math]
Siendo B para [math]n=3[/math](por la fórmula general de las curvas de Bézier): [math]B=(1-t)^3P_0+3t(1-t)^2P_1+3t^2(1-t)P_2+t^3P_3[/math]
Además se tendrán en cuenta los siguientes puntos de control: [math]P_0 =[0,0,0], P_1 = [30,50,5], P_2 = [60,−30,−10], P_3 = [100,0,0][/math].
Analizando el problema con la siguiente animación 3D de la curva, el programa
nos devuelve el valor máximo de velocidad escalar constante posible para que el Ferrari no se salga de la pista: [math]24,1569[/math] [math]m/s[/math]
Por otro lado, la aceleración centrípeta en curvas es: [math]a_c=\frac{ν_0^2}{r}[/math]. Sabiendo que: [math]r=\frac{1}{κ(t)}[/math]. Entonces: [math]a_c=ν_0^2·κ(t)[/math]
Si esta se multiplica por el vector normal unitario a la curva de Bézier, se obtiene el vector aceleración centrípeta en la animación (radial, siempre apuntando al centro de la curvatura y perpendicular a la velocidad, que es tangencial)
% Puntos de control
P0 = [0, 0, 0];
P1 = [30, 50, 5];
P2 = [60, -30, -10];
P3 = [100, 0, 0];
% Constantes
mu = 1.5; % Coeficiente de fricción
g = 9.81; % Aceleración gravitatoria (m/s^2)
% Funciones de la curva de Bézier y derivadas
function B = bezier(t, P0, P1, P2, P3)
B = (1 - t)^3 * P0 + 3 * t * (1 - t)^2 * P1 + 3 * t^2 * (1 - t) * P2 + t^3 * P3;
end
function Bp = bezier_prime(t, P0, P1, P2, P3)
Bp = -3 * (1 - t)^2 * P0 + (3 * (1 - t)^2 - 6 * t * (1 - t)) * P1 ...
+ (6 * t * (1 - t) - 3 * t^2) * P2 + 3 * t^2 * P3;
end
function Bpp = bezier_double_prime(t, P0, P1, P2, P3)
Bpp = 6 * (1 - t) * P0 + (6 - 12 * t) * P1 + (6 * t - 12 * t + 6) * P2 - 6 * t * P3;
end
function k = curvature(t, P0, P1, P2, P3)
Bp = bezier_prime(t, P0, P1, P2, P3);
Bpp = bezier_double_prime(t, P0, P1, P2, P3);
cross_prod = norm(cross(Bp, Bpp));
norm_Bp = norm(Bp);
if norm_Bp == 0
k = 0;
else
k = cross_prod / (norm_Bp^3);
end
end
% Discretización de la curva
t_values = linspace(0, 1, 500);
curve = arrayfun(@(t) bezier(t, P0, P1, P2, P3), t_values, 'UniformOutput', false);
curve = cell2mat(curve')';
% Cálculo de la curvatura
curvatures = arrayfun(@(t) curvature(t, P0, P1, P2, P3), t_values);
% Velocidad máxima segura
kappa_max = max(curvatures);
v0 = sqrt(mu * g / kappa_max);
% Mostrar resultado
disp(['Velocidad máxima segura (v0): ', num2str(v0), ' m/s']);
% Crear figura
figure;
hold on;
grid on;
plot3(curve(1, :), curve(2, :), curve(3, :), 'b-', 'LineWidth', 2);
title('Curva de Bézier y animación del coche');
xlabel('X (m)');
ylabel('Y (m)');
zlabel('Z (m)');
view(3); % Vista 3D
% Congelar los límites de los ejes
axis([min(curve(1, :)) max(curve(1, :)) ...
min(curve(2, :)) max(curve(2, :)) ...
min(curve(3, :)) max(curve(3, :))]);
% Crear los vectores para animación
h_vel = quiver3(0, 0, 0, 0, 0, 0, 'r', 'LineWidth', 2); % Vector velocidad
h_ac = quiver3(0, 0, 0, 0, 0, 0, 'g', 'LineWidth', 2); % Vector aceleración centrípeta
% Animar la curva
for i = 1:10:length(t_values) % Aumentar el paso para controlar la velocidad de animación
t = t_values(i);
% Posición, velocidad y aceleración centrípeta
pos = bezier(t, P0, P1, P2, P3);
Bp = bezier_prime(t, P0, P1, P2, P3);
Bpp = bezier_double_prime(t, P0, P1, P2, P3);
% Dirección del vector normal (centrípeta)
normal_vec = cross(Bp, Bpp);
normal_vec = normal_vec / norm(normal_vec); % Normalizar
ac = curvature(t, P0, P1, P2, P3) * v0^2 * normal_vec;
% Actualizar la posición de los vectores
set(h_vel, 'XData', pos(1), 'YData', pos(2), 'ZData', pos(3), ...
'UData', Bp(1), 'VData', Bp(2), 'WData', Bp(3));
set(h_ac, 'XData', pos(1), 'YData', pos(2), 'ZData', pos(3), ...
'UData', ac(1), 'VData', ac(2), 'WData', ac(3));
% Pausa para crear la animación
pause(0.05);
end
legend('Curva Bézier', 'Velocidad', 'Aceleración centrípeta');
hold off;