TP1 NIzza, Ponti, Pereyra

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 28

UNIVERSIDAD TECNOLÓGICA NACIONAL

FACULTAD REGIONAL PARANÁ

Carrera: INGENIERIA ELECTRONICA

Materia: Informática 2– Comisión: “2R1”

Actividad Grupal Nº: 1.

Tema: Trabajo practica 1.

Equipo de Cátedra:
• Burgos Sergio

• Lencina Adrián

Integrantes Grupo:

• Pereyra, Agustín

• Nizza, Tomás

• Ponti, Pedro

Mail Responsable de Seguimiento: [email protected]

Fecha de Entrega: 28 / 06 / 2024


Parte I: Interfaz de comandos
Para empezar con la explicación debemos saber los pasos a realizar.
Debemos ajustar el código que nos proporcionó el profesor en el ej01 a fin de que funcione en una terminal de
comandos con la ESP32, agregando además funciones para prender, apagar y parpadear el led de la ESP32. A
continuación mostraremos los códigos main.c, menú.c, hardware.c, hardware.h y menú.h.
Cabe mencionar que fin de implementarlos en la interfaz de comandos en el microcontrolador a través de una
terminal serie utilizamos el programa Visual Studio Code, donde los .h están en la carpeta include del proyecto y los
.c están en la carpeta src del proyecto.
Main.c:
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include "hardware.h"
#include "menu.h"

void getLine(char *buffer, size_t length) {


size_t index = 0;
unsigned char ch;

while (index < length - 1) {


ch = fgetc(stdin);

if (ch == 0xFF) {
vTaskDelay(10 / portTICK_PERIOD_MS);
continue;
}

if (ch == '\n' || ch == '\r') {


break;
}

if (ch == 8 || ch == 127) { // 8 es el código ASCII para backspace y 127 es el


código ASCII para DEL
if (index > 0) {
index--;
printf("\b \b"); // Mueve el cursor una posición atrás, imprime un
espacio y vuelve a mover el cursor atrás
}
} else {
buffer[index++] = ch;
fputc(ch, stdout); // Repite el personaje de nuevo al usuario.
}
}
buffer[index] = '\0';
}

void app_main()
{
bool appClose = false;
bool cmdOk;
int argc;
unsigned k;
char line[120];
unsigned lineLength;
char * argv[60];
const cmd *c;
hardware_init();
vTaskDelay(500 / portTICK_PERIOD_MS);
printf("=========== Programa Iniciado ============\n");
c = getCommands();
while(!appClose){
printf(">");
getLine(line,119);
printf("\n");
argc = 1;
line[strlen(line)] = '\0';
argv[0] = line;
lineLength = strlen(line);
for(k = 0; (k < lineLength) && (argc < 60); k++){
if(line[k] == ' '){
line[k] = '\0';
argv[argc] = line + k + 1;
argc++;
}
}
cmdOk = false;
k = 0;
while(c[k].act){
if(strcmp(c[k].keyWord, argv[0]) == 0){
cmdOk = true;
if(c[k].act(argc, argv))
printf(" [%s Fail]\n", argv[0]);
}
k++;
}
if(!cmdOk && strlen(argv[0]))
printf("Comando inexistente\n");
}
esp_restart();
}

Como se puede notar no hay muchas diferencias entre este main con el que nos dio el profesor en el ejemplo de QT,
una diferencia seria el ingreso de los datos ya que se hace por medio de la función getLine (que lee caracteres del
teclado hasta encontrar una nueva línea, retorno de carro o alcanzar el tamaño máximo del buffer, maneja los
caracteres de retroceso y borrado, y almacena la entrada en un buffer proporcionado por el usuario, terminándola
con un carácter nulo), cuando en el ejemplo de QT era por un fgets
Menu.c:
#include "menu.h"
#include "hardware.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

static bool appClose = false;

