bool CIRCLE_WIDGET::create_literal(GESTUREptr gest) { PIXEL hit_start, hit_end; Bpoint* b1 = Bpoint::hit_point(gest->start(), 8, hit_start); Bpoint* b2 = Bpoint::hit_point(gest->end(), 8, hit_end); // Find a plane to project the stroke into, but only // accept planes that are sufficiently parallel to the // film plane. Wplane P = get_plane(b1, b2); if (!P.is_valid()) { b1 = b2 = 0; // Ignoring the endpoints, try for a plane from the FLOOR // or AxisWidget: P = get_draw_plane(gest->pts()); if (!P.is_valid()) { return false; } } // Project pixel trail to the plane, and if the gesture // is "closed", make the Wpt_list form a closed loop. //DrawPen::project_to_plane(gest, P, _literal_shape); _literal_shape.clear(); gest->pts().project_to_plane(P, _literal_shape); if (gest->is_closed()) { // If closed, remove the final few points to prevent jagginess for (int i = _literal_shape.num()-1;i>=0;i--) if (PIXEL(_literal_shape[0]).dist(PIXEL(_literal_shape[i])) < 15) _literal_shape.remove(i); else break; // add the first point as the last point _literal_shape += _literal_shape[0]; _literal_shape.update_length(); } return true; }
int SWEEP_DISK::stroke_cb(CGESTUREptr& g, DrawState*&) { bool debug = debug_all; err_adv(debug, "SWEEP_DISK::stroke_cb"); // need non-const copy to fix endpoints GESTUREptr gest = g; // Activity occurred to extend the deadline for fading away: reset_timeout(); // central axis must be on-screen if (!sweep_origin().in_frustum()) { err_adv(debug, "SWEEP_DISK::stroke_cb: error: sweep origin off-screen"); return 1; } // reject closed or self-intersecting strokes if (gest->is_closed()) { WORLD::message("Can't use closed stroke"); return 1; } if (gest->self_intersects()) { WORLD::message("Can't use self-intersecting stroke"); return 1; } // Get the "silhouette" point on the boundary curve nearest // the start of the stroke: Wpt hit; if (from_center(gest)) { WORLD::message("Stroke from center of region must follow axis"); return 1; } // get the oversketch pixel_list PIXEL_list profile_pixels; bool is_line = false; bool is_from_center = false; if (!hit_boundary_at_sil(gest->start(), hit)) { if (_profile.empty() || !Bcurve::splice_curves(gest->pts(), (PIXEL_list)_profile, 15.0, profile_pixels) || !hit_boundary_at_sil(profile_pixels.front(), hit)) { WORLD::message("Stroke must start at a red dot or base of axis"); return false; } } else { profile_pixels = gest->pts(); is_line = gest->is_line(); is_from_center = from_center(gest); } // If the stroke ends near the guideline, snap it to it: bool cone_top = false; if (hits_line(profile_pixels.back())) { profile_pixels.fix_endpoints(profile_pixels.front(), pix_line().project(profile_pixels.back())); cone_top = true; } // Don't let the stroke cross the guideline (but it can end at it) bool its_bad = false; if (cone_top) its_bad = pts_in_range(profile_pixels, 0, profile_pixels.size()-2). intersects_line(pix_line()); else its_bad = profile_pixels.intersects_line(pix_line()); if (its_bad) { WORLD::message("Stroke cannot cross the dotted line"); return 1; } // A and B are line segments joining start and end of stroke // (respectively) to the guideline, in screen space: PIXELline A(pix_line().project(profile_pixels.front()), profile_pixels.front()); PIXELline B(pix_line().project(profile_pixels.back()), profile_pixels.back()); // Segment A has to be big enough to see what's going on if (A.length() < DIST_THRESH_PIXELS) { WORLD::message("Base curve is too small, zoom in to see better"); return 1; } // Stroke can't cross either line segment, because then the // surface would be self-intersecting its_bad = pts_in_range(profile_pixels, 1, profile_pixels.size()-1).intersects_seg(A); its_bad = its_bad || (!cone_top && pts_in_range(profile_pixels, 0, profile_pixels.size()-2).intersects_seg(B)); if (its_bad) { WORLD::message("Please - no self-intersecting surfaces"); return 1; } if (do_sweep(profile_pixels, hit, is_line, is_from_center)) { // We're done -- start fading reset_timeout(0.5); } else { err_adv(debug_all, "SWEEP_DISK::stroke_cb: error: do_sweep failed"); } return 1; }