示例#1
0
        // </Snippet_GamePiece_OnManipulationDelta>

        // <Snippet_GamePiece_OnManipulationCompleted>
        #region OnManipulationCompleted
        private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            inertiaProcessor.TranslationBehavior.InitialVelocityX = e.Velocities.LinearVelocityX;
            inertiaProcessor.TranslationBehavior.InitialVelocityY = e.Velocities.LinearVelocityY;
            inertiaProcessor.RotationBehavior.InitialVelocity     = e.Velocities.AngularVelocity;
            processInertia = true;
        }
示例#2
0
        private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            // Manipulation portion completed.

            if (_manualComplete && !_manualCompleteWithInertia)
            {
                // This is the last event in the sequence.

                ManipulationCompletedEventArgs completedArguments = ConvertCompletedArguments(e);
                RaiseManipulationCompleted(completedArguments);
            }
            else
            {
                // This event will configure inertia, which will start after this event.

                _lastManipulationBeforeInertia = ConvertDelta(e.Total, null);

                ManipulationInertiaStartingEventArgs inertiaArguments = new ManipulationInertiaStartingEventArgs(
                    _manipulationDevice,
                    LastTimestamp,
                    _currentContainer,
                    new Point(e.OriginX, e.OriginY),
                    ConvertVelocities(e.Velocities),
                    false);

                PushEvent(inertiaArguments);
            }

            _manipulationProcessor = null;
        }
        /// <summary>
        /// Here when manipulation completes.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            ScreenMessage("Manipulation Completed");
            dragCenter = new Point(double.NaN, double.NaN);

            float velocityX    = e.Velocities.LinearVelocityX;
            float velocityY    = e.Velocities.LinearVelocityY;
            float speedSquared = velocityX * velocityX + velocityY * velocityY;

            if (speedSquared < minLinearFlickVelocity * minLinearFlickVelocity)
            {
                velocityX = velocityY = 0;
            }

            inertiaProcessor.TranslationBehavior.InitialVelocityX = velocityX;
            inertiaProcessor.TranslationBehavior.InitialVelocityY = velocityY;
            inertiaProcessor.RotationBehavior.InitialVelocity     = 0.1016f; // e.Velocities.AngularVelocity;

            inertiaProcessor.RotationBehavior.DesiredDeceleration = 0.0000065f;

            SetDesiredRotation(inertiaProcessor);

            inertiaProcessor.RotationBehavior.DesiredRotation = (float)Math.PI * 7.0f;

            inertiaProcessor.ExpansionBehavior.InitialVelocityX = 5.7f; // e.Velocities.ExpansionVelocityX;
            inertiaProcessor.ExpansionBehavior.InitialVelocityY = 5.7f; // e.Velocities.ExpansionVelocityY;
            inertiaProcessor.ExpansionBehavior.InitialRadius    = 11.0f;

            //inertiaProcessor.ExpansionBehavior.InitialVelocityX = 0.05f;
            //inertiaProcessor.ExpansionBehavior.InitialVelocityY = 0.05f;
            //inertiaProcessor.RotationBehavior.DesiredRotation = 55.6f;

            //inertiaProcessor.InitialRadius = (float)Radius;
            inertiaTimer.Start();
        }
示例#4
0
        private void OnInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            // Inertia portion completed.

            ClearTimer();

            if (_manualComplete && _manualCompleteWithInertia)
            {
                // Another inertia portion was requested

                _lastManipulationBeforeInertia = ConvertDelta(e.Total, _lastManipulationBeforeInertia);

                ManipulationInertiaStartingEventArgs inertiaArguments = new ManipulationInertiaStartingEventArgs(
                    _manipulationDevice,
                    LastTimestamp,
                    _currentContainer,
                    new Point(e.OriginX, e.OriginY),
                    ConvertVelocities(e.Velocities),
                    true);

                PushEvent(inertiaArguments);
            }
            else
            {
                // This is the last event in the sequence.

                ManipulationCompletedEventArgs completedArguments = ConvertCompletedArguments(e);

                RaiseManipulationCompleted(completedArguments);
            }

            _inertiaProcessor = null;
        }
