/// <summary> /// Scale the gesture so it's square bounding box is the given size. /// </summary> /// <param name="size">The size of the resultant bounding box.</param> public Gesture Scale(float size) { var bbox = BoundingBox; var result = new Gesture(); foreach (var p in this) { var qX = p.x * size / bbox.width; var qY = p.y * size / bbox.height; result.Add(new Vector2(qX, qY)); } return(result); }
/// <summary> /// Resamples the gesture into a given number of points. /// </summary> /// <param name="n">The number of points to end with.</param> public Gesture Resample(int n) { var I = PathLength() / (n - 1); // interval length var D = 0.0f; var srcPts = new Gesture(this); var dstPts = new Gesture { srcPts[0] }; for (var i = 1; i < srcPts.Count; i++) { var pt1 = srcPts[i - 1]; var pt2 = srcPts[i]; var d = Vector2.Distance(pt1, pt2); if ((D + d) >= I) { var qx = pt1.x + ((I - D) / d) * (pt2.x - pt1.x); var qy = pt1.y + ((I - D) / d) * (pt2.y - pt1.y); var q = new Vector2(qx, qy); dstPts.Add(q); // append new point 'q' srcPts.Insert(i, q); // insert 'q' at position i in points s.t. 'q' will be the next i D = 0.0f; } else { D += d; } } // sometimes we fall a rounding-error short of adding the last point, so add it if so if (dstPts.Count == n - 1) { dstPts.Add(srcPts[srcPts.Count - 1]); } return(dstPts); }
/// <summary> /// Translate the gesture so the center rests at the provided destination. /// </summary> /// <param name="destination">The destination of the translation.</param> public Gesture Translate(Vector2 destination) { var c = Centroid; var result = new Gesture(); foreach (var p in this) { var qX = p.x - c.x + destination.x; var qY = p.y - c.y + destination.y; result.Add(new Vector2(qX, qY)); } return(result); }
/// <summary> /// Rotate the gesture by "theta" radians about it's centroid. /// </summary> /// <param name="theta">The amount of rotation in rads</param> public Gesture Rotate(float theta) { var result = new Gesture(); var centroid = Centroid; foreach (var point in this) { var qX = (point.x - centroid.x) * Mathf.Cos(theta) - (point.y - centroid.y) * Mathf.Sin(theta); var qY = (point.x - centroid.x) * Mathf.Sin(theta) + (point.y - centroid.y) * Mathf.Cos(theta); //translate back to origin and add to result result.Add(new Vector2(qX, qY) + centroid); } return(result); }
// Hanlde a new input vector public void ProcessRawMeasurement(Vector3 input) { // Store a local copy that can be modified by the filters Vector3 v = input; // Store the timestamp when it arrvied float timestamp = Time.realtimeSinceStartup; // While the input vector is still interesting process it by // the successive filters bool valid = true; foreach (IFilter f in filterList) { valid = valid && f.FilterVector(ref v); } // if the vector is not intersting but we were in motion till now // check if the time delay is too large // Stop the gesture if it is if (!valid && isInMotion) { float timeDiff = timestamp - lastValidVectorTimestamp; if (timeDiff > GESTURE_TIMEOUT) { isInMotion = false; Debug.Log("Motion stopped"); gestureIsValid = true; lastGesture = workGesture; } } else if (valid) { // IF it is intresting, add the measurement to the current working gesture // Also update the timestamp when we last saw an interesting vector lastValidVectorTimestamp = timestamp; if (!isInMotion) { isInMotion = true; Debug.Log("Motion started"); workGesture = new Gesture(); } workGesture.Add(v); } }
MouseDirections TrackMouseAttack() { // Track action for idle plus all eight mouse directions var sum = _gesture.Add(InputManager.Instance.MouseX, InputManager.Instance.MouseY) * weaponSensitivity; // Short mouse gestures are ignored if (_gesture.TravelDist / _longestDim < AttackThreshold) { return(MouseDirections.None); } // Treat mouse movement as a vector from the origin // The angle of the vector will be used to determine the angle of attack/swing var angle = Mathf.Atan2(sum.y, sum.x) * Mathf.Rad2Deg; // Put angle into 0 - 360 deg range if (angle < 0f) { angle += 360f; } // The swing gestures are divided into radial segments // Up-down and left-right attacks are in a 30 deg cone about the x/y axes // Up-right and up-left aren't valid so the up range is expanded to fill the range // The remaining 60 deg quadrants trigger the diagonal attacks var radialSection = Mathf.CeilToInt(angle / 15f); MouseDirections direction; switch (radialSection) { case 0: // 0 - 15 deg case 1: case 24: // 345 - 365 deg direction = MouseDirections.Right; break; case 2: // 15 - 75 deg case 3: case 4: case 5: case 6: // 75 - 105 deg case 7: case 8: // 105 - 165 deg case 9: case 10: case 11: direction = MouseDirections.Up; break; case 12: // 165 - 195 deg case 13: direction = MouseDirections.Left; break; case 14: // 195 - 255 deg case 15: case 16: case 17: direction = MouseDirections.DownLeft; break; case 18: // 255 - 285 deg case 19: direction = MouseDirections.Down; break; case 20: // 285 - 345 deg case 21: case 22: case 23: direction = MouseDirections.DownRight; break; default: // Won't happen direction = MouseDirections.None; break; } _gesture.Clear(); return(direction); }