File Name: FIXFUNC.C
Program Name: Eye Fixation Analysis Functions
Company: LC Technologies, Inc.
1483 Chain Bridge Road, Suite 104
McLean, VA 22101
(703) 385-7133
Makers of the Eyegaze System, additional information about LC
Technologies and its products may be found at http://www.eyegaze.com
*****************************************************************************/
/* FUNCTION, VARIABLE AND CONSTANT DEFINITONS: */
#include
#include
#include
#include
#include
#include
#include
#include
#define RING_SIZE 31 /* length of the delay line in */
/* DetectFixation() -- */
/* should be greater than */
/* minimum_fix_samples */
/****************************************************************************/
/* FUNCTION PROTOTYPES: */
SVOID ResetPresFixation(void);
SVOID ResetNewFixation(void);
SVOID StartPresFixAtGazepoint(float x_gaze, float y_gaze);
SVOID StartNewFixAtGazepoint(float x_gaze, float y_gaze);
SVOID UpdatePresFixation(float x_gaze, float y_gaze, int minimum_fix_samples);
SVOID UpdateNewFixation(float x_gaze, float y_gaze);
SVOID CalcGazeDeviationFromPresFix(float x_gaze, float y_gaze);
SVOID CalcGazeDeviationFromNewFix(float x_gaze, float y_gaze);
SVOID CheckIfFixating(int minimum_fix_samples);
SVOID MoveNewFixToPresFix(int minimum_fix_samples);
SVOID DeclareCompletedFixation(int minimum_fix_samples);
SVOID RestoreOutPoints(void);
/****************************************************************************/
/* GLOBAL FIXFUNC VARIABLES: */
SLONG lCallCount; /* number of times this function has been */
/* called since it was initialized */
/* (30ths or 60ths of a second, */
/* depending on eyetracking sample rate) */
SINT iNNoEyeFound; /* number of successive samples with no */
/* eye found */
/* DATA ON PREVIOUS FIXATION */
SLONG lPrevFixEndCount; /* count that the previous fixation ended */
/* DATA ON PRESENT FIXATION */
SLONG lPresFixStartCount; /* call count that the fixation starts */
SLONG lPresFixEndCount; /* call count that the fixation ends */
SINT iNPresFixSamples; /* number of samples in the present fix */
SFLOAT fXPresFixSum; /* summations for calculation of average */
SFLOAT fYPresFixSum; /* fixation position */
SFLOAT fXPresFix; /* average coordinate of the eye fixation */
SFLOAT fYPresFix; /* point (user selected units) */
SINT iNPresOut; /* number of samples outside the fixation */
SFLOAT fPresDr; /* difference between gazepoint and */
/* fixation (x, y, and radius) */
/* DATA ON NEW FIXATION */
SLONG new_fix_start_count; /* call count that the new fixation starts */
SLONG new_fix_end_count; /* call count that the new fixation ends */
SINT n_new_fix_samples; /* number of samples in the fixation */
SFLOAT x_new_fix_sum; /* summations for the FIR filter */
SFLOAT y_new_fix_sum; /* calculations of the eye motion */
SFLOAT x_new_fix; /* average coordinate of the eye fixation */
SFLOAT y_new_fix; /* point (user selected units) */
SFLOAT new_dr; /* difference between gazepoint and */
/* fixation (x, y, and radius) */
/* RING BUFFERS STORING PAST VALUES: */
SFLOAT x_gaze_ring[RING_SIZE];
SFLOAT y_gaze_ring[RING_SIZE];
SBYTE gaze_found_ring[RING_SIZE];
SINT eye_motion_state[RING_SIZE];
/* state of the eye motion: */
/* MOVING */
/* FIXATING */
/* FIXATION_COMPLETED */
SFLOAT x_fix_ring[RING_SIZE];
SFLOAT y_fix_ring[RING_SIZE];
SFLOAT gaze_deviation_ring[RING_SIZE];
SINT sac_duration_ring[RING_SIZE];
SINT fix_duration_ring[RING_SIZE];
SINT iRingIndex; /* ring index of the present gaze sample */
SINT iRingIndexDelay; /* ring index of the gaze sample taken */
/* minimum_fix_samples ago */
/****************************************************************************/
void InitFixation(int minimum_fix_samples)
/* minimum number of gaze samples */
/* that can be considered a */
/* fixation */
/* Note: if the input value is */
/* is less than 3, the function */
/* sets it to 3 */
/* This function clears any previous, present and new fixations, and it */
/* initializes DetectFixation()'s internal ring buffers of prior */
/* gazepoint data. InitFixation() should be called prior to a sequence */
/* of calls to DetectFixation(). */
{
/* Initialize the internal ring buffer. */
for (iRingIndex = 0; iRingIndex < RING_SIZE; iRingIndex++)
{
x_gaze_ring[iRingIndex] = 0.0F;
y_gaze_ring[iRingIndex] = 0.0F;
gaze_found_ring[iRingIndex] = FALSE;
eye_motion_state[iRingIndex] = MOVING;
x_fix_ring[iRingIndex] = 0.0F;
y_fix_ring[iRingIndex] = 0.0F;
gaze_deviation_ring[iRingIndex] = -0.1F;
sac_duration_ring[iRingIndex] = 0;
fix_duration_ring[iRingIndex] = 0;
}
iRingIndex = 0;
iRingIndexDelay = RING_SIZE - minimum_fix_samples;
/* Set the call count to zero, and initialize the previous fixation end */
/* count so the first saccade duration is a legitimate count. */
lCallCount = 0;
lPrevFixEndCount = 0;
/* Reset the present fixation data. */
ResetPresFixation();
/* Reset the new fixation data. */
ResetNewFixation();
/* Initialize the number of successive samples with no eye found. */
iNNoEyeFound = 0;
}
/****************************************************************************/
int DetectFixation(
/* INPUT PARAMETERS: */
BYTE gazepoint_found, /* flag indicating whether or not */
/* the image processing algo */
/* detected the eye and computed */
/* a valid gazepoint (TRUE/FALSE) */
float x_gaze, /* present gazepoint */
float y_gaze, /* (user specified units) */
float gaze_deviation_threshold, /* distance that a gazepoint may */
/* vary from the average fixation */
/* point and still be considered */
/* part of the fixation */
/* (user specified units) */
int minimum_fix_samples, /* minimum number of gaze samples */
/* that can be considered a */
/* fixation */
/* Note: if the input value is */
/* is less than 3, the function */
/* sets it to 3 */
/* OUTPUT PARAMETERS: */
/* Delayed Gazepoint data with */
/* fixation annotations: */
BYTE *ptr_gazepoint_found_delayed,
/* sample gazepoint-found flag, */
/* min_fix_samples ago */
float *ptr_x_gaze_delayed, /* sample gazepoint coordinates, */
float *ptr_y_gaze_delayed, /* min_fix_samples ago */
float *ptr_gaze_deviation_delayed,
/* deviation of the gaze from the */
/* present fixation, */
/* min_fix_samples ago */
/* Fixation data - delayed: */
float *ptr_x_fix_delayed, /* fixation point as estimated */
float *ptr_y_fix_delayed, /* min_fix_samples ago */
int *ptr_saccade_duration_delayed,
/* duration of the saccade */
/* preceeding the preset fixation */
/* (samples) */
int *ptr_fix_duration_delayed)/* duration of the present fixation */
/* (samples) */
/* RETURN VALUES - Eye Motion State: */
/* */
/* MOVING 0 The eye was in motion min_fix_samples ago. */
/* FIXATING 1 The eye was fixating min_fix_samples ago. */
/* FIXATION_COMPLETED 2 A completed fixation has just been detected; */
/* the fixation ended min_fix_samples ago. */
/* */
/* Include FIXFUNC.H for function prototype and above constant definitions. */
/* */
/* SUMMARY */
/* */
/* This function converts a series of uniformly-sampled (raw) gaze */
/* points into a series of variable-duration saccades and fixations. */
/* Fixation analysis may be performed in real time or after the fact. To */
/* allow eye fixation analysis during real-time eyegaze data collection, */
/* the function is designed to be called once per sample. When the eye */
/* is in motion, ie during saccades, the function returns 0 (MOVING). */
/* When the eye is still, ie during fixations, the function returns 1 */
/* (FIXATING). Upon the detected completion of a fixation, the function */
/* returns 2 (FIXATION_COMPLETED) and produces: */
/* a) the time duration of the saccade between the last and present */
/* eye fixation (eyegaze samples) */
/* b) the time duration of the present, just completed fixation */
/* (eyegaze samples) */
/* c) the average x and y coordinates of the eye fixation */
/* (in user defined units of x_gaze and y_gaze) */
/* Note: Although this function is intended to work in "real time", there */
/* is a delay of minimum_fix_samples in the filter which detects the */
/* motion/fixation condition of the eye. */
/* */
/* PRINCIPLE OF OPERATION */
/* */
/* This function detects fixations by looking for sequences of gaze- */
/* point measurements that remain relatively constant. If a new gazepoint */
/* lies within a circular region around the running average of an on-going */
/* fixation, the fixation is extended to include the new gazepoint. */
/* (The radius of the acceptance circle is user specified by setting the */
/* value of the function argument gaze_deviation_threshold.) */
/* To accommodate noisy eyegaze measurements, a gazepoint that exceeds */
/* the deviation threshold is included in an on-going fixation if the */
/* subsequent gazepoint returns to a position within the threshold. */
/* If a gazepoint is not found, during a blink for example, a fixation */
/* is extended if a) the next legitimate gazepoint measurement falls within */
/* the acceptance circle, and b) there are less than minimum_fix_samples */
/* of successive missed gazepoints. Otherwise, the previous fixation */
/* is considered to end at the last good gazepoint measurement. */
/* */
/* UNITS OF MEASURE */
/* */
/* The gaze position/direction may be expressed in any units (e.g. */
/* millimeters, pixels, or radians), but the filter threshold must be */
/* expressed in the same units. */
/* */
/* INITIALIZING THE FUNCTION */
/* */
/* Prior to analyzing a sequence of gazepoint data, the InitFixation */
/* function should be called to clear any previous, present and new */
/* fixations and to initialize the ring buffers of prior gazepoint data. */
/* */
/* PROGRAM NOTES */
/* */
/* For purposes of describing an ongoing sequence of fixations, fixations */
/* in this program are referred to as "previous", "present", and "new". */
/* The present fixation is the one that is going on right now, or, if a */
/* new fixation has just started, the present fixation is the one that */
/* just finished. The previous fixation is the one immediatly preceeding */
/* the present one, and a new fixation is the one immediately following */
/* the present one. Once the present fixation is declared to be completed, */
/* the present fixation becomes the previous one, the new fixation becomes */
/* the present one, and there is not yet a new fixation. */
/*--------------------------------------------------------------------------*/
{
/* Make sure the minimum fix time is at least 3 samples. */
if (minimum_fix_samples < 3) minimum_fix_samples = 3;
/* Make sure the ring size is large enough to handle the delay. */
if (minimum_fix_samples >= RING_SIZE)
{
lct_settextmode();
printf("minimum_fix_samples %i >= RING_SIZE %i\n",
minimum_fix_samples, RING_SIZE);
printf("Press any key to terminate...");
getch();
exit(99);
}
/* Increment the call count, the ring index, and the delayed ring index. */
lCallCount++;
iRingIndex++;
if (iRingIndex >= RING_SIZE) iRingIndex = 0;
iRingIndexDelay = iRingIndex - minimum_fix_samples;
if (iRingIndexDelay < 0) iRingIndexDelay += RING_SIZE;
/* Update the storage rings. */
x_gaze_ring[iRingIndex] = x_gaze;
y_gaze_ring[iRingIndex] = y_gaze;
gaze_found_ring[iRingIndex] = gazepoint_found;
/* Initially assume the eye is moving. */
/* Note: These values are updated during the processing of this and */
/* subsequent gazepoints. */
eye_motion_state[iRingIndex] = MOVING;
x_fix_ring[iRingIndex] = -0.0F;
y_fix_ring[iRingIndex] = -0.0F;
gaze_deviation_ring[iRingIndex] = -0.1F;
sac_duration_ring[iRingIndex] = 0;
fix_duration_ring[iRingIndex] = 0;
/*- - - - - - - - - - - - - Process Tracked Eye - - - - - - - - - - - - - -*/
/* A1 If the eye's gazepoint was successfully measured this sample, */
if (gazepoint_found == TRUE)
{
/* The number of successive no-tracks is zero. */
iNNoEyeFound = 0;
/* B1 If there is a present fixation, */
if (iNPresFixSamples > 0)
{
/* Compute the deviation of the gazepoint from the present fixation. */
CalcGazeDeviationFromPresFix(x_gaze, y_gaze);
/* C1 If the gazepoint is within the present fixation region, */
if (fPresDr <= gaze_deviation_threshold)
{
/* Restore any previous gazepoints that were temporarily left */
/* out of the fixation. */
RestoreOutPoints();
/* Update the present fixation hypothesis, and check if there */
/* are enough samples to declare that the eye is fixating. */
UpdatePresFixation(x_gaze, y_gaze, minimum_fix_samples);
}
/* C2 Otherwise, if the point is outside the present fixation region, */
else /* if (fPresDr > gaze_deviation_threshold) */
{
/* Increment the number of gazepoint samples outside the */
/* present fix. */
iNPresOut++;
/* D1 If the present fixation is finished, i.e. if there have */
/* been minimum_fix_samples since the gazepoint last matched */
/* the present fixation, and the present fixation is long */
/* enough to count as a real fixation, */
if (((int)(lCallCount - lPresFixEndCount) >=
minimum_fix_samples) &&
(iNPresFixSamples >= minimum_fix_samples))
{
/* Declare the present fixation to be completed, move the */
/* present fixation to the prior, move the new fixation to */
/* the present, and check if the new (now present) fixation */
/* has enough points for the eye to be declared to be fixating. */
DeclareCompletedFixation(minimum_fix_samples);
/* Compute the deviation of the gazepoint from the now */
/* present fixation. */
CalcGazeDeviationFromPresFix(x_gaze, y_gaze);
/* E1 If the gazepoint is within the now present fixation region, */
if (fPresDr <= gaze_deviation_threshold)
{
/* Update the present fixation data, and check if there */
/* are enough samples to declare that the eye is fixating. */
UpdatePresFixation(x_gaze, y_gaze, minimum_fix_samples);
}
/* E2 Otherwise, if the gazepoint is outside the now present */
/* fixation, */
else /* if (fPresDr > gaze_deviation_threshold) */
{
/* Start a new fixation at the gazepoint. */
StartNewFixAtGazepoint(x_gaze, y_gaze);
}
}
/* D2 Otherwise, if the present fixation is not finished, */
else
{
/* F1 If there is a new fixation hypothesis, */
if (n_new_fix_samples > 0)
{
/* Compute the deviation of the gazepoint from the new */
/* fixation. */
CalcGazeDeviationFromNewFix(x_gaze, y_gaze);
/* G1 If the new point falls within the new fix, */
if (new_dr <= gaze_deviation_threshold)
{
/* Update the new fixation hypothesis. */
UpdateNewFixation(x_gaze, y_gaze);
/* H. If there are now enough points in the new fix */
/* to declare it a real fix, */
if (n_new_fix_samples == minimum_fix_samples)
{
/* Drop the present fixation data, move the new */
/* new fixation into the present fixation, and see */
/* if the new (now present) fixation has enough */
/* points to declare the eye to be fixating. */
MoveNewFixToPresFix(minimum_fix_samples);
}
}
/* G2 Otherwise, if the point is outside the new fix, */
else /* if (new_dr <= gaze_deviation_threshold) */
{
/* Start the new fixation at the new gazepoint. */
StartNewFixAtGazepoint(x_gaze, y_gaze);
}
}
/* F2 Otherwise, If there is not a new fix, */
else /* if (n_new_fix_counts == 0) */
{
/* Start the new fixation at the gazepoint. */
StartNewFixAtGazepoint(x_gaze, y_gaze);
}
}
}
}
/* B2 Otherwise, if there is not a present fixation, */
else /* if (iNPresFixSamples = 0) */
{
/* Start the present fixation at the gazepoint and reset the */
/* new fixation. */
StartPresFixAtGazepoint(x_gaze, y_gaze);
}
}
/*- - - - - - - - - - - - - Process Untracked Eye - - - - - - - - - - - - -*/
/* A2 Otherwise, if the eye's gazepoint was not successfully measured */
/* this sample, */
else /* if (gazepoint_found == FALSE) */
{
/* Increment the number of successive samples with no eye found. */
iNNoEyeFound++;
/*I If it has been min-fix-samples since the last sample in the */
/* present fixation, */
if ((int)(lCallCount - lPresFixEndCount) >= minimum_fix_samples)
{
/* J If there had been a fixation prior to loosing track of the eye, */
if (iNPresFixSamples >= minimum_fix_samples)
{
/* Declare the present fixation to be completed, move the */
/* present fixation to the prior, move the new fixation to */
/* the present, and check if the new (now present) fixation */
/* has enough points for the eye to be declared to be fixating. */
DeclareCompletedFixation(minimum_fix_samples);
}
/* Reset the present fixation data. */
ResetPresFixation();
}
}
/*---------------------------- Pass Data Back ------------------------------*/
/* Pass the delayed gazepoint data, with the relevant saccade/fixation */
/* data, back to the calling function. */
*ptr_x_gaze_delayed = x_gaze_ring[iRingIndexDelay];
*ptr_y_gaze_delayed = y_gaze_ring[iRingIndexDelay];
*ptr_gazepoint_found_delayed = gaze_found_ring[iRingIndexDelay];
*ptr_x_fix_delayed = x_fix_ring[iRingIndexDelay];
*ptr_y_fix_delayed = y_fix_ring[iRingIndexDelay];
*ptr_gaze_deviation_delayed = gaze_deviation_ring[iRingIndexDelay];
*ptr_saccade_duration_delayed= sac_duration_ring[iRingIndexDelay];
*ptr_fix_duration_delayed = fix_duration_ring[iRingIndexDelay];
/* Return the eye motion/fixation state for the delayed point. */
return(eye_motion_state[iRingIndexDelay]);
}
/****************************************************************************/
SVOID ResetPresFixation(void)
/* This function resets the present fixation, i.e. declares it nonexistent. */
{
lPresFixStartCount = 0;
lPresFixEndCount = 0;
iNPresFixSamples = 0;
fXPresFixSum = 0.0F;
fYPresFixSum = 0.0F;
fXPresFix = 0.0F;
fYPresFix = 0.0F;
iNPresOut = 0;
}
/****************************************************************************/
SVOID ResetNewFixation(void)
/* This function resets the new fixation, i.e. declares it nonexistent. */
{
new_fix_start_count = 0;
new_fix_end_count = 0;
n_new_fix_samples = 0;
x_new_fix_sum = 0.0F;
y_new_fix_sum = 0.0F;
x_new_fix = 0.0F;
y_new_fix = 0.0F;
}
/****************************************************************************/
SVOID StartPresFixAtGazepoint(float x_gaze, float y_gaze)
/* This function starts the present fixation at the argument gazepoint */
/* and makes sure there is no new fixation hypothesis. */
{
/* Start the present fixation at the argument gazepoint. */
iNPresFixSamples = 1;
fXPresFixSum = x_gaze;
fYPresFixSum = y_gaze;
fXPresFix = x_gaze;
fYPresFix = y_gaze;
lPresFixStartCount = lCallCount;
lPresFixEndCount = lCallCount;
iNPresOut = 0;
/* Make sure there is no new fixation. */
ResetNewFixation();
}
/****************************************************************************/
SVOID StartNewFixAtGazepoint(float x_gaze, float y_gaze)
/* This function starts the new fixation at the argument gazepoint. */
{
n_new_fix_samples = 1;
x_new_fix_sum = x_gaze;
y_new_fix_sum = y_gaze;
x_new_fix = x_gaze;
y_new_fix = y_gaze;
new_fix_start_count = lCallCount;
new_fix_end_count = lCallCount;
}
/****************************************************************************/
SVOID UpdatePresFixation(float x_gaze, float y_gaze, int minimum_fix_samples)
/* This function updates the present fixation with the argument gazepoint, */
/* checks if there are enough samples to declare that the eye is now */
/* fixating, and makes sure there is no hypothesis for a new fixation. */
{
/* Update the present fixation with the argument gazepoint. */
iNPresFixSamples++;
fXPresFixSum += x_gaze;
fYPresFixSum += y_gaze;
fXPresFix = fXPresFixSum / iNPresFixSamples;
fYPresFix = fYPresFixSum / iNPresFixSamples;
lPresFixEndCount = lCallCount;
iNPresOut = 0;
/* Check if there are enough samples in the present fixation hypothesis */
/* to declare that the eye is fixating. */
CheckIfFixating(minimum_fix_samples);
/* There is no hypothesis for a new fixation. */
ResetNewFixation();
}
/****************************************************************************/
SVOID UpdateNewFixation(float x_gaze, float y_gaze)
/* This function updates the new fixation with the argument gazepoint. */
{
/* Update the new fixation with the argument gazepoint. */
n_new_fix_samples++;
x_new_fix_sum += x_gaze;
y_new_fix_sum += y_gaze;
x_new_fix = x_new_fix_sum / n_new_fix_samples;
y_new_fix = y_new_fix_sum / n_new_fix_samples;
new_fix_end_count = lCallCount;
}
/****************************************************************************/
SVOID CalcGazeDeviationFromPresFix(float x_gaze, float y_gaze)
/* This function calculates the deviation of the gazepoint from the */
/* present fixation location. */
{
float dx, dy; /* horizontal and vertical deviations */
dx = x_gaze - fXPresFix;
dy = y_gaze - fYPresFix;
fPresDr = (float)sqrt(dx * dx + dy * dy);
/* Put the deviation in the ring buffer for future reference. */
gaze_deviation_ring[iRingIndex] = fPresDr;
}
/****************************************************************************/
SVOID CalcGazeDeviationFromNewFix(float x_gaze, float y_gaze)
/* This function calculate the deviation of the gazepoint from the new */
/* fixation location. */
{
float dx, dy; /* horizontal and vertical deviations */
dx = x_gaze - x_new_fix;
dy = y_gaze - y_new_fix;
new_dr = (float)sqrt(dx * dx + dy * dy);
}
/****************************************************************************/
SVOID CheckIfFixating(int minimum_fix_samples)
/* This function checks to see whether there are enough samples in the */
/* presently hypothesized fixation to declare that the eye is fixating */
/* yet, and if there is a true fixation going on, it updates the ring */
/* buffers to reflect the fixation. */
{
int i, ii; /* dummy ring indices */
/* If there are enough samples for a fixation, */
if (iNPresFixSamples >= minimum_fix_samples)
{
/* Declare the eye to be fixating. Go back through the last */
/* minimum_fix_samples entries of the ring buffer making sure that all */
/* samples from the present fixation are marked as fixating, and set */
/* the entries with the newest estimate of the fixation location. */
for (i = 0; i < minimum_fix_samples; i++)
{
ii = iRingIndex - i;
if (ii < 0) ii += RING_SIZE;
eye_motion_state[ii] = FIXATING;
x_fix_ring[ii] = fXPresFix;
y_fix_ring[ii] = fYPresFix;
sac_duration_ring[ii] = (int)(lPresFixStartCount -
lPrevFixEndCount - 1);
fix_duration_ring[ii] = (int)(lPresFixEndCount -
lPresFixStartCount + 1 - i);
}
}
}
/****************************************************************************/
SVOID MoveNewFixToPresFix(int minimum_fix_samples)
/* This function copies the new fixation data into the present fixation, */
/* and resets the new fixation. */
{
/* Move the new fixation to the present fixation. */
iNPresFixSamples = n_new_fix_samples;
fXPresFixSum = x_new_fix_sum;
fYPresFixSum = y_new_fix_sum;
fXPresFix = x_new_fix;
fYPresFix = y_new_fix;
lPresFixStartCount = new_fix_start_count;
lPresFixEndCount = new_fix_end_count;
iNPresOut = 0;
/* Reset the new fixation. */
ResetNewFixation();
/* Check if there are enough samples in the new (now present) fixation to */
/* declare that the eye is fixating. */
CheckIfFixating(minimum_fix_samples);
}
/****************************************************************************/
SVOID DeclareCompletedFixation(int minimum_fix_samples)
/* This function: */
/* a) declares the present fixation to be completed, */
/* b) moves the present fixation to the prior fixation, */
/* c) moves the new fixation, if any, to the present fixation, and */
{
/* Declare the present fixation to be completed. */
eye_motion_state[iRingIndexDelay] = FIXATION_COMPLETED;
/* Move the present fixation to the previous fixation. This saves the */
/* end time of the present fixation for later computation of the saccade */
/* period between this and the next fixation. */
lPrevFixEndCount = lPresFixEndCount;
/* Move the new fixation data, if any, to the present fixation, reset */
/* the new fixation, and check if there are enough samples in the new */
/* (now present) fixation to declare that the eye is fixating. */
MoveNewFixToPresFix(minimum_fix_samples);
}
/****************************************************************************/
SVOID RestoreOutPoints(void)
/* This function restores any previous gazepoints that were left out of */
/* the fixation and are now known to be part of the present fixation. */
{
int i, ii; /* dummy ring indices */
/* If there were some previous points that temporarily went out of the */
/* fixation region, */
if (iNPresOut > 0)
{
/* Undo the hypothesis that they were outside the fixation and declare */
/* them now to be part of the fix. */
for (i = 1; i <= iNPresOut; i++)
{
ii = iRingIndex - i;
if (ii < 0) ii += RING_SIZE;
if (gaze_found_ring[ii] == TRUE)
{
iNPresFixSamples++;
fXPresFixSum += x_gaze_ring[ii];
fYPresFixSum += y_gaze_ring[ii];
eye_motion_state[ii] = FIXATING;
}
}
/* Set the number of "out" points to be zero. */
iNPresOut = 0;
}
}
/****************************************************************************/
© 2003, LC Technologies, Inc. All rights reserved