示例#5
0
        private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e) 
        {
            // Manipulation portion completed.

            if (_manualComplete && !_manualCompleteWithInertia) 
            {
                // This is the last event in the sequence. 
 
                ManipulationCompletedEventArgs completedArguments = ConvertCompletedArguments(e);
                RaiseManipulationCompleted(completedArguments); 
            }
            else
            {
                // This event will configure inertia, which will start after this event. 

                _lastManipulationBeforeInertia = ConvertDelta(e.Total, null); 
 
                ManipulationInertiaStartingEventArgs inertiaArguments = new ManipulationInertiaStartingEventArgs(
                    _manipulationDevice, 
                    LastTimestamp,
                    _currentContainer,
                    new Point(e.OriginX, e.OriginY),
                    ConvertVelocities(e.Velocities), 
                    false);
 
                PushEvent(inertiaArguments); 
            }
 
            _manipulationProcessor = null;
        }
示例#6
0
 /// <summary>
 ///     Converts an Affine2DOperationCompletedEventArgs object into a ManipulationCompletedEventArgs object.
 /// </summary>
 private ManipulationCompletedEventArgs ConvertCompletedArguments(Manipulation2DCompletedEventArgs e)
 {
     return(new ManipulationCompletedEventArgs(
                _manipulationDevice,
                LastTimestamp,
                _currentContainer,
                new Point(e.OriginX, e.OriginY),
                ConvertDelta(e.Total, _lastManipulationBeforeInertia),
                ConvertVelocities(e.Velocities),
                IsInertiaActive));
 }
        /// <summary>
        /// When the manipulation is completed, either spring the content back into bounds, or begin inertia.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ManipulationCompletedEventArgs"/> instance containing the event data.</param>
        private void ContentManipulationProcessor_Affine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            if (Spring())
            {
                return;
            }

            return;
            //// TODO Figure out inertia
            _inertiaProcessor.TranslationBehavior.InitialVelocityX = e.Velocities.LinearVelocityX;
            _inertiaProcessor.TranslationBehavior.InitialVelocityY = e.Velocities.LinearVelocityY;
            _inertiaTimer.Start();
        }
示例#8
0
        private void OnInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
        { 
            // Inertia portion completed.
 
            ClearTimer(); 

            if (_manualComplete && _manualCompleteWithInertia) 
            {
                // Another inertia portion was requested

                _lastManipulationBeforeInertia = ConvertDelta(e.Total, _lastManipulationBeforeInertia); 

                ManipulationInertiaStartingEventArgs inertiaArguments = new ManipulationInertiaStartingEventArgs( 
                    _manipulationDevice, 
                    LastTimestamp,
                    _currentContainer, 
                    new Point(e.OriginX, e.OriginY),
                    ConvertVelocities(e.Velocities),
                    true);
 
                PushEvent(inertiaArguments);
            } 
            else 
            {
                // This is the last event in the sequence. 

                ManipulationCompletedEventArgs completedArguments = ConvertCompletedArguments(e);

                RaiseManipulationCompleted(completedArguments); 
            }
 
            _inertiaProcessor = null; 
        }
示例#9
0
        /// <summary>
        /// Start the inertia processor in Surface screen space.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAffine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            if (inertiaProcessor != null)
            {
                inertiaProcessor.Delta -= OnAffine2DInertiaDelta;
                inertiaProcessor.Completed -= OnAffine2DInertiaCompleted;
                inertiaProcessor.Complete(stopwatch.Elapsed100Nanoseconds());
            }

            VectorF translation = new VectorF(e.Total.TranslationX, e.Total.TranslationY);

            // Don't start inertia if the tranlation is less than roughly 1/8" regardless of velocity.
            if (translation.Length < 96 / 8f)
            {
                return;
            }

            // Scroll in the opposite direction because a ScrollViewer moves with the touch.
            VectorF initialVelocity = new VectorF(-e.Velocities.LinearVelocityX, -e.Velocities.LinearVelocityY);

            // Check velocity.
            if (initialVelocity.Length < FlickUtilities.MinimumFlickVelocity)
            {
                // If velocity is below this threshold ignore it.
                return;
            }
            
            if (initialVelocity.Length >= FlickUtilities.MaximumFlickVelocity)
            {
                // If velocity is too large, reduce it to a reasonable value.
                initialVelocity.Normalize();
                initialVelocity = FlickUtilities.MaximumFlickVelocity * initialVelocity;
            }

            processInertia = true;
            inertiaProcessor = new InertiaProcessor2D();

            inertiaProcessor.Delta += OnAffine2DInertiaDelta;
            inertiaProcessor.Completed += OnAffine2DInertiaCompleted;
            inertiaProcessor.TranslationBehavior = new InertiaTranslationBehavior2D
            {
                DesiredDisplacement = ConvertFromVerticalValueToScreenSpace(VerticalViewportSize),
                InitialVelocityX = initialVelocity.X * HorizontalViewportSize,
                InitialVelocityY = initialVelocity.Y * VerticalViewportSize
            };

            inertiaProcessor.InitialOriginX = ConvertFromHorizontalValueToScreenSpace(horizontalScrollBarStateMachine.Value);
            inertiaProcessor.InitialOriginY = ConvertFromVerticalValueToScreenSpace(verticalScrollBarStateMachine.Value);
        }
