bool PAPER_DOLL::init(CGESTUREptr& g) { if (!(g && g->is_stroke())) return false; if (g->below_min_length() || g->below_min_spread()) return false; if (!g->is_ellipse()) { err_adv(debug, "PAPER_DOLL::init: non-ellipse"); return false; } Panel* p = dynamic_cast<Panel*>( Bsurface::get_surface(get_top_level(VisRefImage::get_faces(g->pts()))) ); err_adv(debug, "PAPER_DOLL::init: %s panel", p?"found":"could not find"); if (!(p && p->is_selected())) { err_adv(debug, "PAPER_DOLL::init: ellipse not over selected panel"); return false; } assert(p && p->bfaces().size() > 0); Bface_list faces = Bface_list::reachable_faces(p->bfaces().front()); assert(!faces.empty()); if (!faces.is_planar(deg2rad(1.0))) { err_adv(debug, "PAPER_DOLL::init: region is not planar"); return false; } EdgeStrip boundary = faces.get_boundary(); if (boundary.empty()) { err_adv(debug, "PAPER_DOLL::init: region has no boundary"); return false; } Bsurface_list surfs = Bsurface::get_surfaces(faces); if (!are_all_bsurfaces<Panel>(surfs)) { err_adv(debug, "PAPER_DOLL::init: region not all panels"); return 0; } err_adv(debug, "PAPER_DOLL::init: proceeding..."); err_adv(debug, " boundary edges: %d, components: %d, panels: %d", boundary.edges().size(), boundary.num_line_strips(), surfs.num() ); if (get_instance()->build_primitive(faces)) { err_adv(debug, " ... succeeded"); return true; } err_adv(debug, " ... failed"); return false; }
//! Returns true if the gesture is valid for beginning a circle_widget //! session. bool CIRCLE_WIDGET::init(CGESTUREptr& gest) { static bool debug = Config::get_var_bool("DEBUG_CIRCLE_WIDGET_INIT",false) || debug_all; err_adv(debug, "CIRCLE_WIDGET::init"); // Get the ellipse description: PIXEL center; // the center VEXEL axis; // the long axis (unit length) double r1, r2; // the long and short radii, respectively bool suggest_active; if (!gest->is_ellipse(center, axis, r1, r2)) { if (!gest->is_almost_ellipse(center, axis, r1, r2)) { return 0; } else { suggest_active = true; } } else { suggest_active = false; } Wplane plane = get_draw_plane(center); if (!plane.is_valid()) { // didn't work out this time return false; } /////////////////////////////////////////////////////// // // y1 // // x0 c ------> x1 // axis // y0 // // Project the extreme points of the ellipse to the // plane and check that after projection they are // reasonably equidistant from the center. // // I.e., the ellipse should reasonably match the // foreshortened circle as it would actually appear in // the given plane. /////////////////////////////////////////////////////// VEXEL perp = axis.perpend(); Wpt x0 = Wpt(plane, Wline(XYpt(center - axis*r1))); Wpt x1 = Wpt(plane, Wline(XYpt(center + axis*r1))); Wpt y0 = Wpt(plane, Wline(XYpt(center - perp*r2))); Wpt y1 = Wpt(plane, Wline(XYpt(center + perp*r2))); Wpt c = Wpt(plane, Wline(XYpt(center))); // The two diameters -- we'll check their ratio double dx = x0.dist(x1); double dy = y0.dist(y1); // XXX - Use environment variable for testing phase: // XXX - don't make static (see below): double MIN_RATIO = Config::get_var_dbl("EPC_RATIO", 0.85,true); // Be more lenient when the plane is more foreshortened: // // XXX - not sure what the right policy is, but for a // completely edge-on plane there's certainly no sense in // doing a real projection... the following drops the // min_ratio lower for more foreshortened planes: double cos_theta = VIEW::eye_vec(c) * plane.normal(); double scale = sqrt(fabs(cos_theta)); // XXX - just trying this out MIN_RATIO *= scale; // XXX - this is why it can't be static double ratio = min(dx,dy)/max(dx,dy); err_adv(debug, "CIRCLE_WIDGET::init: projected ratio: %f, min: %f", ratio, MIN_RATIO); if (ratio < MIN_RATIO) return false; CIRCLE_WIDGETptr me = get_instance(); static const int DISK_RES = Config::get_var_int("DISK_RES", 4,true); me->_plane = plane; me->_radius = dx/2; me->_disk_res = DISK_RES; me->_center = c; me->_init_stamp = VIEW::stamp(); if( me->_suggest_active = suggest_active ) { me->create_literal(gest); } //PIXEL gest_center = gest->center(); me->make_preview(); return go(); }