using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using bbiwarg.Recognition.Tracking; using bbiwarg.Utility; namespace bbiwarg.Recognition.TouchRecognition { public delegate void TouchEventHandler(object sender, TouchEventArgs e); public class TouchEventArgs : EventArgs { public int TrackID { get; private set; } public Vector2D AbsolutePosition { get; private set; } public Vector2D RelativePosition { get; private set; } public TouchEventArgs(int trackID, Vector2D absolutePosition, Vector2D relativePosition) { TrackID = trackID; AbsolutePosition = absolutePosition; RelativePosition = relativePosition; } } class TrackedTouchEvent : TrackedObject { private Kalman2DPositionFilter absolutePositionKalman; private Kalman2DPositionFilter relativePositionKalman; private int fingerID; private bool isTouchActive; public Vector2D AbsolutePositionPrediction { get { return absolutePositionKalman.getPrediction(); } } public Vector2D RelativePositionPrediction { get { return relativePositionKalman.getPrediction(); } } public event TouchEventHandler TouchDown; public event TouchEventHandler TouchMove; public event TouchEventHandler TouchUp; public TrackedTouchEvent(int id, TouchEvent detectedTouchEvent, int numFramesDetectedUntilTracked, int numFramesLostUntilDeleted) : base(id, detectedTouchEvent, numFramesDetectedUntilTracked, numFramesLostUntilDeleted) { absolutePositionKalman = new Kalman2DPositionFilter(Constants.TouchmXX, Constants.TouchmXY, Constants.TouchmYY); absolutePositionKalman.setInitialPosition(detectedTouchEvent.AbsolutePosition); relativePositionKalman = new Kalman2DPositionFilter(Constants.TouchmXX, Constants.TouchmXY, Constants.TouchmYY); relativePositionKalman.setInitialPosition(detectedTouchEvent.RelativePosition); fingerID = detectedTouchEvent.Finger.TrackID; isTouchActive = false; logStateChange(); } public override void updateFrame(TouchEvent detectedTouchEvent) { base.updateFrame(detectedTouchEvent); if (NumFramesInCurrentState == 1) logStateChange(); if (detectedTouchEvent != null) { Vector2D correctedAbsolutePosition = absolutePositionKalman.getCorrectedPosition(detectedTouchEvent.AbsolutePosition); Vector2D correctedRelativePosition = relativePositionKalman.getCorrectedPosition(detectedTouchEvent.RelativePosition); if (CurrentState == TrackingState.Tracked) { if (!isTouchActive) TriggerTouchDown(new TouchEventArgs(ID, correctedAbsolutePosition, correctedRelativePosition)); else TriggerTouchMove(new TouchEventArgs(ID, correctedAbsolutePosition, correctedRelativePosition)); } } else if (isTouchActive && CurrentState == TrackingState.Deleted) TriggerTouchUp(new TouchEventArgs(ID, AbsolutePositionPrediction, RelativePositionPrediction)); } public override float calculateSimilarity(TouchEvent detectedTouchEvent) { //finger similarity float fingerSimilarity = (fingerID == detectedTouchEvent.Finger.TrackID) ? 1 : 0; //absolute position similarity float absoluteDistance = detectedTouchEvent.AbsolutePosition.getDistanceTo(AbsolutePositionPrediction); float absoluteSimilarity = Math.Max(0, 1 - absoluteDistance / Constants.ImageDiagonalLength); //relative position similarity float relativeDistance = detectedTouchEvent.RelativePosition.getDistanceTo(RelativePositionPrediction); float relativeSimilarity = Math.Max(0, 1 - relativeDistance / 1f); float similarity = fingerSimilarity * absoluteSimilarity * relativeSimilarity; return similarity; } private void logStateChange() { String stateAsString = CurrentState.ToString().ToLower(); Logger.log(String.Format("TouchEvent #{0} {1}", this.ID, stateAsString), LogSubject.TouchTracker); } private void TriggerTouchDown(TouchEventArgs e) { if (TouchDown != null) { isTouchActive = true; TouchDown(this, e); Logger.log(String.Format("TouchEvent #{0} TouchDown at {1}", this.ID, e.RelativePosition), LogSubject.TouchEvents); } } private void TriggerTouchMove(TouchEventArgs e) { if (TouchMove != null) { TouchMove(this, e); Logger.log(String.Format("TouchEvent #{0} TouchMove at {1}", this.ID, e.RelativePosition), LogSubject.TouchEvents); } } private void TriggerTouchUp(TouchEventArgs e) { if (TouchUp != null) { isTouchActive = false; TouchUp(this, e); Logger.log(String.Format("TouchEvent #{0} TouchUp at {1}", this.ID, e.RelativePosition), LogSubject.TouchEvents); } } } }