示例#10
0
 /// <summary>
 /// Inertia is complete so stop processing for it.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void OnAffine2DInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
 {
     processInertia = false;
 }
示例#11
0
 //==========================================================//
 /// <summary>
 /// Event handler for the inertia processor's complete event.
 /// Occurs whenever the item comes to rest after being flicked.
 /// </summary>
 /// <param name="sender">The inertia processor that raised the event.</param>
 /// <param name="e">The event args for the event.</param>
 private void OnAffine2DInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
 {
     extrapolating = false;
 }
示例#12
0
 /// <summary>
 /// Here when manipulation completes.
 /// </summary>
 private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
 {
 }
        /// <summary>
        /// Set the flick to completed so that it stops moving.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void OnAffine2DInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            processInertia = false;
            manipulationProcessor = null;

            if (inertiaProcessor != null)
            {
                inertiaProcessor.Delta -= OnAffine2DInertiaDelta;
                inertiaProcessor.Completed -= OnAffine2DInertiaCompleted;
                inertiaProcessor = null;
            }

        }
示例#14
0
        //==========================================================//
        /// <summary>
        /// Event handler for the manipulation processor's completed event. 
        /// Occurs whenever the manipulation processor processes manipulator 
        /// data where all remaining contacts have been removed.
        /// Check final deltas and start the inertia processor if they are high enough.
        /// </summary>
        /// <param name="sender">The manipulation processor that raised the event.</param>
        /// <param name="e">The event args for the event.</param>
        private void OnAffine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            // manipulation completed
            manipulating = false;

            // Get the inital inertia values
            Vector2 initialVelocity = new Vector2(e.Velocities.LinearVelocityX, e.Velocities.LinearVelocityY);
            float angularVelocity = e.Velocities.AngularVelocity;
            float expansionVelocity = e.Velocities.ExpansionVelocityX;

            bool startFlick = false;
           
            // Rotate and scale around the center of the item
            inertiaProcessor.InitialOriginX = TransformedCenter.X;
            inertiaProcessor.InitialOriginY = TransformedCenter.Y;

            // set initial velocity if translate flicks are allowed
            if (canTranslateFlick && initialVelocity.LengthSquared() > MinimumFlickVelocity * MinimumFlickVelocity)
            {
                startFlick = true;
                inertiaProcessor.TranslationBehavior.InitialVelocityX = initialVelocity.X;
                inertiaProcessor.TranslationBehavior.InitialVelocityY = initialVelocity.Y;
                inertiaProcessor.TranslationBehavior.DesiredDeceleration = Deceleration;
            }
            else
            {
                inertiaProcessor.TranslationBehavior.InitialVelocityX = 0.0f;
                inertiaProcessor.TranslationBehavior.InitialVelocityY = 0.0f;
                inertiaProcessor.TranslationBehavior.DesiredDeceleration = 0.0f;
            }

            // set angular velocity if rotation flicks are allowed
            if (canRotateFlick && Math.Abs(angularVelocity) >= MinimumAngularFlickVelocity)
            {
                startFlick = true;
                inertiaProcessor.RotationBehavior.InitialVelocity = angularVelocity;
                inertiaProcessor.RotationBehavior.DesiredDeceleration = AngularDeceleration;
            }
            else
            {
                inertiaProcessor.RotationBehavior.InitialVelocity = 0.0f;
                inertiaProcessor.RotationBehavior.DesiredDeceleration = 0.0f;
            }

            // set expansion velocity if scale flicks are allowed
            if (canScaleFlick && Math.Abs(expansionVelocity) >= MinimumExpansionFlickVelocity)
            {
                startFlick = true;
                inertiaProcessor.ExpansionBehavior.InitialVelocityX = expansionVelocity;
                inertiaProcessor.ExpansionBehavior.InitialVelocityY = expansionVelocity;
                inertiaProcessor.ExpansionBehavior.InitialRadius = 
                    0.25f * (AxisAlignedBoundingRectangle.Width + AxisAlignedBoundingRectangle.Height);
                inertiaProcessor.ExpansionBehavior.DesiredDeceleration = ExpansionDeceleration;
            }
            else
            {
                inertiaProcessor.ExpansionBehavior.InitialVelocityX = 0.0f;
                inertiaProcessor.ExpansionBehavior.InitialVelocityY = 0.0f;
                inertiaProcessor.ExpansionBehavior.InitialRadius = 1.0f;
                inertiaProcessor.ExpansionBehavior.DesiredDeceleration = 0.0f;
            }

            if (startFlick)
            {
                extrapolating = true;
            }
        }
        /// <summary>
        /// When the manipulation is completed, either spring the content back into bounds, or begin inertia.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ManipulationCompletedEventArgs"/> instance containing the event data.</param>
        private void ContentManipulationProcessor_Affine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            if (Spring())
            {
                return;
            }

            return;

            //// TODO Figure out inertia
            _inertiaProcessor.TranslationBehavior.InitialVelocityX = e.Velocities.LinearVelocityX;
            _inertiaProcessor.TranslationBehavior.InitialVelocityY = e.Velocities.LinearVelocityY;
            _inertiaTimer.Start();
        }
        //==========================================================//
        /// <summary>
        /// Event handler for the manipulation processor's completed event. 
        /// Occurs whenever the manipulation processor processes manipulator 
        /// data where all remaining touches have been removed.
        /// Check final deltas and start the inertia processor if they are high enough
        /// </summary>
        /// <param name="sender">The manipulation processor that raised the event</param>
        /// <param name="e">The event args for the event</param>
        private void OnAffine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            // manipulation completed
            manipulating = false;

            // Get the inital inertia values
            Vector2 initialVelocity = new Vector2(e.Velocities.LinearVelocityX, e.Velocities.LinearVelocityY);
            float angularVelocity = e.Velocities.AngularVelocity;
            // Scale is constrained (ScaleX==ScaleY), just use X
            float expansionVelocity = e.Velocities.ExpansionVelocityX;

            // Calculate the deceleration rates

            // 4 inches/second squared (4 inches * 96 pixels per inch / (10000000 ticks per second)^2)
            const float deceleration = 4.0f * 96.0f / (10000000.0f * 10000000.0f);
            const float expansionDeceleration = 4.0f * 96.0f / (10000000.0f * 10000000.0f);

            // 90 degrees/second squared, specified in radians (1/2 * pi / (1000 miliseconds per second)^2)
            const float angularDeceleration = 90.0f / 180.0f * (float)Math.PI / (10000000.0f * 10000000.0f);

            // Start inertia
            inertiaProcessor.InitialOriginX = e.OriginX;
            inertiaProcessor.InitialOriginY = e.OriginY;

            // set initial velocity if translate flicks are allowed
            if (canTranslateFlick)
            {
                inertiaProcessor.TranslationBehavior = new InertiaTranslationBehavior2D
                {
                    InitialVelocityX = initialVelocity.X,
                    InitialVelocityY = initialVelocity.Y,
                    DesiredDeceleration = deceleration
                };
            }
            else
            {
                inertiaProcessor.TranslationBehavior = new InertiaTranslationBehavior2D
                {
                    InitialVelocityX = 0.0f,
                    InitialVelocityY = 0.0f,
                    DesiredDeceleration = 0.0f
                };
            }


            // set expansion velocity if scale flicks are allowed
            if (!IsZero(expansionVelocity) && canScaleFlick)
            {
                inertiaProcessor.ExpansionBehavior = new InertiaExpansionBehavior2D
                {
                    InitialVelocityX = expansionVelocity,
                    InitialVelocityY = expansionVelocity,
                    InitialRadius = (ActualSize.X / 2f + ActualSize.Y / 2f) / 2f,
                    DesiredDeceleration = expansionDeceleration
                };
            }
            else
            {
                inertiaProcessor.ExpansionBehavior = new InertiaExpansionBehavior2D
                {
                    InitialVelocityX = 0.0f,
                    InitialVelocityY = 0.0f,
                    InitialRadius = 1.0f,
                    DesiredDeceleration = 0.0f
                };
            }


            // set angular velocity if rotation flicks are allowed
            if (!IsZero(angularVelocity) && canRotateFlick)
            {
                inertiaProcessor.RotationBehavior = new InertiaRotationBehavior2D
                {
                    InitialVelocity = angularVelocity,
                    DesiredDeceleration = angularDeceleration
                };
            }
            else
            {
                inertiaProcessor.RotationBehavior = new InertiaRotationBehavior2D
                {
                    InitialVelocity = 0.0f,
                    DesiredDeceleration = 0.0f
                };
            }
   
            extrapolating = true;

        }
