bool Skin::correct_face(Bface* f, bool& changed) { // // BBBBBBBBBBBBBBB // B /| // B / | // B f / | Change this, where quad face f // B / | is adjacent to 2 boundary edgees... // B / | // B / | // B/- - - - - - o // // BBBBBBBBBBBBBBB // B\ | // B \ | // B \ | ... to this, where neither face of // B \ | the quad is adjacent to more than 1 // B \ | boundary edge. // B \ | // B - - - - - - o // assert(f); // boundary edges have flag == 1, others have flag == 0 uint n = num_edge_flags_set(f); if (n < 2) return true; // not a problem if (n > 2) { // unfixable problem err_adv(debug, " can't fix face with %d boundary edges", n); return false; } // 2 boundary edges; get the non-boundary one: Bedge* e = boundary_connector(f); assert(e); // we want to swap it; only possible if it has 2 faces: if (e->nfaces() != 2) { err_adv(debug, " can't fix edge with %d faces", e->nfaces()); return false; } // swapping won't do any good if its other face has boundary edges too: if (!(num_edge_flags_set(e->f1()) == 0 || num_edge_flags_set(e->f2()) == 0)) { err_adv(debug, " unfixable edge found, giving up"); return false; } // try to swap it: if (e->do_swap()) { err_adv(debug, " swapped edge"); return changed = true; } err_adv(debug, " edge swap failed"); return false; }
UVpt LoopUV::centroid(CLvert* v) const { assert(v); switch (UVdata::discontinuity_degree(v)) { case 0: { // No discontinuity: UVpt ret; for (int i=0; i<v->degree(); i++) ret += UVdata::get_uv(v->nbr(i), v->e(i)->get_face()); return ret / v->degree(); } case 2: { // Find the 2 discontinuity edges and get the uv values of // their opposite vertices that agree with the current vertex. CUVpt& uv = UVdata::get_uv(v,_face); UVpt ret; for (int i=0; i<v->degree(); i++) { Bedge* e = v->e(i); if (!UVdata::is_continuous(e)) { if (UVdata::lookup(e->f1()) && UVdata::get_uv(v,e->f1()) == uv) ret += UVdata::get_uv(v->nbr(i), e->f1()); else if (UVdata::lookup(e->f2()) && UVdata::get_uv(v,e->f2()) == uv) ret += UVdata::get_uv(v->nbr(i), e->f2()); else assert(0); } } return ret/2; } default: // Treat as a corner vertex return UVdata::get_uv(v, _face); } }
int SELECT_WIDGET:: slash_cb(CGESTUREptr& gest, DrawState*& s) { if (_mode==SEL_FACE) //widget is in face selection mode { select_list.clear(); Bface* f = find_face(gest->start(),0.25,MIN_PIX_AREA); // f should be the currently selected face if (f && f->is_selected() && f->is_quad()) { f=f->quad_rep(); //line in screen space coresponding to the slash PIXELline slash(gest->start(),gest->end()); Bedge *e1,*e2,*e3,*e4; Bedge* edge = 0; //get and test the quad edges against the stroke line f->get_quad_edges(e1,e2,e3,e4); if( e1->pix_line().intersect_segs(slash) ) { edge=e1; } else if( e2->pix_line().intersect_segs(slash) ) { edge=e2; } else if( e3->pix_line().intersect_segs(slash) ) { edge=e3; } else if( e4->pix_line().intersect_segs(slash) ) { edge=e4; } else { //error cerr << "ERROR no intersection" << endl; return 1; } //walk the geometry and select faces Bface* fn = f; do { if (!fn->is_selected()) select_list +=fn; assert(edge); //I'm paranoid too assert(edge->f1()!=edge->f2()); //grabs the face on the other side of the edge //even if we are not directly adjacent to this edge fn=fn->other_quad_face(edge); if (fn) //if a valid face than advance the edge pointer { assert(edge!=fn->opposite_quad_edge(edge)); edge = fn->opposite_quad_edge(edge); fn = fn->quad_rep(); //all faces on the selection list are rep faces } else cerr << "No face on the other side of the edge" << endl; } //quit if not a valid face or not a quad while(fn&&(fn->is_quad())&&edge&&(fn!=f)); _mode=SLASH_SEL; //go into pattern editing mode end_face=0; //prepare the 2nd step data pattern=0; for (int i=0; i<MAX_PATTERN_SIZE; i++) pattern_array[i]=1; //fill the default pattern with ones } else cerr << "This is not a quad" << endl; } else if( _mode==SLASH_SEL)//pattern editing mode { //activates upon second slash motion //adds the entire list to the selected group //undo deselects the entire group Bface_list final_list; //copy the face pointers to the final list //using the pattern as a repeating template //and stop at the end face for (int i = 0; i<(end_face ? (end_face) : select_list.num()) ; i++) { if (pattern ? pattern_array[(i%pattern)+1] : 1) final_list+=select_list[i]; } WORLD::add_command(new MESH_SELECT_CMD(final_list)); return cancel_cb(gest,s); } else cerr << "wrong mode " << endl; return 1; }