Ejercicio obligatorio 3
Fecha de entrega: Domingo 8 de octubre
Nota
Nunca es buena idea empezar por un ejercicio integrador antes de tener practicados los temas que el trabajo integra.
Se sugiere antes de desarrollar este trabajo resolver, al menos, los siguientes ejercicios de la guía de Memoria dinámica:
Ejercicio 12 (combinar vectores).
Ejercicio 14.a (matriz identidad).
Ejercicio 16 con el 1.b y 1.c de la guía de estructuras (dirección y persona).
Introducción
Queremos modelar una curva de Bézier, para ello definimos la estructura:
typedef struct {
float (*puntos)[2];
size_t n_puntos;
size_t grado;
} bezier_t;
que permite almacenar en memoria una lista de puntos según el siguiente esquema:
Trabajo
Creación y destrucción
Se pide implementar la función bezier_t *bezier_crear(size_t grado);
que genere la memoria necesaria para una curva de Bézier. Como la curva se crea
sin ningún punto, el puntero puntos
debe ser inicializado a NULL
.
La función debe devolver la curva creada o NULL
en caso de falla.
Se pide implementar la función void bezier_destruir(bezier_t *bezier);
que libere la memoria asociada a la bezier
previamente creada.
Tramos
Se pide implementar la función
size_t bezier_cantidad_tramos(const bezier_t *bezier);
que en función
de la cantidad de puntos que tenga la curva de bezier
y su grado diga cuántos
tramos pueden generarse.
Nota
La relación entre grado, puntos y tramos está en el enunciado del EJ2.
Manipulación
Se pide implementar la función
bool bezier_agregar_punto(bezier_t *bezier, float x, float y);
que
agregue un punto de coordenadas (x, y)
a la curva de bezier
recibida. La
función debe devolver true
de poder realizar la operación correctamente.
Se pide implementar la función
bezier_t *bezier_clonar(const bezier_t *bezier);
que devuelva una copia
de bezier
en memoria nueva o NULL
en caso de falla.
Evaluación
Implementar una función
bool bezier_evaluar(const bezier_t *bezier, double t, double *x, double *y);
que evalúe la curva de bezier
en un t
dado. La función debe devolver el
valor de x
e y
en ese punto por la interfaz y por el nombre debe devolver
true
si el valor de t
era válido.
El valor de t
será un número entre 0 y la cantidad de tramos de la curva.
Valores de t
entre 0 y 1 interpolarán el primer tramo, entre 1 y 2 el segundo
tramo, etc.
Aplicación y validación
Se provee el código fuente de la función main()
que realiza llamadas a cada
una de estas funciones. Dicha función debe ser la que se entregue como parte
del trabajo sin efectuarle modificaciones de ningún tipo
#include <stddef.h>
#include <assert.h>
typedef struct {
float (*puntos)[2];
size_t n_puntos;
size_t grado;
} bezier_t;
int main(void) {
float ps[][2] = {
{0.17305465, 10.136934},
{0.19149611, 23.287691},
{12.230908, 23.62676},
{15.632344, 15.423703},
{15.632344, 15.423703},
{13.223768, 15.479423},
{13.223768, 15.479423},
{7.7396987, 22.246678},
{2.9096797, 16.657932},
{2.7566421, 10.345005},
{2.6054406, 4.1079585},
{8.3739896, -0.49167977},
{13.273927, 5.6239999},
{13.273927, 5.6239999},
{16.023752, 5.5849339},
{16.023752, 5.5849339},
{13.505533, -1.4803139},
{0.15461584, -3.0138257},
{0.17305465, 10.136934},
};
bezier_t *bezier = bezier_crear(3);
assert(bezier != NULL);
assert(bezier_cantidad_tramos(bezier) == 0);
for(int i = 0; i < sizeof(ps) / sizeof(ps[0]); i++)
assert(bezier_agregar_punto(bezier, ps[i][0], ps[i][1]));
assert(bezier_cantidad_tramos(bezier) == 6);
bezier_t *clon = bezier_clonar(bezier);
assert(clon != NULL);
bezier_destruir(bezier);
assert(bezier_cantidad_tramos(clon) == 6);
for(double t = 0; t <= bezier_cantidad_tramos(clon); t += 0.01) {
double x, y;
assert(bezier_evaluar(clon, t, &x, &y));
printf("%f,%f\n", x, y);
}
double aux;
assert(!bezier_evaluar(clon, -0.1, &aux, &aux));
assert(!bezier_evaluar(clon, 7.1, &aux, &aux));
bezier_destruir(clon);
return 0;
}
El programa al ser invocado deberá pasar los asserts dados. La salida del programa es la misma C del ejercicio 2.
Entrega
Deberá entregarse el código fuente del programa desarrollado.
El programa debe:
Compilar correctamente con los flags:
-Wall -Werror -std=c99 -pedantic
pasar Valgrind correctamente,
validar los asserts.
La entrega se realiza a través del sistema de entregas.
El ejercicio es de entrega individual.