00001 #ifndef ZCROSS_EXTRACT_H_IS_INCLUDED
00002 #define ZCROSS_EXTRACT_H_IS_INCLUDED
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <vector>
00014 #include <cassert>
00015 #include <limits>
00016
00017 #include "std/support.H"
00018 #include "mlib/points.H"
00019 #include "mesh/bmesh.H"
00020 #include "mesh/zcross_path.H"
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 template <typename To, typename From>
00032 inline To
00033 sign_cast(From val)
00034 {
00035
00036 assert(std::numeric_limits<To>::is_specialized);
00037
00038 assert(!std::numeric_limits<To>::is_signed ||
00039 (val <= static_cast<From>(std::numeric_limits<To>::max())));
00040 assert(std::numeric_limits<To>::is_signed ||
00041 (val >= static_cast<From>(std::numeric_limits<To>::min())));
00042
00043 return static_cast<To>(val);
00044
00045 }
00046
00047
00048
00049
00050
00051 class BarycentricCoord {
00052
00053 public:
00054
00055 BarycentricCoord(double c0 = 0.0, double c1 = 0.0, double c2 = 0.0)
00056 { coords[0] = c0; coords[1] = c1; coords[2] = c2; }
00057
00058 double &operator[](int idx) { return coords[idx]; }
00059 double operator[](int idx) const { return coords[idx]; }
00060
00061
00062
00063 Wpt to_Wpt(const Bface *f) const
00064 { return f->v1()->loc()*coords[0] +
00065 f->v2()->loc()*coords[1] +
00066 f->v3()->loc()*coords[2]; }
00067
00068
00069 Wvec to_Wvec() const
00070 { return Wvec(coords[0], coords[1], coords[2]); }
00071
00072 private:
00073
00074 double coords[3];
00075
00076 };
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 class ZCrossSeg {
00089
00090 public:
00091
00092 ZCrossSeg(Bface *face_in,
00093 BarycentricCoord start_bc_in, double start_conf_in,
00094 BarycentricCoord end_bc_in, double end_conf_in,
00095 bool end_in = false)
00096 : face(face_in),
00097 start_bc(start_bc_in),
00098 end_bc(end_bc_in),
00099 start_conf(start_conf_in),
00100 end_conf(end_conf_in),
00101 end(end_in)
00102 { }
00103
00104 ZCrossSeg flip() const {
00105 return ZCrossSeg(face, end_bc, end_conf, start_bc, start_conf, end);
00106 }
00107
00108 Bface *get_face() const { return face; }
00109
00110 BarycentricCoord get_start_bc() const { return start_bc; }
00111 BarycentricCoord get_end_bc() const { return end_bc; }
00112
00113 Wpt get_start_pt() const { return start_bc.to_Wpt(face); }
00114 Wpt get_end_pt() const { return end_bc.to_Wpt(face); }
00115
00116 double get_start_conf() const { return start_conf; }
00117 double get_end_conf() const { return end_conf; }
00118
00119 bool is_end() const { return end; }
00120
00121 void set_end(bool end_in = true) { end = end_in; }
00122
00123 private:
00124
00125
00126 Bface *face;
00127
00128 BarycentricCoord start_bc, end_bc;
00129
00130 double start_conf, end_conf;
00131
00132
00133
00134 bool end;
00135
00136 };
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00155 class ZCrossExtractor {
00156
00157 public:
00158
00159
00160
00161
00162 ZCrossExtractor(const BMESH *mesh_in,
00163 ScalarField sfield_in = ScalarField(),
00164 Confidence conf_in = Confidence(),
00165 FaceGenerator fgen_in = FaceGenerator())
00166 : mesh(mesh_in), sfield(sfield_in), conf(conf_in), fgen(fgen_in)
00167 { }
00168
00169
00170
00171
00172
00173
00174
00175 void extract();
00176
00177
00178
00179
00180
00181
00182 const BMESH *get_mesh() const { return mesh; }
00183
00184
00185
00186
00187
00188
00189
00190 const std::vector<ZXseg> &segs() const
00191 { return extracted_segs; }
00192
00193
00194 void reset()
00195 { extracted_segs.clear(); }
00196
00197
00198
00199 private:
00200
00201 bool get_zcross_points(const Bface *f,
00202 BarycentricCoord bc_pts[2], int edge_nums[2]);
00203
00204 double get_confidence(const Bface *f, const BarycentricCoord &bc);
00205
00206 bool walk_line(Bface *start_face,
00207 Bface *next_face,
00208 std::vector<ZCrossSeg> &line);
00209
00210 void extract_line(Bface *f);
00211
00212 void add_seg(const ZCrossSeg &seg);
00213
00214 std::vector<ZXseg> extracted_segs;
00215
00216 std::vector<bool> face_markers;
00217
00218 const BMESH *mesh;
00219
00220 ScalarField sfield;
00221 Confidence conf;
00222 FaceGenerator fgen;
00223
00224 };
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235 class ZCrossScalarFieldInterface {
00236
00237 public:
00238
00239 virtual ~ZCrossScalarFieldInterface() {}
00240 virtual double operator()(const Bvert*) = 0;
00241
00242 };
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 class ZCrossConfidenceInterface {
00255
00256 public:
00257
00258 virtual ~ZCrossConfidenceInterface() {}
00259 virtual double operator()(const Bvert*) = 0;
00260
00261 };
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 class ZCrossFaceGeneratorInterface {
00282
00283 public:
00284
00285 virtual ~ZCrossFaceGeneratorInterface() {}
00286
00287 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00288 void operator()(const ZCrossExtractor<ScalarField,Confidence,FaceGenerator>*)
00289 { }
00290 virtual int operator()() = 0;
00291
00292 };
00293
00294
00295
00296
00297
00298
00299 class ZCrossAllFaceGenerator : public ZCrossFaceGeneratorInterface {
00300
00301 public:
00302
00303 ZCrossAllFaceGenerator()
00304 : i(0), num_faces(0)
00305 { }
00306
00307 virtual ~ZCrossAllFaceGenerator() {}
00308 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00309 void operator()(const ZCrossExtractor<ScalarField,Confidence,FaceGenerator> *extractor)
00310 { i = 0; num_faces = extractor->get_mesh()->nfaces(); }
00311
00312 virtual int operator()()
00313 { return (i < num_faces) ? i++ : -1; }
00314
00315 private:
00316
00317 int i, num_faces;
00318
00319 };
00320
00321
00322
00323
00324
00325
00326 class ZCrossRandFaceGenerator : public ZCrossFaceGeneratorInterface {
00327
00328 public:
00329
00330 ZCrossRandFaceGenerator()
00331 : i(0), num_faces(0)
00332 { }
00333
00334 virtual ~ZCrossRandFaceGenerator() {}
00335 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00336 void operator()(const ZCrossExtractor<ScalarField,Confidence,FaceGenerator> *extractor)
00337 { i = 0; total_faces = extractor->get_mesh()->nfaces();
00338 num_faces = compute_num_faces(total_faces); }
00339
00340 virtual int operator()()
00341 { return (i < num_faces) ? i++, gen_rand_face() : -1; }
00342
00343 private:
00344
00345 int compute_num_faces(int n)
00346 { return static_cast<int>(sqrt(4.0 * n)); }
00347
00348 int gen_rand_face()
00349 { return gen_rand_val() % total_faces; }
00350
00351 int gen_rand_val()
00352 { return static_cast<int>(drand48() * total_faces); }
00353
00354 int i, num_faces, total_faces;
00355
00356 };
00357
00358
00359
00360
00361
00362
00363
00364 class ZCrossPreviousFaceGenerator : public ZCrossFaceGeneratorInterface {
00365
00366 public:
00367
00368 virtual ~ZCrossPreviousFaceGenerator() {}
00369 ZCrossPreviousFaceGenerator();
00370
00371 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00372 void operator()(const ZCrossExtractor<ScalarField,Confidence,FaceGenerator> *extractor)
00373 { all_faces(extractor); init(extractor->segs()); }
00374
00375 virtual int operator()()
00376 { return gen_face(this); }
00377
00378 private:
00379
00380 void init(const std::vector<ZXseg> &segs);
00381
00382 static int gen_all_faces(ZCrossPreviousFaceGenerator *self)
00383 { return self->all_faces(); }
00384
00385 static int gen_prev_faces(ZCrossPreviousFaceGenerator *self);
00386
00387 int (*gen_face)(ZCrossPreviousFaceGenerator *);
00388
00389 ZCrossAllFaceGenerator all_faces;
00390
00391 std::vector<int> prev_faces;
00392
00393 };
00394
00395
00396
00397
00398
00399
00400
00401 class ZCrossPreviousAndRandFaceGenerator : public ZCrossFaceGeneratorInterface {
00402
00403 public:
00404
00405 virtual ~ZCrossPreviousAndRandFaceGenerator() {}
00406 ZCrossPreviousAndRandFaceGenerator()
00407 { }
00408
00409 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00410 void operator()(const ZCrossExtractor<ScalarField,Confidence,FaceGenerator> *extractor)
00411 { prev_faces(extractor); rand_faces(extractor); }
00412
00413 virtual int operator()()
00414 { int prev_faces_val = prev_faces();
00415 return prev_faces_val != -1 ? prev_faces_val : rand_faces(); }
00416
00417 private:
00418
00419 ZCrossPreviousFaceGenerator prev_faces;
00420 ZCrossRandFaceGenerator rand_faces;
00421
00422 };
00423
00424
00425
00426 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00427 void
00428 ZCrossExtractor<ScalarField, Confidence, FaceGenerator>::extract()
00429 {
00430
00431
00432 fgen(this);
00433
00434
00435 assert(face_markers.size() == 0);
00436 face_markers.resize(mesh->nfaces(), false);
00437
00438
00439 reset();
00440
00441 int face_idx;
00442
00443 while((face_idx = fgen()) != -1){
00444
00445 if(face_markers[face_idx]) continue;
00446
00447 face_markers[face_idx] = true;
00448
00449 extract_line(mesh->bf(face_idx));
00450
00451 }
00452
00453 face_markers.clear();
00454
00455 }
00456
00457 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00458 bool
00459 ZCrossExtractor<ScalarField,
00460 Confidence,
00461 FaceGenerator>::get_zcross_points(const Bface *f,
00462 BarycentricCoord bc_pts[2],
00463 int edge_nums[2])
00464 {
00465
00466 double sf_vals[3];
00467
00468
00469 for(int i = 0; i < 3; ++i){
00470
00471 sf_vals[i] = sfield(f->v(i + 1));
00472
00473
00474
00475 sf_vals[i] = (sf_vals[i] == 0.0) ? 1.0e-8 : sf_vals[i];
00476
00477 }
00478
00479 bool has_zcrossing = false;
00480
00481 int cur_crossing_idx = 0;
00482
00483
00484 for(int i = 0; i < 3; ++i){
00485
00486 if(((sf_vals[i] < 0.0) && (sf_vals[(i + 1) % 3] > 0.0)) ||
00487 ((sf_vals[i] > 0.0) && (sf_vals[(i + 1) % 3] < 0.0))){
00488
00489 has_zcrossing = true;
00490
00491 double sf_val_diff = sf_vals[i] - sf_vals[(i + 1) % 3];
00492
00493
00494 assert((cur_crossing_idx >= 0) && (cur_crossing_idx < 2));
00495
00496 bc_pts[cur_crossing_idx][i] = sf_vals[i] / sf_val_diff;
00497 bc_pts[cur_crossing_idx][(i + 1) % 3] = sf_vals[(i + 1) % 3] / -sf_val_diff;
00498 bc_pts[cur_crossing_idx][(i + 2) % 3] = 0.0;
00499
00500 edge_nums[cur_crossing_idx] = i;
00501
00502
00503 assert(isEqual(bc_pts[cur_crossing_idx][0] +
00504 bc_pts[cur_crossing_idx][1] +
00505 bc_pts[cur_crossing_idx][2],
00506 1.0));
00507
00508
00509 assert((bc_pts[cur_crossing_idx][0] >= 0.0) &&
00510 (bc_pts[cur_crossing_idx][1] >= 0.0) &&
00511 (bc_pts[cur_crossing_idx][2] >= 0.0));
00512
00513 ++cur_crossing_idx;
00514
00515 }
00516
00517 }
00518
00519
00520
00521 assert(!has_zcrossing || (cur_crossing_idx == 2));
00522
00523 return has_zcrossing;
00524
00525 }
00526
00527 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00528 double
00529 ZCrossExtractor<ScalarField,
00530 Confidence,
00531 FaceGenerator>::get_confidence(const Bface *f,
00532 const BarycentricCoord &bc)
00533 {
00534
00535 double total_conf = 0.0;
00536
00537 for(int i = 0; i < 3; ++i){
00538
00539 total_conf += (conf(f->v(i + 1)) * bc[i]);
00540
00541 }
00542
00543 return total_conf;
00544
00545 }
00546
00547 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00548 bool
00549 ZCrossExtractor<ScalarField,
00550 Confidence,
00551 FaceGenerator>::walk_line(Bface *start_face,
00552 Bface *next_face,
00553 std::vector<ZCrossSeg> &line)
00554 {
00555
00556
00557 assert(start_face != 0);
00558
00559
00560
00561 if(next_face == 0)
00562 return false;
00563
00564
00565 assert(start_face->shared_edge(next_face) != 0);
00566
00567 Bface *prev_face = start_face;
00568 Bface *cur_face = next_face;
00569
00570 BarycentricCoord zcross_pts[2];
00571 int zcross_edges[2];
00572 bool loop_complete = false;
00573
00574 #ifndef NDEBUG
00575
00576 long face_count = 0;
00577
00578 #endif // NDEBUG
00579
00580 while(true){
00581
00582 #ifndef NDEBUG
00583
00584 ++face_count;
00585
00586
00587
00588 assert(start_face->mesh());
00589 assert(face_count < start_face->mesh()->nfaces());
00590
00591 #endif // NDEBUG
00592
00593
00594 assert(face_markers[cur_face->index()] == false);
00595
00596 face_markers[cur_face->index()] = true;
00597
00598
00599 if(!get_zcross_points(cur_face, zcross_pts, zcross_edges))
00600 break;
00601
00602 int next_pt = (cur_face->nbr(zcross_edges[0] + 1) == prev_face) ? 1 : 0;
00603
00604 next_face = cur_face->nbr(zcross_edges[next_pt] + 1);
00605
00606 line.push_back(ZCrossSeg(cur_face,
00607 zcross_pts[(next_pt + 1) % 2],
00608 get_confidence(cur_face, zcross_pts[(next_pt + 1) % 2]),
00609 zcross_pts[next_pt],
00610 get_confidence(cur_face, zcross_pts[next_pt])));
00611
00612
00613 if(next_face == 0)
00614 break;
00615
00616
00617 if(next_face == start_face){
00618
00619 loop_complete = true;
00620 break;
00621
00622 }
00623
00624 prev_face = cur_face;
00625 cur_face = next_face;
00626
00627 };
00628
00629 return loop_complete;
00630
00631 }
00632
00633 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00634 void
00635 ZCrossExtractor<ScalarField,
00636 Confidence,
00637 FaceGenerator>::extract_line(Bface *f)
00638 {
00639
00640
00641 assert(f != 0);
00642
00643
00644 assert(f->mesh() != 0);
00645
00646 BarycentricCoord f_zcross_pts[2];
00647 int f_zcross_edges[2];
00648
00649 if(!get_zcross_points(f, f_zcross_pts, f_zcross_edges))
00650 return;
00651
00652 int starting_pt = 0;
00653
00654 assert(starting_pt != -1);
00655
00656 std::vector<ZCrossSeg> zcross_line_part;
00657
00658 if(!walk_line(f, f->nbr(f_zcross_edges[starting_pt] + 1), zcross_line_part)){
00659
00660
00661
00662
00663 vector<ZCrossSeg> zcross_line_other_part;
00664
00665 walk_line(f, f->nbr(f_zcross_edges[(starting_pt + 1) % 2] + 1),
00666 zcross_line_other_part);
00667
00668
00669
00670 assert(zcross_line_other_part.size() < sign_cast<unsigned long>(f->mesh()->nfaces()));
00671
00672
00673 for(long i = (sign_cast<long>(zcross_line_other_part.size()) - 1); i >= 0; --i){
00674
00675
00676 assert((i == (sign_cast<long>(zcross_line_other_part.size()) - 1)) ||
00677 (zcross_line_other_part[i + 1].flip().get_end_pt()
00678 == zcross_line_other_part[i].flip().get_start_pt()));
00679
00680
00681 assert((i == 0) ||
00682 (zcross_line_other_part[i].flip().get_end_pt()
00683 == zcross_line_other_part[i - 1].flip().get_start_pt()));
00684
00685 add_seg(zcross_line_other_part[i].flip());
00686
00687 }
00688
00689 }
00690
00691
00692
00693 assert(sign_cast<long>(zcross_line_part.size()) < f->mesh()->nfaces());
00694
00695 bool start_is_end = (zcross_line_part.size() == 0);
00696
00697 if(!start_is_end)
00698 zcross_line_part.back().set_end();
00699
00700 add_seg(ZCrossSeg(f,
00701 f_zcross_pts[(starting_pt + 1) % 2],
00702 get_confidence(f, f_zcross_pts[(starting_pt + 1) % 2]),
00703 f_zcross_pts[starting_pt],
00704 get_confidence(f, f_zcross_pts[starting_pt]),
00705 start_is_end));
00706
00707 for(unsigned i = 0; i < zcross_line_part.size(); ++i){
00708
00709
00710 assert((i == 0) ||
00711 (zcross_line_part[i - 1].get_end_pt() == zcross_line_part[i].get_start_pt()));
00712
00713
00714 assert((i == (zcross_line_part.size() - 1)) ||
00715 (zcross_line_part[i].get_end_pt() == zcross_line_part[i + 1].get_start_pt()));
00716
00717 add_seg(zcross_line_part[i]);
00718
00719 }
00720
00721 }
00722
00723 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00724 inline void
00725 ZCrossExtractor<ScalarField,
00726 Confidence,
00727 FaceGenerator>::add_seg(const ZCrossSeg &seg)
00728 {
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 assert(isZero(seg.get_start_bc()[0]) ||
00741 isZero(seg.get_start_bc()[1]) ||
00742 isZero(seg.get_start_bc()[2]));
00743
00744
00745 assert(((seg.get_start_bc()[0] != 0.0) && (seg.get_start_bc()[1] != 0.0)) ||
00746 ((seg.get_start_bc()[1] != 0.0) && (seg.get_start_bc()[2] != 0.0)) ||
00747 ((seg.get_start_bc()[2] != 0.0) && (seg.get_start_bc()[0] != 0.0)));
00748
00749 int vert_index = (seg.get_start_bc()[0] == 0.0) ? 1 :
00750 (seg.get_start_bc()[1] == 0.0) ? 2 :
00751 0;
00752
00753 Bface *f = seg.get_face();
00754
00755 extracted_segs.push_back(
00756 ZXseg(f,
00757 seg.get_start_pt(),
00758 f->v(vert_index + 1),
00759 seg.get_start_conf(),
00760 seg.get_start_bc().to_Wvec(),
00761 STYPE_SUGLINE,
00762 false)
00763 );
00764
00765 if(seg.is_end() ){
00766
00767 extracted_segs.push_back(
00768 ZXseg(0,
00769 seg.get_end_pt(),
00770 f->v(vert_index + 1),
00771 seg.get_end_conf(),
00772 seg.get_end_bc().to_Wvec(),
00773 STYPE_SUGLINE,
00774 true)
00775 );
00776
00777 }
00778
00779 }
00780
00781 #endif // ZCROSS_EXTRACT_H_IS_INCLUDED