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