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