class CVertex { public: double X; double Y; double Z; }; typedef CVertex *CVertexPtr; enum Rotation { abcd,acdb,adbc,badc,bcad,bdca, cabd,cbda,cdab,dacb,dbac,dcba }; const int NAdj[12]={0,2,1,1,0,3,0,3,2,2,1,3}; const Rotation TAdj[12]={ abcd,bcad,cabd,abcd,cabd,bcad, bcad,cabd,abcd,cabd,bcad,abcd }; const Rotation RAdj[12]={ abcd,cabd,bcad,abcd,bcad,cabd, cabd,bcad,abcd,bcad,cabd,abcd }; const Rotation Mult[12][12]={ abcd,acdb,adbc,badc,bcad,bdca,cabd,cbda,cdab,dacb,dbac,dcba, acdb,adbc,abcd,bdca,badc,bcad,cbda,cdab,cabd,dcba,dacb,dbac, adbc,abcd,acdb,bcad,bdca,badc,cdab,cabd,cbda,dbac,dcba,dacb, badc,cabd,dacb,abcd,cbda,dbac,acdb,bcad,dcba,adbc,bdca,cdab, bcad,cdab,dbac,adbc,cabd,dcba,abcd,bdca,dacb,acdb,badc,cbda, bdca,cbda,dcba,acdb,cdab,dacb,adbc,badc,dbac,abcd,bcad,cabd, cabd,dacb,badc,dbac,abcd,cbda,bcad,dcba,acdb,cdab,adbc,bdca, cbda,dcba,bdca,dacb,acdb,cdab,badc,dbac,adbc,cabd,abcd,bcad, cdab,dbac,bcad,dcba,adbc,cabd,bdca,dacb,abcd,cbda,acdb,badc, dacb,badc,cabd,cbda,dbac,abcd,dcba,acdb,bcad,bdca,cdab,adbc, dbac,bcad,cdab,cabd,dcba,adbc,dacb,abcd,bdca,badc,cbda,acdb, dcba,bdca,cbda,cdab,dacb,acdb,dbac,adbc,badc,bcad,cabd,abcd }; const Rotation Revr[12]={ abcd,adbc,acdb,badc,cabd,dacb, bcad,dbac,cdab,bdca,cbda,dcba }; const int Vert[12][4]={ 0,1,2,3, 0,2,3,1, 0,3,1,2, 1,0,3,2, 1,2,0,3, 1,3,2,0, 2,0,1,3, 2,1,3,0, 2,3,0,1, 3,0,2,1, 3,1,0,2, 3,2,1,0 }; inline Rotation operator*(Rotation a,Rotation b){ return Mult[b][a];} class CTetrahedron { public: class CAdjPtr; class CPtr { public: CTetrahedron *P; Rotation R; CPtr(CTetrahedron* p=0,Rotation r=abcd):P(p),R(r){} CPtr(CAdjPtr&A):P(A.Ptr.P->P[NAdj[A.Ptr.R]].P),R(A.Ptr.P->P[NAdj[A.Ptr.R]].R*TAdj[A.Ptr.R]){} CPtr operator*(Rotation r){ return CPtr(P,R*r);} CVertexPtr& operator[](int n){ return P->V[Vert[R][n]];} CAdjPtr Adj(){ return CAdjPtr(*this);} CPtr Abcd(){ return *this;} CPtr Acdb(){ return *this*acdb;} CPtr Adbc(){ return *this*adbc;} CPtr Badc(){ return *this*badc;} CPtr Bcad(){ return *this*bcad;} CPtr Bdca(){ return *this*bdca;} CPtr Cabd(){ return *this*cabd;} CPtr Cbda(){ return *this*cbda;} CPtr Cdab(){ return *this*cdab;} CPtr Dacb(){ return *this*dacb;} CPtr Dbac(){ return *this*dbac;} CPtr Dcba(){ return *this*dcba;} }; class CAdjPtr { public: CPtr &Ptr; CAdjPtr(CPtr&p):Ptr(p){} void operator=(CPtr&p){ Ptr.P->P[NAdj[Ptr.R]].P=p.P; Ptr.P->P[NAdj[Ptr.R]].R=p.R*RAdj[Ptr.R];} CPtr Adj(){ return Ptr;} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CPtr Abcd(){ return CPtr(*this).Abcd();} CPtr Acdb(){ return CPtr(*this).Acdb();} CPtr Adbc(){ return CPtr(*this).Adbc();} CPtr Badc(){ return CPtr(*this).Badc();} CPtr Bcad(){ return CPtr(*this).Bcad();} CPtr Bdca(){ return CPtr(*this).Bdca();} CPtr Cabd(){ return CPtr(*this).Cabd();} CPtr Cbda(){ return CPtr(*this).Cbda();} CPtr Cdab(){ return CPtr(*this).Cdab();} CPtr Dacb(){ return CPtr(*this).Dacb();} CPtr Dbac(){ return CPtr(*this).Dbac();} CPtr Dcba(){ return CPtr(*this).Dcba();} }; CVertex *V[4]; CPtr P[4]; CVertexPtr& operator[](int n){ return V[n];} CTetrahedron(CVertex*v0=0,CVertex*v1=0,CVertex*v2=0,CVertex*v3=0); }; inline CTetrahedron::CTetrahedron(CVertex*v0,CVertex*v1,CVertex*v2,CVertex*v3) { V[0]=v0; V[1]=v1; V[2]=v2; V[3]=v3; P[0]=0; P[1]=0; P[2]=0; P[3]=0; }