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

bface.H

Go to the documentation of this file.
00001 /**********************************************************************
00002  * bface.H
00003  **********************************************************************/
00004 #ifndef BFACE_H_HAS_BEEN_INCLUDED
00005 #define BFACE_H_HAS_BEEN_INCLUDED
00006 
00007 #include "bvert.H"
00008 //#include "vert_attrib.H"
00009 
00010 class EdgeStrip;
00011 class Patch;
00012 /**********************************************************************
00013  * Bface:
00014  *
00015  *      3-sided face, vertices listed in CCW order.
00016  * <pre>
00017  *                    v3
00018  *                   /  \
00019  *                  /    \
00020  *                 /      \
00021  *               e3       e2
00022  *               /          \
00023  *              /            \
00024  *             /              \
00025  *           v1 -------e1------ v2
00026  * </pre>
00027  **********************************************************************/
00028 class Bface  : public Bsimplex {
00029  public:
00030 
00031    //******** FLAG BITS ********
00032    // Used to store boolean states (see Bsimplex class):
00033    enum {
00034       BAD_BIT = Bsimplex::NEXT_AVAILABLE_BIT, // set in constructor if error
00035       VALID_NORMAL_BIT,                       // tells if normal is up-to-date
00036       FRONT_FACING_BIT,                       // tells if it's front-facing
00037       SECONDARY_BIT,                          // face is not in primary layer
00038       NEXT_AVAILABLE_BIT                      // derived classes start here
00039    };
00040 
00041    //******** MANAGERS ********
00042    Bface(Bvert*, Bvert*, Bvert*, Bedge*, Bedge*, Bedge*);
00043    virtual ~Bface();
00044 
00045    //******** ACCESSORS ********
00046    // vertices:
00047    Bvert *v1()     const  { return _v1; }
00048    Bvert *v2()     const  { return _v2; }
00049    Bvert *v3()     const  { return _v3; }
00050    Bvert *v(int i) const  { return (i>0&&i<4)?(&_v1)[i-1]:0; } // i in [1..3]
00051 
00052    // edges:
00053    Bedge *e1()     const  { return _e1; }
00054    Bedge *e2()     const  { return _e2; }
00055    Bedge *e3()     const  { return _e3; }
00056    Bedge *e(int i) const  { return (i>0&&i<4)?(&_e1)[i-1]:0; } // i in [1..3]
00057 
00058    // Face normal (cached value -- recomputed as needed):
00059    CWvec& norm() const {
00060       if (!is_set(VALID_NORMAL_BIT))
00061          ((Bface*)this)->set_normal();
00062       return _norm;
00063    }
00064 
00065    // Vertex normal - average of face normals around vertex, not
00066    // crossing any crease edges to reach the other faces, starting
00067    // from this one. 2nd version returns result by copying.
00068    CWvec& vert_normal(CBvert* v, Wvec& n) const;
00069    Wvec vert_normal(CBvert* v) const {
00070       Wvec n;
00071       return vert_normal(v, n);
00072    }
00073 
00074    // Returns 1 if this face faces the camera in the current frame:
00075    int front_facing() const;
00076    // for zx silhouettes
00077    bool zx_mark() const;       //mark face as visited ( with view::stamp )     
00078    bool zx_query() const;      //has face been visited? ( == view::stamp )
00079 
00080    Patch* patch()  const  { return _patch; }
00081 
00082    // for tri-stripping
00083    // XXX - should rename
00084    void   orient_strip(Bvert* a) { _orient = a; }
00085    Bvert* orient_strip() const { return _orient; }
00086 
00087    // return the vertex's "index." i.e., 1, 2, or 3 according to
00088    // whether it is vertex _v1, _v2, or _v3, respectively:
00089    int vindex(CBvert* v) const {
00090       return (v==_v1) ? 1 : (v==_v2) ? 2 : (v==_v3) ? 3 : -1;
00091    }
00092 
00093    //******** ADJACENCY ********
00094    bool contains(CBvert* v) const { return (v==_v1 || v==_v2 || v==_v3); }
00095    bool contains(CBedge* e) const { return (e==_e1 || e==_e2 || e==_e3); }
00096    bool contains(CBsimplex* s) const {
00097       if (s->dim()==1) return contains( (CBedge*)s );
00098       if (s->dim()==0) return contains( (CBvert*)s );
00099       return 0;
00100    }
00101    bool contains(CWpt& pt, double threshold=0) const ;
00102 
00103    Bvert* other_vertex(CBvert* u, CBvert* v) const {
00104       return (!(contains(u) && contains(v)) ? 0 :
00105               (u==_v1) ? ((v==_v2) ? _v3 : (v==_v3) ? _v2 : 0) :
00106               (u==_v2) ? ((v==_v1) ? _v3 : (v==_v3) ? _v1 : 0) :
00107               (u==_v3) ? ((v==_v1) ? _v2 : (v==_v2) ? _v1 : 0) :
00108               0);
00109    }
00110    Bvert* other_vertex(CBedge* e) const {
00111       return e ? other_vertex(e->v1(), e->v2()) : (Bvert*)0;
00112    }
00113    Bvert* next_vert_ccw(CBvert* u) const {
00114       return (u==_v1) ? _v2 : (u==_v2) ? _v3 : (u==_v3) ? _v1 : 0;
00115    }
00116 
00117    // Return the vertex of the given edge (of this face)
00118    // that comes first WRT this face, in CCW order:
00119    Bvert* leading_vert_ccw(CBedge* e) const {
00120       return (
00121          e ? ((next_vert_ccw(e->v1()) == e->v2()) ? e->v1() : e->v2()) : 0
00122          );
00123    }
00124 
00125    Bedge* next_edge_ccw(CBedge* u) const {
00126       return (u==_e1) ? _e2 : (u==_e2) ? _e3 : (u==_e3) ? _e1 : 0;
00127    }
00128    Bedge* edge_from_vert(CBvert* u) const {
00129       return (u==_v1) ? _e1 : (u==_v2) ? _e2 : (u==_v3) ? _e3 : 0; 
00130    }
00131    Bedge* edge_before_vert(CBvert* u) const {
00132       return (u==_v1) ? _e3 : (u==_v2) ? _e1 : (u==_v3) ? _e2 : 0; 
00133    }
00134    Bface* next_face_ccw(CBvert* u) const {
00135       return edge_before_vert(u)->other_face(this);
00136    }
00137 
00138    // neighboring face (i in [1..3]):
00139    Bface* nbr(int i) const {
00140       Bedge* ei = e(i);
00141       return ei ? ei->other_face(this) : 0;
00142    }
00143 
00144    // return edge shared with given face:
00145    Bedge* shared_edge(CBface* f) const {
00146       return ((_e1->other_face(this) == f) ? _e1 :
00147               (_e2->other_face(this) == f) ? _e2 :
00148               (_e3->other_face(this) == f) ? _e3 :
00149               0);
00150    }
00151 
00152    Bedge* opposite_edge(CBvert* a) const {
00153       return ((a == _v1) ? _e2 :
00154               (a == _v2) ? _e3 :
00155               (a == _v3) ? _e1 : 0
00156          );
00157    }
00158    Bface* opposite_face(CBvert* a) const {
00159       Bedge* e = opposite_edge(a);
00160       return e ? e->other_face(this) : 0;
00161    }
00162    Bface* next_strip_face() const {
00163       CBedge* e = opposite_edge(orient_strip());
00164       return (e && e->is_crossable()) ? e->other_face(this) : 0;
00165    }
00166    Bedge* other_edge(CBvert* v, CBedge* e) const {
00167       return ((_e1 != e && _e1->contains(v)) ? _e1 :
00168               (_e2 != e && _e2->contains(v)) ? _e2 :
00169               (_e3 != e && _e3->contains(v)) ? _e3 :
00170               0);
00171    }
00172 
00173    int orientation(CBedge* e) const {
00174       return (contains(e) ? (next_vert_ccw(e->v1()) == e->v2() ? 1 : -1) : 0);
00175    }    
00176 
00177    //******** FACE TESTS ********
00178    // set in the constructor if face could not be defined with given
00179    // vertices and edges:
00180    bool is_bad()      const  { return is_set(BAD_BIT); }
00181 
00182    // meshes can represent non-manifold surfaces.
00183    // the "primary" layer is still manifold, however.
00184    bool is_primary()   const  { return is_clear(SECONDARY_BIT); }
00185    bool is_secondary() const  { return !is_primary(); }
00186 
00187    ushort layer()                       const   { return _layer; }
00188    virtual void set_layer(ushort l)             { _layer = l; }
00189 
00190    // For non-manifold meshes:
00191    // Label the face as "primary" or "secondary." I.e., as being
00192    // in the primary layer or not, respectively. In Lface, the
00193    // same action is passed down to all child faces.
00194    virtual void make_primary();
00195    virtual void make_secondary();
00196 
00197    //******** GEOMETRIC MEASURES ********
00198    double area() const {
00199       if (!is_set(VALID_NORMAL_BIT))
00200          ((Bface*)this)->set_normal();
00201       return _area;
00202    }
00203    double volume_el() const {
00204       CWpt& a = _v1->loc();
00205       CWpt& b = _v2->loc();
00206       CWpt& c = _v3->loc();
00207       // nx = cross(b-a, c-a)[0];
00208       double nx = (b[1] - a[1])*(c[2] - a[2]) - (c[1] - a[1])*(b[2] - a[2]);
00209       return (nx * (a[0] + b[0] + c[0]) / 6.0);
00210    }
00211    double angle(CBvert* v) const {
00212       if (!contains(v))
00213          return 0;
00214       Bvert* a = next_vert_ccw(v);
00215       Bvert* b = next_vert_ccw(a);
00216       return (v->loc() - a->loc()).angle(v->loc() - b->loc());
00217    }    
00218 
00219    Wpt    centroid()     const { return (_v1->loc()+_v2->loc()+_v3->loc())/3;}
00220    NDCZpt ndc_centroid() const { return (_v1->ndc()+_v2->ndc()+_v3->ndc())/3;}
00221    Wplane  plane()       const { return Wplane(_v1->loc(), norm()); }
00222 
00223    double signed_area(CWpt& a, CWpt& b, CWpt& c) const {
00224       return 0.5 * (cross(b-a,c-a) * norm());
00225    }
00226    double signed_area(CNDCpt& a, CNDCpt& b, CNDCpt& c) const {
00227       return 0.5 * det(b-a,c-a);
00228    }
00229 
00230    double ndc_area() const {
00231       NDCpt a = _v1->ndc();
00232       NDCpt b = _v2->ndc();
00233       NDCpt c = _v3->ndc();
00234       return fabs(signed_area(a,b,c));
00235    }
00236 
00237  
00238 
00239    //******** QUAD STUFF ********
00240 
00241    // A quad consists of 2 triangles that share a "weak" edge.
00242    // None of the other edges of either face should be labelled
00243    // weak.  The "weak" label just means that the edge is an
00244    // internal, diagonal edge of a quad.
00245    int num_weak_edges() const {
00246       return (
00247          (_e1->is_weak() ? 1 : 0) +
00248          (_e2->is_weak() ? 1 : 0) +
00249          (_e3->is_weak() ? 1 : 0)
00250          );
00251    }
00252    bool is_quad() const  { return (num_weak_edges() == 1); }
00253    Bedge* weak_edge() const {
00254       return  (_e1->is_weak() ? _e1 :
00255                _e2->is_weak() ? _e2 :
00256                _e3->is_weak() ? _e3 : 0
00257          );
00258    }
00259 
00260    // The other Bface making up the quad:
00261    Bface* quad_partner() const {
00262       return is_quad() ? weak_edge()->other_face(this) : (Bface*)0;
00263    }
00264 
00265    // Arbitrarily (but consistently) pick one face to
00266    // represent the quad:
00267    Bface* quad_rep() const {
00268       return min((Bface*)this, quad_partner());
00269    }
00270 
00271    // Return true if this one is the quad rep:
00272    bool is_quad_rep() const { return is_quad() && quad_rep() == this; }
00273 
00274    Bvert* quad_vert() const {
00275       return is_quad() ? weak_edge()->opposite_vert(this) : (Bvert*)0;
00276    }
00277    Bvert* quad_opposite_vert(CBvert* v) const {
00278       Bedge* e = weak_edge();
00279       if (!e) return 0;
00280       if (e->contains(v))
00281          return e->other_vertex(v);
00282       if (contains(v))
00283          return e->opposite_vert(this);
00284       Bface* f = quad_partner();
00285       return f && f->contains(v) ? e->opposite_vert(f) : 0;
00286    }
00287 
00288    // Given one edge of quad, return opposite edge
00289    Bedge* opposite_quad_edge(CBedge* e) const {
00290       if (is_quad()) {
00291          Bvert* u1=other_vertex(e->v1(), e->v2());
00292          Bvert* u2=quad_vert();
00293          return u1->lookup_edge(u2);
00294       }
00295       else
00296          return 0;
00297    }
00298 
00299    //added by Karol for the quad mesh traversal
00300    Bface* other_quad_face(CBedge *e) const {
00301       
00302       
00303     if (!e) return 0; //safety first
00304    
00305       //we may be on the other quad face not directly adjacent to this edge
00306       //in that case get the other quad face
00307       if ((this!=e->f1())&&(this!=e->f2()))
00308       {
00309          return e->other_face(this->quad_partner());
00310       }
00311 
00312       return e->other_face(this);
00313    }
00314 
00315    // Convenience. only call these on quads:
00316    double quad_area() const {
00317       return area() + quad_partner()->area();
00318    }
00319    double quad_ndc_area() const {
00320       return ndc_area() + quad_partner()->ndc_area();
00321    }
00322    Wpt quad_centroid() const {
00323       return (_v1->loc() + _v2->loc() +
00324               _v3->loc() + quad_vert()->loc())*0.25;
00325    }
00326    NDCZpt ndc_quad_centroid() const {
00327       return (_v1->ndc() + _v2->ndc() +
00328               _v3->ndc() + quad_vert()->ndc())*0.25;
00329    }
00330    Wvec quad_norm() const {
00331       return (norm() + quad_partner()->norm()).normalized();
00332    }
00333 
00334    Wvec qnorm() const { return is_quad() ? quad_norm() : norm(); }
00335    
00336    //  Return CCW verts a, b, c, d as in the picture, 
00337    //  orienting things so that the weak edge runs NE
00338    //  as shown:
00339    //
00340    //    d ---------- c = w->v2()              ^      
00341    //    |          / |                        |       
00342    //    |        /   |                        |       
00343    //    |    w /     |       tan1        tan2 |       
00344    //    |    /       |    -------->           |       
00345    //    |  /     f   |                        |       
00346    //    |/           |                                
00347    //    a ---------- b                                
00348    //   a = w->v1()
00349    //
00350    bool get_quad_verts(Bvert*& a, Bvert*& b, Bvert*& c, Bvert*& d) const;
00351    bool get_quad_verts(Bvert_list& verts)                          const;
00352    bool get_quad_pts(Wpt& a, Wpt& b, Wpt& c, Wpt& d)               const;  
00353    
00354    bool get_quad_edges(Bedge*& ab, Bedge*& bc, Bedge*& cd, Bedge*& da) const;
00355    bool get_quad_edges(Bedge_list& edges)                          const;
00356 
00357 
00358    // vectors perpendicular to the quad normal, each one aligned
00359    // with a pair of opposite sides of the quad:
00360    Wvec quad_tan1() const;      // runs right/left in diagram above
00361    Wvec quad_tan2() const;      // runs    up/down in diagram above
00362 
00363    // Based on the 4 verts in standard orientation as above,
00364    // return the average of the two horizontal or vertical edge
00365    // lengths, respectively:
00366    double quad_dim1()    const;    // avg length of ab and dc
00367    double quad_dim2()    const;    // avg length of ad and bc
00368 
00369    // Convenience methods related to the previous two methods:
00370    double quad_avg_dim() const { return (quad_dim1() + quad_dim2())/2; }
00371    double quad_max_dim() const { return max(quad_dim1(), quad_dim2()); }
00372    double quad_min_dim() const { return min(quad_dim1(), quad_dim2()); }
00373 
00374    // Convert barycentric coords WRT this face to uv coords
00375    // WRT the quad that this face is part of:
00376    UVpt quad_bc_to_uv(CWvec& bc) const;
00377 
00378    // Use bilinear interpolation on the quad vertices to map
00379    // the given uv coordinate (WRT the quad) to a Wpt:
00380    Wpt  quad_uv2loc(CUVpt& uv) const;
00381 
00382    //******** TEXTURE COORDINATES ********
00383    // texture coordinates are stored per vertex per face
00384    // i.e.-- a given vertex can be assigned separate texture
00385    // coordinates for each face that contains the vertex
00386 
00387    // XXX - should not be called -- use UVdata::get_uv() to
00388    //       lookup texture coordinates
00389    UVpt &tex_coord(int vert_index) const {
00390       // vert_index must be 1, 2 or 3.
00391       // explicitly warn about this little-understood fact:
00392       assert (vert_index > 0 || vert_index < 4);
00393       return (_tc?(_tc):(((Bface*)this)->_tc = new UVpt[3]))[vert_index - 1];
00394    }
00395    UVpt &tex_coord(CBvert* v) const { return tex_coord(vindex(v)); }
00396 
00397    // set coordinates for vertices 1, 2, 3, respectively:
00398    void set_tex_coords(CUVpt& a, CUVpt& b, CUVpt& c) {
00399       tex_coord(1) = a; tex_coord(2) = b; tex_coord(3) = c;
00400    }
00401 
00402    UVpt* tc_array() const { return _tc; }
00403 
00404    //******** BARYCENTRIC COORDINATES ********
00405    // compute barycentric coords of a point wrt this face,
00406    virtual void project_barycentric(CWpt& p, Wvec& ret) const {
00407       double u = signed_area(p, _v2->loc(), _v3->loc()) / area();
00408       double v = signed_area(_v1->loc(), p, _v3->loc()) / area();
00409       ret.set(u, v, 1 - u - v);
00410    }
00411    // compute barycentric coords of a point wrt this face,
00412    // measuring vertex positions in NDC coordinates
00413    void project_barycentric_ndc(CNDCpt& p, Wvec& ret) const {
00414       NDCpt a = _v1->ndc(), b = _v2->ndc(), c = _v3->ndc();
00415       double A = signed_area(a, b, c);
00416       double u = signed_area(p, b, c) / A;
00417       double v = signed_area(a, p, c) / A;
00418       ret.set(u, v, 1 - u - v);
00419    }
00420 
00421    virtual void bc2pos(CWvec& bc, Wpt& pos) const {
00422       pos = (bc[0]*_v1->loc()) + (bc[1]*_v2->loc()) + (bc[2]*_v3->loc());
00423    }
00424 
00425    virtual void bc2norm_blend(CWvec& bc, Wvec& vec) const {
00426       Wvec v1,v2,v3;
00427       vert_normal(_v1,v1);
00428       vert_normal(_v2,v2);
00429       vert_normal(_v3,v3);
00430       vec = ((bc[0]*v1) +
00431              (bc[1]*v2) +
00432              (bc[2]*v3)).normalized();
00433    }
00434 
00435    virtual Bsimplex* bc2sim(CWvec& bc) const;
00436 
00437    // returns the closest vertex to the barycentric coords
00438    Bvert* bc2vert(CWvec& bc) const {
00439       double max = 0; 
00440       int best_v;
00441       for (int i=0; i<3; i++)
00442          if (bc[i] >= max) {
00443             max = bc[i];
00444             best_v = i;
00445          }
00446       return v(best_v+1);
00447    }
00448 
00449    // returns the closest edge to the barycentric coords
00450    Bedge* bc2edge(CWvec& bc) const {
00451       double min = 1; 
00452       int best_v;
00453       for (int i=0; i<3; i++)
00454          if (bc[i] <= min) {
00455             min = bc[i];
00456             best_v = i;
00457          }
00458       return opposite_edge(v(best_v+1));
00459    }
00460 
00461    Wvec bc2norm(CWvec& bc) const {
00462       Bsimplex* sim = bc2sim(bc);
00463       return (is_vert(sim) ? ((Bvert*)sim)->norm() :
00464               is_edge(sim) ? ((Bedge*)sim)->norm() :
00465               norm()
00466          );
00467    }
00468 
00469    //******** INTERSECTION ********
00470 
00471    // (Bsimplex virtual method):
00472    // Intersection w/ ray from given screen point -- returns the point
00473    // on the Bface that is nearest to the given screen space point.
00474    // Note: the returned "near point" and "normal" are both
00475    //       transformed to world space.
00476    virtual bool view_intersect(
00477       CNDCpt&,  // Given screen point. Following are returned:
00478       Wpt&,     // Near point on the simplex IN WORLD SPACE (not object space)
00479       double&,  // Distance from camera to near point
00480       double&,  // Screen distance (in PIXELs) from given point
00481       Wvec& n   // "normal" vector at intersection point IN WORLD SPACE
00482       ) const;
00483 
00484    // Similar to above, but returns the hit point 
00485    // both in local and barycentric coords:
00486    Wpt near_pt(CNDCpt& ndc, Wvec& hit_bc) const;
00487 
00488    // Ditto, but hold the barycentric coords:
00489    Wpt near_pt(CNDCpt& ndc) const {
00490       Wvec hit_bc;
00491       return near_pt(ndc, hit_bc);
00492    }
00493 
00494    // Ray intersection: returns true if given ray exactly intersects
00495    // the face:
00496    bool ray_intersect(CWpt&, CWvec&, Wpt& ret, double& depth) const;
00497    bool ray_intersect(CWline& ray, Wpt& ret, double& depth) const {
00498       return ray_intersect(ray.point(), ray.vector(), ret, depth);
00499    }
00500    // Similar to above, but return barycentric coords of hit point:
00501    bool ray_intersect(CWline& ray, Wvec& bc) const {
00502       Wpt hit; double depth;
00503       if (ray_intersect(ray, hit, depth)) {
00504          project_barycentric(hit, bc);
00505          return 1;
00506       }
00507       return 0;
00508    }
00509 
00510    // Intersect a line with the plane of the face:
00511    Wpt plane_intersect(CWline& line) const {
00512       return plane().intersect(line);
00513    }
00514    Wpt plane_intersect(CNDCpt& ndc) const {
00515       return plane_intersect(Wline(XYpt(ndc)));
00516    }
00517    Bsimplex* find_intersect_sim(CNDCpt& target, Wpt& hit_pt) const;
00518 
00519    bool ndc_contains(CNDCpt &p) {
00520       NDCpt a(_v1->ndc());
00521       NDCpt b(_v2->ndc());
00522       NDCpt c(_v3->ndc());
00523       return (det(b-a, p-a) * det(p-a, c-a) >= 0) &&
00524          (det(c-b, p-b) * det(p-b, a-b) >= 0);
00525    }
00526    
00527    Bface* plane_walk(Bedge* cur_edge, CWplane& plane, Bedge*& next_edge) const;
00528 
00529    // Returns the NDC point on this face that is nearest the given
00530    // NDC point; optionally also returns the corresponding (NDC)
00531    // barycentric coords and a flag indicating if the original
00532    // screen point was inside the triangle:
00533    NDCpt nearest_pt_ndc(CNDCpt& p, Wvec &bc, int &is_on_tri) const;
00534    NDCpt nearest_pt_ndc(CNDCpt& p, Wvec &bc) const {
00535       int i; return nearest_pt_ndc(p, bc, i);
00536    }
00537    NDCpt nearest_pt_ndc(CNDCpt& p) const {
00538       Wvec bc; return nearest_pt_ndc(p, bc);
00539    }
00540 
00541    // Returns the object-space point on this face that is nearest
00542    // the given object-space point p; optionally also returns the
00543    // corresponding barycentric coords and a flag indicating if the
00544    // original point p projects to the interior of the triangle:
00545    virtual Wpt nearest_pt(CWpt& p, Wvec &bc, bool &is_on_tri) const;
00546 
00547    //******** BUILDING/REDEFINING ********
00548    virtual int  detach();
00549    virtual void reverse();
00550 
00551    int  redefine(Bvert *v, Bvert *u);
00552    int  redefine(Bvert *u, Bvert *nu, Bvert *v, Bvert *nv);
00553 
00554    // New versions of face redefinition, under development 12/2004:
00555 
00556    // Perform a lightweight face redefinition, replacing
00557    // vert 'a' with vert 'b', but not changing the edges.
00558    virtual bool redef2(Bvert *a, Bvert *b);
00559 
00560    // Redefine this face, replacing edge 'a' with 'b'.
00561    // Update the old edge to forget this face,
00562    // and the new edge to remember it.
00563    virtual bool redef2(Bedge *a, Bedge *b);
00564 
00565    // Return true if stored edges match stored verts;
00566    // used in redef ops to ensure face is not all bollocksed up:
00567    bool check() const;
00568 
00569    //******** HANDLING CACHED VALUES ********
00570    virtual void geometry_changed();
00571    virtual void normal_changed();
00572 
00573    //******** I/O ********
00574    friend ostream &operator <<(ostream &os, CBface &f) {
00575       return os << f.v(1)->index() << " "
00576                 << f.v(2)->index() << " "
00577                 << f.v(3)->index() << endl;
00578    }
00579    friend STDdstream &operator <<(STDdstream &d, CBface &f) {
00580       return d << f.v(1)->index() << f.v(2)->index() << f.v(3)->index();
00581    }
00582 
00583    //******** Bsimplex VIRTUAL METHODS ********
00584 
00585    // dimension:
00586    virtual int dim() const { return 2; }
00587 
00588    // index in BMESH Bedge array:
00589    virtual int  index() const;
00590    
00591    virtual Bface* get_face()            const   { return (Bface*)this; }
00592    virtual bool   on_face(CBface* f)    const   { return f == this; }
00593 
00594    // Return a list of adjacent Bsimplexes:
00595    // (returns v1, v2, v3, e1, e2, e3);
00596    virtual Bsimplex_list neighbors() const;
00597 
00598    //******** XXX - OBSOLETE -- OLD TESSELLATOR STUFF
00599    bool local_search(Bsimplex *&end, Wvec &final_bc,
00600                      CWpt &target, Wpt &reached, 
00601                      Bsimplex *repeater = 0, int iters = 30);
00602 
00603    //*******************************************************
00604    // PROTECTED
00605    //*******************************************************
00606  protected:
00607    friend       class Patch;
00608 
00609    Bvert*       _v1;            // vertex 1 (vertices listed in CCW order)
00610    Bvert*       _v2;            // vertex 2
00611    Bvert*       _v3;            // vertex 3
00612    Bedge*       _e1;            // edge from _v1 to _v2
00613    Bedge*       _e2;            // edge from _v2 to _v3
00614    Bedge*       _e3;            // edge from _v3 to _v1
00615    Wvec         _norm;          // unit length face normal
00616    double       _area;          // area of this face
00617    Patch*       _patch;         // patch which owns this face
00618    int          _patch_index;   // index of face in list on patch
00619    Bvert*       _orient;        // for triangle stripping
00620    uint         _ff_stamp;      // for computing front-facing
00621    uint         _zx_stamp;      // zero-cross path flag
00622    UVpt*        _tc;            // texture coords
00623    ushort       _layer;         // layer number (used for non-manifold meshes)
00624 
00625    // Setting the Patch -- nobody's bizness but the Patch's.
00626    // (You want to set it? call Patch::add(Bface*).)
00627    virtual void set_patch(Patch* p)      { _patch = p; }
00628    void    set_patch_index(int k)        { _patch_index = k; }
00629    int     patch_index() const           { return _patch_index; }
00630 
00631    //******** INTERNAL METHODS ********
00632 
00633    Bsimplex* ndc_walk(CNDCpt& target, CWvec &bc=Wvec(),
00634                       CNDCpt &nearest=NDCpt(),
00635                       int is_on_tri=0, bool use_passed_in_params=false) const;
00636 
00637    // methods for recomputing cached values when needed:
00638    void set_normal() {
00639       set_bit(VALID_NORMAL_BIT,1);
00640       _norm = (cross(_v2->loc()-_v1->loc(),_v3->loc()-_v1->loc())).normalized();
00641       _area = signed_area(_v1->loc(),_v2->loc(),_v3->loc());
00642    }
00643 };
00644 
00645 /*******************************************************
00646  * Inline methods
00647  *******************************************************/
00648 
00649 // Convenient "upcast":
00650 inline Bface*
00651 bface(Bsimplex* sim)
00652 {
00653    return is_face(sim) ? (Bface*)sim : 0;
00654 }
00655 
00656 inline Bface*
00657 lookup_face(CBedge* e, CBvert* v)
00658 {
00659    return (e && v) ? e->lookup_face(v) : 0;
00660 }
00661 
00662 inline Bface*
00663 lookup_face(CBedge* a, CBedge* b)
00664 {
00665    return (a && b) ? a->lookup_face(b) : 0;
00666 }
00667 
00668 inline Bface*
00669 lookup_face(CBvert* a, CBvert* b, CBvert* c)
00670 {
00671    Bedge* e = a ? a->lookup_edge(b) : 0;
00672 
00673    return e ? e->lookup_face(c) : 0;
00674 }
00675 
00676 inline Bvert* 
00677 next_vert_ccw(CBface* f, CBvert* v) 
00678 {
00679    // Returns the next vertex of f following v in CCW order.
00680 
00681    // v must be a vertex of f.
00682 
00683    return f ? f->next_vert_ccw(v) : 0; 
00684 }
00685 
00686 inline Bface* 
00687 ccw_face(CBedge* e, CBvert* v) 
00688 {
00689    // Returns the Bface adjacent to e for which the next
00690    // vertex in CCW order following v also belongs to e.
00691 
00692    // v must be a vertex of e.
00693 
00694    Bvert* u = e ? e->other_vertex(v) : 0;
00695 
00696    return ((u == 0)                        ? 0       :
00697            (next_vert_ccw(e->f1(),v) == u) ? e->f1() :
00698            (next_vert_ccw(e->f2(),v) == u) ? e->f2() :
00699            0);
00700 }
00701 
00702 inline Bface* 
00703 ccw_face(CBedge* e) 
00704 {
00705    return e ? ccw_face(e, e->v1()) : 0;
00706 }
00707 
00708 inline void
00709 reverse_faces(CARRAY<Bface*>& faces)
00710 {
00711    for (int k=faces.num()-1; k>=0; k--)
00712       faces[k]->reverse();
00713 }
00714 
00715 // Return the closest vertex to the 
00716 // given point (in world space):
00717 inline Bvert*
00718 closest_vert(Bface* f, CWpt& p)
00719 {
00720    if (!f) return 0;
00721    double d1 = f->v1()->wloc().dist(p);
00722    double d2 = f->v2()->wloc().dist(p);
00723    double d3 = f->v3()->wloc().dist(p);
00724    if (d1 < d2)
00725       return (d3 < d1) ? f->v3() : f->v1();
00726    else
00727       return (d3 < d2) ? f->v3() : f->v2();
00728 }
00729 
00730 // Like above, but work in NDC space
00731 inline Bvert*
00732 closest_vert(Bface* f, CNDCpt& p)
00733 {
00734    if (!f) return 0;
00735    double d1 = NDCpt(f->v1()->wloc()).dist(p);
00736    double d2 = NDCpt(f->v2()->wloc()).dist(p);
00737    double d3 = NDCpt(f->v3()->wloc()).dist(p);
00738    if (d1 < d2)
00739       return (d3 < d1) ? f->v3() : f->v1();
00740    else
00741       return (d3 < d2) ? f->v3() : f->v2();
00742 }
00743 
00744 /*****************************************************************
00745  * Bface filters
00746  *****************************************************************/
00747 class FrontFacingBfaceFilter : public SimplexFilter {
00748  public:
00749    virtual bool accept(CBsimplex* s) const {
00750       return is_face(s) && ((Bface*)s)->front_facing();
00751    }
00752 };
00753 
00754 class PrimaryFaceFilter : public SimplexFilter {
00755  public:
00756    virtual bool accept(CBsimplex* s) const {
00757       return is_face(s) && ((Bface*)s)->is_primary();
00758    }
00759 };
00760 
00761 class SecondaryFaceFilter : public SimplexFilter {
00762  public:
00763    virtual bool accept(CBsimplex* s) const {
00764       return is_face(s) && ((Bface*)s)->is_secondary();
00765    }
00766 };
00767 
00768 class QuadFaceFilter : public SimplexFilter {
00769  public:
00770    virtual bool accept(CBsimplex* s) const {
00771       return is_face(s) && ((Bface*)s)->is_quad();
00772    }
00773 };
00774 
00775 class QuadRepFaceFilter : public SimplexFilter {
00776  public:
00777    virtual bool accept(CBsimplex* s) const {
00778       return is_face(s) && ((Bface*)s)->is_quad_rep();
00779    }
00780 };
00781 
00782 /************************************************************
00783  * Bface_list
00784  ************************************************************/
00785 class Bface_list;
00786 typedef const Bface_list CBface_list;
00787 class Bface_list : public SimplexArray<Bface_list,Bface*> {
00788  public:
00789 
00790    //******** MANAGERS ********
00791 
00792    Bface_list(CARRAY<Bface*>& list) : SimplexArray<Bface_list,Bface*>(list) {}
00793    explicit Bface_list(int n=0)     : SimplexArray<Bface_list,Bface*>(n)    {}
00794    explicit Bface_list(Bface* f)    : SimplexArray<Bface_list,Bface*>(f) {
00795       if (f && f->is_quad())
00796          add(f->quad_partner());
00797    }
00798 
00799    //******** ADJACENCY ********
00800 
00801    // Returns list of verts or edges contained in a given
00802    // set of faces:
00803    Bvert_list get_verts() const;
00804    Bedge_list get_edges() const;
00805 
00806    //******** GEOMETRY  ********
00807 
00808    // Returns the average of the contained face normals:
00809    Wvec avg_normal() const;
00810 
00811    // Returns the maximum deviation, in radians, of a contained face
00812    // normal from the given vector n:
00813    double max_norm_deviation(CWvec& n) const;
00814 
00815    // Returns true if the angle between each face normal and the
00816    // average normal is less than the given max_angle (in radians):
00817    bool is_planar(double max_angle) const {
00818       return(max_norm_deviation(avg_normal()) < max_angle);
00819    }
00820 
00821    // Returns the sum of the "volume elements" for each face.
00822    // Really only makes sense for a list of faces forming a
00823    // closed surface; though if the faces form a nearly-closed
00824    // surface it can tell you if they are oriented mostly
00825    // inside-out or not. (Negative volume == inside out.)
00826    // Uses the divergence theorem.
00827    double volume() const;
00828 
00829    //******** TOPOLOGY ********
00830 
00831    // Returns true if the faces form a single connected component:
00832    // Note: two faces that share a vertex but not an edge are
00833    //       NOT connected.
00834    bool is_connected()                  const;
00835 
00836    // Returns true if no edge *interior* to this set of faces 
00837    // has 2 adjacent faces with inconsistent orientation:
00838    bool is_consistently_oriented()      const;
00839 
00840    // Returns true if every contained edge is adjacent to no more than
00841    // 2 faces of *this* face set:
00842    bool is_2_manifold()                 const;
00843 
00844    // Returns true if the set is connected, the boundary is a simple
00845    // loop, and the faces form a 2-manifold (WRT faces of this set):
00846    bool is_disk()                       const;
00847 
00848    // Flip the orientation:
00849    void reverse_faces() const { 
00850       for (int k=0; k<_num; k++)
00851          _array[k]->reverse();
00852    }
00853 
00854    // Extract boundary edges in one or more continuous chains
00855    // running counter-clockwise around the face set:
00856    EdgeStrip get_boundary() const;
00857 
00858    Bedge_list boundary_edges() const;
00859    Bedge_list interior_edges() const;
00860    Bvert_list interior_verts() const;
00861 
00862    // Returns the 1-ring faces of a set of faces.  The
00863    // returned list contains the original faces, plus the
00864    // external faces reachable within 1 edge length.
00865    Bface_list one_ring_faces() const { return get_verts().one_ring_faces(); }
00866 
00867    // Like the one-ring, but doesn't include faces of this set:
00868    Bface_list exterior_faces() const;
00869 
00870    // Returns the 2-ring faces of a set of faces:
00871    Bface_list two_ring_faces() const { return one_ring_faces().one_ring_faces();}
00872 
00873    // Like above, generalized to n
00874    Bface_list n_ring_faces(int n) {
00875       Bface_list ret = *this;
00876       for (int i=0; i<n; i++)
00877          ret = ret.one_ring_faces();
00878       return ret;
00879    }
00880 
00881    // If the list contains any "quad" faces but not their partners,
00882    // returns the "completed" list, containing the missing partners:
00883    Bface_list quad_complete_faces() const;
00884 
00885    //************ GROW CONNECTED *******
00886 
00887    // reachable_faces:
00888    // 
00889    //   Returns the list of faces reachable from f,
00890    //   crossing only edges accepted by the filter.
00891    //   (The default filter accepts all edges.)
00892    //   It sets needed flags (on the entire mesh)
00893    //   then calls grow_connected(), below:
00894    static Bface_list reachable_faces(Bface* f, CSimplexFilter& =BedgeFilter());
00895 
00896    // grow_connected:
00897    // 
00898    //   Collect all reachable faces whose flag == 1, starting at f,
00899    //   crossing only edges that are accepted by the given
00900    //   filter. (The default filter accepts all edges.)
00901    //
00902    //   NOTE:
00903    //     Assumes all face flags are initialized to 1.
00904    //     This method sets face flags to 2 as it
00905    //     collects each face.
00906    //
00907    bool grow_connected(Bface* f, CSimplexFilter& =BedgeFilter());
00908 
00909    //******** PUSH LAYER ********
00910 
00911    // Given a set of faces from a single mesh, mark the
00912    // faces as a separate "layer" of the mesh, with
00913    // lower priority than the primary, manifold layer:
00914    bool push_layer(bool push_boundary=true) const;
00915 
00916    // Reports whether it valid to call push_layer() on this face set:
00917    bool can_push_layer() const;
00918 
00919    // unpush_layer() undoes the effect of push_layer(), if possible:
00920    bool unpush_layer(bool unpush_boundary=true) const;
00921 
00922    // Tells if it's possible:
00923    bool can_unpush_layer() const;
00924 
00925    // Label each face as "primary"
00926    void make_primary() const {
00927       for (int i=0; i<_num; i++)
00928          _array[i]->make_primary();
00929    }
00930 
00931    // Label each face as "secondary",
00932    // i.e., as not being in the primary layer
00933    void make_secondary() const {
00934       for (int i=0; i<_num; i++)
00935          _array[i]->make_secondary();
00936    }
00937 
00938    //******** PRIMARY/SECONDARY FACES ********
00939    // Convenience: get the primary or secondary faces
00940    Bface_list secondary_faces() const{
00941       return filter(BitSetSimplexFilter(Bface::SECONDARY_BIT));
00942    }
00943    Bface_list primary_faces() const{
00944       return filter(BitClearSimplexFilter(Bface::SECONDARY_BIT));
00945    }
00946 
00947    bool is_all_primary() const {
00948       return all_satisfy(BitClearSimplexFilter(Bface::SECONDARY_BIT));
00949    }
00950    bool is_all_secondary() const {
00951       return all_satisfy(BitSetSimplexFilter(Bface::SECONDARY_BIT));
00952    }
00953    bool has_any_primary() const {
00954       return any_satisfy(BitClearSimplexFilter(Bface::SECONDARY_BIT));
00955    }
00956    bool has_any_secondary() const {
00957       return any_satisfy(BitSetSimplexFilter(Bface::SECONDARY_BIT));
00958    }
00959    bool num_primary() const {
00960       return num_satisfy(BitClearSimplexFilter(Bface::SECONDARY_BIT))!=0;
00961    }
00962    bool num_secondary() const {
00963       return num_satisfy(BitSetSimplexFilter(Bface::SECONDARY_BIT))!=0;
00964    }
00965    
00966  protected:
00967 
00968    //******** PROTECTED METHODS ********
00969    void clear_vert_flags() const;
00970    void clear_edge_flags() const;
00971 
00972    // Set the flag of each face to 1, and clear the flags of
00973    // each face around the boundary of this set of faces:
00974    void mark_faces() const;
00975 };
00976 
00977 /*****************************************************************
00978  * Inlined Bvert methods
00979  *****************************************************************/
00980 inline Bface_list 
00981 Bvert::get_all_faces() const
00982 {
00983    Bface_list ret;
00984    get_all_faces(ret);
00985    return ret;
00986 }
00987 
00988 inline Bface_list
00989 Bvert::get_faces() const
00990 {
00991    Bface_list ret;
00992    get_faces(ret);
00993    return ret;
00994 }
00995 
00996 /*****************************************************************
00997  * Inlined Bedge methods
00998  *****************************************************************/
00999 inline void
01000 Bedge::clear_flag02() 
01001 {
01002    // Clear flag of this edge and adjacent faces:
01003    // (clearing propagates from dim 0 to dim 2)
01004 
01005    clear_flag();
01006    if (_f1)  _f1->clear_flag();
01007    if (_f2)  _f2->clear_flag();
01008    if (_adj) _adj->clear_flags();
01009 }
01010 
01011 inline int
01012 Bedge::num_quads() const
01013 {
01014    return (
01015       (_f1 && _f1->is_quad() ? 1 : 0) +
01016       (_f2 && _f2->is_quad() ? 1 : 0)
01017       );
01018 }
01019 
01020 inline Bface* 
01021 Bedge::screen_face(CSimplexFilter& filter) const 
01022 {
01023    // Return the first face accepted by the filter:
01024 
01025    return (
01026       filter.accept(_f1) ? _f1 :
01027       filter.accept(_f2) ? _f2 :
01028       _adj ? _adj->first_satisfies(filter) : 0
01029       );
01030 }
01031 
01032 inline bool
01033 Bedge::is_primary() const
01034 {
01035    // Return true if one or more adjacent faces are primary
01036 
01037    return ((_f1 && _f1->is_primary()) || (_f2 && _f2->is_primary()));
01038 }
01039 
01040 inline Bvert* 
01041 Bedge::opposite_vert(CBface* f) const 
01042 {
01043    // Only meaningful for primary faces:
01044    // If f is _f1, return the other vertex of _f2;
01045    // and vice versa:
01046 
01047    Bface* g = other_face(f);
01048    return g ? g->other_vertex(_v1,_v2) : 0;
01049 }
01050 
01051 inline bool 
01052 Bedge::contains(CBface* f) const 
01053 {
01054    return (_f1 == f || _f2 == f || (_adj && _adj->contains((Bface*)f)));
01055 }
01056 
01057 /*****************************************************************
01058  * Inlined Bedge_list methods
01059  *****************************************************************/
01060 inline Bface_list 
01061 Bedge_list::get_primary_faces() const
01062 {
01063    return get_faces().primary_faces();
01064 }
01065 
01066 /**********************************************************************
01067  * PrimaryVertFilter:
01068  *
01069  *   Accept a Bvert if it is adjacent to at least 1 primary face
01070  *****************************************************************/
01071 class PrimaryVertFilter : public SimplexFilter {
01072  public:
01073    virtual bool accept(CBsimplex* s) const {
01074       return is_vert(s) &&
01075          !((Bvert*)s)->get_all_faces().primary_faces().empty();
01076    }
01077 };
01078 
01079 #endif  // BFACE_H_HAS_BEEN_INCLUDED
01080 
01081 /* end of file bface.H */

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