示例#17
0
        // </Snippet_GamePiece_OnInertiaDelta>

        // <Snippet_GamePiece_OnInertiaCompleted>
        #region OnInertiaCompleted
        private void OnInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            processInertia = false;
        }
        /// <summary>
        /// Here when manipulation completes.
        /// </summary>
        private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            // Get the inital inertia values
            var   initialVelocity   = new Vector(e.Velocities.LinearVelocityX, e.Velocities.LinearVelocityY);
            float angularVelocity   = e.Velocities.AngularVelocity;
            float expansionVelocity = e.Velocities.ExpansionVelocityX;

            bool startFlick = false;

            // Rotate and scale around the center of the item
            _inertiaProcessor.InitialOriginX = (float)_center.X;
            _inertiaProcessor.InitialOriginY = (float)_center.Y;

            // set initial velocity if translate flicks are allowed
            double velocityLengthSquared = initialVelocity.LengthSquared;

            if (IsTranslateEnabled && velocityLengthSquared > MinimumFlickVelocity * MinimumFlickVelocity)
            {
                const double maximumLengthSquared = MaximumFlickVelocityFactor * MinimumFlickVelocity * MinimumFlickVelocity;
                if (velocityLengthSquared > maximumLengthSquared)
                {
                    initialVelocity = Math.Sqrt(maximumLengthSquared / velocityLengthSquared) * initialVelocity;
                }

                startFlick = IsInertiaEnabled;
                _inertiaProcessor.TranslationBehavior.InitialVelocityX = (float)initialVelocity.X;
                _inertiaProcessor.TranslationBehavior.InitialVelocityY = (float)initialVelocity.Y;
            }
            else
            {
                _inertiaProcessor.TranslationBehavior.InitialVelocityX = 0.0f;
                _inertiaProcessor.TranslationBehavior.InitialVelocityY = 0.0f;
            }

            // set angular velocity if rotation flicks are allowed
            if (Math.Abs(angularVelocity) >= MinimumAngularFlickVelocity)
            {
                const float maximumAngularFlickVelocity = MaximumFlickVelocityFactor * MinimumAngularFlickVelocity;
                if (Math.Abs(angularVelocity) > maximumAngularFlickVelocity)
                {
                    angularVelocity = angularVelocity > 0 ? maximumAngularFlickVelocity : -maximumAngularFlickVelocity;
                }
                startFlick = IsInertiaEnabled;
                _inertiaProcessor.RotationBehavior.InitialVelocity = angularVelocity;
            }
            else
            {
                _inertiaProcessor.RotationBehavior.InitialVelocity = 0.0f;
            }

            // set expansion velocity if scale flicks are allowed
            if (IsScaleEnabled && Math.Abs(expansionVelocity) >= MinimumExpansionFlickVelocity)
            {
                const float maximumExpansionFlickVelocity = MaximumFlickVelocityFactor * MinimumExpansionFlickVelocity;
                if (Math.Abs(expansionVelocity) >= maximumExpansionFlickVelocity)
                {
                    expansionVelocity = expansionVelocity > 0 ? maximumExpansionFlickVelocity : -maximumExpansionFlickVelocity;
                }
                startFlick = IsInertiaEnabled;
                _inertiaProcessor.ExpansionBehavior.InitialVelocityX = expansionVelocity;
                _inertiaProcessor.ExpansionBehavior.InitialVelocityY = expansionVelocity;
                _inertiaProcessor.ExpansionBehavior.InitialRadius    = (float)_radius;
            }
            else
            {
                _inertiaProcessor.ExpansionBehavior.InitialVelocityX = 0.0f;
                _inertiaProcessor.ExpansionBehavior.InitialVelocityY = 0.0f;
                _inertiaProcessor.ExpansionBehavior.InitialRadius    = 1.0f;
            }

            if (startFlick)
            {
                _inertiaTimer.Start();
            }
        }
 /// <summary>
 /// Here when inertia completes.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void OnInertiaCompleted(object sender, Manipulation2DCompletedEventArgs e)
 {
     inertiaTimer.Stop();
 }
