Code:
//////////////////////////////////////////////////////////////////////////
#ifndef Map_hh
#define Map_hh
#include "ElMap.hh"
#include "GenFunc.hh"
#include "Layer.hh"
#include "String.hh"
#include "DynBaseObj.hh"
#include "List.hh"
#include "Stack.hh"
#include "Tree.hh"
class Map; // Forward declaration for class Map
// ***********************************************************************
// ***** CLASS: Phase ****************************************************
// ***********************************************************************
class Phase {
public:
Phase();
Phase(const Phase& P);
void Reset();
int size() const;
ElMap Last() const;
void Convert (const String& S);
Phase& operator = (const Phase& P);
void operator += (const ElMap& E);
friend bool Compatible(
const Phase& ph,
const Phase& hi);
friend
bool Equal(
const Phase& ph,
const Phase& hi);
// friend operator += (
// Phase &P,
// const ElMap E )
// {
// P.L += E;
// }
friend bool operator == (
const Phase& P1,
const Phase& P2);
friend bool operator != (
const Phase& P1,
const Phase& P2);
friend ostream& operator << (
ostream& os,
const Phase& P);
friend class Map;
protected:
List<ElMap> L;
};
// ***********************************************************************
// ***** CLASS: Map ******************************************************
// ***********************************************************************
class Map {
public:
Map();
Map(const Map& m);
// ~Map();
void Start();
void Reset();
void Add(const Phase& Ph);
bool ShotP() const;
bool ShotS() const;
bool IsTP(const int lay) const;
bool IsTS(const int lay) const;
bool IsRP(const int lay) const;
bool IsRS(const int lay) const;
bool Continue(const int lay) const;
void Advance(
const ElMap& ev,
const bool cont);
void Print(ostream& os) const;
Map& operator = (const Map& m);
protected:
Tree<ElMap>* M; // Map
List<Tree<ElMap> *> Ptr; // Pointers to possible directions
bool IsNext(const ElMap& ev) const;
};
//////////////////////////////////////////////////////////////////////////
// ***********************************************************************
// ***** IMPLEMENTATION: Map *********************************************
// ***********************************************************************
inline Map::Map() {
M = NULL;
}
//////////////////////////////////////////////////////////////////////////
inline Map::Map(const Map& m) {
M->Reset();
M = m.M;
Ptr = m.Ptr;
}
//////////////////////////////////////////////////////////////////////////
// Map::~Map();
// {
// Reset();
// }
//////////////////////////////////////////////////////////////////////////
void Map::Start() {
Ptr.Reset();
for ( int i = 0; i < M->NChild(); i++ ) { Ptr += M->GetChild(i); }
}
//////////////////////////////////////////////////////////////////////////
void Map::Reset() {
Ptr.Reset();
if (M != NULL) {
M->Reset();
delete M;
}
}
//////////////////////////////////////////////////////////////////////////
// Create an ElMap tree. ElMap output stream << is overloaded
// so that it can be used for output.
void Map::Add(const Phase& Ph) {
int i = 0;
Tree<ElMap>* T = M;
int n;
if (M == NULL) {
M = new Tree<ElMap>(ElMap(RT, 0)); // Start from root of the tree
T = M;
}
// Ph.L.size() defines the number of phases to consider
for (i = 0; i < Ph.L.size(); i++) {
n = T->InsNDup(Ph.L[i]);
T = T->GetChild(n);
}
}
//////////////////////////////////////////////////////////////////////////
inline bool Map::ShotP() const {
return (M->IsChild(ElMap(SP,0)));
}
//////////////////////////////////////////////////////////////////////////
inline bool Map::ShotS() const {
return (M->IsChild(ElMap(SS,0)));
}
//////////////////////////////////////////////////////////////////////////
inline bool Map::IsTP(const int lay) const {
return (IsNext(ElMap(TP,lay)));
}
//////////////////////////////////////////////////////////////////////////
inline bool Map::IsTS(const int lay) const {
return (IsNext(ElMap(TS,lay)));
}
//////////////////////////////////////////////////////////////////////////
inline bool Map::IsRP(const int lay) const {
return (IsNext(ElMap(RP,lay)));
}
//////////////////////////////////////////////////////////////////////////
inline bool Map::IsRS(const int lay) const {
return (IsNext(ElMap(RS,lay)));
}
//////////////////////////////////////////////////////////////////////////
bool Map::Continue(const int lay) const {
if (lay == 0) { return (false); }
if (Ptr.size() == 0) { return (true); }
ElMap ev;
for (int i = 0; i < Ptr.size(); i++) {
ev = Ptr[i]->GetVal();
switch (ev.Ev) {
case FS : return (true);
case TP :
case TS :
case RP :
case RS : if (ev.Lay != lay) { return (true); }
}
}
return (false);
}
//////////////////////////////////////////////////////////////////////////
void Map::Advance(
const ElMap& ev,
const bool cont) {
int i, j;
ElMap ev1;
// Delete pointers that stop
i = 0;
while (i < Ptr.size()) {
ev1 = Ptr[i]->GetVal();
if (cont) {
if ((ev.Lay == ev1.Lay) && (ev.Ev != ev1.Ev)) {
Ptr.Delete(i);
i = 0;
} else {
i++;
}
} else {
if (ev != ev1) {
Ptr.Delete(i);
i = 0;
} else {
i++;
}
}
}
// Append pointers that advance
if (IsNext(ev)) {
for (i = 0; Ptr[i]->GetVal() != ev; i++);
for (j = 0; j < Ptr[i]->NChild(); j++) { Ptr += Ptr[i]->GetChild(j); }
Ptr.Delete(i);
}
}
//////////////////////////////////////////////////////////////////////////
// Map::Print
// Prints M (Tree<ElMap>* M) in class Map using an output stream.
// The Tree class is declared in dynstr.h.
// Calls Tree<Type>::Print, where type is ElMap.
inline void Map::Print(ostream& os) const {
M->Print(os);
}
//////////////////////////////////////////////////////////////////////////
inline Map& Map::operator = (const Map& m) {
if (M != NULL) { M->Reset(); }
M = m.M;
Ptr = m.Ptr;
return (*this);
}
//////////////////////////////////////////////////////////////////////////
bool Map::IsNext(const ElMap& ev) const {
for (int i = 0; i < Ptr.size(); i++) {
if ( (Ptr[i]->GetVal()) == ev ) { return (true); }
}
return (false);
}
// ***********************************************************************
// ***** IMPLEMENATATION: Phase ******************************************
// ***********************************************************************
//////////////////////////////////////////////////////////////////////////
inline Phase::Phase() {
// empty
}
//////////////////////////////////////////////////////////////////////////
inline Phase::Phase(const Phase& P) {
L = P.L;
}
//////////////////////////////////////////////////////////////////////////
inline void Phase::Reset() {
L.Reset();
}
//////////////////////////////////////////////////////////////////////////
inline int Phase::size() const {
return (L.size());
}
//////////////////////////////////////////////////////////////////////////
inline ElMap Phase::Last() const {
return (L[L.size()-1]);
}
//////////////////////////////////////////////////////////////////////////
// Phase::Convert
// Convert a string to a Phase class
// In class Phase, create the Elmap list L (of type List<ElMap>) by
// setting ev and lay defined in class ElMap by passing the phase string.
void Phase::Convert (const String& S) {
int count = 0;
bool ex = false;
String NS = S;
char c1, c2;
int lay;
cerr << endl << "map.h, Phase::Convert" << endl
<< "|-- Phases for (S)hot, (R)eflection, (T)ransmission "
<< "or (F)ree Surface" << endl;
// Check for aliases
if (NS == String("P")) {
cerr << "|-- Phase Alias P encountered" << endl;
NS = "SP FS";
} else if (NS == String("S")) {
cerr << "|-- Phase Alias S encountered" << endl;
NS = "SS FS";
} else if (NS == String("PP")) {
cerr << "|-- Phase Alias PP encountered" << endl;
NS = "SP RP2 FS";
} else if (NS == String("PS")) {
cerr << "|-- Phase Alias PS encountered" << endl;
NS = "SP RS2 FS";
}
NS.ToUpper();
cerr << "|-- Parameters, S = " << S << ", NS = " << NS << endl;
L.Reset();
do {
// Read each phase entry from string NS
do {
NS >> c1;
} while (c1 == ' ');
NS >> c2;
cerr << "|-- c1 = " << c1 << ", c2 = " << c2 << endl;
switch (c1) {
// SHOT, ElMap(Ev, Lay) sets Ev = ev and Lay = lay
case 'S':
if (count != 0) { error("|-- Bad PHASE string"); }
if (c2 == 'P') {
L += ElMap(SP, 0); // Uses enum Events value SP
} else if (c2 == 'S') {
L += ElMap(SS, 0); // Uses enum Events value SS
} else {
error("|-- Bad PHASE string, c1 = S, c2 not P or S");
}
break;
// REFLECTION, ElMap(Ev, Lay) sets Ev = ev and Lay = lay
case 'R':
NS >> lay;
if (c2 == 'P') {
L += ElMap(RP, lay); // Uses enum Events value RP
} else if (c2 == 'S') {
L += ElMap(RS, lay); // Uses enum Events value RS
} else {
error("|-- Bad PHASE string, c1 = R, c2 not P or S");
}
break;
// TRANSMISSION, ElMap(Ev, Lay) sets Ev = ev and Lay = lay
case 'T':
NS >> lay;
if (c2 == 'P') {
L += ElMap(TP, lay); // Uses enum Events value TP
} else if (c2 == 'S') { //
L += ElMap(TS, lay); // Uses enum Events value TS
} else {
error("|-- Bad PHASE string, c1 = T, c2 not P or S");
}
if (lay == 0) { error("|- Two is not a valid map element"); }
break;
// FREE SURFACE, ElMap(Ev, Lay) sets Ev = ev and Lay = lay
case 'F':
if (c2 == 'S') {
L += ElMap(FS, 0); // Uses enum Events value FS
} else {
error("|-- Bad PHASE string, c1 = F, c2 not S");
}
ex = true;
break;
// DEFAULT
default :
error("|-- Bad PHASE string, c1 not S, R, T, or F");
} // switch c1
} while ( !NS.End() && !ex );
if ( ! ((L[0] == ElMap(SP, 0)) || (L[0] == ElMap(SS, 0))) ) {
L.Insert(0, ElMap(SP, 0));
}
}
//////////////////////////////////////////////////////////////////////////
inline Phase& Phase::operator = (const Phase& P) {
L = P.L;
return (*this);
}
//////////////////////////////////////////////////////////////////////////
inline void Phase::operator += (const ElMap& E) {
L += E;
}
//////////////////////////////////////////////////////////////////////////
bool Compatible(
const Phase& ph,
const Phase& hi) {
int iph = 0;
int ihi = 0;
TWave tw;
if (hi.size() == 0) { return (true); }
if (hi.L[0].Ev == SP) { tw = PWave;
} else { tw = SWave; }
while ((iph < ph.L.size()) && (ihi < hi.L.size())) {
if (ph.L[iph] == hi.L[ihi]) {
iph++;
} else {
switch (ph.L[iph].Ev) {
case SP:
case SS: return (false);
case TP:
case TS:
case RP:
case RS:
case FS:
if ((hi.L[ihi].Ev == RP) || (hi.L[ihi].Ev == RS)) {return (false);}
if ((hi.L[ihi].Ev == TP) && (tw == SWave)) {return (false);}
if ((hi.L[ihi].Ev == TS) && (tw == PWave)) {return (false);}
break;
}
}
if ((hi.L[ihi].Ev == RP) || (hi.L[ihi].Ev == TP)) { tw = PWave; }
if ((hi.L[ihi].Ev == RS) || (hi.L[ihi].Ev == TS)) { tw = SWave; }
ihi++;
}
return (true);
}
//////////////////////////////////////////////////////////////////////////
bool Equal(
const Phase& ph,
const Phase& hi) {
int iph = 0;
int ihi = 0;
TWave tw;
if (hi.size() == 0) { return (false); }
if (hi.L[0].Ev == SP) { tw = PWave;
} else { tw = SWave; }
while ((iph < ph.L.size()) && (ihi < hi.L.size())) {
if ( ph.L[iph] == hi.L[ihi] ) {
iph++;
} else {
switch (ph.L[iph].Ev) {
case SP:
case SS: return (false);
case TP:
case TS:
case RP:
case RS:
case FS:
if ((hi.L[ihi].Ev == RP) || (hi.L[ihi].Ev == RS)) {return (false);}
if ((hi.L[ihi].Ev == TP) && (tw == SWave)) {return (false);}
if ((hi.L[ihi].Ev == TS) && (tw == PWave)) {return (false);}
break;
}
}
if ((hi.L[ihi].Ev == RP) || (hi.L[ihi].Ev == TP)) { tw = PWave; }
if ((hi.L[ihi].Ev == RS) || (hi.L[ihi].Ev == TS)) { tw = SWave; }
ihi++;
}
if (iph == ph.L.size()) { return (true); }
return (false);
}
//////////////////////////////////////////////////////////////////////////
inline bool operator == (
const Phase& P1,
const Phase& P2) {
return (P1.L == P2.L);
}
//////////////////////////////////////////////////////////////////////////
inline bool operator != (
const Phase& P1,
const Phase& P2) {
return (P1.L != P2.L);
}
//////////////////////////////////////////////////////////////////////////
// List<ElMap> L;
inline ostream& operator << (
ostream& os,
const Phase& P) {
return (os << P.L);
}
//////////////////////////////////////////////////////////////////////////
#endif