00001 #ifndef SYNAPS_SHAPE_GAIA_LSEGMENT_H
00002 #define SYNAPS_SHAPE_GAIA_LSEGMENT_H
00003
00004 #include <shape/ssi/ssi_sample.hpp>
00005
00006 #define TMPL template<class C, class V>
00007
00008
00009 namespace mmx {
00010 namespace ssi {
00011
00012 struct mark_t
00013 {
00014 rid_t head;
00015 coord_t j;
00016 vcode_t code;
00017 mark_t * next;
00018 inline coord_t a() { return j; };
00019 inline coord_t b() { return (this+1)->a(); };
00020 };
00021
00022 TMPL
00023 struct lsegment: sample<C,V>
00024 {
00025 typedef typename sample<C,V>::ParametricSurface ParametricSurface;
00026 typedef coord_t bounds_t[2];
00027
00028 struct region_t
00029 {
00030 coord_t _umin, _umax;
00031 vcode_t _code;
00032 void * data;
00033 bool operator<( const region_t& b ) const { return _umin < b._umin; };
00034 coord_t min ( coord_t u ) const { return ((bounds_t*)data)[u][0]; };
00035 coord_t max ( coord_t u ) const { return ((bounds_t*)data)[u][1]; };
00036 coord_t umin () const { return _umin; };
00037 coord_t umax () const { return _umax; };
00038 inline bool inside( coord_t u, coord_t v )
00039 {
00040 if ( u >= umin() && u < umax() )
00041 if ( v >= min(u) && v < max(u) ) return true;
00042 return false;
00043 };
00044 vcode_t code() const { return _code; };
00045 friend class lsegment_t;
00046 };
00047
00048 mark_t * marks;
00049 unsigned _size;
00050 unsigned * lines;
00051
00052
00053 unsigned nmarks () const { return _size; };
00054 void lines_changes();
00055 public:
00056
00057 void rfree( region_t& r )
00058 {
00059 free((void*)(((bounds_t*)(r.data)) + r._umin));
00060 };
00061
00062
00063
00064 mark_t * begin( unsigned i ) { return &(marks[lines[i]]); };
00065 mark_t * end ( unsigned i ) { return &(marks[lines[i+1]-1]);};
00066
00067 std::vector< region_t > regions;
00068 graph_t * grp;
00069 void pushm( vcode_t code, coord_t j );
00070 void pushr( coord_t i, mark_t * p );
00071 void addneighbors( mark_t * m0, mark_t * m1 );
00072 void promote( region_t& r );
00073 void convert_regions();
00074 void find_regions();
00075 public:
00076 double _lt;
00077
00078 lsegment( const ParametricSurface * s , unsigned _w, unsigned _h );
00079 unsigned size() const { return regions.size(); };
00080 region_t& operator[]( unsigned i ) { return regions[i]; };
00081
00082 ~lsegment();
00083 };
00084
00085 TMPL
00086 void lsegment<C,V>::pushm(vcode_t code, coord_t j)
00087 {
00088 marks[_size].code = code;
00089 marks[_size].j = j;
00090 marks[_size].head =-1;
00091 marks[_size].next = 0;
00092 _size++;
00093 }
00094
00095 TMPL
00096 void lsegment<C,V>::addneighbors( mark_t * m0, mark_t * m1 )
00097 {
00098 if ( coherent_code( m0->code, m1->code ) )
00099 {
00100 grp->add_link(m0->head,m1->head);
00101 grp->add_link(m1->head,m0->head);
00102 };
00103 };
00104
00105 TMPL
00106 void lsegment<C,V>::pushr( coord_t i, mark_t * p )
00107 {
00108 p->head = regions.size();
00109 regions.push_back( region_t() );
00110 region_t * r =&(regions.back());
00111 r->_umin = i;
00112 r->_umax = 1;
00113 r->data = (void*)p;
00114 r->_code = p->code;
00115 grp->add_node();
00116 };
00117
00118 TMPL
00119 void lsegment<C,V>::lines_changes()
00120 {
00121 int i,j;
00122 lines = (unsigned*)(malloc(sizeof(unsigned)*this->nrows()));
00123 unsigned max_marks = this->nrows()*this->ncols();
00124 while ( !(marks = (mark_t*)(malloc(sizeof(mark_t)*max_marks))) ) max_marks >>= 1;
00125 vector3 * ptr = this->base();
00126 for ( i = 0; i < this->nrows()-1; i++ )
00127 {
00128 lines[i] = this->nmarks();
00129 vcode_t code = vcode(*ptr,*(ptr+this->ncols()),*(ptr+1));
00130 pushm(code,0);
00131 for ( j = 0; j < this->ncols()-1; j++, ptr++ )
00132 {
00133 vcode_t tmp = vcode(*ptr,*(ptr+this->ncols()),*(ptr+1));
00134 if ( tmp != code )
00135 { code = tmp; this->pushm(code,j); };
00136 };
00137 pushm(code,this->ncols()-1);
00138 ptr++;
00139 };
00140 lines[this->nrows()-1] = nmarks();
00141 marks = (mark_t*)realloc(marks,sizeof(mark_t)*nmarks());
00142 };
00143
00144 TMPL
00145 void lsegment<C,V>::find_regions()
00146 {
00147 mark_t * p;
00148 for ( p = begin(0); p != end(0); p++ )
00149 pushr(0,p);
00150 for ( p = begin(0)+1; p != end(0); p++ )
00151 addneighbors(p,p-1);
00152
00153 int ncolsTemp = this->ncols();
00154 mark_t * neighbors[ncolsTemp];
00155 unsigned n_neigh;
00156 coord_t i;
00157 #define INTERVALTEST ( std::abs(std::min(down->b(),up->b())-std::max(down->a(),up->a())) > 1 )
00158 for ( i = 0; i < this->nrows()-2; i++ )
00159 {
00160 mark_t * startup = begin(i);
00161 for ( mark_t * down = begin(i+1); down != end(i+1); down++ )
00162 {
00163 while ( startup->b() <= down->a() ) startup++;
00164 mark_t * up = startup;
00165 n_neigh = 0;
00166 while( down->b() > up->a() )
00167 if ( (up->next == 0) && ( up->code == down->code ) && INTERVALTEST)
00168 {
00169 regions[up->head]._umax++;
00170 up->next = down;
00171 down->head = up->head, up++;
00172 break;
00173 }
00174 else
00175 neighbors[n_neigh++] = up, up++;
00176
00177 if ( down->head == -1 ) pushr( i+1, down );
00178
00179 for ( unsigned k = 0; k < n_neigh; k ++ ) addneighbors(down,neighbors[k]);
00180 while( down->b() > up->a() ) addneighbors(down,up), up++;
00181 };
00182 };
00183 };
00184
00185 TMPL
00186 void lsegment<C,V>::promote( region_t& r )
00187 {
00188 mark_t * mpointer;
00189 bounds_t * bpointer;
00190 mpointer = (mark_t*)(r.data);
00191 r.data = (void*)(malloc(sizeof(bounds_t)*(r._umax)));
00192 bpointer = (bounds_t*)(r.data);
00193
00194 for ( unsigned i = 0; i < r._umax; i++ )
00195 {
00196 bpointer[i][0] = mpointer->a();
00197 bpointer[i][1] = mpointer->b();
00198 mpointer = mpointer->next;
00199 };
00200
00201 r._umax += r._umin;
00202 r.data = (void*)(((bounds_t*)(r.data))-r._umin);
00203 };
00204
00205 TMPL
00206 void lsegment<C,V>::convert_regions()
00207 {
00208 for ( unsigned i = 0; i < regions.size(); i++ )
00209 promote( regions[i] );
00210 };
00211
00212
00213
00214 TMPL
00215 lsegment<C,V>::lsegment( const ParametricSurface * s , unsigned _w, unsigned _h ) : sample<C,V>(s,_w,_h)
00216 {
00217
00218 _size = 0;
00219 lines_changes ();
00220 grp = new graph_t();
00221 find_regions ();
00222 convert_regions();
00223 delete[] marks;
00224 delete[] lines;
00225
00226 };
00227
00228 TMPL
00229 lsegment<C,V>::~lsegment()
00230 {
00231 delete grp;
00232 for ( unsigned i = 0; i < regions.size(); i++ )
00233 rfree(regions[i]);
00234 };
00235
00236 }
00237 }
00238
00239 # undef ParametricSurface
00240 # endif