Exemple #1
0
 /// <summary>
 /// Calculates the determinant of two vectors.
 /// </summary>
 /// <param name="vector1">The first vector to evaluate.</param>
 /// <param name="vector2">The second vector to evaluate.</param>
 /// <returns>The determinant of vector1 and vector2.</returns>
 public static float Determinant(VectorF vector1, VectorF vector2)
 {
     // In the case of two 2D vectors, the determinant is the cross-product.
     return CrossProduct(vector1, vector2);
 }
Exemple #2
0
 /// <summary>
 /// Retrieves the angle, expressed in radians, between the two specified vectors.
 /// </summary>
 /// <param name="vector1">The first vector to evaluate.</param>
 /// <param name="vector2">The second vector to evaluate.</param>
 /// <returns>The angle, in radians, between vector1 and vector2.</returns>
 public static float AngleBetween(VectorF vector1, VectorF vector2)
 {
     vector1.Normalize();
     vector2.Normalize();
     double angle = Math.Atan2(vector2.y, vector2.x) - Math.Atan2(vector1.y, vector1.x);
     if (angle > Math.PI)
     {
         angle -= Math.PI * 2.0;
     }
     else if (angle < -Math.PI)
     {
         angle += Math.PI * 2.0;
     }
     return (float)angle;
 }
Exemple #3
0
 /// <summary>
 /// Calculates the dot product of the two specified vectors and returns the result.
 /// </summary>
 /// <param name="vector1">The first vector to multiply.</param>
 /// <param name="vector2">The second vector structure to multiply.</param>
 /// <returns>The scalar dot product of vector1 and vector2, which is calculated
 /// using the following formula: (vector1.X * vector2.X) + (vector1.Y * vector2.Y)</returns>
 public static float Multiply(VectorF vector1, VectorF vector2)
 {
     return vector1 * vector2;
 }
Exemple #4
0
 /// <summary>
 /// Calculates the cross product of two vectors.
 /// </summary>
 /// <param name="vector1">The first vector to evaluate.</param>
 /// <param name="vector2">The second vector to evaluate.</param>
 /// <returns>The cross product of vector1 and vector2. The following formula is used to
 /// calculate the cross product: (Vector1.X * Vector2.Y) - (Vector1.Y * Vector2.X)</returns>
 public static float CrossProduct(VectorF vector1, VectorF vector2)
 {
     return (vector1.x * vector2.y) - (vector1.y * vector2.x);
 }
Exemple #5
0
 /// <summary>
 /// Multiplies the specified scalar by the specified vector and returns the resulting vector.
 /// </summary>
 /// <param name="vector">The vector to multiply.</param>
 /// <param name="scalar">The scalar to multiply.</param>
 /// <returns>The result of multiplying scalar and vector.</returns>
 public static VectorF Multiply(VectorF vector, float scalar)
 {
     return vector * scalar;
 }
Exemple #6
0
 /// <summary>
 /// Divides the specified vector by the specified scalar and returns the result.
 /// </summary>
 /// <param name="vector">The vector structure to divide.</param>
 /// <param name="scalar">The amount by which vector is divided.</param>
 /// <returns>The result of dividing vector by scalar.</returns>
 public static VectorF Divide(VectorF vector, float scalar)
 {
     return vector / scalar;
 }
Exemple #7
0
 /// <summary>
 /// Subtracts the specified vector from another specified vector.
 /// </summary>
 /// <param name="vector1">The vector from which vector2 is subtracted.</param>
 /// <param name="vector2">The vector to subtract from vector1.</param>
 /// <returns>The difference between vector1 and vector2.</returns>
 public static VectorF Subtract(VectorF vector1, VectorF vector2)
 {
     return vector1 - vector2;
 }
Exemple #8
0
 /// <summary>
 /// Multiplies the specified scalar by the specified vector and returns the resulting vector.
 /// </summary>
 /// <param name="scalar">The scalar to multiply.</param>
 /// <param name="vector">The vector to multiply.</param>
 /// <returns>The result of multiplying scalar and vector.</returns>
 public static VectorF Multiply(float scalar, VectorF vector)
 {
     return scalar * vector;
 }
Exemple #9
0
 /// <summary>
 /// Adds two vectors and returns the result.
 /// </summary>
 /// <param name="vector1">The first vector to add.</param>
 /// <param name="vector2">The second vector to add.</param>
 /// <returns> The sum of vector1 and vector2.</returns>
 public static VectorF Add(VectorF vector1, VectorF vector2)
 {
     return vector1 + vector2;
 }
Exemple #10
0
 /// <summary>
 /// Translates the specified point by the specified vector and returns the resulting point.
 /// </summary>
 /// <param name="vector">The amount to translate the specified point.</param>
 /// <param name="point">The point to translate.</param>
 /// <returns>The result of translating point by vector.</returns>
 public static PointF Add(VectorF vector, PointF point)
 {
     return vector + point;
 }
Exemple #11
0
 /// <summary>
 /// Compares two vectors for equality.
 /// </summary>
 /// <param name="value">The vector to compare with this vector.</param>
 /// <returns>true if value has the same X and Y values as this vector;
 /// otherwise, false.</returns>
 public bool Equals(VectorF value)
 {
     return value == this;
 }
