vuoi
o PayPal
tutte le volte che vuoi
Il programma implementa una classe 'retta' nel piano, che utilizza la classe punto.
La classe deve avere:
due o tre data members (a seconda che si scelga di usare la rappresentazione y=ax+b o ax+by+c=0)
-il corrispondente constructor con due o tre doubles in entrata
-un costruttore con argomenti due oggetti di tipo punto (si costruisce la retta passante)
-tutte le funzioni "standard" get e set
-una funzione che rende un oggetto punto rappresentante l'intersezione di due rette
#include <iostream>
#include "es_4a_class.h" // classe punto
#include "es_5a_class.h" // classe rettaAB
using namespace std;
int main(){
rettaAB r1(3.0/2.0, 0);
punto p1(4,1),p2(5,0);
rettaAB r2(p1,p2);
cout << "\n\n--> Funzioni get:";
cout << "\n--> Retta 1: a = " << r1.get_a() << "; b = " << r1.get_b();
cout << "\n--> Retta 2 creata con i punti (4,1) e (5,0)";
cout << "\n--> Retta 2: a = " << r2.get_a() << "; b = " << r2.get_b() <<
endl; rettaAB r3(14,-4);
cout << "\n--> Funzioni set:";
cout << "\n--> Retta 3, prima: a = " << r3.get_a() << "; b = " <<
r3.get_b();
r3.set_a(10);
r3.set_b(2);
cout << "\n--> Retta 3, dopo: a = " << r3.get_a() << "; b = " <<
r3.get_b() << endl;
cout << "\n--> Intersezione tra r1 ed r2:\n--> ";
punto in = r1.intersezione(r2);
in.stampa();
cout << endl;
rettaAB ra(4,2), rb(4,2), rc(4,-1);
punto pb = ra.intersezione(rb), pc = ra.intersezione(rc);
cout << "\n--> Casi patologici:\n--> intersezione di una retta con se
stessa: ";
pb.stampa();
cout << "\n--> Intersezione di due rette parallele: ";
pc.stampa();
cout << "\n\n--> Fine.\n";
return 0;
}
*******************************************
* es_5a_class.h *
*******************************************
#ifndef RETTA_AB
#define RETTA_AB
#include "es_4a_class.h" // senza questa non si puo' usare
// l'oggetto punto in questo header file!
// retta nella notazione y = ax + b
class rettaAB{
/* Una classe puo' avere piu' costruttori!
Anzi, in generale:
possono esistere ** piu' funzioni ** con lo STESSO NOME
purche' differiscano per (almeno uno tra):
- numero di argomenti
- tipi di argomenti
- tipo di dato di ritorno
fintanto che ci sono queste differenze, il compilatore sapra' sempre
come risolvere l'ambiguita'.
Quindi non ci sono problemi a scrivere:
...
retta(double, double);
retta(punto&, punto&);
(nota sulla '&': quando i due punti vengono passati al costruttore, se non
ci fosse
la '&' ne verrebbero fatte due copie temporanee - inutili in questo caso -
con dispendio di risorse, tempo e chiamate addizionali ai costruttori di
'punto').
Mettendo la '&' vengono passati al costruttore gli originali!
*/
public:
rettaAB(double=0, double=0);
rettaAB(const punto&, const punto&);
double set_a(double);
double set_b(double);
double get_a() const;
double get_b() const;
punto intersezione(rettaAB&);
private:
double a,b;
};
#endif
*******************************************
* es_5a_class.cpp *
*******************************************
#include "es_5a_class.h"
#include <iostream>
using namespace std;
rettaAB::rettaAB(double n_a, double n_b){a=n_a; b=n_b;}
double rettaAB::set_a(double n_a) {return a=n_a;}
double rettaAB::set_b(double n_b) {return b=n_b;}
double rettaAB::get_a() const {return a;}
double rettaAB::get_b() const {return b;}
rettaAB::rettaAB(const punto& p1, const punto& p2) {
// date le coordinate dei due punti si calcolano e
// si impostano a e b della retta passante per essi.
// Primo controllo: p1==p2? Se si', e' meglio impostare un valore
// di default di a e b, poiche' il calcolo darebbe infinito.
// Non si puo' pero' usare la condizione (p1==p2) perche'
// l'azione dell'operatore '==' tra oggetti 'punto' non e'
// definita (per farlo servira' l'overloading); si deve
// quindi procedere per componenti (con degli '==' tra numeri)
// Il secondo check da fare e': p1 e p2 hanno la stessa x?
// In tal caso non e' possibile esprimere la retta nella forma
// y=ax+b, e viene di nuovo reso un valore di default.
// (cio' significa che in questi due casi la retta creata
// con questo constructor NON E' quella per i due punti)
// conviene inserire questi due controlli in un'unica struttura:
if (p1.get_x()==p2.get_x()) {
// ulteriore suddivisione dei casi
if (p1.get_y()==p2.get_y()) { //stesso punto!
a = b = 0; // scelta di default convenzionale
}
else { // due punti distinti sulla stessa verticale
a = b = 0; // questa scelta poteva essere
// diversa dalla precedente...
}
}
else {// in questo caso si possono applicare ciecamente le formuline!
a = (p2.get_y()-p1.get_y())/(p2.get_x()-p1.get_x());
b = ((p1.get_y()*p2.get_x())-(p1.get_x()*p2.get_y()))/(p2.get_x()-
p1.get_x());
}
}
punto rettaAB::intersezione(rettaAB& altraR){
// questo e' un caso interessante: una delle due
// rette e' quella "in cui" si sta eseguendo il codice,
// l'altra e' passata come argomento: la chiamata
// e' qualcosa come: p=r1.intersezione(r2)
// (e sara' simmetrica per r1 <--> r2...)
// non ci sono comunque problemi di ambiguita'
// nel recuperare i dati delle due rette...
// anche qui bisogna fare attenzione a certi casi prima di
// fare il calcolo! Due rette parallele o coincidenti non
// potranno essere trattate come se fossero incidenti, pena
// delle divisioni per zero...
double x,y;
// Il sistema da risolvere e' del tipo
// -1
// | x | | - a_1 1 | | b_1 |
// | | = | | . | |
// | y | | - a_2 1 | | b_2 |
//
// cioe'...
double det = - a + altraR.get_a();
if (det==0) { // casi non invertibili: parallele o coincidenti...
if (b == altraR.get_b()) { // coincidenti
// si decide di rendere come intersezione di default il
punto... x = 0;
y = b;
}
else { // parallele e distinte
// si decide di rendere l'origine!
x = y = 0;
}
}
else { // formule...
// si ha qui:
// -1
// | - a_1 1 | 1 | 1 -1 |
// | | = --------- | |
// | - a_2 1 | a_2 - a_1 | a_2 -a_1 |
x = (b-altraR.get_b())/det;