static const cmd commands [] = {


{sumar, "sumar", "Suma dos valores dados como argumentos de línea de órdenes"},
{restar, "restar", "Suma dos valores dados como argumentos de línea de órdenes"},
{exitCmd, "exit", "Finaliza el intérprete de comandos"},
{help, "help", "Brinda información sobre los comandos disponibles"},
{multiplicar,"mul", "Multiplica 2 valores como argumentos de linea de ordenes"},
{led,"led","Para encender 'on'. Para apagar 'off'. Para parpadear 'parpadear'"},
{NULL, NULL, NULL}
};

int led(int argc, char * argv[]){


int ret,i;
char v1[10];
if (argc == 2){
sscanf(argv[1], "%9s", v1);
if (strcmp(v1, "on") == 0) {
ledOn();
ret = 0;
} else if (strcmp(v1, "off") == 0) {
ledOff();
ret = 0;
} else if (strcmp(v1,"parpadear") == 0){
for (i = 0; i < 3; i++) {
ledOn();
vTaskDelay(300 / portTICK_PERIOD_MS); // 300 milisegundos
ledOff();
vTaskDelay(300 / portTICK_PERIOD_MS); // 300 milisegundos
}
ret = 0;
}
else {
printf("Argumento invalido: %s\n", v1);
ret = -1;
}
}
else{
printf("Cantidad de argumentos incorrecta");
ret = -1;
}
return ret;
}

int sumar(int argc, char * argv[]){


float v1;
float v2;
int ret;
if (argc == 3){
sscanf(argv[1], "%f", &v1);
sscanf(argv[2], "%f", &v2);
printf("%.2f + %.2f = %.2f\n", v1, v2, v1 + v2);
ret = 0;
}
else{
printf("Canidad de argumentos incorrecta");
ret = -1;
}
return ret;
}

int multiplicar(int argc, char * argv[]){


float v1;
float v2;
int ret;
if (argc == 3){
sscanf(argv[1], "%f", &v1);
sscanf(argv[2], "%f", &v2);
printf("%.2f * %.2f = %.2f\n", v1, v2, v1 * v2);
ret = 0;
}
else{
printf("Canidad de argumentos incorrecta");
ret = -1;
}
return ret;
}

int restar(int argc, char * argv[]){


float v1;
float v2;
int ret;
if (argc == 3){
sscanf(argv[1], "%f", &v1);
sscanf(argv[2], "%f", &v2);
printf("%.2f - %.2f = %.2f\n", v1, v2, v1 - v2);
ret = 0;
}
else{
printf("Cantidad de argumentos incorrecta");
ret = -1;
}
return ret;
}

int exitCmd(int argc , char * argv[]){


appClose = true;
return 0;
}

int help(int argc, char * argv[]){


int k = 0;
while(commands[k].act){
printf("\t[%6s] : %s\n", commands[k].keyWord, commands[k].help);
k++;
}
return 0;
}

const cmd * getCommands(void){


return commands;
}

Para este menu.c agregamos la función multiplicar (que la pedía a fin de entender el funcionamiento) y la función led
(que tiene como fin utilizar el led de la ESP32). Para hacer la función led tomamos como referencia las funciones
anteriores, tiene que devolver un 1 (en caso de éxito en la implementación) o -1 (en caso de falla), como vemos
compara el segundo argumento(argv[1]) con las palabras “off”, “on” y “parpadear” ya que esos son los 3 comandos
solicitados, si es así ejecuta la función requerida, la función “ledOn()” y “ledOff()” las reutilizamos de los ejemplos de
las clase 3. Las demás funciones son las mismas utilizadas en el ejemplo de QT que nos dio el profe.

Hardware.c:
#include "hardware.h"
#include <driver/gpio.h>

#define ledPin GPIO_NUM_2

