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 CabcdPtr; class CacdbPtr; class CadbcPtr; class CbadcPtr; class CbcadPtr; class CbdcaPtr; class CcabdPtr; class CcbdaPtr; class CcdabPtr; class CdacbPtr; class CdbacPtr; class CdcbaPtr; 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(CabcdPtr&A):P(A.Ptr.P),R(A.Ptr.R*abcd){} CPtr(CacdbPtr&A):P(A.Ptr.P),R(A.Ptr.R*acdb){} CPtr(CadbcPtr&A):P(A.Ptr.P),R(A.Ptr.R*adbc){} CPtr(CbadcPtr&A):P(A.Ptr.P),R(A.Ptr.R*badc){} CPtr(CbcadPtr&A):P(A.Ptr.P),R(A.Ptr.R*bcad){} CPtr(CbdcaPtr&A):P(A.Ptr.P),R(A.Ptr.R*bdca){} CPtr(CcabdPtr&A):P(A.Ptr.P),R(A.Ptr.R*cabd){} CPtr(CcbdaPtr&A):P(A.Ptr.P),R(A.Ptr.R*cbda){} CPtr(CcdabPtr&A):P(A.Ptr.P),R(A.Ptr.R*cdab){} CPtr(CdacbPtr&A):P(A.Ptr.P),R(A.Ptr.R*dacb){} CPtr(CdbacPtr&A):P(A.Ptr.P),R(A.Ptr.R*dbac){} CPtr(CdcbaPtr&A):P(A.Ptr.P),R(A.Ptr.R*dcba){} CPtr operator*(Rotation r){ return CPtr(P,R*r);} CVertexPtr& operator[](int n){ return P->V[Vert[R][n]];} CAdjPtr Adj(){ return CAdjPtr(*this);} CabcdPtr Abcd(){ return *this;} CacdbPtr Acdb(){ return *this;} CadbcPtr Adbc(){ return *this;} CbadcPtr Badc(){ return *this;} CbcadPtr Bcad(){ return *this;} CbdcaPtr Bdca(){ return *this;} CcabdPtr Cabd(){ return *this;} CcbdaPtr Cbda(){ return *this;} CcdabPtr Cdab(){ return *this;} CdacbPtr Dacb(){ return *this;} CdbacPtr Dbac(){ return *this;} CdcbaPtr Dcba(){ return *this;} }; 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];} CabcdPtr Abcd(){ return CPtr(*this).Abcd();} CacdbPtr Acdb(){ return CPtr(*this).Acdb();} CadbcPtr Adbc(){ return CPtr(*this).Adbc();} CbadcPtr Badc(){ return CPtr(*this).Badc();} CbcadPtr Bcad(){ return CPtr(*this).Bcad();} CbdcaPtr Bdca(){ return CPtr(*this).Bdca();} CcabdPtr Cabd(){ return CPtr(*this).Cabd();} CcbdaPtr Cbda(){ return CPtr(*this).Cbda();} CcdabPtr Cdab(){ return CPtr(*this).Cdab();} CdacbPtr Dacb(){ return CPtr(*this).Dacb();} CdbacPtr Dbac(){ return CPtr(*this).Dbac();} CdcbaPtr Dcba(){ return CPtr(*this).Dcba();} }; class CabcdPtr { public: CPtr &Ptr; CabcdPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CabcdPtr Abcd(){ return Ptr;} CacdbPtr Acdb(){ return Ptr;} CadbcPtr Adbc(){ return Ptr;} CbadcPtr Badc(){ return Ptr;} CbcadPtr Bcad(){ return Ptr;} CbdcaPtr Bdca(){ return Ptr;} CcabdPtr Cabd(){ return Ptr;} CcbdaPtr Cbda(){ return Ptr;} CcdabPtr Cdab(){ return Ptr;} CdacbPtr Dacb(){ return Ptr;} CdbacPtr Dbac(){ return Ptr;} CdcbaPtr Dcba(){ return Ptr;} }; class CacdbPtr { public: CPtr &Ptr; CacdbPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CacdbPtr Abcd(){ return Ptr;} CadbcPtr Acdb(){ return Ptr;} CabcdPtr Adbc(){ return Ptr;} CcabdPtr Badc(){ return Ptr;} CcdabPtr Bcad(){ return Ptr;} CcbdaPtr Bdca(){ return Ptr;} CdacbPtr Cabd(){ return Ptr;} CdcbaPtr Cbda(){ return Ptr;} CdbacPtr Cdab(){ return Ptr;} CbadcPtr Dacb(){ return Ptr;} CbcadPtr Dbac(){ return Ptr;} CbdcaPtr Dcba(){ return Ptr;} }; class CadbcPtr { public: CPtr &Ptr; CadbcPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CadbcPtr Abcd(){ return Ptr;} CabcdPtr Acdb(){ return Ptr;} CacdbPtr Adbc(){ return Ptr;} CdacbPtr Badc(){ return Ptr;} CdbacPtr Bcad(){ return Ptr;} CdcbaPtr Bdca(){ return Ptr;} CbadcPtr Cabd(){ return Ptr;} CbdcaPtr Cbda(){ return Ptr;} CbcadPtr Cdab(){ return Ptr;} CcabdPtr Dacb(){ return Ptr;} CcdabPtr Dbac(){ return Ptr;} CcbdaPtr Dcba(){ return Ptr;} }; class CbadcPtr { public: CPtr &Ptr; CbadcPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CbadcPtr Abcd(){ return Ptr;} CbdcaPtr Acdb(){ return Ptr;} CbcadPtr Adbc(){ return Ptr;} CabcdPtr Badc(){ return Ptr;} CadbcPtr Bcad(){ return Ptr;} CacdbPtr Bdca(){ return Ptr;} CdbacPtr Cabd(){ return Ptr;} CdacbPtr Cbda(){ return Ptr;} CdcbaPtr Cdab(){ return Ptr;} CcbdaPtr Dacb(){ return Ptr;} CcabdPtr Dbac(){ return Ptr;} CcdabPtr Dcba(){ return Ptr;} }; class CbcadPtr { public: CPtr &Ptr; CbcadPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CbcadPtr Abcd(){ return Ptr;} CbadcPtr Acdb(){ return Ptr;} CbdcaPtr Adbc(){ return Ptr;} CcbdaPtr Badc(){ return Ptr;} CcabdPtr Bcad(){ return Ptr;} CcdabPtr Bdca(){ return Ptr;} CabcdPtr Cabd(){ return Ptr;} CacdbPtr Cbda(){ return Ptr;} CadbcPtr Cdab(){ return Ptr;} CdbacPtr Dacb(){ return Ptr;} CdcbaPtr Dbac(){ return Ptr;} CdacbPtr Dcba(){ return Ptr;} }; class CbdcaPtr { public: CPtr &Ptr; CbdcaPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CbdcaPtr Abcd(){ return Ptr;} CbcadPtr Acdb(){ return Ptr;} CbadcPtr Adbc(){ return Ptr;} CdbacPtr Badc(){ return Ptr;} CdcbaPtr Bcad(){ return Ptr;} CdacbPtr Bdca(){ return Ptr;} CcbdaPtr Cabd(){ return Ptr;} CcdabPtr Cbda(){ return Ptr;} CcabdPtr Cdab(){ return Ptr;} CabcdPtr Dacb(){ return Ptr;} CadbcPtr Dbac(){ return Ptr;} CacdbPtr Dcba(){ return Ptr;} }; class CcabdPtr { public: CPtr &Ptr; CcabdPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CcabdPtr Abcd(){ return Ptr;} CcbdaPtr Acdb(){ return Ptr;} CcdabPtr Adbc(){ return Ptr;} CacdbPtr Badc(){ return Ptr;} CabcdPtr Bcad(){ return Ptr;} CadbcPtr Bdca(){ return Ptr;} CbcadPtr Cabd(){ return Ptr;} CbadcPtr Cbda(){ return Ptr;} CbdcaPtr Cdab(){ return Ptr;} CdcbaPtr Dacb(){ return Ptr;} CdacbPtr Dbac(){ return Ptr;} CdbacPtr Dcba(){ return Ptr;} }; class CcbdaPtr { public: CPtr &Ptr; CcbdaPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CcbdaPtr Abcd(){ return Ptr;} CcdabPtr Acdb(){ return Ptr;} CcabdPtr Adbc(){ return Ptr;} CbcadPtr Badc(){ return Ptr;} CbdcaPtr Bcad(){ return Ptr;} CbadcPtr Bdca(){ return Ptr;} CdcbaPtr Cabd(){ return Ptr;} CdbacPtr Cbda(){ return Ptr;} CdacbPtr Cdab(){ return Ptr;} CacdbPtr Dacb(){ return Ptr;} CabcdPtr Dbac(){ return Ptr;} CadbcPtr Dcba(){ return Ptr;} }; class CcdabPtr { public: CPtr &Ptr; CcdabPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CcdabPtr Abcd(){ return Ptr;} CcabdPtr Acdb(){ return Ptr;} CcbdaPtr Adbc(){ return Ptr;} CdcbaPtr Badc(){ return Ptr;} CdacbPtr Bcad(){ return Ptr;} CdbacPtr Bdca(){ return Ptr;} CacdbPtr Cabd(){ return Ptr;} CadbcPtr Cbda(){ return Ptr;} CabcdPtr Cdab(){ return Ptr;} CbcadPtr Dacb(){ return Ptr;} CbdcaPtr Dbac(){ return Ptr;} CbadcPtr Dcba(){ return Ptr;} }; class CdacbPtr { public: CPtr &Ptr; CdacbPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CdacbPtr Abcd(){ return Ptr;} CdcbaPtr Acdb(){ return Ptr;} CdbacPtr Adbc(){ return Ptr;} CadbcPtr Badc(){ return Ptr;} CacdbPtr Bcad(){ return Ptr;} CabcdPtr Bdca(){ return Ptr;} CcdabPtr Cabd(){ return Ptr;} CcabdPtr Cbda(){ return Ptr;} CcbdaPtr Cdab(){ return Ptr;} CbdcaPtr Dacb(){ return Ptr;} CbadcPtr Dbac(){ return Ptr;} CbcadPtr Dcba(){ return Ptr;} }; class CdbacPtr { public: CPtr &Ptr; CdbacPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CdbacPtr Abcd(){ return Ptr;} CdacbPtr Acdb(){ return Ptr;} CdcbaPtr Adbc(){ return Ptr;} CbdcaPtr Badc(){ return Ptr;} CbadcPtr Bcad(){ return Ptr;} CbcadPtr Bdca(){ return Ptr;} CadbcPtr Cabd(){ return Ptr;} CabcdPtr Cbda(){ return Ptr;} CacdbPtr Cdab(){ return Ptr;} CcdabPtr Dacb(){ return Ptr;} CcbdaPtr Dbac(){ return Ptr;} CcabdPtr Dcba(){ return Ptr;} }; class CdcbaPtr { public: CPtr &Ptr; CdcbaPtr(CPtr&p):Ptr(p){} CAdjPtr Adj(){ return CPtr(*this).Adj();} CVertexPtr& operator[](int n){ return CPtr(*this)[n];} CdcbaPtr Abcd(){ return Ptr;} CdbacPtr Acdb(){ return Ptr;} CdacbPtr Adbc(){ return Ptr;} CcdabPtr Badc(){ return Ptr;} CcbdaPtr Bcad(){ return Ptr;} CcabdPtr Bdca(){ return Ptr;} CbdcaPtr Cabd(){ return Ptr;} CbcadPtr Cbda(){ return Ptr;} CbadcPtr Cdab(){ return Ptr;} CadbcPtr Dacb(){ return Ptr;} CacdbPtr Dbac(){ return Ptr;} CabcdPtr Dcba(){ return Ptr;} }; 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; }