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

bedge.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * bedge.C
00003  **********************************************************************/
00004 #include "disp/ray.H"
00005 #include "mesh/bmesh.H"
00006 #include "mesh/patch.H"
00007 #include "std/run_avg.H"
00008 #include "std/config.H"
00009 #include "bfilters.H"
00010 #include "uv_data.H"
00011 #include "tex_coord_gen.H"
00012 
00013 using namespace mlib;
00014 
00015 Bedge::Bedge(Bvert* u, Bvert* v) :
00016    _v1(u),
00017    _v2(v),
00018    _f1(0),
00019    _f2(0),
00020    _adj(0),
00021    _sil_stamp(0)
00022 {
00023    *_v1 += this;
00024    *_v2 += this;
00025 }
00026 
00027 Bedge::~Bedge()
00028 {
00029    // remove self from global selection list, if needed
00030    if (is_selected())
00031       MeshGlobal::deselect(this);
00032 
00033    // adjacent faces may not outlive this edge
00034    if (_mesh) {
00035       if (_f1) _mesh->remove_face(_f1);
00036       if (_f2) _mesh->remove_face(_f2);
00037       if (_adj) {
00038          for (int i=0; i<_adj->num(); i++)
00039             _mesh->remove_face((*_adj)[i]);
00040       }
00041    }   
00042 
00043    if (!detach()) 
00044       err_msg("Bedge::~Bedge: can't detach");
00045 }
00046 
00047 int
00048 Bedge::index() const
00049 {
00050    // index in BMESH Bedge array:
00051 
00052    if (!_mesh) return -1;
00053    return _mesh->edges().get_index((Bedge*)this);
00054 }
00055    
00056 int
00057 Bedge::num_all_faces() const
00058 {
00059    // Number of faces, including multi faces:
00060 
00061    int ret = nfaces();
00062    if (_adj)
00063       ret += _adj->num();
00064    return ret;
00065 }
00066 
00067 Bface_list 
00068 Bedge::get_all_faces() const
00069 {
00070    // return a list of all adjacent faces, including f1 and f2:
00071 
00072    Bface_list ret(num_all_faces());
00073    if (_adj) ret = *_adj;
00074    if (_f1) ret += _f1;
00075    if (_f2) ret += _f2;
00076    return ret;
00077 }
00078 
00079 Bface* 
00080 Bedge::f(int k) const
00081 {
00082    switch (k) {
00083     case 1: return _f1;
00084     case 2: return _f2;
00085    }
00086    k -= 3;
00087    return (_adj && _adj->valid_index(k)) ? (*_adj)[k] : 0;
00088 }
00089 
00090 int
00091 Bedge::nfaces() const
00092 {
00093    // XXX - not counting "multi" edges at this time
00094 
00095    return (_f1?1:0) + (_f2?1:0); // + (_adj?_adj->num():0);
00096 }
00097 
00098 Bface*
00099 Bedge::lookup_face(CBvert *v) const
00100 {
00101    // Reject null pointers.
00102    // Also, it's not helpful if the vertex belongs
00103    // to this edge.
00104    if (!v || this->contains(v))
00105       return 0;
00106    // Return an adjacent Bface containing the vertex
00107    
00108    if (_f1 && _f1->contains(v))
00109       return _f1;
00110    if (_f2 && _f2->contains(v))
00111       return _f2;
00112    if (_adj) {
00113       for (int i=0; i<_adj->num(); i++) {
00114          Bface* f = (*_adj)[i];
00115          if (f->contains(v))
00116             return f;
00117       }
00118    }
00119    return 0;
00120 }
00121 
00122 Bface* 
00123 Bedge::lookup_face(CBedge *e) const 
00124 {
00125    // Reject null pointers.
00126    // Also, it's not helpful if the edge is this one.
00127    if (!e || this == e)
00128       return 0;
00129 
00130    // Return an adjacent Bface containing the edge
00131    
00132    if (_f1 && _f1->contains(e))
00133       return _f1;
00134    if (_f2 && _f2->contains(e))
00135       return _f2;
00136    if (_adj) {
00137       for (int i=0; i<_adj->num(); i++) {
00138          Bface* f = (*_adj)[i];
00139          if (f->contains(e))
00140             return f;
00141       }
00142    }
00143    return 0;
00144 }
00145 
00146 int 
00147 Bedge::detach() 
00148 {
00149    if (nfaces() > 0 || is_multi()) {
00150       err_msg("Bedge::detach: error: faces present");
00151       return 0;
00152    }
00153    int ret = (*_v1 -= this);
00154    return (*_v2 -= this) && ret;
00155 }
00156 
00157 Wvec 
00158 Bedge::vec() const
00159 {
00160    // Vector from vertex 1 to vertex 2
00161    return (_v2->loc() - _v1->loc()); 
00162 }
00163 
00164 Wline
00165 Bedge::line() const
00166 {
00167    return Wline(_v1->loc(),_v2->loc()); 
00168 }
00169 
00170 PIXELline
00171 Bedge::pix_line() const
00172 {
00173    return PIXELline(_v1->pix(), _v2->pix());
00174 }
00175 
00176 bool
00177 Bedge::ndc_intersect(
00178    CNDCpt& p,
00179    CNDCpt& q,
00180    NDCpt&  ret) const
00181 {
00182    return NDCline(_v1->ndc(), _v2->ndc()).intersect_segs(NDCline(p, q), ret);
00183 }
00184 
00185 bool
00186 Bedge::view_intersect(
00187    CNDCpt& p,           // Screen point at which to do intersect
00188    Wpt&    nearpt,      // Point on edge visually nearest to p
00189    double& dist,        // Distance from nearpt to ray from camera
00190    double& d2d,         // Distance in pixels nearpt to p
00191    Wvec& n              // "normal" at nearpt in world space
00192    ) const
00193 {
00194    // (Bsimplex virtual method):
00195    // Intersection w/ ray from given screen point -- returns the point
00196    // on the Bedge that is nearest to the given screen space point.
00197    // Note: the returned "near point" and "normal" are both
00198    //       transformed to world space.
00199 
00200    // Find nearest point on the edge in screen-space, and make a 3D
00201    // ray out of it (world space, not object space):
00202    Wline ray(NDCline(_v1->ndc(), _v2->ndc()).project_to_seg(p));
00203 
00204    // Working in world space (applying mesh xf to verts), find
00205    // nearest point on the edge to the ray:
00206    nearpt = Wline(_v1->wloc(), _v2->wloc()).project_to_seg(ray);
00207 
00208    // Compute world and screen distances
00209    dist = nearpt.dist(ray.point());
00210    d2d  = PIXEL(nearpt).dist(PIXEL(ray.point()));
00211 
00212    // Return a "normal" vector:
00213    Wvec n1;
00214    if (nfaces() == 2)
00215       n1 = norm();
00216    else if (nfaces() == 1)
00217       n1 = get_face()->norm();
00218    else
00219       n1 = (ray.point() - nearpt).normalized();
00220 
00221    // Transform the normal properly:
00222    n = (_mesh->inv_xform().transpose()*n1).normalized();
00223 
00224    return 1;
00225 }
00226 
00227 bool
00228 Bedge::operator +=(Bface* f) 
00229 {
00230    if (!(f && f->contains(this))) {
00231       cerr << "Bedge::operator+=(Bface*): error: "
00232            << (f ? "face doesn't contain edge" : "null face")
00233            << endl;
00234       return 0;
00235    }
00236 
00237    // Is the face already recorded?
00238    // (Not supposed to happen):
00239    if (this->contains(f))
00240       return true;
00241 
00242    if (_f1 && _f2) {
00243       if (_f2->is_secondary())
00244          demote(_f2);
00245       else if (_f1->is_secondary())
00246          demote(_f1);
00247    }
00248    if (_f1 && _f2) {
00249       // Can't add as a primary face, so add as a "multi" face:
00250       bool ret = add_multi(f);
00251       assert(ret);      // the plan cannot fail
00252    } else if (_f1) {
00253       _f2 = f;
00254    } else {
00255       _f1 = f;
00256    }
00257 
00258    faces_changed();
00259    _v1->star_changed();
00260    _v2->star_changed();
00261 
00262    return true;
00263 }
00264 
00265 bool
00266 Bedge::operator -=(Bface* f) 
00267 {
00268    if (f == _f1)
00269       _f1 = 0;
00270    else if (f == _f2)
00271       _f2 = 0;
00272    else if (is_multi(f))
00273       _adj->rem(f);
00274    else {
00275       err_msg("Bedge::operator-=(Bface*): error: unknown face");
00276       return 0;
00277    }
00278 
00279    faces_changed();
00280    _v1->star_changed();
00281    _v2->star_changed();
00282 
00283    return 1;
00284 }
00285 
00286 bool
00287 Bedge::is_patch_boundary() const
00288 {
00289    // todo: should be able to rely correctly
00290    //       on PATCH_BOUNDARY_BIT
00291 
00292    // XXX - retessellation for skin is broken when patch
00293    // boundaries take into acount uv discontinuities.
00294    //
00295    // until it gets fixed, allow skin-users to suppress 
00296    // use of uv-coords to retessellation works.
00297    static bool USE_UV = !Config::get_var_bool("SKIN_INHIBIT_UV",false);
00298 
00299    return (
00300       (_f1 && _f2 && _f1->patch() != _f2->patch()) ||
00301       is_set(PATCH_BOUNDARY_BIT) ||
00302       (USE_UV && !UVdata::is_continuous(this))
00303       );
00304 }
00305 
00306 Wpt&
00307 Bedge::mid_pt(Wpt& v) const
00308 {
00309    v = (_v1->loc() + _v2->loc())/2;
00310  
00311    return v; 
00312 }
00313 
00314 double
00315 Bedge::avg_area() const
00316 {
00317    RunningAvg<double> avg(0);
00318    if (_f1) avg.add(_f1->area());
00319    if (_f2) avg.add(_f2->area());
00320    if (_adj) {
00321       for (int i=0; i<_adj->num(); i++)
00322          avg.add((*_adj)[i]->area());
00323    }
00324    return (avg.num() > 0) ? avg.val() : 0.0;
00325 }
00326 
00327 Patch*
00328 Bedge::patch() const 
00329 {
00330    Bface* f = frontfacing_face();
00331    f = f ? f : _f1 ? _f1 : _f2;
00332    return f ? f->patch() : 0;
00333 }
00334 
00335 Wvec 
00336 Bedge::norm() const 
00337 {
00338    // XXX - ignoring multi edges
00339 
00340    return ((_f1&&_f2) ? (_f1->qnorm()+_f2->qnorm()).normalized() :
00341            _f1 ? _f1->qnorm() :
00342            _f2 ? _f2->qnorm() :
00343            vec().perpend()
00344            );
00345 }
00346 
00347 // we return a 1 because that indicates that our faces are smooth.
00348 // since we don't have faces, we might as well think of them as smooth.
00349 double
00350 Bedge::dot() const
00351 {
00352    return (_f1 && _f2) ? (_f1->norm() * _f2->norm()) : 1.0;
00353 }
00354 
00355 void 
00356 Bedge::allocate_adj()
00357 {
00358    if (!_adj) _adj = new Bface_list(1);  assert(_adj);
00359 }
00360 
00361 bool 
00362 Bedge::is_multi() const 
00363 {
00364    // Is the edge a non-manifold ("multi") edge?
00365 
00366    return (_adj && !_adj->empty()); 
00367 }
00368 
00369 bool 
00370 Bedge::is_multi(CBface* f) const
00371 {
00372    // Is the face a secondary face of this edge?
00373 
00374    return (f && _adj && f->contains(this) && _adj->contains((Bface*)f));
00375 }
00376 
00377 bool
00378 Bedge::demote(Bface* f)
00379 {
00380    // Move f from _f1 or _f2 to the _adj list:
00381 
00382    static bool debug = Config::get_var_bool("DEBUG_NON_MANIFOLD",false);
00383    if (!(f && f->contains(this))) {
00384       if (debug)
00385          MeshGlobal::select(this);
00386       err_msg("Bedge::demote: error: %s face", f ? "unknown" : "null");
00387       return false;
00388    }
00389 
00390 //   UVdata::split(this);
00391 
00392    if (_f1 == f) {
00393       _f1 = 0;
00394    } else if (_f2 == f) {
00395       _f2 = 0;
00396    } else {
00397       assert(_adj && _adj->contains(f));
00398 
00399       // It's already demoted. Return true indicating "success".
00400       return true;
00401    }
00402    bool ret = add_multi(f);
00403    assert(ret);
00404    return true;
00405 }
00406 
00407 bool
00408 Bedge::add_multi(Bface* f)
00409 {
00410    // Protected virtual method used in Bedge::demote() and
00411    // Bedge::operator+=(Bface*).  Put the face into the _adj
00412    // list of non-primary faces.  In Ledge, do the same for
00413    // the appropriate child faces.
00414 
00415    if (!(f && f->contains(this)))
00416       return false;
00417    if (f == _f1 || f == _f2) {
00418       // (Should this be an error?)
00419       // It's currently a primary face. Demote it.
00420       return demote(f);
00421    } else {
00422       allocate_adj();
00423       _adj->add_uniquely(f);
00424       faces_changed();
00425       return true;
00426    }
00427 }
00428 
00429 bool
00430 Bedge::can_promote() const
00431 {
00432    // Returns true if there is at least one available primary slot (_f1 or _f2).
00433    // In Ledge, all child edges must also have available slots.
00434 
00435    return (!_f1 || _f1->is_secondary()) || (!_f2 || _f2->is_secondary());
00436 }
00437 
00438 bool
00439 Bedge::promote(Bface* f)
00440 {
00441    // Move f from the _adj list to _f1 or _f2:
00442    // It's up to the caller to check Bedge::can_promote().
00443 
00444    if (!(f && f->contains(this))) {
00445       if (Config::get_var_bool("DEBUG_NON_MANIFOLD",false))
00446          MeshGlobal::select(this);
00447       err_msg("Bedge::promote: error: %s face", f ? "unknown" : "null");
00448       return false;
00449    }
00450 
00451    if (!(_adj && _adj->contains(f))) {
00452       // Allow this case only if f is already _f1 or _f2.
00453       // Then return true, indicating "success".
00454       assert(f == _f1 || f == _f2);
00455       return true;
00456    }
00457    _adj->rem(f);
00458    bool ret = add_primary(f);
00459    assert(ret);
00460    return ret;
00461 }
00462 
00463 bool
00464 Bedge::add_primary(Bface* f)
00465 {
00466    // Add the face as a primary face (in slot _f1 or _f2).
00467    // In Ledge, do the same for the appropriate child faces.
00468 
00469    if (!(f && f->contains(this)))
00470       return false;
00471 
00472    // Could relax this...
00473    assert(!this->contains(f));
00474 
00475    // Find an available slot for f (or make one if possible):
00476    if (!_f1) {
00477       _f1 = f;
00478    } else if (!_f2) {
00479       _f2 = f;
00480    } else if (_f1->is_secondary()) {
00481       demote(_f1);
00482       _f1 = f;
00483    } else if (_f2->is_secondary()) {
00484       demote(_f2);
00485       _f2 = f;
00486    } else {
00487       return false;     // no available slot
00488    }
00489    return true;
00490 }
00491 
00492 void 
00493 Bedge::fix_multi()
00494 {
00495    // If any faces in the _adj listed are labelled "primary",
00496    // then move them to a primary slot (_f1 or _f2). Used when
00497    // reading a mesh from file, when primary/secondary face
00498    // labels are specified only after all faces are created.
00499 
00500    if (!_adj)   // no _adj, so no fixing required
00501       return;
00502 
00503    // It's not possible if the total number of "primary" faces
00504    // exceeds 2.
00505    if (nfaces_satisfy(PrimaryFaceFilter()) > 2) {
00506       cerr << "Bedge::fix_multi: error: more than 2 primary faces" << endl;
00507       return;
00508    }
00509 
00510    // Work backwards to remove items from the list:
00511    for (int i=_adj->num()-1; i>=0; i--) {
00512       Bface *face = (*_adj)[i];
00513       if (face->is_primary()) {
00514          promote(face);
00515       }
00516    }
00517 }
00518 
00519 Bface*
00520 Bedge::ccw_face(CBvert* v) const
00521 {
00522    // Given vertex v belonging to this edge, return the adjacent
00523    // face (_f1 or _f2) for which this edge follows v in CCW
00524    // order within the face.
00525 
00526    return (!contains(v) ? 0 :
00527            (_f1 && _f1->edge_from_vert(v) == this) ? _f1 :
00528            (_f2 && _f2->edge_from_vert(v) == this) ? _f2 : 0
00529       );
00530 }
00531 
00532 bool
00533 Bedge::consistent_orientation() const
00534 {
00535    return ((nfaces()<2) ? 1 :
00536            ((_f1->orientation(this) * _f2->orientation(this)) == -1) ? 1 : 0
00537            );
00538 }
00539 
00540 bool 
00541 Bedge::oriented_ccw(Bface* f) const
00542 {
00543    // if _v1 and _v2 in this edge are ordered CCW in the given face,
00544    // return true.
00545 
00546    if (!f && !(f = get_face()))
00547       return 0;
00548 
00549    return f->orientation(this) == 1;
00550 }
00551 
00552 void
00553 Bedge::bc2pos(CWvec& bc, Wpt& pos) const
00554 {
00555    pos = (bc[0]*_v1->loc()) + (bc[1]*_v2->loc());
00556 }
00557 
00558 void 
00559 Bedge::project_barycentric(CWpt &p, Wvec &bc) const 
00560 {
00561    double t = ((p - _v1->loc()) * vec()) / sqr(length());
00562    bc.set(1.0 - t, t, 0);
00563 }
00564 
00565 int
00566 Bedge::redefine(Bvert *v, Bvert *u)
00567 {
00568    // redefine this edge, replacing v with u
00569 
00570    // precondition:
00571    //   edge does not already contain u.
00572    //   v is a vertex of this edge.
00573    //   faces have already been detached.
00574    //   can't duplicate an existing edge.
00575 
00576    assert(contains(v) && nfaces() == 0);
00577 
00578    if (contains(u))
00579       return 0;
00580 
00581    Bedge* dup = 0;
00582    if (v == _v1) {
00583       if ((dup = u->lookup_edge(_v2))) {
00584          // can't redefine, but if this is a crease edge
00585          // should ensure the duplicated edge is also
00586          if (is_crease())
00587             dup->set_crease(crease_val());
00588          return 0;
00589       }
00590       // can redefine:
00591       *_v1 -= this;     // say bye to old _v1
00592       _v1 = u;          // record new _v1
00593       *_v1 += this;     // say hi to new _v1
00594    } else if (v == _v2) {
00595       // see comments above
00596       if ((dup = u->lookup_edge(_v1))) {
00597          if (is_crease())
00598             dup->set_crease(crease_val());
00599           return 0;
00600       }
00601       *_v2 -= this;
00602       _v2 = u;
00603       *_v2 += this;
00604    } else assert(0);
00605 
00606    geometry_changed();
00607 
00608    return 1;
00609 }
00610 
00611 bool
00612 Bedge::redef2(Bvert *v, Bvert *u)
00613 {
00614    static bool debug = Config::get_var_bool("DEBUG_MESH_OPS",false);
00615 
00616    // redefine this edge, replacing v with u
00617 
00618    // preconditions:
00619    //   v is a vertex of this edge.
00620    //   edge does not already contain u.
00621    //   can't duplicate an existing edge.
00622 
00623    if (!contains(v)) {
00624       err_adv(debug, "Bedge::redef2: error: edge doesn't contain v");
00625       return false;
00626    }
00627    if (contains(u)) {
00628       err_adv(debug, "Bedge::redef2: error: edge already contains u");
00629       return false;
00630    }
00631    Bvert* keeper = other_vertex(v);
00632    if (keeper->lookup_edge(u)) {
00633       err_adv(debug, "Bedge::redef2: error: would duplicate existing edge");
00634       return false;
00635    }
00636 
00637    if (v == _v1) {
00638       *_v1 -= this;     // say bye to old _v1
00639       _v1 = u;          // record new _v1
00640       *_v1 += this;     // say hi to new _v1
00641    } else if (v == _v2) {
00642       *_v2 -= this;
00643       _v2 = u;
00644       *_v2 += this;
00645    } else assert(0);
00646 
00647    geometry_changed();
00648 
00649    return true;
00650 }
00651 
00652 void
00653 Bedge::set_new_vertices(
00654    Bvert *v1, 
00655    Bvert *v2)
00656 {
00657    // used in edge swap
00658 
00659    assert(nfaces() == 0 && !v1->lookup_edge(v2));
00660 
00661    *_v1 -= this;
00662    *_v2 -= this;
00663    _v1 = v1;
00664    _v2 = v2;
00665 
00666    *_v1 += this;
00667    *_v2 += this;
00668    
00669    geometry_changed();
00670 }
00671 
00672 void 
00673 Bedge::notify_split(
00674    Bsimplex *new_simp)
00675 {
00676    Bsimplex::notify_split(new_simp);
00677    if (is_crease() && new_simp->dim() == 1)
00678       ((Bedge*)new_simp)->set_crease(crease_val());
00679 }
00680 
00681 bool
00682 Bedge::is_polyline_end() const
00683 {
00684    return (is_polyline() && (_v1->is_polyline_end() || _v2->is_polyline_end()));
00685 }
00686 
00687 bool
00688 Bedge::is_crease_end() const
00689 {
00690    return (is_crease() && (_v1->is_crease_end() || _v2->is_crease_end()));
00691 }
00692 
00693 bool
00694 Bedge::is_chain_tip(CSimplexFilter& filter) const
00695 {
00696    return (filter.accept((Bedge*)this) &&
00697            (_v1->degree(filter) != 2 || _v2->degree(filter) != 2));
00698 }
00699 
00700 // -----------
00701 
00702 bool 
00703 Bedge::is_sil() const
00704 {
00705    // Border edge: yes
00706    if (is_border())
00707       return true;
00708 
00709    // Polyline edge: no
00710    if (!(_f1 || _f2))
00711       return false;
00712 
00713    // 2 faces, both valid normals: regular case
00714    if (!(_f1->norm().is_null() || _f2->norm().is_null()))
00715       return (_f1->front_facing() != _f2->front_facing());
00716 
00717    // Fuked-up case
00718    if (_f1->norm().is_null() && _f2->norm().is_null())
00719       return false;
00720 
00721    // There's exactly one adjacent face with zero area.  This
00722    // happens sometimes with quads that are trying to look like
00723    // triangles, so we're gonna check for that common case. If
00724    // it's not the common case we just give up below, at this
00725    // time.
00726 
00727    // Quad diagonal? Then say no:
00728    if (is_weak())
00729       return false;
00730 
00731    // Identify the zero-area triangle
00732    Bface* good_face = _f1;
00733    Bface* null_face = _f2;
00734    if (good_face->norm().is_null())
00735       swap(good_face, null_face);
00736    assert(null_face->norm().is_null());
00737 
00738    if (null_face->is_quad() && !null_face->quad_partner()->norm().is_null())
00739       return (good_face->front_facing() !=
00740               null_face->quad_partner()->front_facing());
00741 
00742    // We could keep trying but it's easier to give up:
00743    return false;
00744 }
00745 
00746 Bsimplex_list
00747 Bedge::neighbors() const
00748 {
00749    Bsimplex_list ret(4);
00750    ret += _v1;
00751    ret += _v2;
00752    if (_f1) ret += _f1;
00753    if (_f2) ret += _f2;
00754    if (_adj) {
00755       for (int j=0; j<_adj->num(); j++)
00756          ret += (*_adj)[j];
00757    }
00758    return ret;
00759 }
00760 
00761 bool 
00762 Bedge :: is_texture_seam()const
00763 {
00764    //this function is under construction
00765    //do not use yet
00766    
00767    //fix for skin users
00768    static bool USE_UV = !Config::get_var_bool("SKIN_INHIBIT_UV",false);
00769    if(  USE_UV && !UVdata::is_continuous(this)) return true;
00770    
00771    
00772    if (_f1 && _f2 && !is_patch_boundary())//patches on both sides are the same
00773    {
00774     
00775       TexCoordGen* tg = patch()->tex_coord_gen();
00776       if (tg)
00777       {
00778          UVpt tx1A = tg->uv_from_vert(_v1,_f1);
00779          UVpt tx1B = tg->uv_from_vert(_v1,_f2);
00780          UVpt tx2A = tg->uv_from_vert(_v2,_f1);
00781          UVpt tx2B = tg->uv_from_vert(_v2,_f2);
00782 
00783          if ((tx1A!=tx1B) || (tx2A!=tx2B)) return true;
00784 
00785       }
00786    }
00787 
00788    return false;
00789 }
00790 
00791 bool
00792 Bedge::is_crossable() const
00793 {
00794 
00795    return (consistent_orientation() &&
00796            !(is_crease() || is_patch_boundary() || is_texture_seam()) );
00797 }
00798 
00799 bool
00800 Bedge::is_stressed() const
00801 {
00802    return !is_crease() && _f1 && _f2 && (_f1->norm() * _f2->norm() < -.5);
00803 }
00804 
00805 void  
00806 Bedge::set_crease(ushort c) 
00807 {
00808    set_bit(CREASE_BIT,c);
00809    crease_changed();
00810 }
00811 
00812 void 
00813 Bedge::inc_crease(ushort max_val)
00814 {
00815 //    cerr << "inc_crease: from " << crease_val() << endl;
00816 
00817    ushort c = crease_val();
00818    if (c == USHRT_MAX)
00819       return;
00820    else if (c >= max_val)
00821       c = USHRT_MAX;
00822    else
00823       c++;
00824    set_crease(c);
00825 }
00826 
00827 void 
00828 Bedge::dec_crease(ushort max_val)
00829 {
00830 //    cerr << "dec_crease: from " << crease_val() << endl;
00831 
00832    ushort c = crease_val();
00833    if (c == 0)
00834       return;
00835    else if (c <= max_val)
00836       c--;
00837    else
00838       c = max_val;
00839    set_crease(c);
00840 }
00841 
00842 void
00843 Bedge::compute_crease(double d)
00844 {
00845    // in case this is an Ledge, specify "infinitely sharp" crease.
00846 
00847    set_crease((dot() < d) ? USHRT_MAX : 0);
00848 }
00849 
00850 void
00851 Bedge::set_convex()
00852 {
00853    set_bit(CONVEX_VALID_BIT);
00854    int b = (!_f1 || !_f2 ||
00855             ((_f1->norm() + _f2->norm()) *
00856              (_f1->other_vertex(_v1,_v2)->loc()-_v1->loc()) < 0));
00857    set_bit(CONVEX_BIT,b);
00858 }
00859 
00860 Bface*
00861 Bedge::frontfacing_face() const
00862 {
00863    // Only check primary edges
00864 
00865    return ((_f1 && _f1->front_facing()) ? _f1 :
00866            (_f2 && _f2->front_facing()) ? _f2 :
00867            0);
00868 }
00869 
00870 ostream& operator <<(ostream &os, CBedge &e) 
00871 {
00872    return os << e.v(1)->index() << " " << e.v(2)->index() << " " ;
00873 }
00874 
00875 bool
00876 Bedge::swapable(Bface*& face1,
00877                 Bface*& face2,
00878                 Bvert*& verta,
00879                 Bvert*& vertb,
00880                 Bvert*& vertc,
00881                 Bvert*& vertd,
00882                 bool    favor_degree_six)
00883 {
00884    /*
00885    //                  c
00886    //                / | \
00887    //              /   |   \
00888    //            /     |     \
00889    //          /       |       \
00890    //        d    f1  /|\   f2   b
00891    //          \       |       /
00892    //            \     |     /
00893    //              \   |   /
00894    //                \ | /
00895    //                  a
00896    //
00897    //      this edge goes from a to c.
00898    //  "swapping" the edge means deleting it
00899    //   and putting in an edge from d to b.
00900    //  an edge is "swapable" if the operation
00901    //  is both legal (no change to topology)
00902    //   and preferable (e.g. it leads to a 
00903    //           bigger minimum angle).
00904    */
00905 
00906    static bool debug = Config::get_var_bool("DEBUG_EDGE_SWAP",false);
00907    if (is_patch_boundary() || is_crease() || is_multi()) {
00908       err_adv(debug, "Bedge::swapable: bad edge type");
00909       return 0;
00910    }
00911 
00912    // get faces as above
00913    face1 = ccw_face();
00914    face2 = other_face(face1);
00915 
00916    // gotta have two faces
00917    if (!(face1 && face2)) {
00918       err_adv(debug, "Bedge::swapable: need 2 faces");
00919       return 0;
00920    }
00921 
00922    // if dihedral angle is sharp, refuse
00923    static const double DOT_THRESH = cos(60.0 * M_PI / 180.0);
00924    if ((face1->norm() * face2->norm()) < DOT_THRESH) {
00925       err_adv(debug, "Bedge::swapable: too sharp");
00926       return 0;
00927    }
00928 
00929    // get vertices as above
00930    verta = _v1;
00931    vertc = _v2;
00932    vertb = face2->other_vertex(verta, vertc);
00933    vertd = face1->other_vertex(verta, vertc);
00934 
00935    // hoppe et. al. (siggraph 93) say:
00936    // edge swap is valid iff edge db is not already defined.
00937    if (!vertb || !vertd || vertb->lookup_edge(vertd)) {
00938       err_adv(debug, "Bedge::swapable: topology violation");
00939       return 0;
00940    }
00941 
00942    CWpt& a=verta->loc();
00943    CWpt& b=vertb->loc();
00944    CWpt& c=vertc->loc();
00945    CWpt& d=vertd->loc();
00946 
00947    // don't proceed if new edge is sharp
00948    if ((cross(a-d,b-d).normalized() * cross(b-d,c-d).normalized()) <= DOT_THRESH) {
00949       err_adv(debug, "Bedge::swapable: new edge too sharp");
00950       return 0;
00951    }
00952 
00953    Wvec  ca = vec().normalized();
00954    Wvec  ba = (b-a).normalized();
00955    Wvec  da = (d-a).normalized();
00956    Wvec  bc = (b-c).normalized();
00957    Wvec  dc = (d-c).normalized();
00958 
00959    // find smallest angle in current arrangement
00960    // (bigger dot means teenier angle):
00961    double cur_max_dot = ca * ba;
00962    cur_max_dot = max(cur_max_dot, (ca * da));
00963    cur_max_dot = max(cur_max_dot,-(ca * bc));
00964    cur_max_dot = max(cur_max_dot,-(ca * dc));
00965 
00966    Wvec  bd = (b-d).normalized();
00967    double swap_max_dot = -(bd * da);
00968    swap_max_dot = max(swap_max_dot, -(bd * dc));
00969    swap_max_dot = max(swap_max_dot,  (bd * ba));
00970    swap_max_dot = max(swap_max_dot,  (bd * bc));
00971 
00972    // if we keep these lines, probably want to
00973    // use a tabulated function for acos:
00974    double cur_min_angle  = Acos(cur_max_dot);
00975    double swap_min_angle = Acos(swap_max_dot);
00976 
00977    // do handicapping to promote degree-6 verts:
00978    int k = 0;
00979    if (favor_degree_six) {
00980       k += ((verta->degree() <= 6) ? 1 : -1);      // k measures how bad
00981       k += ((vertc->degree() <= 6) ? 1 : -1);      //   is the swap.
00982       k += ((vertd->degree() >= 6) ? 1 : -1);      // higher (positive) numbers
00983       k += ((vertb->degree() >= 6) ? 1 : -1);      //   are worse.
00984    }
00985 
00986    // for each unit of k, penalize the
00987    // swapped min angle by 8 degrees:
00988    static const double handicap_unit = 8.0 / 180.0 * M_PI;
00989    return (swap_min_angle > (cur_min_angle + k*(handicap_unit)));
00990 }
00991 
00992 bool
00993 Bedge::swap_is_legal() const
00994 {
00995    static bool debug = Config::get_var_bool("DEBUG_EDGE_SWAP",false);
00996 
00997    if (!is_interior() || is_patch_boundary() || is_crease() || is_multi()) {
00998       err_adv(debug, "Bedge::swap_is_legal: bad edge type");
00999       return false;
01000    }
01001    if (!is_weak() && (_f1->is_quad() || _f2->is_quad())) {
01002       err_adv(debug, "Bedge::swap_is_legal: swap would wreck quad-ness");
01003       return false;
01004    }
01005    if ((UVdata::has_uv(_f1) || UVdata::has_uv(_f2)) &&
01006        !UVdata::is_continuous(this)) {
01007       err_adv(debug, "Bedge::swap_is_legal: can't swap uv-discontinuous edge");
01008       return false;
01009    }
01010    Bvert* o1 = opposite_vert1();
01011    Bvert* o2 = opposite_vert2();
01012    assert(o1 && o2); // must be: we checked for 2 faces
01013 
01014    return !lookup_edge(o1,o2);
01015 }
01016 
01017 bool
01018 Bedge::do_swap()
01019 {
01020    /*
01021    //                  v2                           v2                          
01022    //                / | \                        /   \                        
01023    //              /   |   \                    /       \                       
01024    //            /     |     \                /     g2    \                      
01025    //          /       |       \            /               \                    
01026    //       o1    g1  /|\  g2    o2      o1 - - - - - - - - - o2                 
01027    //          \       |       /            \               /                    
01028    //            \     |     /                \     g1    /                    
01029    //              \   |   /                    \       /                      
01030    //                \ | /                        \   /                       
01031    //                  v1                           v1                          
01032    //
01033    //                 old                          new
01034    //
01035    //  This edge goes from v1 to v2, and we will "swap" it to go
01036    //  from o2 to o1. We also redefine adjacent faces g1 and g2.
01037    //  Requires that the operation is topologically legal.
01038    //
01039    */
01040 
01041    static bool debug = Config::get_var_bool("DEBUG_MESH_OPS",false);
01042 
01043    if (!swap_is_legal()) {
01044       err_adv(debug, "Bedge::do_swap: illegal");
01045       return false;
01046    }
01047 
01048    // get faces as above
01049    Bface* g1 = ccw_face();
01050    Bface* g2 =  cw_face();
01051    assert(g1 && g2); // check for 2 faces is in swap_is_legal()
01052 
01053    // get vertices as above
01054    Bvert* o1 = g1->other_vertex(this);
01055    Bvert* o2 = g2->other_vertex(this);
01056    Bvert* v1 = _v1;     // save these now
01057    Bvert* v2 = _v2;     // before we forget
01058 
01059    // deal w/ uv if needed
01060    UVpt uvo1, uvo2, uvv1, uvv2;
01061    bool do_uv = false;
01062    if ((UVdata::has_uv(_f1) || UVdata::has_uv(_f2))) {
01063       assert(UVdata::has_uv(_f1) && UVdata::has_uv(_f2));
01064       assert(UVdata::is_continuous(this));
01065       do_uv = true;
01066       uvo1 = UVdata::get_uv(o1,g1);
01067       uvo2 = UVdata::get_uv(o2,g2);
01068       uvv1 = UVdata::get_uv(v1,g1);
01069       uvv2 = UVdata::get_uv(v2,g1);
01070    }
01071    
01072    // detach faces
01073    g1->Bface::detach(); // XXX - hack to prevent subdiv elements from
01074    g2->Bface::detach(); //       being deleted; swap will be propagated down
01075 
01076    // redefine edge
01077    Bedge::set_new_vertices(o2,o1);
01078 
01079    // redefine faces
01080    g1->Bface::redefine(v2,o2);
01081    g2->Bface::redefine(v1,o1);
01082 
01083    if (do_uv) {
01084       UVdata::set(o1,g1,uvo1);
01085       UVdata::set(v1,g1,uvv1);
01086       UVdata::set(o2,g1,uvo2);
01087       UVdata::set(o2,g2,uvo2);
01088       UVdata::set(v2,g2,uvv2);
01089       UVdata::set(o1,g2,uvo1);
01090    }
01091 
01092    if (!(g1->check() && g2->check())) {
01093       err_adv(debug, "Bedge::do_swap: check failed");
01094    }
01095 
01096    return true;
01097 }
01098 
01099 void
01100 Bedge::geometry_changed()
01101 {
01102    // an adjacent vertex changed location
01103 
01104    Bsimplex::geometry_changed();
01105 }
01106 
01107 void 
01108 Bedge::crease_changed()
01109 {
01110    _v1->crease_changed();
01111    _v2->crease_changed();
01112 }
01113 
01114 void 
01115 Bedge::normal_changed()
01116 {
01117    clear_bit(CONVEX_VALID_BIT);
01118    _sil_stamp = 0;
01119 
01120    Bsimplex::normal_changed();
01121 }
01122 
01123 void 
01124 Bedge::faces_changed()
01125 {
01126    // called when faces are added or deleted
01127    normal_changed();
01128 
01129    // This could be finer grained, and just call
01130    // the following when the non-manifold status
01131    // of the edge changes:
01132    _v1->clear_bit(Bvert::VALID_NON_MANIFOLD_BIT);
01133    _v2->clear_bit(Bvert::VALID_NON_MANIFOLD_BIT);
01134 }
01135 
01136 // returns 0 if plane intersects edge, 
01137 //        -1 if edge is on negative side of plane normal,
01138 //         1 if edge is on positive side of plane normal
01139 int
01140 Bedge::which_side(CWplane& plane) const
01141 {
01142    Wpt  p = plane.origin();
01143    Wvec n = plane.normal();
01144    double dot1 = (p - _v1->loc()) * n;
01145    double dot2 = (p - _v2->loc()) * n;
01146    return dot1*dot2 < 1e-20 ? 0 : Sign(dot1);
01147 }
01148 
01149 
01150 // TODO: unreadable arguments!
01151 // what's input? what's output?
01152 //              -tc
01153 bool 
01154 Bedge::local_search(Bsimplex *&end, Wvec &final_bc,
01155                     CWpt &target, Wpt &reached, 
01156                     Bsimplex *repeater, int iters) 
01157 { 
01158    if (iters <= 0)
01159       return 0;
01160 
01161    Wvec      bc;
01162    bool      is_on_sim = 0;
01163    Wpt       nearpt    = nearest_pt(target, bc, is_on_sim);
01164    Bsimplex* sim       = bc2sim(bc);
01165 
01166    if (!is_on_sim) {
01167       
01168       if (sim == repeater) // We hit a loop in the recursion, so stop
01169          return 0;
01170 
01171       if (sim != this) { // We're on the boundary of the edge
01172          assert(is_vert(sim));
01173          Bvert* v = (Bvert*)sim;
01174 
01175          for (int i=0; i<v->degree(); i++) {
01176             int good_path = v->e(i)->local_search(end, final_bc, target,
01177                                                   reached, sim, iters-1);
01178             if (good_path == 1)
01179                return 1;
01180             else if (good_path==-1)
01181                return repeater ? true : false; // XXX - changed from -1 : 0 -- should check
01182 
01183          }
01184       }
01185    }
01186 
01187    reached = nearpt;
01188    end = this;
01189    final_bc = bc;
01190 
01191    return 1;
01192 }
01193 
01194 NDCpt 
01195 Bedge::nearest_pt_ndc(CNDCpt& p, Wvec &bc, int &is_on_simplex) const
01196 { 
01197    NDCpt a = _v1->ndc();
01198    NDCpt b = _v2->ndc();
01199 
01200    NDCvec ab = b - a;
01201    NDCvec ac = p - a;
01202 
01203    double dot = (ab * ac) / ab.length_sqrd();
01204    bc.set(1-dot, dot, 0);
01205 
01206    if (dot < gEpsZeroMath) {
01207       bc.set(1, 0, 0);
01208       is_on_simplex = 0;
01209    } else if (1-dot < gEpsZeroMath) {
01210       bc.set(0, 1, 0);
01211       is_on_simplex = 0;
01212    }
01213 
01214    return (bc[0] * a) + (bc[1] * b); 
01215 }
01216 
01217 Wpt   
01218 Bedge::nearest_pt(CWpt& p, Wvec &bc, bool &is_on_simplex) const
01219 { 
01220    Wvec ab = _v2->loc() - _v1->loc();
01221    Wvec ac = p - _v1->loc();
01222 
01223    double dot = (ab * ac) / ab.length_sqrd();
01224    bc.set(1-dot, dot, 0);
01225 
01226    if (dot < gEpsZeroMath) {
01227       bc.set(1, 0, 0);
01228       is_on_simplex = (dot >= 0);
01229    } else if (1-dot < gEpsZeroMath) {
01230       bc.set(0, 1, 0);
01231       is_on_simplex = (dot <= 1);
01232    }
01233 
01234    return (bc[0] * _v1->loc()) + (bc[1] * _v2->loc());
01235 }
01236 
01237 Wpt  
01238 Bedge::mid_pt() const 
01239 { 
01240    return (_v1->loc() + _v2->loc())/2; 
01241 }
01242 
01243 int 
01244 Bedge::nfaces_satisfy(CSimplexFilter& f) const
01245 {
01246    return ((f.accept(_f1) ? 1 : 0) +
01247            (f.accept(_f2) ? 1 : 0) +
01248            (_adj ? _adj->num_satisfy(f) : 0));
01249 }
01250 
01251 /*****************************************************************
01252  * BoundaryEdgeFilter:
01253  *
01254  *   Accepts edges along the boundary between faces of a
01255  *   given type and faces not of that type.
01256  *****************************************************************/
01257 bool 
01258 BoundaryEdgeFilter::accept(CBsimplex* s) const 
01259 {
01260    // What makes an edge a "boundary" WRT faces of a given type?
01261    // We'll say the number of adjacent faces of the given type
01262    // is > 0 but not == 2. I.e., faces of the given type do not
01263    // locally form a 2-manifold along the edge.
01264 
01265    if (!is_edge(s))
01266       return false;
01267    int n = ((Bedge*)s)->nfaces_satisfy(_filter);
01268    return (n > 0 && n != 2);
01269 }
01270 
01271 /************************************************************
01272  * Bedge_list
01273  ************************************************************/
01274 
01275 void
01276 Bedge_list::clear_vert_flags() const
01277 {   
01278    // Clear the flag of each vertex of each edge
01279 
01280    for (int i=0; i<_num; i++) {
01281       _array[i]->v1()->clear_flag();
01282       _array[i]->v2()->clear_flag();
01283    }
01284 }
01285 
01286 // l'il helper used in Bedge_list::get_verts():
01287 inline void
01288 screen(Bvert_list& list, Bvert* v)
01289 {
01290    if (v && !v->flag()) {
01291       v->set_flag();
01292       list += v;
01293    }
01294 }
01295 
01296 Bvert_list 
01297 Bedge_list::get_verts() const
01298 {
01299    // Extract a list of the verts found in the given edges.
01300 
01301    // Get clean slate
01302    clear_vert_flags();
01303 
01304    // Put verts into output array uniquely:
01305    Bvert_list ret;
01306    for (int i=0; i<_num; i++) {
01307       screen(ret, _array[i]->v1());
01308       screen(ret, _array[i]->v2());
01309    }
01310    return ret;
01311 }
01312 
01313 inline void
01314 add_face(Bface* f, Bface_list& ret)
01315 {
01316    // Helper used in both add_faces(), below.
01317    //
01318    // Add the face to the list if it is non-null and
01319    // its flag is not set. Set the flag to prevent it
01320    // from being added again subsequently.
01321 
01322    if (f && !f->flag()) {
01323       f->set_flag();
01324       ret += f;
01325    }
01326 }
01327 
01328 inline void
01329 add_faces(Bface_list* faces, Bface_list& ret)
01330 {
01331    // Helper used in add_faces(), below.
01332 
01333    if (!faces)
01334       return;
01335    for (int i=0; i<faces->num(); i++)
01336       add_face((*faces)[i], ret);
01337 }
01338 
01339 inline void
01340 add_faces(Bedge* e, Bface_list& ret)
01341 {
01342    // Helper used in Bedge_list::get_faces(), below.
01343    // Get faces adjacent to e and add them to the return list
01344    // avoiding duplicates by testing and setting flags.
01345 
01346    if (e) {
01347       add_face(e->f1(), ret);
01348       add_face(e->f2(), ret);
01349       add_faces(e->adj(), ret);
01350    }
01351 }
01352 
01353 Bface_list 
01354 Bedge_list::get_faces() const
01355 {
01356    // Returns list of faces adjacent to these edges:
01357 
01358    // Clear flags of adjacent faces
01359    clear_flag02();
01360 
01361    // Put faces into output array uniquely:
01362    Bface_list ret;
01363    for (int i=0; i<_num; i++)
01364       add_faces(_array[i], ret);
01365    return ret;
01366 }
01367 
01368 void
01369 Bedge_list::mark_edges() const
01370 {
01371    // Set the flag of each edge to 1, and clear the flag of
01372    // any other edge connected to one of these.
01373 
01374    // Clear vertex, edge, and face flags within a 1-neighborhood
01375    // of any vertex of this set of edges:
01376    get_verts().clear_flag02();
01377 
01378    // Set edge flags to 1:
01379    set_flags(1);
01380 }
01381 
01382 Bvert_list
01383 Bedge_list::fold_verts() const
01384 {
01385    // set internal edge flags to 1, neighboring edge flags to 0:
01386    mark_edges();
01387 
01388    // Using an edge filter that screens for edges with flag = 1,
01389    // construct a "fold vertex" filter that checks for vertics
01390    // with 2 of the acceptable edges arranged view-dependently
01391    // in a "fold" configuration:
01392 
01393    return get_verts().filter(FoldVertFilter(SimplexFlagFilter(1)));
01394 }
01395 
01396 bool
01397 Bedge_list::is_simple() const
01398 {
01399    mark_edges();
01400    return
01401       get_verts().filter(
01402          !(VertDegreeFilter(2, SimplexFlagFilter(1)) ||
01403            VertDegreeFilter(1, SimplexFlagFilter(1)))).empty();
01404 }
01405 
01406 /* end of file bedge.C */

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