#ifdef _MSC_VER
// this extra #define is only needed for Microsoft Visual C++
#define _USE_MATH_DEFINES
#include <cmath>
#else
#include <cmath>
#endif

#include <complex>
#include <iostream>
#include <iomanip>

using namespace std;

/*
Uitgangspunten:
- 	een Component
	-	is een abstracte base class
	-	heeft een impedantie Z die afhankelijk is van de frequentie f
	-	kan geprint worden
-	een R (weerstand)
	-	is een soort Component
	-	heeft een waarde (value)
	-	Z(f)=value+j*0
-	een L (spoel)
	-	is een soort Component
	-	heeft een waarde (value)
	-	Z(f)=0+j*2*pi*f*value
-	een C (condensator)
	-	is een soort Component
	-	heeft een waarde (value)
	-	Z(f)=0-j/(2*pi*f*value)
*/

class Component {
public:
	virtual ~Component() {
	}
	virtual complex<double> Z(double f) const=0; // bereken de impedantie Z (een complex
														      // getal) bij de frequentie f
	virtual void print(ostream& o) const=0;      // print
};

ostream& operator<<(ostream& o, const Component& c) {
	c.print(o);
	return o;
}

class R: public Component { // R=Weerstand
public:
	R(double r): value(r) {
	}
	virtual complex<double> Z(double) const {
		return value;
	}
	virtual void print(ostream& o) const {
		o<<"R("<<value<<")";
	}
private:
	double value;
};

class L: public Component { // L=Spoel
public:
	L(double l): value(l) {
	}
	virtual complex<double> Z(double f) const {
		return complex<double>(0, 2*M_PI*f*value);
	}
	virtual void print(ostream& o) const {
		o<<"L("<<value<<")";
	}
private:
	double value;
};

class C: public Component { // C=Condensator
public:
	C(double c): value(c) {
	}
	virtual complex<double> Z(double f) const {
		return complex<double>(0, -1/(2*M_PI*f*value));
	}
	virtual void print(ostream& o) const {
		o<<"C("<<value<<")";
	}
private:
	double value;
};

void printImpedanceTable(const Component& c) {
	cout<<"Impedantie tabel voor: "<<c<<endl<<endl;
	cout<<"freq\tZ"<<endl;
	for (double freq(10);freq<10E6;freq*=10)
		cout<<setw(5)<<freq<<'\t'<<c.Z(freq)<<endl;
	cout<<endl<<endl;
}

int main() {
	R r(1E2);
	printImpedanceTable(r);
	cin.get();
	C c(1E-5);
	printImpedanceTable(c);
	cin.get();
	L l(1E-3);
	printImpedanceTable(l);
	cin.get();
	return 0;
}

