00001 #ifndef SYNAPS_SHAPE_GAIA_QNODE_H
00002 #define SYNAPS_SHAPE_GAIA_QNODE_H
00003
00004 #include <shape/ssi/ssi_def.hpp>
00005 #include <shape/ssi/ssi_sample.hpp>
00006
00007 #define TMPL template<class C, class V>
00008
00009 namespace mmx {
00010 namespace ssi
00011 {
00012
00013 template <class C, class V>
00014 struct qnode
00015 {
00016 aabb3 box;
00017 coord_t umin,umax,vmin,vmax;
00018 qnode<C,V> * l, *r;
00019 qnode<C,V> * father;
00020 bool leaf() const { return (l == 0); };
00021 qnode(): l(0), r(0) {};
00022 void split_u();
00023 void split_v();
00024 void fill( vector3 ** qp, sample<C,V> * s ) const;
00025 void fill( vector3 * qp, sample<C,V> * s ) const;
00026 void convert( vector2 *v, sample<C,V> * s, int n ) const ;
00027 void mbox( sample<C,V> * s );
00028 void split( sample<C,V> * s );
00029 ~qnode();
00030 };
00031
00032 TMPL std::ostream& operator<<( std::ostream& o, const qnode<C,V>& );
00033 TMPL inline coord_t du ( const qnode<C,V> * q ) { return q->umax-q->umin; };
00034 TMPL inline coord_t dv ( const qnode<C,V> * q ) { return q->vmax - q->vmin; };
00035 TMPL inline coord_t umin( const qnode<C,V> * q ) { return q->umin; };
00036 TMPL inline coord_t umax( const qnode<C,V> * q ) { return q->umax; };
00037 TMPL inline coord_t vmin( const qnode<C,V> * q ) { return q->vmin; };
00038 TMPL inline coord_t vmax( const qnode<C,V> * q ) { return q->vmax; };
00039 TMPL inline bool leaf( qnode<C,V> const * const q ) { return (q->l == 0); };
00040 TMPL inline bool unit( const qnode<C,V> * q ) { return du(q)==1 && dv(q) == 1; };
00041 TMPL inline bool inside( coord_t u, coord_t v, qnode<C,V> * q )
00042 {
00043 if ( q->umin > u ) return false;
00044 if ( q->umax <= u ) return false;
00045 if ( q->vmin > v ) return false;
00046 if ( q->vmax <= v ) return false;
00047 return true;
00048 };
00049 TMPL qnode<C,V> * search( coord_t u, coord_t v, qnode<C,V> * start );
00050 TMPL inline qnode<C,V> * up ( qnode<C,V> * q ) { return search( q->umin + 1, q->vmin, q ); };
00051 TMPL inline qnode<C,V> * down( qnode<C,V> * q ) { return search( q->umin - 1, q->vmin, q ); };
00052 TMPL inline qnode<C,V> * left( qnode<C,V> * q ) { return search( q->umin, q->vmin - 1, q ); };
00053 TMPL inline qnode<C,V> * right( qnode<C,V> * q ) { return search( q->umin, q->vmin + 1, q ); };
00054
00055 TMPL
00056 std::ostream& operator<<( std::ostream& o, const qnode<C,V> & q )
00057 {
00058 o << "[ " << q.umin << ", " << q.umax << " ] x ";
00059 o << "[ " << q.vmin << ", " << q.vmax << " ]";
00060 return o;
00061 };
00062
00063 TMPL
00064 void qnode<C,V>::split_u()
00065 {
00066 l = new qnode();
00067 r = new qnode();
00068 l->umin = umin;
00069 l->umax = (umin+umax)/2;
00070 r->umin = (umin+umax)/2;
00071 r->umax = umax;
00072 l->vmin = r->vmin = vmin;
00073 l->vmax = r->vmax = vmax;
00074 l->father = r->father = this;
00075 };
00076
00077 TMPL
00078 void qnode<C,V>::split_v()
00079 {
00080 l = new qnode();
00081 r = new qnode();
00082 l->vmin = vmin;
00083 l->vmax = (vmin+vmax)/2;
00084 r->vmin = l->vmax;
00085 r->vmax = vmax;
00086 l->umin = r->umin = umin;
00087 l->umax = r->umax = umax;
00088 l->father = this;
00089 r->father = this;
00090 };
00091
00092
00093 TMPL
00094 qnode<C,V>::~qnode()
00095 {
00096 if (l ) delete l;
00097 if ( r ) delete r;
00098 };
00099
00100 TMPL
00101 void qnode<C,V>::fill( vector3 ** qp, sample<C,V> * s ) const
00102 {
00103 qp[0] = s->base() + this->umin*s->m_ncols + this->vmin;
00104 qp[1] = s->base() + this->umax*s->m_ncols + this->vmin;
00105 qp[2] = qp[1] + this->vmax - this->vmin;
00106 qp[3] = qp[0] + this->vmax - this->vmin;
00107 };
00108
00109 TMPL
00110 void qnode<C,V>::split( sample<C,V> * s)
00111 {
00112
00113 if ( l ) return;
00114 if ( du(this) > dv(this) )
00115 {
00116 this->split_u();
00117 l->mbox(s);
00118 r->mbox(s);
00119 }
00120 else if ( dv(this) > 1 )
00121 {
00122 this->split_v();
00123 l->mbox(s);
00124 r->mbox(s);
00125 };
00126
00127 };
00128
00129 TMPL
00130 void qnode<C,V>::mbox( sample<C,V> * s )
00131 {
00132 vector3 * qp[4];
00133 fill( qp, s );
00134 for ( int i = 0; i < 3; i ++ ) box[i].m = box[i].M = qp[0]->data[i];
00135 for ( int i = 1; i < 4; i ++ )
00136 for ( int d = 0; d < 3; d ++ )
00137 {
00138 if ( qp[i]->data[d] < box[d].m ) box[d].m = qp[i]->data[d];
00139 else { if ( qp[i]->data[d] > box[d].M ) box[d].M = qp[i]->data[d]; };
00140 };
00141 };
00142
00143 TMPL
00144 void qnode<C,V>::fill( vector3 *qp, sample<C,V> * s ) const
00145 {
00146 vector3 *r = s->base() + this->umin*s->m_ncols + this->vmin;
00147 qp[0] = *r;
00148 qp[3] = *(r + this->vmax - this->vmin);
00149 r = s->base() + this->umax*s->m_ncols + this->vmin;
00150 qp[1] = *r;
00151 qp[2] = *(r + this->vmax - this->vmin);
00152 };
00153
00154 TMPL
00155 qnode<C,V> * search( coord_t u, coord_t v, qnode<C,V> * start )
00156 {
00157 qnode<C,V> * tmp = start;
00158 do { tmp=tmp->father; } while(tmp && !inside(u,v,tmp) );
00159 if ( !tmp ) return 0;
00160 while(1){
00161 if ( leaf(tmp) ) return tmp;
00162 if ( inside(u,v,tmp->l) ) { tmp = tmp->l; continue; };
00163 if ( inside(u,v,tmp->r) ) { tmp = tmp->r; continue; };
00164 return 0;
00165 };
00166 };
00167
00168 TMPL
00169 void qnode<C,V>::convert( vector2 * p, sample<C,V> * s, int n ) const
00170 {
00171 assert(du(this)==1 && dv(this)==1);
00172 double u = s->uvalue(umin);
00173 double v = s->vvalue(vmin);
00174 double vu = s->uvalue(umax)-u;
00175 double vv = s->vvalue(vmax)-v;
00176 for ( int i = 0; i < n; i ++ )
00177 {
00178 p[i][0] = u + p[i][0]*vu;
00179 p[i][1] = v + p[i][1]*vv;
00180 };
00181 }
00182
00183 }
00184 }
00185 #endif