Пример #1
0
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;
}
Пример #2
0
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;
}