Exemple #12
0
 /// <summary>
 /// Compares the two specified vectors for equality.
 /// </summary>
 /// <param name="vector1">The first vector to compare.</param>
 /// <param name="vector2">The second vector to compare.</param>
 /// <returns>true if the X and Y components of vector1 and vector2 are equal;
 /// otherwise, false.</returns>
 public static bool Equals(VectorF vector1, VectorF vector2)
 {
     return vector1 == vector2;
 }
        /// <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);
        }
        /// <summary>
        /// Start the flicking behavior. 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAffine2DManipulationCompleted(object sender, Affine2DOperationCompletedEventArgs e)
        {
            if (inertiaProcessor != null)
            {
                inertiaProcessor.Affine2DInertiaDelta -= OnAffine2DInertiaDelta;
                inertiaProcessor.Affine2DInertiaCompleted -= 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.VelocityX, 0);
                maxViewPortSize = new VectorF(numberOfPixelsInAxis * viewportSize, 0);
            }
            else
            {
                initialVelocity = new VectorF(0, e.VelocityY);
                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 Affine2DInertiaProcessor();

                inertiaProcessor.Affine2DInertiaDelta += OnAffine2DInertiaDelta;
                inertiaProcessor.Affine2DInertiaCompleted += 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.DesiredDisplacement = float.IsInfinity(displacement) ? 0 : Math.Abs(displacement);
                inertiaProcessor.InitialTimestamp = stopwatch.ElapsedTicks;
                inertiaProcessor.InitialVelocityX = initialVelocity.X;
                inertiaProcessor.InitialVelocityY = initialVelocity.Y;

                inertiaProcessor.InitialOriginX = ToScreenSpace(Value);
                inertiaProcessor.InitialOriginY = ToScreenSpace(Value);
            }
        }
        /// <summary>
        /// Calculates the page size for a flick with a given velocity.
        /// The method chooses vertical or horizontal direction depending on the
        /// given initial velocity.
        /// </summary>
        /// <param name="velocity">flick velocity in device independent units per msec.</param>
        /// <param name="flickDistance">flick page size in device independent units.</param>
        /// <param name="maxViewportSize">The maximum size of the viewport.</param>
        /// <returns></returns>
        public static bool TryGetFlickDistance(VectorF velocity, out VectorF flickDistance, VectorF maxViewportSize)
        {
            Debug.Assert(!float.IsNaN(velocity.X) && !float.IsInfinity(velocity.X), "Cannot start flick with invalid velocity.X");
            Debug.Assert(!float.IsNaN(velocity.Y) && !float.IsInfinity(velocity.Y), "Cannot start flick with invalid velocity.Y");

            // Set the flickDistance to the maximum viewport size.
            flickDistance = maxViewportSize;

            // choose the main direction of the flick based on duration
            float durationX = float.PositiveInfinity;
            float durationY = float.PositiveInfinity;

            if (Math.Abs(velocity.X) > float.Epsilon && !float.IsInfinity(flickDistance.X))
            {
                durationX = GetDurationGivenDistanceAndVelocity(flickDistance.X, velocity.X);
            }

            if (Math.Abs(velocity.Y) > float.Epsilon && !float.IsInfinity(flickDistance.Y))
            {
                durationY = GetDurationGivenDistanceAndVelocity(flickDistance.Y, velocity.Y);
            }

            // choose the minimum duration
            float duration = Math.Min(durationX, durationY);
            if (float.IsInfinity(duration))
            {
                // cannot calculate flick page size
                return false;
            }

            // make sure that duration doesn't exceed MaximumFlickDuration,
            if (duration > MaximumFlickDuration)
            {
                // recalculate duration for the 'flick' direction
                if (durationX <= durationY)
                {
                    // calculate deceleration based on X page size and MaximumFlickDuration
                    Debug.Assert(flickDistance.X > 0);
                    float deceleration = GetDecelerationGivenDistanceAndDuration(flickDistance.X, MaximumFlickDuration);
                    duration = GetDurationGivenVelocityAndDeceleration(velocity.X, deceleration);
                }
                else
                {
                    // calculate deceleration based on Y page size and MaximumFlickDuration
                    Debug.Assert(flickDistance.Y > 0);
                    float deceleration = GetDecelerationGivenDistanceAndDuration(flickDistance.Y, MaximumFlickDuration);
                    duration = GetDurationGivenVelocityAndDeceleration(velocity.Y, deceleration);
                }
                Debug.Assert(duration <= MaximumFlickDuration, "Duration is supposed to be less than MaximumFlickDuration.");
            }

            // adjust the flick distance
            if (duration < durationX)
            {
                flickDistance.X = Math.Abs(GetDistanceGivenVelocityAndDuration(velocity.X, duration));
            }

            if (duration < durationY)
            {
                flickDistance.Y = Math.Abs(GetDistanceGivenVelocityAndDuration(velocity.Y, duration));
            }

            return true;
        }