00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #ifndef MLN_IO_OFF_LOAD_HH
00027 # define MLN_IO_OFF_LOAD_HH
00028 
00035 
00036 # include <cstdlib>
00037 # include <iostream>
00038 # include <fstream>
00039 # include <string>
00040 
00041 # include <mln/literal/black.hh>
00042 # include <mln/core/concept/object.hh>
00043 # include <mln/core/alias/complex_image.hh>
00044 
00045 
00046 namespace mln
00047 {
00048 
00049   namespace io
00050   {
00051 
00052     namespace off
00053     {
00054 
00062       void load(bin_2complex_image3df& ima, const std::string& filename);
00063 
00064       
00065       
00066 
00074       void load(float_2complex_image3df& ima, const std::string& filename);
00075 
00083       void load(rgb8_2complex_image3df& ima, const std::string& filename);
00084 
00085 
00086       namespace internal
00087       {
00088 
00089         template <typename I, typename E>
00090         struct off_loader : public Object<E>
00091         {
00092           typedef off_loader<I, E> self;
00093 
00095           static const unsigned D = 2;
00097           typedef metal::vec<D + 1, std::vector< mln_value(I) > > values;
00099           typedef mln_domain(I) domain;
00100 
00102           off_loader();
00103 
00105           void operator()(I& ima, const std::string& filename);
00106 
00109           static std::istream& eat_comment(std::istream& istr);
00110         };
00111 
00112 
00113         struct bin_off_loader
00114           : public off_loader< bin_2complex_image3df, bin_off_loader >
00115         {
00119           void read_face_data(std::istream& istr);
00120 
00122           void assign(values& vs, const domain& s);
00123 
00127           void reserve(unsigned nvertices, unsigned nedges, unsigned nfaces);
00128         };
00129 
00130 
00131         
00132 
00133 
00134 
00135         struct float_off_loader
00136           : public off_loader< float_2complex_image3df, float_off_loader >
00137         {
00139           void read_face_data(std::istream& istr);
00140 
00142           void reserve(unsigned nvertices, unsigned nedges, unsigned nfaces);
00143 
00145           void assign(values& vs, const domain& s);
00146 
00148           std::vector<float> face_value;
00149         };
00150 
00151 
00152         struct rgb8_off_loader
00153           : public off_loader< rgb8_2complex_image3df, rgb8_off_loader >
00154         {
00156           void read_face_data(std::istream& istr);
00157 
00159           void reserve(unsigned nvertices, unsigned nedges, unsigned nfaces);
00160 
00162           void assign(values& vs, const domain& s);
00163 
00165           std::vector<value::rgb8> face_value;
00166         };
00167 
00168       } 
00169 
00170 
00171 
00172 # ifndef MLN_INCLUDE_ONLY
00173 
00174       
00175 
00176 
00177 
00178       void
00179       load(bin_2complex_image3df& ima, const std::string& filename)
00180       {
00181         trace::entering("mln::io::off::load");
00182         internal::bin_off_loader()(ima, filename);
00183         trace::exiting("mln::io::off::load");
00184       }
00185 
00186       void
00187       load(float_2complex_image3df& ima, const std::string& filename)
00188       {
00189         trace::entering("mln::io::off::load");
00190         internal::float_off_loader()(ima, filename);
00191         trace::exiting("mln::io::off::load");
00192       }
00193 
00194       void
00195       load(rgb8_2complex_image3df& ima, const std::string& filename)
00196       {
00197         trace::entering("mln::io::off::load");
00198         internal::rgb8_off_loader()(ima, filename);
00199         trace::exiting("mln::io::off::load");
00200       }
00201 
00202 
00203 
00204       
00205 
00206 
00207 
00208       
00209       
00210       
00211 
00212       namespace internal
00213       {
00214 
00215         template <typename I, typename E>
00216         inline
00217         off_loader<I, E>::off_loader()
00218         {
00219           
00220           void (E::*m1)(std::istream&) = &E::read_face_data;
00221           m1 = 0;
00222           void (E::*m2)(unsigned, unsigned, unsigned) = &E::reserve;
00223           m2 = 0;
00224           void (E::*m3)(values&, const domain&) = &E::assign;
00225           m3 = 0;
00226         }
00227 
00228 
00229         template <typename I, typename E>
00230         inline
00231         void
00232         off_loader<I, E>::operator()(I& ima, const std::string& filename)
00233         {
00234           const std::string me = "mln::io::off::load";
00235 
00236           std::ifstream istr(filename.c_str());
00237           if (!istr)
00238             {
00239               std::cerr << me << ": `" << filename << "' not found."
00240                         << std::endl;
00241               
00242 
00243 
00244 
00245 
00246               std::exit(1);
00247             }
00248 
00249           
00250 
00251 
00252 
00253           
00254 
00255 
00256           
00257 
00258           std::string type;
00259           istr >> &self::eat_comment >> type;
00260           if (type != "OFF")
00261             {
00262               std::cerr << me << ": `" << filename << "': ill-formed header."
00263                         << std::endl;
00264               std::exit(1);
00265             }
00266 
00267           
00268 
00269 
00270           unsigned nvertices, nfaces, nedges;
00271           istr >> &self::eat_comment >> nvertices
00272                >> &self::eat_comment >> nfaces
00273                >> &self::eat_comment >> nedges;
00274 
00276           exact(this)->reserve(nvertices, nedges, nfaces);
00277 
00278           
00279 
00280 
00281 
00282           
00283 
00284 
00285           
00286           
00287           
00288 
00289           const unsigned D = 2;
00290           topo::complex<D> c;
00291 
00292           
00293           
00294           
00295 
00296           
00297 
00298 
00299           
00300 
00301           for (unsigned v = 0; v < nvertices; ++v)
00302             c.add_face();
00303 
00304           typedef point3df P;
00305           typedef mln_coord_(P) C;
00306           typedef geom::complex_geometry<D, P> G;
00307           G geom;
00308           for (unsigned v = 0; v < nvertices; ++v)
00309             {
00310               C x, y, z;
00311               istr >> &self::eat_comment >> x
00312                    >> &self::eat_comment >> y
00313                    >> &self::eat_comment >> z;
00314               geom.add_location(point3df(x, y, z));
00315             }
00316 
00317           
00318           
00319           
00320 
00321           
00322 
00323 
00324 
00325 
00326           
00327           typedef std::vector< std::vector<bool> > complex_edges_t;
00328           complex_edges_t complex_edges (nvertices,
00329                                          std::vector<bool>(nvertices, false));
00330 
00331           for (unsigned f = 0; f < nfaces; ++f)
00332             {
00333               unsigned nface_vertices;
00334               istr >> &self::eat_comment >> nface_vertices;
00335               if (nface_vertices <= 2)
00336                 {
00337                   std::cerr << me << ": `" << filename
00338                             << "': ill-formed face (having "
00339                             << nface_vertices << ' '
00340                             << (nface_vertices < 2 ? "vertex" : "vertices")
00341                             << ')' << std::endl;
00342                   std::exit(1);
00343                 }
00344 
00345               
00346               topo::n_faces_set<1, D> face_edges_set;
00347               face_edges_set.reserve(nface_vertices);
00348 
00349               
00350               unsigned first_vertex_id;
00351               istr >> &self::eat_comment >> first_vertex_id;
00352               
00353               unsigned vertex_id = first_vertex_id;
00354               if (first_vertex_id >= nvertices)
00355                 {
00356                   std::cerr << me << ": `" << filename
00357                             << "': invalid vertex id " << first_vertex_id
00358                             << std::endl;
00359                   std::exit(1);
00360                 }
00361               
00362               for (unsigned v = 0; v < nface_vertices; ++v)
00363                 {
00364                   
00365 
00366 
00367                   unsigned next_vertex_id;
00368                   
00369 
00370 
00371                   if (v == nface_vertices - 1)
00372                     next_vertex_id = first_vertex_id;
00373                   else
00374                     {
00375                       istr >> &self::eat_comment >> next_vertex_id;
00376                       if (next_vertex_id >= nvertices)
00377                         {
00378                           std::cerr << me << ": `" << filename
00379                                     << "': invalid vertex id "
00380                                     << next_vertex_id << std::endl;
00381                           std::exit(1);
00382                         }
00383                     }
00384                   
00385                   topo::n_face<0, D> vertex(c, vertex_id);
00386                   topo::n_face<0, D> next_vertex(c, next_vertex_id);
00387                   
00388                   topo::algebraic_n_face<1, D> edge;
00389                   
00390                   
00391                   if (!complex_edges[vertex_id][next_vertex_id])
00392                     {
00393                       complex_edges[vertex_id][next_vertex_id] = true;
00394                       complex_edges[next_vertex_id][vertex_id] = true;
00395                       edge =
00396                         make_algebraic_n_face(c.add_face(vertex -
00397                                                          next_vertex),
00398                                               true);
00399                     }
00400                   else
00401                     {
00402                       edge = topo::edge(vertex, next_vertex);
00403                       mln_assertion(edge.is_valid());
00404                     }
00405                   
00406                   face_edges_set += edge;
00407                   
00408                   vertex_id = next_vertex_id;
00409                 }
00410 
00411               
00412               exact(this)->read_face_data(istr);
00413 
00414               
00415               c.add_face(face_edges_set);
00416             }
00417 
00418           
00419 
00420 
00421 
00422           
00423           domain s(c, geom);
00424 
00425           
00426           values vs;
00427           exact(this)->assign(vs, s);
00428 
00429           
00430           ima.init_(s, vs);
00431 
00432           
00433 
00434 
00435 
00436           istr >> &self::eat_comment;
00437           if (!istr.eof())
00438             {
00439               std::cerr << me << ": `" << filename
00440                         << "': end of file not reached" << std::endl;
00441               std::exit(1);
00442             }
00443           istr.close();
00444         }
00445 
00446 
00447         
00448         
00449         
00450 
00451         
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00498         void
00499         bin_off_loader::read_face_data(std::istream& )
00500         {
00501           
00502         }
00503 
00504         void
00505         float_off_loader::read_face_data(std::istream& istr)
00506         {
00507           
00508 
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519           
00520           float r, g, b, a;
00521           istr >> r >> g >> b >> a;
00522           mln_assertion(0.0f <= r);  mln_assertion(r <= 1.0f);
00523           mln_assertion(0.0f <= g);  mln_assertion(g <= 1.0f);
00524           mln_assertion(0.0f <= b);  mln_assertion(b <= 1.0f);
00525           mln_assertion(0.0f <= a);  mln_assertion(a <= 1.0f);
00526           face_value.push_back(r);
00527         }
00528 
00529         void
00530         rgb8_off_loader::read_face_data(std::istream& istr)
00531         {
00532           
00533 
00534 
00535 
00536 
00537 
00538           
00539           float r, g, b, a;
00540           istr >> r >> g >> b >> a;
00541           mln_assertion(0.0f <= r);  mln_assertion(r <= 1.0f);
00542           mln_assertion(0.0f <= g);  mln_assertion(g <= 1.0f);
00543           mln_assertion(0.0f <= b);  mln_assertion(b <= 1.0f);
00544           mln_assertion(0.0f <= a);  mln_assertion(a <= 1.0f);
00545           face_value.push_back(value::rgb8(int(255 * r),
00546                                            int(255 * g),
00547                                            int(255 * b)));
00548         }
00549         
00550 
00551 
00552         void
00553         bin_off_loader::reserve(unsigned ,
00554                                 unsigned ,
00555                                 unsigned )
00556         {
00557           
00558         }
00559 
00560         void
00561         float_off_loader::reserve(unsigned ,
00562                                   unsigned ,
00563                                   unsigned nfaces)
00564         {
00565           face_value.reserve(nfaces);
00566         }
00567 
00568 
00569         void
00570         rgb8_off_loader::reserve(unsigned ,
00571                                  unsigned ,
00572                                  unsigned nfaces)
00573         {
00574           face_value.reserve(nfaces);
00575         }
00576 
00577 
00578         void
00579         bin_off_loader::assign(values& vs, const domain& s)
00580         {
00581           
00582           for (unsigned i = 0; i <= D; ++i)
00583             vs[i].insert(vs[i].begin(), s.cplx().nfaces_of_dim(i), true);
00584         }
00585 
00586         void
00587         float_off_loader::assign(values& vs, const domain& s)
00588         {
00589           
00590           for (unsigned i = 0; i < D; ++i)
00591             vs[i].insert(vs[i].begin(), s.cplx().nfaces_of_dim(i), 0.0f);
00592           
00593           vs[D] = face_value;
00594         }
00595 
00596         void
00597         rgb8_off_loader::assign(values& vs, const domain& s)
00598         {
00599           
00600           for (unsigned i = 0; i < D; ++i)
00601             vs[i].insert(vs[i].begin(), s.cplx().nfaces_of_dim(i),
00602                          literal::black);
00603           
00604           vs[D] = face_value;
00605         }
00606 
00607 
00608         
00609         
00610         
00611 
00612         template <typename I, typename E>
00613         inline
00614         std::istream&
00615         off_loader<I, E>::eat_comment(std::istream& istr)
00616         {
00617           
00618           std::ws(istr);
00619           while (istr.peek() == '#')
00620             {
00621               
00622 
00623               char c;
00624               do
00625                 istr.get(c);
00626               while (c != '\n' && c != '\r' && !istr.eof());
00627               
00628               std::ws(istr);
00629             }
00630           return istr;
00631         }
00632 
00633       } 
00634 
00635 
00636 # endif // ! MLN_INCLUDE_ONLY
00637 
00638 
00639     } 
00640 
00641   } 
00642 
00643 } 
00644 
00645 
00646 #endif // ! MLN_IO_OFF_LOAD_HH