00001
00002
00003
00004 #ifndef clusterTree_hh
00005 #define clusterTree_hh
00006
00007 #include <iostream>
00008
00009 #include "basics/typedefs.hh"
00010 #include "basics/vectorsMatricesForward.hh"
00011 #include "basics/exceptions.hh"
00012 #include "space/space.hh"
00013 #include "bem/element.hh"
00014
00015 namespace cluster {
00016
00017
00018
00020 void cebysev(const concepts::Real3d& x0, const concepts::Real3d& x1,
00021 concepts::Real3d& c, concepts::Real& r);
00022 void cebysev(const concepts::Real3d& x0, const concepts::Real3d& x1,
00023 const concepts::Real3d& x2, concepts::Real3d& c,
00024 concepts::Real& r);
00025
00026
00027
00032 template<class F>
00033 class BBall {
00034 public:
00040 virtual void operator()(const concepts::Element<F>& elm,
00041 concepts::Real3d& c, concepts::Real& r) const = 0;
00042 };
00043
00044
00045
00049 template<class F>
00050 class BBall000 : public BBall<F> {
00051 public:
00058 void operator()(const concepts::Element<F>& elm, concepts::Real3d& c,
00059 concepts::Real& r) const;
00060 };
00061
00062 template<class F>
00063 void BBall000<F>::operator()(const concepts::Element<F>& elm,
00064 concepts::Real3d& c, concepts::Real& r) const {
00065
00066 const bem::Linear3d000<F>* elmA =
00067 dynamic_cast<const bem::Linear3d000<F>*>(&elm);
00068 if (elmA != 0) {
00069 cebysev(elmA->vertex(0), elmA->vertex(1), elmA->vertex(2), c, r);
00070 return;
00071 }
00072
00073 const bem::Constant3d000<F>* elmB =
00074 dynamic_cast<const bem::Constant3d000<F>*>(&elm);
00075 if (elmB != 0) {
00076 cebysev(elmB->vertex(0), elmB->vertex(1), elmB->vertex(2), c, r);
00077 return;
00078 }
00079
00080 const bem::Constant3d001<F>* elmC =
00081 dynamic_cast<const bem::Constant3d001<F>*>(&elm);
00082 if (elmC != 0) {
00083 cebysev(elmC->vertex(0), elmC->vertex(1), elmC->vertex(2), c, r);
00084 return;
00085 }
00086
00087 const bem::Constant3d002<F>* elmD =
00088 dynamic_cast<const bem::Constant3d002<F>*>(&elm);
00089 if (elmD != 0) {
00090 cebysev(elmD->vertex(0), elmD->vertex(1), elmD->vertex(2), c, r);
00091 return;
00092 }
00093
00094 const bem::Dirac3d000<F>* elmE =
00095 dynamic_cast<const bem::Dirac3d000<F>*>(&elm);
00096 if (elmE != 0) {
00097 switch (elmE->T().n()) {
00098 case 1:
00099 c = elmE->vertex(0); r = 0.0;
00100 break;
00101 case 2:
00102 cebysev(elmE->vertex(0), elmE->vertex(1), c, r);
00103 break;
00104 case 3:
00105 cebysev(elmE->vertex(0), elmE->vertex(1), elmE->vertex(2), c, r);
00106 break;
00107 }
00108 return;
00109 }
00110
00111 throw conceptsException(concepts::MissingFeature("cell not supported"));
00112 }
00113
00114
00115
00116 template<typename F>
00117 class Cluster;
00118
00119 template<typename F>
00120 std::ostream& operator<<(std::ostream& os, const Cluster<F>& clst);
00121
00125 template<class F>
00126 class Cluster {
00127 public:
00129 typedef F CF;
00130
00136 Cluster(const concepts::Element<F>& elm, const BBall<F>& ball,
00137 Cluster<F>* lnk);
00145 Cluster(uint idx, Cluster<F>& chld, const concepts::Real3d& c,
00146 concepts::Real r, uint nlf = 0);
00147
00149 inline Cluster<F>* child(uint j) const;
00151 inline Cluster<F>* child() const;
00153 inline Cluster<F>* link() const {return lnk_;}
00154 inline Cluster<F>*& link() {return lnk_;}
00156 inline const concepts::Element<F>* element() const;
00158 inline const concepts::Real3d& center() const {return c_;}
00160 inline concepts::Real radius() const {return r_;}
00162 inline uint nleaf() const {return nlf_;}
00164 inline uint index() const {return idx_;}
00165 std::ostream& info(std::ostream& os) const;
00166
00167 private:
00168 friend std::ostream& operator<< <>(std::ostream& os,
00169 const Cluster<F>& clst);
00171 union CE {
00172 Cluster<F>* chld;
00173 const concepts::Element<F>* elm;
00174 };
00175
00177 Cluster<F>* lnk_;
00179 CE ce_;
00180
00182 uint idx_;
00184 uint nlf_;
00185
00187 concepts::Real3d c_;
00189 concepts::Real r_;
00190 };
00191
00192 template<class F>
00193 inline Cluster<F>* Cluster<F>::child(uint j) const {
00194 Cluster<F>* c = child();
00195 while (c && j) {c = c->link(); j--;}
00196 return (j) ? (Cluster<F>*)0 : c;
00197 }
00198
00199 template<class F>
00200 inline Cluster<F>* Cluster<F>::child() const {
00201 return (nlf_) ? ce_.chld : (Cluster<F>*)0;
00202 }
00203
00204 template<class F>
00205 inline const concepts::Element<F>* Cluster<F>::element() const {
00206 return (nlf_) ? (concepts::Element<F>*)0 : ce_.elm;
00207 }
00208
00209 template<class F>
00210 inline std::ostream& operator<<(std::ostream& os, const Cluster<F>& clst) {
00211 return clst.info(os);
00212 }
00213
00214 template<class F>
00215 Cluster<F>::Cluster(uint idx, Cluster<F>& chld, const concepts::Real3d& c,
00216 concepts::Real r, uint nlf)
00217 : lnk_(0), idx_(idx), nlf_(nlf), c_(c), r_(r) {
00218
00219 ce_.chld = &chld;
00220
00221 if (nlf_ == 0)
00222 for(const Cluster<F>* c = &chld; c != 0; c = c->lnk_)
00223 nlf_ += c->nlf_ ? c->nlf_ : 1;
00224 }
00225
00226 template<class F>
00227 Cluster<F>::Cluster(const concepts::Element<F>& elm,
00228 const BBall<F>& ball, Cluster<F>* lnk)
00229 : lnk_(lnk), idx_(0), nlf_(0) {
00230
00231 ce_.elm = &elm;
00232 ball(elm, c_, r_);
00233 }
00234
00235 template<class F>
00236 std::ostream& Cluster<F>::info(std::ostream& os) const {
00237 os << "Cluster(idx = " << idx_ << ", r = " << r_ << ", c = " << c_;
00238 os << ", nleaf = " << nlf_ << ", lnk = " << lnk_;
00239 os << ", chld = " << child() << ')';
00240 return os;
00241 }
00242
00243
00244
00248 template<class Node>
00249 class TreeTraits {
00250 public:
00252 typedef typename Node::CF F;
00253
00254 static Node* child(const Node* nd, uint j) {return nd->child(j);}
00255 static const concepts::Element<F>* element(const Node* nd) {
00256 return nd->element();
00257 }
00258 static const concepts::Real3d& center(const Node* nd) {
00259 return nd->center();}
00260
00261 static concepts::Real radius(const Node* nd) {
00262 return nd->radius();
00263 }
00264 static uint nleaf(const Node* nd) {return nd->nleaf();}
00265 static uint index(const Node* nd) {return nd->index();}
00266 };
00267
00268
00269
00270 template<class CNode>
00271 class Tree;
00272
00273 template<class CNode>
00274 inline std::ostream& operator<<(std::ostream& os, const Tree<CNode>& t) {
00275 return t.info(os);
00276 }
00277
00281 template<class CNode>
00282 class Tree {
00283 friend std::ostream& operator<< <>(std::ostream& os, const Tree<CNode>& t);
00284
00285 public:
00287 typedef TreeTraits<CNode> Traits;
00289 typedef typename Traits::F F;
00291 typedef CNode Node;
00292
00296 inline Tree(const concepts::Space<F>& spc) : spc_(spc) {}
00297 virtual ~Tree() {}
00298
00299 virtual std::ostream& info(std::ostream& os) const;
00301 virtual uint nclst() const = 0;
00303 virtual uint nleaf() const = 0;
00305 virtual const Node* root() const = 0;
00307 inline const concepts::Space<F>& space() const {return spc_;}
00308
00309 private:
00311 const concepts::Space<F>& spc_;
00312
00321 void info_(const Node* clst, concepts::Real& rhomin,
00322 concepts::Real& rhomax, concepts::Real& taumin,
00323 concepts::Real& taumax, uint& h) const;
00324 };
00325
00326 template<class CNode>
00327 void Tree<CNode>::info_(const CNode* clst, concepts::Real& rhomin,
00328 concepts::Real& rhomax, concepts::Real& taumin,
00329 concepts::Real& taumax, uint& h) const {
00330 uint j = 0;
00331 const CNode* chld = Traits::child(clst, j);
00332
00333 while (chld) {
00334 if (Traits::nleaf(chld)) {
00335 uint hh = 0;
00336 info_(chld, rhomin, rhomax, taumin, taumax, hh);
00337
00338 if (hh > h) h = hh;
00339
00340 concepts::Real rho = Traits::radius(chld) / Traits::radius(clst);
00341 if (rho < rhomin) rhomin = rho;
00342 if (rho > rhomax) rhomax = rho;
00343
00344 concepts::Real tau =
00345 (concepts::Real)Traits::nleaf(chld) / Traits::nleaf(clst);
00346 if (tau < taumin) taumin = tau;
00347 if (tau > taumax) taumax = tau;
00348
00349 if (rho > 2) {
00350 std::cout << *clst << std::endl;
00351 std::cout << *chld << std::endl;
00352 }
00353
00354 }
00355 chld = Traits::child(clst, ++j);
00356 }
00357 ++h;
00358 }
00359
00360 template<class CNode>
00361 std::ostream& Tree<CNode>::info(std::ostream& os) const {
00362
00363 concepts::Real rhomin = 1, rhomax = 0;
00364 concepts::Real taumin = 1, taumax = 0;
00365 uint h = 0;
00366
00367 info_(root(), rhomin, rhomax, taumin, taumax, h);
00368
00369 os << "cluster::Tree(nclst = " << nclst() << ", nleaf = " << nleaf();
00370 os << ", h = " << h;
00371
00372 if (h > 1) {
00373 os << ", rho in [" << rhomin << ", " << rhomax;
00374 os << "], tau in [" << taumin << ", " << taumax << "])";
00375 } else {
00376 os << ')';
00377 }
00378
00379 return os;
00380 }
00381
00382 }
00383
00384 #endif // clusterTree_hh