/// <summary> /// Updates spotlight circle position with new sampling point. /// </summary> /// <param name="newPt"> /// A <see cref="PointF"/> with the new sampling data. /// </param> /// <param name="toDraw"> /// The <see cref="SampleType"/> to draw. /// </param> private void DrawSpotlight(TimedPoint newPt, SampleType toDraw) { switch (toDraw) { case SampleType.Gaze: // Draw circle var gazeRadius = this.gazeFixDiameterDiv * 10; var gazeBubbleRect = new RectangleF( newPt.Position.X - gazeRadius, newPt.Position.Y - gazeRadius, 2 * gazeRadius, 2 * gazeRadius); this.gazePicEllipse.Bounds = gazeBubbleRect; break; case SampleType.Mouse: // Draw circle var mouseRadius = this.mouseFixDiameterDiv * 10; var mouseBubbleRect = new RectangleF( newPt.Position.X - mouseRadius, newPt.Position.Y - mouseRadius, 2 * mouseRadius, 2 * mouseRadius); this.mousePicEllipse.Bounds = mouseBubbleRect; break; } }
/// <summary> /// This method removes the elements for which the onset time /// is greater than the time of the given /// first valid sample. /// </summary> /// <param name="firstValidSample"> /// A <see cref="TimedPoint"/> /// with the sample that is the first one not to be removed /// </param> private void RemoveFixations(TimedPoint firstValidSample) { var elementsToRemove = new VGElementCollection(); var removedGazeFixationsCount = 0; var removedMouseFixationsCount = 0; foreach (VGElement element in this.Elements) { if (element.ElementGroup != "Default") { if (element.OnsetTime > firstValidSample.Time) { if (element.StyleGroup == VGStyleGroup.RPL_PEN_GAZE_FIX) { removedGazeFixationsCount++; } else if (element.StyleGroup == VGStyleGroup.RPL_PEN_MOUSE_FIX) { removedMouseFixationsCount++; } elementsToRemove.Add(element); } else if (element.EndTime > firstValidSample.Time) { // Scale ellipse } } } this.gazeFixations.RemoveRange(this.gazeFixations.Count - removedGazeFixationsCount, removedGazeFixationsCount); this.mouseFixations.RemoveRange(this.mouseFixations.Count - removedMouseFixationsCount, removedMouseFixationsCount); this.gazeFixConPolyline.RemoveLastPts(removedGazeFixationsCount); this.mouseFixConPolyline.RemoveLastPts(removedMouseFixationsCount); this.Elements.RemoveAll(elementsToRemove); }
/// <summary> /// Updates mouse or gaze cursor position /// </summary> /// <param name="newPt"> /// A <see cref="PointF"/> with the new sampling data. /// </param> /// <param name="toDraw"> /// The <see cref="SampleType"/> to draw. /// </param> private void DrawCursor(TimedPoint newPt, SampleType toDraw) { if (newPt.Position.IsEmpty) { return; } switch (toDraw) { case SampleType.Gaze: this.gazeCursor.Center = newPt.Position; break; case SampleType.Mouse: this.mouseCursor.Center = newPt.Position; break; } }
/// <summary> /// This method draws the given range of samples with the given drawing modes. /// </summary> /// <param name="drawingMode"> /// The <see cref="ReplayDrawingModes"/> to use. /// </param> /// <param name="sampleType"> /// The <see cref="SampleType"/> to use /// </param> /// <param name="lastValidSample"> /// A <see cref="TimedPoint"/> with the last valid sample. /// </param> /// <param name="validFixationSamples"> /// A <see cref="List{TimedPoint}"/> with /// valid fixation samples. /// </param> /// <param name="validPathSamples"> /// A <see cref="List{PointF}"/> with /// valid path samples. /// </param> /// <param name="validMouseClicks"> /// A <see cref="List{MouseStopCondition}"/> with /// valid mouse clicks. /// </param> private void DrawValidSampleRange( ReplayDrawingModes drawingMode, SampleType sampleType, TimedPoint lastValidSample, List<TimedPoint> validFixationSamples, List<PointF> validPathSamples, List<MouseStopCondition> validMouseClicks) { if (((drawingMode & ReplayDrawingModes.Fixations) == ReplayDrawingModes.Fixations) || ((drawingMode & ReplayDrawingModes.FixationConnections) == ReplayDrawingModes.FixationConnections)) { foreach (var point in validFixationSamples) { this.DrawFixations(point.Time, point.Position, sampleType, false); } if (validFixationSamples.Count > 0) { var lastvalidFixationSample = validFixationSamples[validFixationSamples.Count - 1]; this.DrawFixations(lastvalidFixationSample.Time, lastvalidFixationSample.Position, sampleType, true); } } if ((drawingMode & ReplayDrawingModes.Clicks) == ReplayDrawingModes.Clicks) { if (validMouseClicks == null) { throw new ArgumentNullException("Mouse click list is null, but drawing is activated."); } this.DrawMouseClicks(validMouseClicks); } if ((drawingMode & ReplayDrawingModes.Path) == ReplayDrawingModes.Path) { this.DrawPaths(validPathSamples, sampleType, lastValidSample.Time); } if (!this.currentLoopState.IsBlink) { if ((drawingMode & ReplayDrawingModes.Cursor) == ReplayDrawingModes.Cursor) { this.DrawCursor(lastValidSample, sampleType); } if ((drawingMode & ReplayDrawingModes.Spotlight) == ReplayDrawingModes.Spotlight) { this.DrawSpotlight(lastValidSample, sampleType); } } }
/// <summary> /// This method removes all given samples drawing elements from /// the canvas. /// </summary> /// <param name="drawingMode"> /// The <see cref="ReplayDrawingModes"/> to use. /// </param> /// <param name="sampleType"> /// The <see cref="SampleType"/> to use /// </param> /// <param name="firstValidSample"> /// A <see cref="TimedPoint"/> with the first valid sample /// to be removed. /// </param> /// <param name="validFixationSamples"> /// A <see cref="List{TimedPoint}"/> with /// valid fixation samples. /// </param> /// <param name="validPathSamples"> /// A <see cref="List{PointF}"/> with /// valid path samples. /// </param> private void RemoveValidSampleRange( ReplayDrawingModes drawingMode, SampleType sampleType, TimedPoint firstValidSample, List<TimedPoint> validFixationSamples, List<PointF> validPathSamples) { if (((drawingMode & ReplayDrawingModes.Fixations) == ReplayDrawingModes.Fixations) || ((drawingMode & ReplayDrawingModes.FixationConnections) == ReplayDrawingModes.FixationConnections)) { this.RemoveFixations(firstValidSample); } if ((drawingMode & ReplayDrawingModes.Path) == ReplayDrawingModes.Path) { this.RemovePathPoints(validPathSamples, sampleType); } if ((drawingMode & ReplayDrawingModes.Clicks) == ReplayDrawingModes.Clicks) { this.RemoveMouseClicks(); } if (!this.currentLoopState.IsBlink) { if ((drawingMode & ReplayDrawingModes.Cursor) == ReplayDrawingModes.Cursor) { this.DrawCursor(firstValidSample, sampleType); } if ((drawingMode & ReplayDrawingModes.Spotlight) == ReplayDrawingModes.Spotlight) { this.DrawSpotlight(firstValidSample, sampleType); } } }
/// <summary> /// This method draws the samples in the given data row array with /// the currently selected <see cref="ReplayDrawingModes"/> and /// sets the visibility of the blink rectangle. /// It calls internally the overload DrawSamples(DataRow[],ReplayDrawingModes,SampleType,Boolean). /// </summary> /// <param name="rows"> /// An array of <see cref="DataRow"/> with /// the sampling data. /// </param> /// <param name="remove"> /// Indicates whether to remove the given samples or not. /// </param> private void DrawSamples(DataRow[] rows, bool remove) { try { // Gaze variables PointF? newGazeSamplePoint; bool isValidGazeData; var lastValidGazeSample = new TimedPoint(); var firstValidGazeSample = new TimedPoint(-1, PointF.Empty); var validGazeFixationSamples = new List<TimedPoint>(); var validGazePathSamples = new List<PointF>(); // Mouse variables PointF? newMouseSamplePoint; bool isValidMouseData; var lastValidMouseSample = new TimedPoint(); var firstValidMouseSample = new TimedPoint(-1, PointF.Empty); var validMouseFixationSamples = new List<TimedPoint>(); var validMousePathSamples = new List<PointF>(); var validMouseClicks = new List<MouseStopCondition>(); foreach (var row in rows) { // Check trial sequence change var trialSequence = (int)row["TrialSequence"]; if (trialSequence != this.currentTrialSequence) { this.OnTrialSequenceChanged(new TrialSequenceChangedEventArgs(trialSequence)); this.currentTrialSequence = trialSequence; } // Check events if (!row.IsNull("EventID")) { var eventID = (int)row["EventID"]; if (((ReplayModule)this.OwningForm).TrialEvents.ContainsKey(eventID)) { if (!remove) { this.OnTrialEventIDFound(new TrialEventIDFoundEventArgs(eventID)); } var occuredEvent = ((ReplayModule)this.OwningForm).TrialEvents[eventID]; switch (occuredEvent.Type) { case EventType.None: break; case EventType.Mouse: switch (((InputEvent)occuredEvent).Task) { case InputEventTask.Down: var parameter = occuredEvent.Param; var msc = (MouseStopCondition)TypeDescriptor.GetConverter(typeof(StopCondition)).ConvertFrom(parameter); validMouseClicks.Add(msc); break; } break; case EventType.Key: break; case EventType.Slide: break; case EventType.Flash: break; case EventType.Audio: break; case EventType.Video: break; case EventType.Usercam: break; case EventType.Response: break; case EventType.Marker: break; case EventType.Scroll: // Update scroll position var scrollOffsets = occuredEvent.Param.Split(';'); var newScrollPosition = new Point( Convert.ToInt32(scrollOffsets[0]), Convert.ToInt32(scrollOffsets[1])); this.visiblePartOfScreen.Location = newScrollPosition; break; case EventType.Webpage: break; default: break; } } } // Iterate through rows fetching valid mouse samples and sending move events isValidMouseData = this.CheckSamples(row, SampleType.Mouse, out newMouseSamplePoint); var sampleTime = Convert.ToInt64(row[3].ToString()); if (isValidMouseData) { validMouseFixationSamples.Add( new TimedPoint(sampleTime, newMouseSamplePoint.Value)); if (!newMouseSamplePoint.Value.IsEmpty && !Queries.OutOfScreen(newMouseSamplePoint.Value, this.StimulusSize)) { if (Point.Round(newMouseSamplePoint.Value) != Point.Round(lastValidMouseSample.Position)) { validMousePathSamples.Add(newMouseSamplePoint.Value); } lastValidMouseSample = new TimedPoint(sampleTime, newMouseSamplePoint.Value); if (firstValidMouseSample.Time == -1) { firstValidMouseSample = new TimedPoint(sampleTime, newMouseSamplePoint.Value); } } } // Iterate through rows fetching valid samples if (this.gazeDrawingMode != ReplayDrawingModes.None) { isValidGazeData = this.CheckSamples(row, SampleType.Gaze, out newGazeSamplePoint); if (isValidGazeData) { validGazeFixationSamples.Add( new TimedPoint(sampleTime, newGazeSamplePoint.Value)); if (!newGazeSamplePoint.Value.IsEmpty && !Queries.OutOfScreen( newGazeSamplePoint.Value, this.StimulusSize)) { if (Point.Round(newGazeSamplePoint.Value) != Point.Round(lastValidGazeSample.Position)) { validGazePathSamples.Add(newGazeSamplePoint.Value); } lastValidGazeSample = new TimedPoint(sampleTime, newGazeSamplePoint.Value); if (firstValidGazeSample.Time == -1) { firstValidGazeSample = new TimedPoint(sampleTime, newGazeSamplePoint.Value); } } } } } if (remove) { // Remove gaze this.RemoveValidSampleRange( this.gazeDrawingMode, SampleType.Gaze, firstValidGazeSample, validGazeFixationSamples, validGazePathSamples); // Remove mouse this.RemoveValidSampleRange( this.mouseDrawingMode, SampleType.Mouse, firstValidMouseSample, validMouseFixationSamples, validMousePathSamples); } else { // Draw gaze this.DrawValidSampleRange( this.gazeDrawingMode, SampleType.Gaze, lastValidGazeSample, validGazeFixationSamples, validGazePathSamples, null); // Draw mouse this.DrawValidSampleRange( this.mouseDrawingMode, SampleType.Mouse, lastValidMouseSample, validMouseFixationSamples, validMousePathSamples, validMouseClicks); } if (this.showBlinks) { if (this.currentLoopState.IsBlink) { this.rectBlink.Visible = true; } else { this.rectBlink.Visible = false; } } } catch (Exception ex) { ExceptionMethods.HandleException(ex); } }