00001
00002
00003
00004
00005 #ifndef GESTURE_H_HAS_BEEN_INCLUDED
00006 #define GESTURE_H_HAS_BEEN_INCLUDED
00007
00008 #include "disp/view.H"
00009 #include "geom/command.H"
00010 #include "geom/fsa.H"
00011 #include "mlib/points.H"
00012 #include "mlib/vec2.H"
00013 #include "std/stop_watch.H"
00014 #include "std/config.H"
00015
00016 extern const double MIN_GESTURE_LENGTH;
00017 extern const double MIN_GESTURE_SPREAD;
00018
00019 class GestureDrawer;
00020 class GEST_INT;
00021
00022 MAKE_PTR_SUBC(GESTURE,GEL);
00023 typedef const GESTURE CGESTURE;
00024 typedef const GESTUREptr CGESTUREptr;
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 class GESTURE : public GEL {
00037 public:
00038
00039
00040
00041
00042 GESTURE(GEST_INT* gi, int index, mlib::CPIXEL& p, double pressure,
00043 GestureDrawer* drawer=0, CEvent& down = Event()) :
00044 _gest_int(gi), _index(index),
00045 _start_frame(0), _end_frame(0),
00046 _drawer(drawer), _complete(false) { init(p, down, pressure); }
00047
00048
00049 GESTURE(CGESTURE& gest) :
00050 _gest_int(0), _index(0),
00051 _pts(gest.pts()), _times(gest.timing()), _pressures(gest.pressures()),
00052 _start_frame(0), _end_frame(0),
00053 _bbox(gest.bbox(0)), _pix_bbox(gest.pix_bbox()),
00054 _complete(true){}
00055
00056
00057
00058 DEFINE_RTTI_METHODS3("GESTURE", GESTURE*, GEL, CDATA_ITEM *);
00059
00060
00061
00062 void init (mlib::CPIXEL& p, CEvent& down, double pressure);
00063 void add (mlib::CPIXEL& p, double min_dist, double pressure);
00064 void complete(mlib::CPIXEL& p, CEvent& up = Event());
00065 void trim();
00066
00067
00068
00069 GestureDrawer* drawer() { return _drawer; }
00070 void set_drawer(GestureDrawer* drawer) { _drawer = drawer; }
00071
00072
00073
00074
00075
00076
00077
00078 void set_command(CCOMMANDptr& u) { _cmd = u; }
00079 void undo() {
00080 if (_cmd)
00081 _cmd->undoit();
00082 }
00083
00084
00085
00086
00087 const mlib::PIXEL_list& pts() const { return _pts; }
00088
00089 mlib::PIXEL start() const { return _pts[0]; }
00090
00091 mlib::PIXEL end() const { return _pts.last(); }
00092
00093 mlib::PIXEL center() const { return _pts.average(); }
00094
00095 mlib::VEXEL endpt_vec() const { return (end() - start()); }
00096
00097 mlib::PIXEL endpt_midpt() const { return (end() + start())*0.5; }
00098
00099 double length() const { return _pts.length(); }
00100
00101 double endpoint_dist() const { return start().dist(end()); }
00102
00103 double dist(CGESTUREptr& g) const { return center().dist(g->center()); }
00104 bool complete() const { return _complete; }
00105
00106
00107 void smooth_points();
00108
00109
00110 void smooth_points(int n);
00111
00112
00113 double spread() const { return _pts.spread(); }
00114
00115
00116 void reflect_points(const mlib::PIXELline& l);
00117
00118 void fix_endpoints(mlib::CPIXEL& a, mlib::CPIXEL& b) {
00119 _pts.fix_endpoints(a,b);
00120 }
00121
00122 mlib::PIXELline endpt_line() const { return mlib::PIXELline(start(), end()); }
00123 mlib::PIXEL_list endpt_seg() const {
00124 mlib::PIXEL_list ret; ret += start(); ret += end(); return ret;
00125 }
00126
00127
00128 bool self_intersects() const { return _pts.self_intersects(); }
00129
00130
00131 bool intersects_line(const mlib::PIXELline& l) const {
00132 return _pts.intersects_line(l);
00133 }
00134
00135
00136 bool intersects_seg(const mlib::PIXELline& l) const {
00137 return _pts.intersects_seg(l);
00138 }
00139
00140
00141
00142 bool below_min_length() const { return length() < MIN_GESTURE_LENGTH; }
00143
00144 bool below_min_spread() const { return length() < MIN_GESTURE_SPREAD; }
00145
00146
00147 CARRAY<double>& timing() const { return _times; }
00148
00149 double start_time() const { return _times[0]; }
00150
00151 double end_time() const { return _times.last(); }
00152
00153 double elapsed_time() const { return end_time() - start_time(); }
00154
00155 double elapsed_time(int i) const { return _times[i] - start_time(); }
00156
00157 double remaining_time(int i) const { return end_time() - _times[i]; }
00158
00159 double elapsed_time(CGESTUREptr& g) const {
00160 return fabs(end_time() - g->start_time());
00161 }
00162 double between_time(CGESTUREptr& g) const {
00163 return fabs(start_time() - g->end_time());
00164 }
00165 double age() const { return stop_watch::sys_time() - end_time(); }
00166
00167
00168 CARRAY<double>& pressures() const { return _pressures; }
00169 void set_pressure(int i, double p) { if (i>0 && i<_pressures.num()) _pressures[i] = p; }
00170
00171
00172 double radius() const;
00173 double speed() const;
00174
00175
00176
00177 double startup_time(
00178 double dist_thresh=Config::get_var_dbl("GEST_STARTUP_DIST_THRESH",10.0,true)
00179 ) const;
00180
00181 double remaining_time(
00182 double dist_thresh=Config::get_var_dbl("GEST_STARTUP_DIST_THRESH",10.0,true)
00183 ) const {
00184
00185
00186 return elapsed_time() - startup_time(dist_thresh);
00187 }
00188
00189
00190 double straightness() const {
00191 double l = length(); return (l > 0) ? endpoint_dist()/length() : 0;
00192 }
00193 double winding (bool do_trim=1, bool abs=0) const;
00194 double winding_abs(bool do_trim=1) const { return winding(do_trim, true); }
00195
00196 int index() const { return _index; }
00197 void set_index(int k) { _index = k; }
00198
00199 GESTUREptr prev(int k=1) const;
00200
00201
00202
00203
00204
00205 bool is_corner(int i) const;
00206 int num_corners() const { return corners().num(); }
00207 ARRAY<int> corners() const;
00208
00209 virtual bool is_stroke() const;
00210
00211
00212 virtual bool is_line(double min_straightness, double min_len) const;
00213
00214
00215 virtual bool is_line() const;
00216
00217 virtual bool is_tap() const;
00218 virtual bool is_double_tap() const;
00219 virtual bool is_slash() const;
00220 virtual bool is_dslash() const;
00221 virtual bool is_tslash() const;
00222 virtual bool is_slash_tap() const;
00223 virtual bool is_dot() const;
00224 virtual bool is_scribble() const;
00225
00226 virtual bool is_zip_zap() const;
00227 virtual bool is_arc() const;
00228 virtual bool is_small_arc() const;
00229
00230 virtual bool is_closed() const;
00231 virtual bool is_loop() const;
00232 virtual bool is_lasso() const;
00233
00234 virtual bool is_circle(double max_ratio=1.25) const;
00235
00236 virtual bool is_small_circle(double max_ratio=1.25) const;
00237
00238 virtual bool is_ellipse(
00239 mlib::PIXEL& center, mlib::VEXEL& axis,
00240 double& r1, double& r2, double err_mult=1
00241 ) const;
00242
00243 virtual bool is_almost_ellipse(mlib::PIXEL& center, mlib::VEXEL& axis,
00244 double& r1, double& r2) const {
00245 return is_ellipse(center, axis, r1, r2,
00246 Config::get_var_dbl("ALMOST_ELLIPSE_MULTIPLIER", 3,true)
00247 );
00248 }
00249
00250 virtual bool is_ellipse() const {
00251 mlib::PIXEL center; mlib::VEXEL axis; double r1=0, r2=0;
00252 return is_ellipse(center, axis, r1, r2);
00253 }
00254
00255 virtual bool is_n_line() const;
00256 virtual bool is_e_line() const;
00257 virtual bool is_s_line() const;
00258 virtual bool is_w_line() const;
00259 virtual bool is_ne_line() const;
00260 virtual bool is_se_line() const;
00261 virtual bool is_sw_line() const;
00262 virtual bool is_nw_line() const;
00263 virtual bool is_x() const;
00264
00265 virtual bool is_click_hold() const;
00266 virtual bool is_press_hold() const;
00267
00268
00269
00270 void print_stats() const;
00271 void print_types() const;
00272
00273
00274
00275 virtual int draw(CVIEWptr &v);
00276 virtual int draw_final(CVIEWptr &v);
00277
00278
00279 virtual bool needs_blend() const { return true; }
00280
00281 virtual BBOX bbox(int) const { return _bbox; }
00282 virtual BBOXpix pix_bbox() const { return _pix_bbox; }
00283
00284
00285
00286 virtual DATA_ITEM *dup() const {
00287
00288 return 0;
00289
00290 }
00291
00292 protected:
00293
00294
00295
00296 GEST_INT* _gest_int;
00297 int _index;
00298 mlib::PIXEL_list _pts;
00299 ARRAY<double> _times;
00300 ARRAY<double> _pressures;
00301 int _start_frame;
00302 double _end_frame;
00303 Event _down, _up;
00304 GestureDrawer* _drawer;
00305 COMMANDptr _cmd;
00306 BBOX _bbox;
00307 BBOXpix _pix_bbox;
00308 bool _complete;
00309
00310
00311
00312
00313 mlib::VEXEL vec (int i) const { return _pts[i] - _pts[i-1]; }
00314 mlib::VEXEL vecn (int i) const { return vec(i).normalized(); }
00315 double angle(int i) const { return mlib::Acos(vecn(i)*vecn(i+1)); }
00316 };
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 class GestureDrawer {
00327 public:
00328 virtual ~GestureDrawer() {}
00329 virtual GestureDrawer* dup() const { return new GestureDrawer; }
00330 virtual int draw(const GESTURE*, CVIEWptr& view);
00331 };
00332
00333 #endif // GESTURE_H_HAS_BEEN_INCLUDED
00334
00335