| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- // Filename: pointerEventList.cxx
- // Created by: jyelon (20Sep2007)
- //
- ////////////////////////////////////////////////////////////////////
- //
- // PANDA 3D SOFTWARE
- // Copyright (c) Carnegie Mellon University. All rights reserved.
- //
- // All use of this software is subject to the terms of the revised BSD
- // license. You should have received a copy of this license along
- // with this source code in a file named "LICENSE."
- //
- ////////////////////////////////////////////////////////////////////
- #include "pointerEventList.h"
- #include "indent.h"
- #include "config_event.h"
- #include "clockObject.h"
- #include "mathNumbers.h"
- #include <math.h>
- TypeHandle PointerEventList::_type_handle;
- ////////////////////////////////////////////////////////////////////
- // Function: delta_angle
- // Access: Static, Inline
- // Description: Compute the difference between two angles.
- // Returns a value in the range -180 to 180.
- ////////////////////////////////////////////////////////////////////
- INLINE double delta_angle(double angle1, double angle2) {
- double deltang = angle2 - angle1;
- while (deltang < -180.0) deltang += 360.0;
- while (deltang > 180.0) deltang -= 360.0;
- return deltang;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: delta_angle
- // Access: Static, Inline
- // Description: Compute the difference between two angles.
- // Returns a value in the range -180 to 180.
- ////////////////////////////////////////////////////////////////////
- INLINE double normalize_angle(double angle) {
- while (angle < 0.0) angle += 360.0;
- while (angle > 360.0) angle -= 360.0;
- return angle;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::output
- // Access: Public, Virtual
- // Description:
- ////////////////////////////////////////////////////////////////////
- void PointerEventList::
- output(ostream &out) const {
- if (_events.empty()) {
- out << "(no pointers)";
- } else {
- Events::const_iterator ei;
- ei = _events.begin();
- out << "(" << (*ei);
- ++ei;
- while (ei != _events.end()) {
- out << " " << (*ei);
- ++ei;
- }
- out << ")";
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::write
- // Access: Public
- // Description:
- ////////////////////////////////////////////////////////////////////
- void PointerEventList::
- write(ostream &out, int indent_level) const {
- indent(out, indent_level) << _events.size() << " events:\n";
- Events::const_iterator ei;
- for (ei = _events.begin(); ei != _events.end(); ++ei) {
- indent(out, indent_level + 2) << (*ei) << "\n";
- }
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::add_event
- // Access: Published
- // Description: Adds a new event to the end of the list.
- // Automatically calculates the dx, dy, length,
- // direction, and rotation for all but the first event.
- ////////////////////////////////////////////////////////////////////
- void PointerEventList::
- add_event(bool in_win, int xpos, int ypos, int seq, double time) {
- PointerEvent pe;
- pe._in_window = in_win;
- pe._xpos = xpos;
- pe._ypos = ypos;
- pe._sequence = seq;
- pe._time = time;
- if (_events.size() > 0) {
- pe._dx = xpos - _events.back()._xpos;
- pe._dy = ypos - _events.back()._ypos;
- double ddx = pe._dx;
- double ddy = pe._dy;
- pe._length = sqrt(ddx*ddx + ddy*ddy);
- if (pe._length > 0.0) {
- pe._direction = normalize_angle(atan2(-ddy,ddx) * (180.0 / MathNumbers::pi));
- } else {
- pe._direction = _events.back()._direction;
- }
- pe._rotation = delta_angle(_events.back()._direction, pe._direction);
- } else {
- pe._dx = 0;
- pe._dy = 0;
- pe._length = 0.0;
- pe._direction = 0.0;
- pe._rotation = 0.0;
- }
- _events.push_back(pe);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::encircles
- // Access: Published
- // Description: Returns true if the trail loops around the
- // specified point.
- ////////////////////////////////////////////////////////////////////
- bool PointerEventList::
- encircles(int x, int y) const {
- int tot_events = _events.size();
- if (tot_events < 3) {
- return false;
- }
- int last = tot_events-1;
- double dx = _events[last]._xpos - x;
- double dy = _events[last]._ypos - y;
- double lastang = atan2(dy, dx) * (180.0/MathNumbers::pi);
- double total = 0.0;
- for (int i=last; (i>=0) && (total < 360.0) && (total > -360.0); i--) {
- dx = _events[i]._xpos - x;
- dy = _events[i]._ypos - y;
- if ((dx==0.0)&&(dy==0.0)) {
- continue;
- }
- double angle = atan2(dy,dx) * (180.0/MathNumbers::pi);
- double deltang = delta_angle(lastang, angle);
- if (deltang * total < 0.0) {
- total = 0.0;
- }
- total += deltang;
- lastang = angle;
- }
- return (total > 360.0) || (total < -360.0);
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::total_turns
- // Access: Published
- // Description: returns the total angular deviation that the trail
- // has made in the specified time period. A small
- // number means that the trail is moving in a relatively
- // straight line, a large number means that the trail
- // is zig-zagging or spinning. The result is in degrees.
- ////////////////////////////////////////////////////////////////////
- double PointerEventList::
- total_turns(double sec) const {
- double old = ClockObject::get_global_clock()->get_frame_time() - sec;
- int pos = _events.size()-1;
- double tot = 0.0;
- while ((pos >= 0)&&(_events[pos]._time >= old)) {
- double rot = _events[pos]._rotation;
- if (rot < 0.0) rot = -rot;
- tot += rot;
- }
- return tot;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::match_pattern
- // Access: Published
- // Description: This function is not implemented yet. It is a work
- // in progress. The intent is as follows:
- //
- // Returns a nonzero value if the mouse movements
- // match the specified pattern. The higher the value,
- // the better the match. The pattern is a sequence
- // of compass directions (ie, "E", "NE", etc) separated
- // by spaces. If rot is nonzero, then the pattern is
- // rotated counterclockwise by the specified amount
- // before testing. Seglen is the minimum length a
- // mouse movement needs to be in order to be considered
- // significant.
- ////////////////////////////////////////////////////////////////////
- double PointerEventList::
- match_pattern(const string &ascpat, double rot, double seglen) {
- // Convert the pattern from ascii to a more usable form.
- pvector <double> pattern;
- parse_pattern(ascpat, pattern);
-
- // Apply the rotation to the pattern.
- for (size_t i=0; i<pattern.size(); i++) {
- pattern[i] = normalize_angle(pattern[i] + rot);
- }
-
- return 0.0;
- }
- ////////////////////////////////////////////////////////////////////
- // Function: PointerEventList::parse_pattern
- // Access: Private
- // Description: Parses a pattern as used by match_pattern.
- ////////////////////////////////////////////////////////////////////
- void PointerEventList::
- parse_pattern(const string &ascpat, pvector <double> &pattern) {
- int chars = 0;
- double dir = 180.0;
- for (size_t i=0; i<ascpat.size(); i++) {
- char c = ascpat[i];
- double ang = -1.0;
- if ((c=='E')||(c=='e')) ang=0.0;
- else if ((c=='N')||(c=='n')) ang=90.0;
- else if ((c=='W')||(c=='w')) ang=180.0;
- else if ((c=='S')||(c=='s')) ang=270.0;
- if (ang >= 0.0) {
- double offset = delta_angle(dir, ang);
- double newang = dir + offset;
- dir = normalize_angle((dir * chars + newang) / (chars + 1));
- chars += 1;
- } else {
- if ((c != ' ')&&(c != '\t')) {
- event_cat.warning() <<
- "Invalid pattern in PointerEventList::match_pattern\n";
- pattern.clear();
- return;
- }
- if (chars > 0) {
- pattern.push_back(dir);
- }
- chars = 0;
- dir = 180.0;
- }
- }
- if (chars > 0) {
- pattern.push_back(dir);
- }
-
- cerr << "Pattern: ";
- for (int i=0; i<(int)pattern.size(); i++) {
- cerr << pattern[i] << " ";
- }
- cerr << "\n";
- }
|