Пример #1
0
        /// <summary>
        /// Determine what ratio amounts to a given pixel distance
        /// </summary>
        /// <param name="p_points">
        /// A <see cref="Point"/> array of 4 points specifying the Bezier curve to analyze
        /// </param>
        /// <param name="p_pixels">
        /// A <see cref="System.Int32"/> indicating how many pixels the returned ratio should indicate
        /// </param>
        /// <returns>
        /// A <see cref="System.Double"/> representing the ratio on the curve that amounts to p_pixels distance
        /// </returns>
        static public double CalculateRatioSizeToPixelAccuracy(Point [] p_points, int p_pixels)
        {
            if (p_points.Length != 4)
            {
                throw new Exception("p_points array passed to GetRatioSizeToPixelAccuracy must have exactly 4 items, this one has " + p_points.Length);
            }

            double testRatio = 1.0d;
            PointF prevPoint = BezierSprite.CalculatePoint(p_points, 0.0d);

            // first cut test ratio in half repeatedly until we fall below the requested
            // pixel threshold, then increment the ratio back up by .01 until we hit the
            // threshold again.
            while (true)
            {
                testRatio /= 2.0d;
                PointF nextPoint = BezierSprite.CalculatePoint(p_points, testRatio);

                if (BezierSprite.Hypot(prevPoint, nextPoint) < p_pixels)
                {
                    while (true)
                    {
                        testRatio += 0.01d;
                        PointF nextPoint2 = BezierSprite.CalculatePoint(p_points, testRatio);
                        if (BezierSprite.Hypot(prevPoint, nextPoint2) > p_pixels)
                        {
                            break;
                        }
                    }
                    break;
                }
            }

            return(testRatio);
        }
Пример #2
0
        /// <summary>
        /// Returns the sprites next position on the path using the following formula:
        ///
        /// Bx(t) = (1-t)^3  x P1x + 3 x (1-t)^2 x t x P2x + 3 x (1-t) x t^2 x P3x + t^3 x P4x
        /// By(t) = (1-t)^3  x P1y + 3 x (1-t)^2 x t x P2y + 3 x (1-t) x t^2 x P3y + t^3 x P4y
        ///
        /// http://upload.wikimedia.org/math/2/d/5/2d5e5d58562d8ec2c35f16df98d2b974.png
        /// B(t)=(1-t)^2)*p0 + 2(1-t)*t*p1 + t^2(p2)
        /// quadratic: http://upload.wikimedia.org/wikipedia/commons/b/bf/Bezier_2_big.png
        /// cubic: http://upload.wikimedia.org/wikipedia/commons/c/c1/Bezier_3_big.png
        /// </summary>
        /// <returns>Point indicating next position of sprite</returns>
        protected override Point GetNewPosition()
        {
            currentPoint =
                BezierSprite.CalculatePoint(
                    points.GetRange(segmentIndex * 3, 4).ToArray(),
                    ratio
                    );

            // if approaching end of current curve, then get pre-calculated angle
            if ((1.0d - ratio) < ratioStep)
            {
                tangentAngle = lengthRatios[segmentIndex].endTangent;
            }
            else
            if (ratio < ratioStep)             // if just past the start of next curve, then use pre-calculated angle
            {
                tangentAngle = lengthRatios[segmentIndex].startTangent;
            }
            else             // else get angle along the curve based on ratio
            {
                tangentAngle = CalculateTangentAngle(points.GetRange(segmentIndex * 3, 4).ToArray(), ratio, currentPoint);
            }
//Console.WriteLine("tangentAngle={0}, seg={1}, ratio={2}", tangentAngle, segmentIndex, ratio);
            ratio = (double)(ratio + ratioStep);

            if (ratio > 1.0d)
            {
                ratio -= 1.0d;
                segmentIndex++;
                if (segmentIndex >= segmentCount)
                {
                    if (remainingLoops != -1)
                    {
                        if (--remainingLoops > 0)
                        {
                            segmentIndex = 0;
                        }
                        else
                        {
                            completed = true;
                        }
                    }
                    else
                    {
                        segmentIndex = 0;
                    }

                    loopCount++;
                }
                else
                {
                    ratioStep = lengthRatios[segmentIndex].ratio;
                }
            }

            return(new Point((int)Math.Round(currentPoint.X), (int)Math.Round(currentPoint.Y)));
        }