Panda3D
 All Classes Functions Variables Enumerations
pointerEventList.cxx
00001 // Filename: pointerEventList.cxx
00002 // Created by: jyelon (20Sep2007)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "pointerEventList.h"
00016 #include "indent.h"
00017 #include "config_event.h"
00018 #include "clockObject.h"
00019 #include "deg_2_rad.h"
00020 #include "cmath.h"
00021 
00022 TypeHandle PointerEventList::_type_handle;
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: delta_angle
00026 //       Access: Static, Inline
00027 //  Description: Compute the difference between two angles.
00028 //               Returns a value in the range -180 to 180.
00029 ////////////////////////////////////////////////////////////////////
00030 INLINE double delta_angle(double angle1, double angle2) {
00031   double deltang = angle2 - angle1;
00032   while (deltang < -180.0) deltang += 360.0;
00033   while (deltang >  180.0) deltang -= 360.0;
00034   return deltang;
00035 }
00036 
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: delta_angle
00040 //       Access: Static, Inline
00041 //  Description: Compute the difference between two angles.
00042 //               Returns a value in the range -180 to 180.
00043 ////////////////////////////////////////////////////////////////////
00044 INLINE double normalize_angle(double angle) {
00045   while (angle <   0.0) angle += 360.0;
00046   while (angle > 360.0) angle -= 360.0;
00047   return angle;
00048 }
00049 
00050 
00051 
00052 ////////////////////////////////////////////////////////////////////
00053 //     Function: PointerEventList::output
00054 //       Access: Public, Virtual
00055 //  Description: 
00056 ////////////////////////////////////////////////////////////////////
00057 void PointerEventList::
00058 output(ostream &out) const {
00059   if (_events.empty()) {
00060     out << "(no pointers)";
00061   } else {
00062     Events::const_iterator ei;
00063     ei = _events.begin();
00064     out << "(" << (*ei);
00065     ++ei;
00066     while (ei != _events.end()) {
00067       out << " " << (*ei);
00068       ++ei;
00069     }
00070     out << ")";
00071   }
00072 }
00073 
00074 ////////////////////////////////////////////////////////////////////
00075 //     Function: PointerEventList::write
00076 //       Access: Public
00077 //  Description: 
00078 ////////////////////////////////////////////////////////////////////
00079 void PointerEventList::
00080 write(ostream &out, int indent_level) const {
00081   indent(out, indent_level) << _events.size() << " events:\n";
00082   Events::const_iterator ei;
00083   for (ei = _events.begin(); ei != _events.end(); ++ei) {
00084     indent(out, indent_level + 2) << (*ei) << "\n";
00085   }
00086 }
00087 
00088 ////////////////////////////////////////////////////////////////////
00089 //     Function: PointerEventList::add_event
00090 //       Access: Published
00091 //  Description: Adds a new event to the end of the list.
00092 //               Automatically calculates the dx, dy, length,
00093 //               direction, and rotation for all but the first event.
00094 ////////////////////////////////////////////////////////////////////
00095 void PointerEventList::
00096 add_event(bool in_win, int xpos, int ypos, int seq, double time) {
00097   PointerEvent pe;
00098   pe._in_window = in_win;
00099   pe._xpos = xpos;
00100   pe._ypos = ypos;
00101   pe._sequence = seq;
00102   pe._time = time;
00103   if (_events.size() > 0) {
00104     pe._dx = xpos - _events.back()._xpos;
00105     pe._dy = ypos - _events.back()._ypos;
00106     double ddx = pe._dx;
00107     double ddy = pe._dy;
00108     pe._length = csqrt(ddx*ddx + ddy*ddy);
00109     if (pe._length > 0.0) {
00110       pe._direction = normalize_angle(rad_2_deg(catan2(-ddy,ddx)));
00111     } else {
00112       pe._direction = _events.back()._direction;
00113     }
00114     pe._rotation = delta_angle(_events.back()._direction, pe._direction);
00115   } else {
00116     pe._dx = 0;
00117     pe._dy = 0;
00118     pe._length = 0.0;
00119     pe._direction = 0.0;
00120     pe._rotation = 0.0;
00121   }
00122   _events.push_back(pe);
00123 }       
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: PointerEventList::encircles
00127 //       Access: Published
00128 //  Description: Returns true if the trail loops around the
00129 //               specified point.
00130 ////////////////////////////////////////////////////////////////////
00131 bool PointerEventList::
00132 encircles(int x, int y) const {
00133   int tot_events = _events.size();
00134   if (tot_events < 3) {
00135     return false;
00136   }
00137   int last = tot_events-1;
00138   double dx = _events[last]._xpos - x;
00139   double dy = _events[last]._ypos - y;
00140   double lastang = rad_2_deg(catan2(dy, dx));
00141   double total = 0.0;
00142   for (int i=last; (i>=0) && (total < 360.0) && (total > -360.0); i--) {
00143     dx = _events[i]._xpos - x;
00144     dy = _events[i]._ypos - y;
00145     if ((dx==0.0)&&(dy==0.0)) {
00146       continue;
00147     }
00148     double angle = rad_2_deg(catan2(dy,dx));
00149     double deltang = delta_angle(lastang, angle);
00150     if (deltang * total < 0.0) {
00151       total = 0.0;
00152     }
00153     total += deltang;
00154     lastang = angle;
00155   }
00156   return (total > 360.0) || (total < -360.0);
00157 }
00158 
00159 ////////////////////////////////////////////////////////////////////
00160 //     Function: PointerEventList::total_turns
00161 //       Access: Published
00162 //  Description: returns the total angular deviation that the trail
00163 //               has made in the specified time period.  A small
00164 //               number means that the trail is moving in a relatively
00165 //               straight line, a large number means that the trail
00166 //               is zig-zagging or spinning.  The result is in degrees.
00167 ////////////////////////////////////////////////////////////////////
00168 double PointerEventList::
00169 total_turns(double sec) const {
00170   double old = ClockObject::get_global_clock()->get_frame_time() - sec;
00171   int pos = _events.size()-1;
00172   double tot = 0.0;
00173   while ((pos >= 0)&&(_events[pos]._time >= old)) {
00174     double rot = _events[pos]._rotation;
00175     if (rot < 0.0) rot = -rot;
00176     tot += rot;
00177   }
00178   return tot;
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: PointerEventList::match_pattern
00183 //       Access: Published
00184 //  Description: This function is not implemented yet.  It is a work
00185 //               in progress.  The intent is as follows:
00186 //
00187 //               Returns a nonzero value if the mouse movements 
00188 //               match the specified pattern.  The higher the value,
00189 //               the better the match.  The pattern is a sequence
00190 //               of compass directions (ie, "E", "NE", etc) separated
00191 //               by spaces.  If rot is nonzero, then the pattern is
00192 //               rotated counterclockwise by the specified amount 
00193 //               before testing.  Seglen is the minimum length a
00194 //               mouse movement needs to be in order to be considered
00195 //               significant.
00196 ////////////////////////////////////////////////////////////////////
00197 double PointerEventList::
00198 match_pattern(const string &ascpat, double rot, double seglen) {
00199   // Convert the pattern from ascii to a more usable form.
00200   vector_double pattern;
00201   parse_pattern(ascpat, pattern);
00202   
00203   // Apply the rotation to the pattern.
00204   for (size_t i=0; i<pattern.size(); i++) {
00205     pattern[i] = normalize_angle(pattern[i] + rot);
00206   }
00207   
00208   return 0.0;
00209 }
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: PointerEventList::parse_pattern
00213 //       Access: Private
00214 //  Description: Parses a pattern as used by match_pattern.
00215 ////////////////////////////////////////////////////////////////////
00216 void PointerEventList::
00217 parse_pattern(const string &ascpat, vector_double &pattern) {
00218   int chars = 0;
00219   double dir = 180.0;
00220   for (size_t i=0; i<ascpat.size(); i++) {
00221     char c = ascpat[i];
00222     double ang = -1.0;
00223     if      ((c=='E')||(c=='e')) ang=0.0;
00224     else if ((c=='N')||(c=='n')) ang=90.0;
00225     else if ((c=='W')||(c=='w')) ang=180.0;
00226     else if ((c=='S')||(c=='s')) ang=270.0;
00227     if (ang >= 0.0) {
00228       double offset = delta_angle(dir, ang);
00229       double newang = dir + offset;
00230       dir = normalize_angle((dir * chars + newang) / (chars + 1));
00231       chars += 1;
00232     } else {
00233       if ((c != ' ')&&(c != '\t')) {
00234         event_cat.warning() <<
00235           "Invalid pattern in PointerEventList::match_pattern\n";
00236         pattern.clear();
00237         return;
00238       }
00239       if (chars > 0) {
00240         pattern.push_back(dir);
00241       }
00242       chars = 0;
00243       dir = 180.0;
00244     }
00245   }
00246   if (chars > 0) {
00247     pattern.push_back(dir);
00248   }
00249   
00250   cerr << "Pattern: ";
00251   for (int i=0; i<(int)pattern.size(); i++) {
00252     cerr << pattern[i] << " ";
00253   }
00254   cerr << "\n";
00255 }
 All Classes Functions Variables Enumerations