void hardware_init(void){
gpio_config_t gpioLed =
{
.pin_bit_mask = 1ULL << ledPin,
.mode = GPIO_MODE_DEF_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
ESP_ERROR_CHECK(gpio_config(&gpioLed));
ledOff();
}
void ledOn(void){
ESP_ERROR_CHECK(gpio_set_level(ledPin, 1));
}

void ledOff(void){
ESP_ERROR_CHECK(gpio_set_level(ledPin, 0));
}

El campo pin bit mask contiene 64 posiciones, la primera corresponde con el pin 0 (GPIO NUM 0), la siguiente con el
pint 1 (GPIO NUM 1) y asi sucesivamente hasta el pin 39 (GPIO NUM 39). Cuando se ponen unos en esas posiciones,
se indica que esos pines recibiran la configuracion indicada. La función “hardware_init” configura un pin GPIO en la
ESP32 como una salida sin resistencias pull-up ni pull-down y sin interrupciones. Después de configurar el pin, apaga
el LED utilizando la función “ledOff”.
Hardware.h:
#ifndef hardware_h
#define hardware_h

void hardware_init(void);
void ledOn(void);
void ledOff(void);

#endif

Menú.h:
#ifndef MENU_H
#define MENU_H
#include <stdio.h>
#include <stdbool.h>
typedef int (*pAction)(int, char **);

typedef struct {
pAction act;
char *keyWord;
char *help;
} cmd;
int sumar(int argc, char * argv[]);
int multiplicar (int argc, char *argv[]);
int restar(int argc, char * argv[]);
int exitCmd(int argc, char * argv[]);
int help(int argc, char * argv[]);
int led(int argc, char * argv[]);

const cmd * getCommands(void);


#endif // MENU_H
Doxygen:

Lo primero que hicimos fue documentar los archivos de cabecera los ¨.h¨:
Menu.h:
/**
* @title menu.
* @file munu.h.
* @version 1.0.
* @date 14/06/2024.
* @author grupoinfo.
*/

#ifndef MENU_H
#define MENU_H
#include <stdio.h>
#include <stdbool.h>

/**
* @brief puntero a funcion
*/
typedef int (*pAction)(int, char **);
/**
* @brief hace funcionar el menu.
*/
typedef struct {
pAction act;
char *keyWord;
char *help;
} cmd;
/**
* @brief sumar la funcion suma
* @param argc dica la cantidad de argumentos en la llamada de línea de comandos.
* @param argv es una matriz de cadenas que contiene los argumentos en la llamada de
línea de comandos.
* @return Una descripción del valor de retorno de la función.
*/
int sumar(int argc, char * argv[]);
/**
* @brief multiplicar funcion multiplicar
* @param argc :Este es un parámetro de la función que indica la cantidad de argumentos
en la llamada de línea de comandos.
* @param argv :Este es un parámetro de la función que es una matriz de cadenas que
contiene los argumentos en la llamada de línea de comandos.
* @return devuelve el resultado de una operación.
*/
int multiplicar (int argc, char *argv[]);
/**
* @brief restar funcion de resta
* @param argc :Este es un parámetro de la función que indica la cantidad de argumentos
en la llamada de línea de comandos.
* @param argv :Este es un parámetro de la función que es una matriz de cadenas que
contiene los argumentos en la llamada de línea de comandos.
* @return Una descripción del valor de retorno de la función.
*/
int restar(int argc, char * argv[]);
/**
* @brief exitCmd la operación de salida del programa
* @param argc :Este es un parámetro de la función que indica la cantidad de argumentos
en la llamada de línea de comandos.
* @param argv :Este es un parámetro de la función que es una matriz de cadenas que
contiene los argumentos en la llamada de línea de comandos.
* @return retorno de la función.
*/
int exitCmd(int argc, char * argv[]);
/**
* @brief help proporcione ayuda al usuario.
* @param argc :Este es un parámetro de la función que indica la cantidad de argumentos
en la llamada de línea de comandos.
* @param argv :Este es un parámetro de la función que es una matriz de cadenas que
contiene los argumentos en la llamada de línea de comandos.
* @return retorno de la función.
*/
int help(int argc, char * argv[]);
/**
* @brief led maneje la operación de un LED
* @param argc :Este es un parámetro de la función que indica la cantidad de argumentos
en la llamada de línea de comandos.
* @param argv :Este es un parámetro de la función que es una matriz de cadenas que
contiene los argumentos en la llamada de línea de comandos.
* @return retorno de la función.
*/
int led(int argc, char * argv[]);
/**
* @brief getCommands devuelve un puntero a una matriz de estructuras
* @return retorno de la función.
*/

const cmd * getCommands(void);


#endif // MENU_H

Hardware.h:
/**
*@title hardware.
* @file hardware.h.
* @version 1.0.
* @date 14/06/2024.
* @author grupoinfo.
*/

#ifndef hardware_h
#define hardware_h
/**
* @brief hardware_init :Esta función inicializa el hardware, habilitada para la
iluminación del LED.
*/
void hardware_init(void);
/**
* @brief ledOn :Esta función enciende el LED.
*/
void ledOn(void);
/**
* @brief ledOff :Esta función enciende el LED.
*/
void ledOff(void);

#endif

Después documentamos los archivos en doxygen, tuvimos que poner un título del proyecto,
también de que se trataba el código, después pusimos la ruta del código fuente y también ruta de
donde queríamos que se guarde el programa.
Pagina principal:

Clases:
Archivos:
Parte II: Resolución de ecuaciones

Para empezar con la explicación debemos tener en cuenta las funciones que nos da el enunciado.
Curva catenaria: Longitud del cable:
𝑥 𝑥
𝑓 (𝑥 ) = 𝑐 ∗ (cosh ( ) − 1) 𝑠 = 2 ∗ 𝑐 ∗ 𝑠𝑒𝑛ℎ ( )
𝑐 𝑐
Para este caso los valores usados son x = 50, que es la mitad de la distancia entre los postes y f(x) = 2, que es la
longitud de la catenaria, distancia entre el punto más bajo y más alto. Con lo cual la función de la catenaria dad es la
siguiente:
50
2 = 𝑐 ∗ (cosh ( ) − 1)
𝑐
Para poder realizar el método de punto fijo, hay que despejar “c”. A continuación, vamos a mostrar 2 formas en la
cual se puede expresar la ecuación para poder realizar el método de punto fijo.
Despeje 1 Despeje 2
50 Dividimos todo por “c”
2 = 𝑐 ∗ (cosh ( ) − 1) 50
𝑐
50 2 𝑐 ∗ (cosh ( 𝑐 ) − 1)
0 = 𝑐 ∗ cosh ( ) − 𝑐 − 2 =
𝑐 𝑐 𝑐
2 50
+ 1 = cosh ( )
50 𝑐 𝑐
𝑐 = 𝑐 ∗ cosh ( ) − 2 2 50
𝑐 𝑐𝑜𝑠ℎ−1 ( + 1) =
𝑐 𝑐

50
𝑐=
2
𝑐𝑜𝑠ℎ−1 ( + 1)
𝑐

De las 2 formas funciona, solo que usando el despeje 1 necesita muchas mas iteraciones para poder llegar al mismo
valor de c. Pero el inconveniente que tenemos es que, al usar la ecuación de menos iteraciones, el despeje 2, luego
no nos sirve para usar el método de la bisección, ya que el primer valor que retorna esta fuera del intervalo en el
cual el método de la bisección puede trabajar para obtener el mismo valor de c. Así que por ese motivo vamos a usar
la ecuación del despeje 1 para que puedan funcionar los otros 2 métodos.

Después de esa aclaración vamos al código, mostraremos primero los .h de cada clase y a continuación los .cpp de
las respectivas clases. Y por último el main.cpp:

MetodoNumerico.h:
#ifndef METODO_NUMERICO_H
#define METODO_NUMERICO_H

#include <cmath>

class MetodoNumerico {
protected:
double distPostesDiv2;
double longCatenaria;
double c; // Constante c
double longitudCable; // Longitud del cable

public:
MetodoNumerico(double distPostesDiv2, double longCatenaria);
double getConstanteC();
double getLongitudCable();
// Función con c despejada
double ecuacion(double c, double x, double fx);
// Función igualada a 0
double ecuacion2(double c, double x, double fx);
double calcularLongitudCable(double c);
};

#endif // METODO_NUMERICO_H

MetodoNumerico.cpp:
#include "metodonumerico.h"

MetodoNumerico::MetodoNumerico(double distPostesDiv2, double longCatenaria){


this->distPostesDiv2 = distPostesDiv2;
this->longCatenaria = longCatenaria;
this->c = 0;
this->longitudCable = 0;
}

double MetodoNumerico::getConstanteC(){
return c;
}

double MetodoNumerico::getLongitudCable(){
return longitudCable;
}

double MetodoNumerico::ecuacion(double c, double x, double fx) {


return c * cosh(x / c) - fx; // despeje 1
}

double MetodoNumerico::ecuacion2(double c, double x, double fx) {


return c * (cosh(x / c) - 1) - fx;
}

double MetodoNumerico::calcularLongitudCable(double c) {
return 2 * c * sinh(distPostesDiv2 / c);
}
Esta clase sirve como una base común para implementar diferentes métodos numéricos (PuntoFijo, Secante y
Bisección) que comparten funcionalidades comunes relacionadas con el cálculo de constante “c” y longitud del cable
“s”.

PuntoFijo.h:
#ifndef PUNTO_FIJO_H
#define PUNTO_FIJO_H

#include "metodonumerico.h"

class PuntoFijo : public MetodoNumerico {


private:
double x0;
int maxIt;
double epsilon;
double* SegundoValor;

public:
PuntoFijo(double x0, int maxIt, double epsilon, double* SegundoValor, double
distPostesDiv2, double longCatenaria);
void CalculoC();
double getConstanteC();
double getLongitudCable();
};

#endif // PUNTO_FIJO_H

PuntoFijo.cpp:
#include "puntofijo.h"
#include <iostream>
using namespace std;

PuntoFijo::PuntoFijo(double x0, int maxIt, double epsilon, double* SegundoValor, double


distPostesDiv2, double longCatenaria)
: MetodoNumerico(distPostesDiv2, longCatenaria) {
this->x0 = x0;
this->maxIt = maxIt;
this->epsilon = epsilon;
this->SegundoValor = SegundoValor;
}

void PuntoFijo::CalculoC() {
double x1 = x0;
int itCnt = 0;
bool finish = false;
cout << "Punto Fijo:" << endl;
cout << "Iteracion x0 x1" << endl;
cout << "---------------------------------------" << endl;
while ((itCnt < maxIt) && (!finish)) {
x1 = ecuacion(x0, distPostesDiv2, longCatenaria);
cout << itCnt + 1 << "\t\t" << x0 << "\t\t" << x1 << endl;
finish = fabs(x1 - x0) < epsilon;
if (itCnt == 0) {
*SegundoValor = x1; // Guarda el primer resultado para el metodo Secante y
Biseccion
}
itCnt++;
x0 = x1;
}
c = x1;
longitudCable = calcularLongitudCable(c);
}

double PuntoFijo::getConstanteC() {
return MetodoNumerico::getConstanteC(); // Llama al método de la clase base
}

double PuntoFijo::getLongitudCable() {
return MetodoNumerico::getLongitudCable(); // Llama al método de la clase base }

Secante.h:
#ifndef SECANTE_H
#define SECANTE_H

#include "metodonumerico.h"
class Secante : public MetodoNumerico{
private:
double x0;
double x1;
double epsilon;
int maxIt;

public:
Secante(double x0, double x1, double epsilon, int maxIt, double distPostesDiv2,
double longCatenaria);
void CalculoC();
double getConstanteC();
double getLongitudCable();
};

#endif // SECANTE_H

Secante.cpp:
#include "secante.h"
#include <iostream>
using namespace std;

Secante::Secante(double x0, double x1, double epsilon, int maxIt, double


distPostesDiv2, double longCatenaria)
: MetodoNumerico(distPostesDiv2, longCatenaria) {
this->x0 = x0;
this->x1 = x1;
this->epsilon = epsilon;
this->maxIt = maxIt;
}

void Secante::CalculoC() {
double x2;
int itCnt = 0;
bool finish = false;
cout << endl << "Secante:" << endl;
cout << "Iteracion x0 x1 x2" << endl;
cout << "-------------------------------------------------------" << endl;
do {
double f_x1 = ecuacion2(x1, distPostesDiv2, longCatenaria);
double f_x0 = ecuacion2(x0, distPostesDiv2, longCatenaria);
x2 = x1 - (f_x1 * (x1 - x0) / (f_x1 - f_x0));
cout << itCnt + 1 << "\t\t" << x0 << "\t\t" << x1 << "\t\t" << x2 << endl;
finish = (fabs(ecuacion2(x2, distPostesDiv2, longCatenaria)) < epsilon) ||
(fabs(x2 - x1) < epsilon);
x0 = x1;
x1 = x2;
itCnt++;
} while ((itCnt < maxIt) && (!finish));
c = x2;
longitudCable = calcularLongitudCable(c);
}

double Secante::getConstanteC() {
return MetodoNumerico::getConstanteC(); // Llama al método de la clase base
}

double Secante::getLongitudCable() {
return MetodoNumerico::getLongitudCable(); // Llama al método de la clase base }
Biseccion.h:
#ifndef BISECCION_H
#define BISECCION_H

#include "metodonumerico.h"

class Biseccion : public MetodoNumerico{


private:
double xi;
double xd;
double epsilon;
int maxIt;

public:
Biseccion(double xi, double xd, double epsilon, int maxIt, double distPostesDiv2,
double longCatenaria);
void CalculoC();
double getConstanteC();
double getLongitudCable();
};

#endif // BISECCION_H

Biseccion.cpp:
#include "biseccion.h"
#include <iostream>
using namespace std;

Biseccion::Biseccion(double xi, double xd, double epsilon, int maxIt, double


distPostesDiv2, double longCatenaria)
: MetodoNumerico(distPostesDiv2, longCatenaria) {
this->xi = xi;
this->xd = xd;
this->epsilon = epsilon;
this->maxIt = maxIt;
}

void Biseccion::CalculoC() {
double xm;
int itCnt = 0;
bool finish = false;
cout << endl << "Biseccion:" << endl;
cout << "Iteracion xi xm xd" << endl;
cout << "-------------------------------------------------------" << endl;
do {
xm = (xd + xi) / 2;
cout << itCnt + 1 << "\t\t" << xi << "\t\t" << xm << "\t\t" << xd << endl;
finish = (fabs(ecuacion2(xm, distPostesDiv2, longCatenaria)) < epsilon) ||
(fabs(xd - xi) < epsilon);
if (!finish) {
if (ecuacion2(xi, distPostesDiv2, longCatenaria) * ecuacion2(xm,
distPostesDiv2, longCatenaria) > 0)
xi = xm;
else
xd = xm;
}
itCnt++;
} while ((itCnt < maxIt) && (!finish));
c = xm;
longitudCable = calcularLongitudCable(c);
}
double Biseccion::getConstanteC() {
return MetodoNumerico::getConstanteC(); // Llama al método de la clase base
}

double Biseccion::getLongitudCable() {
return MetodoNumerico::getLongitudCable(); // Llama al método de la clase base }

Las clases PuntoFijo, Secante y Biseccion contienen la implementación específica de cada método, aprovechando la
estructura y funcionalidad proporcionada por la clase base MetodoNumerico para realizar los cálculos numéricos
respectivos y obtener los correctos resultados.

Main.cpp:
#include <iostream>
#include "puntofijo.h"
#include "secante.h"
#include "biseccion.h"

using namespace std;

int main() {
double SegundoValor;
double longCatenaria, distPostes, distPostesDiv2;

cout << "Ingrese la longitud de la catenaria [m](distancia del punto mas alto al
mas bajo): ";
cin >> longCatenaria;

cout << "Ingrese la distancia entre los postes [m]: ";


cin >> distPostes;
distPostesDiv2 = distPostes / 2;

// Método de Punto Fijo


PuntoFijo metodoPuntoFijo(10, 3250, 1E-5, &SegundoValor, distPostesDiv2,
longCatenaria);
metodoPuntoFijo.CalculoC();

// Método de la Secante
Secante metodoSecante(10, SegundoValor, 1E-5, 25, distPostesDiv2, longCatenaria);
metodoSecante.CalculoC();

// Método de Bisección
Biseccion metodoBiseccion(10, SegundoValor, 1E-5, 25, distPostesDiv2,
longCatenaria);
metodoBiseccion.CalculoC();

// Imprimir resultados finales


cout << endl << "Constante c obtenida:" << endl;
cout << "Punto Fijo: " << metodoPuntoFijo.getConstanteC() << endl;
cout << "Secante: " << metodoSecante.getConstanteC() << endl;
cout << "Biseccion: " << metodoBiseccion.getConstanteC() << endl;

// Calculo del largo del cable


cout << endl << "Largo del cable con las constantes c obtenidas:" << endl;
cout << "Usando metodo Punto Fijo: " << metodoPuntoFijo.getLongitudCable() << endl;
cout << "Usando metodo Secante: " << metodoSecante.getLongitudCable() << endl;
cout << "Usando metodo Biseccion: " << metodoBiseccion.getLongitudCable() << endl;

return 0; }
El main del programa solicita al usuario la longitud de la catenaria y la distancia entre los postes, esto lo hicimos así
para que sea una aplicación útil y que se pueda calcular con diferentes valores, no solo con los valores propuestos
por el ejercicio.

Diagrama de clases – Star UML:


Parte III: Programación Orientada a Objetos
Para realizar esta actividad, utilizamos tres clases con un método de agregación.
Estas clases son: puntos, triángulos y malla.

UML explicativo donde se pueden observar las diferentes clases utilizadas con sus relaciones, atributos y métodos.

Para realizar el programa decidimos utilizar los puntos que nos daba el enunciado, que forman la siguiente malla:

Después de estas aclaraciones, mostraremos los .h y los .cpp de cada clase. Y finalmente el main.cpp:

PUNTOS.H:
#ifndef PUNTOS_H
#define PUNTOS_H

class puntos
{
private:
int x;
int y;
public:
puntos(int x, int y);
int getX(void);
int getY(void);

};
#endif // PUNTOS_H

PUNTOS.CPP:
#include "puntos.h"

puntos::puntos(int x, int y){


this->x=x;
this->y=y;
}

int puntos::getX(){
return x;
}

int puntos::getY(){
return y;
}

Como podemos observar la clase puntos consta de dos coordenadas, un constructor que sirve para introducir sus
valores, y dos métodos “get” para obtener cada una de estas.

TRIANGULOS.H:
#ifndef TRIANGULOS_H
#define TRIANGULOS_H
#include <cmath>

#include "puntos.h"

class triangulos
{
private:
puntos *punto1;
puntos *punto2;
puntos *punto3;
float area;

public:
triangulos(puntos*punto1,puntos*punto2,puntos*punto3);
void setArea();
float getArea();

};

#endif // TRIANGULOS_H

TRIANGULOS.CPP:
#include "triangulos.h"

triangulos::triangulos(puntos*punto1,puntos*punto2,puntos*punto3)
{
this->punto1=punto1;
this->punto2=punto2;
this->punto3=punto3;
}

void triangulos::setArea(){
float ladoA,ladoB,ladoC;
//para sacar lados de el triangulo
//1-2 , 2-3 , 3-1
ladoA=sqrt(pow(punto1->getX()-punto2->getX(),2)+pow(punto1->getY()-punto2-
>getY(),2));
ladoB=sqrt(pow(punto2->getX()-punto3->getX(),2)+pow(punto2->getY()-punto3-
>getY(),2));
ladoC=sqrt(pow(punto3->getX()-punto1->getX(),2)+pow(punto3->getY()-punto1-
>getY(),2));
//heron
float s=(ladoA+ladoB+ladoC)/2;
area=sqrt(s*(s-ladoA)*(s-ladoB)*(s-ladoC));
}

float triangulos::getArea(){
return area;
}

Esta clase contiene tres direcciones de memoria de puntos, que se ingresan mediante su constructor. También
consta de un área, que se puede calcular y obtener mediante dos métodos.
El área de los triángulos la calculamos mediante la formula de Heron, que sirve para calcular el área de triángulos
que no necesariamente son rectángulos a partir de los lados de el triángulo. A estos lados, los calculamos haciendo
el modulo de la resta de sus puntos.

MALLA.H:
#ifndef MALLA_H
#define MALLA_H

#include "triangulos.h"

struct nodo{
triangulos *triangulo;
nodo* sig;
};

class malla
{
private:
nodo* inicio;
float superficieTotal;
int cantTriangulos;
public:
malla();
void agregarTriangulo(triangulos *triangulo);
void setSupTotal();
float getSupTotal();
int cantTriangulosMayoresA(float c);
~malla();
};

#endif // MALLA_H

MALLA.CPP:
#include "malla.h"

malla::malla(){
cantTriangulos=0;
inicio=nullptr;
}

void malla::agregarTriangulo(triangulos *triangulo){


nodo*actual=inicio;
nodo*anterior;

nodo *trianguloNuevo;
trianguloNuevo= new(nodo);
trianguloNuevo->triangulo=triangulo;
trianguloNuevo->sig=nullptr;
if(inicio==nullptr){
inicio=trianguloNuevo;
cantTriangulos=1;
}
else {
while(actual!=nullptr){
anterior=actual;
actual=actual->sig;
}
anterior->sig=trianguloNuevo;
cantTriangulos=cantTriangulos+1;
}
}

void malla::setSupTotal(){
nodo*actual=inicio;
float suptotal=0;
while (actual!=nullptr) {
actual->triangulo->setArea();
suptotal=suptotal+actual->triangulo->getArea();
actual=actual->sig;
}
superficieTotal=suptotal;
}

float malla::getSupTotal(){
return superficieTotal;
}

int malla::cantTriangulosMayoresA(float c){


int contador=0;
nodo*actual=inicio;
while(actual!=nullptr){
actual->triangulo->setArea();
if(actual->triangulo->getArea()>c)
contador++;
actual=actual->sig;
}
return contador;
}

malla::~malla(){
nodo*actual=inicio;
nodo*anterior;
while (actual!=nullptr) {
anterior=actual;
actual=actual->sig;
delete (anterior);
}
}

Esta clase guarda la dirección de inicio de una lista enlazada de triángulos, a esto lo realizamos de esta forma para
que sea sencillo cambiar la malla.
Esta clase también permite mediante un método de calcular la superficie total de la malla completa, sumando la
superficie de cada triangulo.
Otro atributo que contiene es la cantidad de triángulos de la malla, esto lo agregamos porque es una información
que podría llegar a ser útil en algunas posibles ocasiones.
Finalmente consta de un método al que el usuario le entrega un número y este devuelve la cantidad de triángulos
que tienen un área superior a este número.
Por ultimo el destructor de este elimina la lista enlazada, para que no quede memoria dinámica guardada.

MAIN.CPP:
#include <iostream>
#include "malla.h"

using namespace std;

int main()
{
puntos p1(1,5), p2(2,3), p3(3,7), p4(5,5),p5(5,2),p6(6,7),p7(7,3);
triangulos
t1(&p1,&p2,&p4),t2(&p1,&p3,&p4),t3(&p2,&p4,&p5),t4(&p3,&p4,&p6),t5(&p4,&p5,&p7),t6(&p4,
&p6,&p7);
malla m;
int n;
m.agregarTriangulo(&t1);
m.agregarTriangulo(&t2);
m.agregarTriangulo(&t3);
m.agregarTriangulo(&t4);
m.agregarTriangulo(&t5);
m.agregarTriangulo(&t6);
m.setSupTotal();
cout<<"area total: "<<m.getSupTotal()<<endl;
cout<<"ingrese un numero para saber cuantas areas hay superior a este:"<<endl;
cin>>n;
cout<<"cant areas mayores a "<<n<<" :"<<m.cantTriangulosMayoresA(n)<<endl;
return 0;
}

En el main creamos todos los puntos, introduciendo en ellos sus coordenadas. Después, con estos puntos creamos
los triángulos correspondientes. Luego de esto, añadimos cada triangulo a la malla.
Finalmente devolvemos el área de la malla y le preguntamos al usuario un área para comunicarle cuantos de estos
triángulos son mayores a esta.

También podría gustarte