Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

zcross_extractor.H

Go to the documentation of this file.
00001 #ifndef ZCROSS_EXTRACT_H_IS_INCLUDED
00002 #define ZCROSS_EXTRACT_H_IS_INCLUDED
00003 
00004 /*!
00005  *  \file zcross_extractor.H
00006  *  \brief Contains the definition of the ZCrossExtractor class.  A class for
00007  *  extracting zero crossing lines of arbitrary scalar fields on a mesh.
00008  *
00009  *  \sa zcross_extractor.C
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  *  \brief A function intended to cast from a signed value to an unsigned value
00024  *  or from an unsigned value to a signed value.
00025  *
00026  *  Performs assertions (using the standard assert macro) to check that the value
00027  *  being cast in within the range of values that can be represented by the type
00028  *  it is being converted to.
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  *  \brief A set of barycentric coordinates on a triangular face.
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    //! \brief Returns the position of Barycentric coordinate on the given
00062    //! face in world coordinates.
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    //! \brief Return the Barycentric coordinate store in a Wvec.
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  *  \brief A segment on a zero crossing line.
00080  *
00081  *  This segment spans exactly one face on the mesh.
00082  *
00083  *  These segments are meant to be kept in a sequence (like an array or vector)
00084  *  with the \p end_pt of one segment corresponding to the \p start_pt of the
00085  *  next segment in the sequence.
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    //! \brief The face the segment lies on.
00126    Bface *face;
00127    //! \brief The endpoints of the segment in barycentric coordinates.
00128    BarycentricCoord start_bc, end_bc;
00129    //! \brief The confidences of the endpoints.
00130    double start_conf, end_conf;
00131    //! \brief End flag.
00132    //!
00133    //! Marks this segment as the end of a contiguous zero crossing line.
00134    bool end;
00135    
00136 };
00137 
00138 /*!
00139  *  \brief A class for extracting the zero crossing lines of arbitrary scalar
00140  *  fields on a mesh.
00141  *
00142  *  This class is templated on a series of functors (function objects) that
00143  *  determine what type of zero crossing lines it extracts, what confidence it
00144  *  assigns to each extracted point, and how the faces of a mesh (in terms of
00145  *  ordering and number) are processed to extract the zero crossing lines.  The
00146  *  interfaces of the three functors can be found in the following abstract base
00147  *  classes:
00148  *
00149  *  \li \c ScalarField - \sa ZCrossScalarFieldInterface
00150  *  \li \c Confidence - \sa ZCrossConfidenceInterface
00151  *  \li \c FaceGenerator - \sa ZCrossFaceGeneratorInterface
00152  *
00153  */
00154 template <typename ScalarField, typename Confidence, typename FaceGenerator>
00155 class ZCrossExtractor {
00156    
00157  public:
00158    
00159    //! \name Constructors
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    //! \name Extraction Functions
00172    //@{
00173       
00174    //! \brief Extract the zero crossing lines from the given mesh.
00175    void extract();
00176       
00177    //@}
00178       
00179    //! \name Accessors
00180    //@{
00181       
00182    const BMESH *get_mesh() const { return mesh; }
00183       
00184    //@}
00185       
00186    //! \name Result Accessors
00187    //@{
00188       
00189    //! \brief Access the resulting extracted segments.
00190    const std::vector<ZXseg> &segs() const
00191       { return extracted_segs; }
00192       
00193    //! \brief Clear the extracted segments.
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  *  \brief The interface for the ZCrossExtractor ScalarField functor template
00228  *  argument.
00229  *
00230  *  This functor should take a single \c const \c Bvert* as an argument and return
00231  *  a \c double that is the value of the scalar field that the zero crossing lines
00232  *  are being extracted from at the given vertex.
00233  *
00234  */
00235 class ZCrossScalarFieldInterface {
00236    
00237  public:
00238    
00239    virtual ~ZCrossScalarFieldInterface() {}
00240    virtual double operator()(const Bvert*) = 0;
00241    
00242 };
00243 
00244 /*!
00245  *  \brief The interface for the ZCrossExtractor Confidence functor template
00246  *  argument.
00247  *
00248  *  This functor should take two arguments:  a \c const \c Bface* and a \c const
00249  *  \c BarycentricCoord&.  It should return a double between 0.0 and 1.0 that is
00250  *  the confidence of the point on the given face at the given Barycentric
00251  *  coordinates.
00252  *
00253  */
00254 class ZCrossConfidenceInterface {
00255    
00256  public:
00257    
00258    virtual ~ZCrossConfidenceInterface() {}
00259    virtual double operator()(const Bvert*) = 0;
00260    
00261 };
00262 
00263 /*!
00264  *  \brief The interface for the ZCrossExtractor FaceGenerator functor template
00265  *  argument.
00266  *
00267  *  This functor should have two overloaded forms.
00268  *  
00269  *  The first form should take a single \c const \c ZCrossExtractor* as an
00270  *  argument and should have a \c void return type.  This form should reset the
00271  *  generator and perform any initialization needed (specifically using
00272  *  information available through the \c ZCrossExtractor*).
00273  *
00274  *  The second form should take no arguments and return an \c int.  The \c int is
00275  *  the index of the face that the \c ZCrossExtractor should examine next to look
00276  *  for zero crossing lines (the index is into the \c ZCrossExtractor's mesh's
00277  *  list of faces).  When the \c ZCrossExtractor should stop looking for zero
00278  *  crossing lines, a value of -1 should be returned.
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  *  \brief A simple FaceGenerator for the ZCrossExtractor class that generates
00296  *  all the faces on the mesh being processed.
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  *  \brief A FaceGenerator for the ZCrossExtractor class that generates random
00323  *  faces on the mesh being processed.
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  *  \brief A FaceGenerator for the ZCrossExtractor class that generates the faces
00360  *  that were extracted in the previous extraction (or all faces in none have
00361  *  been extracted).
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  *  \brief A FaceGenerator for the ZCrossExtractor class that generates previous
00397  *  faces (as per the ZCrossPreviousFaceGenerator) followed by random faces (as
00398  *  per the ZCrossRandFaceGenerator).
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    // Reset the FaceGenerator
00432    fgen(this);
00433    
00434    // Reset the face markers:
00435    assert(face_markers.size() == 0);
00436    face_markers.resize(mesh->nfaces(), false);
00437    
00438    // Clear out previously extracted lines:
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    // Get scalar field values for all vertices on this face:
00469    for(int i = 0; i < 3; ++i){
00470       
00471       sf_vals[i] = sfield(f->v(i + 1));
00472       
00473       // Perturb scalar field slightly so that we don't have any zeros exactly
00474       // on vertices:
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    // Find zero crossing in Barycentric coordinates:
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          // Should never have more than two edges with zero crossings:
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          // Make sure the Barycentric coords add up to 1.0:
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          // Make sure none of the Barycentric coords are negative:
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    // If this has face has a zero crossing, there must be exactly two edges that
00520    // contain the crossing.  So, two Barycentric points should have been computed.
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    // Make sure the starting face pointer is non-NULL:
00557    assert(start_face != 0);
00558    
00559    // A NULL next face indicates that we're at a boundary.  Don't extract any
00560    // segments in this case and say that the loop wasn't completed:
00561    if(next_face == 0)
00562       return false;
00563    
00564    // Make sure starting face and next face share an edge:
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       // Make sure the number of faces processed doesn't exceed the number of
00587       // faces in the mesh:
00588       assert(start_face->mesh());      
00589       assert(face_count < start_face->mesh()->nfaces());
00590 
00591 #endif // NDEBUG
00592       
00593       // This face shouldn't have been seen before:
00594       assert(face_markers[cur_face->index()] == false);
00595       
00596       face_markers[cur_face->index()] = true;
00597       
00598       // This should never fail:
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       // See if we are at a boundary edge:
00613       if(next_face == 0)
00614          break;
00615       
00616       // See if we are back at the beginning (i.e. the loop is complete):
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    // Make sure the face pointer is non-NULL:
00641    assert(f != 0);
00642    
00643    // Make sure the face has a non-NULL mesh pointer:
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       // Wasn't able to complete the zero crossing loop, need to walk the other
00661       // end of the line as well...
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       // Make sure number of line segments is less than the number of faces on
00669       // the mesh:
00670       assert(zcross_line_other_part.size() < sign_cast<unsigned long>(f->mesh()->nfaces()));
00671       
00672       // Add all of these segments in reverse order so they 
00673       for(long i = (sign_cast<long>(zcross_line_other_part.size()) - 1); i >= 0; --i){
00674          
00675          // Make sure end point of previous segment equals start point of this segment:
00676          assert((i == (sign_cast<long>(zcross_line_other_part.size()) - 1)) || // Don't check if i == index of first segment
00677                 (zcross_line_other_part[i + 1].flip().get_end_pt()
00678                  == zcross_line_other_part[i].flip().get_start_pt()));
00679       
00680          // Make sure end point of this segment equals start point of next segment:
00681          assert((i == 0) || // Don't check if i == index of last segment
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    // Make sure number of line segments is less than the number of faces on
00692    // the mesh:
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       // Make sure end point of previous segment equals start point of this segment:
00710       assert((i == 0) || // Don't check if i == 0
00711              (zcross_line_part[i - 1].get_end_pt() == zcross_line_part[i].get_start_pt()));
00712    
00713       // Make sure end point of this segment equals start point of next segment:
00714       assert((i == (zcross_line_part.size() - 1)) || // Don't check if i == index of last segment
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 //    const double SC_THRESH = 0.05;
00731 //    
00732 //    if((seg.get_start_conf() <= SC_THRESH) &&
00733 //       (extracted_segs.size() > 0) && (extracted_segs.back().end())){
00734 //       
00735 //       return;
00736 //       
00737 //    }
00738    
00739    // Make sure at least one of the Barycentric coords is zero:
00740    assert(isZero(seg.get_start_bc()[0]) ||
00741           isZero(seg.get_start_bc()[1]) ||
00742           isZero(seg.get_start_bc()[2]));
00743    
00744    // Make sure at least two of the Barycentric coords are not zero:
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; // assume seg.get_start_pt()[2] == 0.0 here
00752    
00753    Bface *f = seg.get_face();
00754    
00755    extracted_segs.push_back(
00756       ZXseg(f,                            // Face
00757             seg.get_start_pt(),           // World space point
00758             f->v(vert_index + 1),         // Vertex (what's this for?)
00759             seg.get_start_conf(),         // Confidence
00760             seg.get_start_bc().to_Wvec(), // Barycentric coords
00761             STYPE_SUGLINE,                // Type
00762             false)                        // End flag
00763       );
00764    
00765    if(seg.is_end() /* || (seg.get_end_conf() <= SC_THRESH) */ ){
00766    
00767       extracted_segs.push_back(
00768          ZXseg(0,                            // Face
00769                seg.get_end_pt(),             // World space point
00770                f->v(vert_index + 1),         // Vertex (what's this for?)
00771                seg.get_end_conf(),           // Confidence
00772                seg.get_end_bc().to_Wvec(),   // Barycentric coords
00773                STYPE_SUGLINE,                // Type
00774                true)                         // End flag
00775          );
00776          
00777    }
00778    
00779 }
00780 
00781 #endif // ZCROSS_EXTRACT_H_IS_INCLUDED

Generated on Mon Sep 18 11:39:34 2006 for jot by  doxygen 1.4.4