示例#20
0
 /// <summary>
 /// Unused
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void OnAffine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
 {
 }
示例#21
0
 /// <summary>
 ///     Converts an Affine2DOperationCompletedEventArgs object into a ManipulationCompletedEventArgs object.
 /// </summary> 
 private ManipulationCompletedEventArgs ConvertCompletedArguments(Manipulation2DCompletedEventArgs e)
 { 
     return new ManipulationCompletedEventArgs( 
         _manipulationDevice,
         LastTimestamp, 
         _currentContainer,
         new Point(e.OriginX, e.OriginY),
         ConvertDelta(e.Total, _lastManipulationBeforeInertia),
         ConvertVelocities(e.Velocities), 
         IsInertiaActive);
 } 
示例#22
0
 /// <summary>
 /// Here when manipulation completes.
 /// </summary>
 private void OnManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
 {
     Utils.ResetCompositeTransformCenter(AssociatedObject, _initialCenter);
 }
        /// <summary>
        /// Start the flicking behavior. 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAffine2DManipulationCompleted(object sender, Manipulation2DCompletedEventArgs e)
        {
            if (inertiaProcessor != null)
            {
                inertiaProcessor.Delta -= OnAffine2DInertiaDelta;
                inertiaProcessor.Completed -= OnAffine2DInertiaCompleted;
                inertiaProcessor = null;
            }

            // The Manipulations should all run in screen space so don't convert between spaces.
            VectorF initialVelocity;
            VectorF maxViewPortSize;
            if (Orientation == Orientation.Horizontal)
            {
                initialVelocity = new VectorF(e.Velocities.LinearVelocityX, 0);
                maxViewPortSize = new VectorF(numberOfPixelsInAxis * viewportSize, 0);
            }
            else
            {
                initialVelocity = new VectorF(0, e.Velocities.LinearVelocityY);
                maxViewPortSize = new VectorF(0, numberOfPixelsInAxis * viewportSize);
            }

            // Check velocity.
            if (initialVelocity.Length < FlickUtilities.MinimumFlickVelocity)
            {
                return;
            }

            if (initialVelocity.Length >= MaximumFlickVelocity)
            {
                // If velocity is too large, reduce it to a reasonable value.
                initialVelocity.Normalize();
                initialVelocity = MaximumFlickVelocity * initialVelocity;
            }

            VectorF flickDistance;

            if (FlickUtilities.TryGetFlickDistance(initialVelocity, out flickDistance, maxViewPortSize))
            {
                processInertia = true;
                inertiaProcessor = new InertiaProcessor2D();

                inertiaProcessor.Delta += OnAffine2DInertiaDelta;
                inertiaProcessor.Completed += OnAffine2DInertiaCompleted;

                float displacement = 0;

                if (flickDistance.X == 0)
                {
                    displacement = flickDistance.Y;
                }
                else if (flickDistance.Y == 0)
                {
                    displacement = flickDistance.X;
                }
                else
                {
                    displacement = Math.Min(flickDistance.X, flickDistance.Y);
                }

                inertiaProcessor.TranslationBehavior = new InertiaTranslationBehavior2D
                {
                    DesiredDisplacement = float.IsInfinity(displacement) ? 0 : Math.Abs(displacement),
                    InitialVelocityX = initialVelocity.X,
                    InitialVelocityY = initialVelocity.Y
                };

                inertiaProcessor.InitialOriginX = ToScreenSpace(Value);
                inertiaProcessor.InitialOriginY = ToScreenSpace(Value);
            }
        }