// Programación en C++ para Ingenieros, Ed. Thomson Paraninfo, 2006 // Capítulo 5: Subprogramas: Acciones y funciones #include <iostream> #include <math.h> using namespace std; // Lee un vertice (generico) template <class T> void leerVertice(T& coordX, T& coordY); // Escribe los 4 valores de la caja englobante (generico) template <class T> void escribeCaja(T& coordX, T& coordY, T& coordXFin, T& coordYFin); // Determina si se repiten dos vertices de enteros bool heAcabado(int x0, int y0, int xFin, int yFin); // Determina si se repiten dos vertices de reales bool heAcabado(double x0, double y0, double xFin, double yFin); // Devuelve el minimo de dos elementos template <class T> T minimo(T x, T y); // Devuelve el maximo de dos elementos template <class T> T maximo(T x, T y); // Calcula la caja englobante (generico) template <class T> void cajaEnglobante(T& coordX0, T& coordY0, T& coordXFin, T& coordYFin); int main(void) { char c; // El usuario selecciona el tipo de vertices (validacion) do { cout << "¿Vertices reales (R) o enteros (E)? " << endl; cin >> c; } while (c != 'r' && c != 'R' && c != 'e' && c != 'E'); // Se llama a la funcion correspondiente switch (c) { case 'r': case 'R': { cout << "Leyendo reales" << endl; double xMinR, xMaxR, yMinR, yMaxR; cajaEnglobante(xMinR, xMaxR, yMinR, yMaxR); escribeCaja(xMinR, xMaxR, yMinR, yMaxR); } break; case 'e': case 'E': { cout << "Leyendo enteros " << endl; int xMin, xMax, yMin, yMax; cajaEnglobante(xMin, xMax, yMin, yMax); escribeCaja(xMin, xMax, yMin, yMax); } break; } return 0; } // Funcion generica que lee un vertice template <class T> void leerVertice(T& coordX, T& coordY) { cout << "Entra el siguiente vertice: "; cin >> coordX >> coordY; } // Funcion que determina si dos vertices de enteros son iguales bool heAcabado(int x0, int y0, int xFin, int yFin) { return (x0 == xFin && y0 == yFin); } // Funcion que determina si dos vertices de reales son iguales // Notese que se utiliza un esquema ligeramente diferente porque // dos reales supuestamente iguales se pueden almacenar con algun // decimal diferente en funcion de la precision, aqui asumimos que // dos reales con una diferencia menor de 0.000001 son iguales bool heAcabado(double x0, double y0, double xFin, double yFin) { const double precision = 0.000001; return (fabs(x0 - xFin) < precision && fabs(y0 - yFin) < precision); } // Calcula la caja englobante (generico) template <class T> void cajaEnglobante(T& coordX0, T& coordY0, T& coordXFin, T& coordYFin) { T x, y, xIni, yIni; leerVertice(xIni, yIni); coordX0 = coordXFin = xIni; coordY0 = coordYFin = yIni; leerVertice(x, y); while (!heAcabado(xIni, yIni, x, y)) { coordX0 = minimo(x, coordX0); coordY0 = minimo(y, coordY0); coordXFin = maximo(x, coordXFin); coordYFin = maximo(y, coordYFin); leerVertice(x, y); } } // Calcula el minimo de dos elementos template <class T> T minimo(T x, T y) { T aux = x; if (y < aux) aux = y; return aux; } // Calcula el maximo de dos elementos template <class T> T maximo(T x, T y) { T aux = x; if (y > aux) aux = y; return aux; } // Escribe los componentes de una caja englobante template <class T> void escribeCaja(T& coordX, T& coordY, T& coordXFin, T& coordYFin) { cout.precision(5); cout << "La caja englobante va de " << coordX << " " << coordY << " a " << coordXFin << " " << coordYFin << endl; }