Пример #1
0
        public RTandInt Interpolate(double[] starttimes, double[] intensities)
        {
            List <double> intensityList  = new List <double>();
            List <double> starttimesList = new List <double>();

            //First step is interpolating a spline, then choosing the pointsat which to add values:
            CubicSpline interpolation = CubicSpline.InterpolateNatural(starttimes, intensities);

            //Now we work out how many to add so we reach at least 100 datapoints and add them:
            double stimesinterval = starttimes.Last() - starttimes[0];
            int    numNeeded      = 100 - starttimes.Count();
            double intervals      = stimesinterval / numNeeded;

            intensityList  = intensities.OfType <double>().ToList();
            starttimesList = starttimes.OfType <double>().ToList();
            for (int i = 0; i < numNeeded; i++)
            {
                double placetobe = starttimes[0] + (intervals * i);

                //insert newIntensity into the correct spot in the array
                for (int currentintensity = 0; currentintensity < 100; currentintensity++)
                {
                    if (starttimesList[currentintensity] < placetobe)
                    {
                        continue;
                    }
                    else
                    {
                        if (currentintensity > 0)
                        {
                            if (starttimesList[currentintensity] == placetobe)
                            {
                                placetobe = placetobe + 0.01;
                            }
                            double newIntensity = interpolation.Interpolate(placetobe);
                            intensityList.Insert(currentintensity, newIntensity);
                            starttimesList.Insert(currentintensity, placetobe);
                        }
                        else
                        {
                            if (starttimesList[currentintensity] == placetobe)
                            {
                                placetobe = placetobe - 0.01;
                            }
                            double newIntensity = interpolation.Interpolate(placetobe);
                            intensityList.Insert(currentintensity, newIntensity);
                            starttimesList.Insert(currentintensity, placetobe);
                        }

                        break;
                    }
                }
            }
            RTandInt ri = new RTandInt();

            ri.intensities = intensityList.Select(item => Convert.ToDouble(item)).ToArray();
            ri.starttimes  = starttimesList.Select(item => Convert.ToDouble(item)).ToArray();

            return(ri);
        }
Пример #2
0
    public void MoveFeetAlongCurve(HumanBodyBones foot, AvatarIKGoal goal, Vector3 currentPosition, float speed)
    {
        var step           = speed * Time.deltaTime;
        var newYlocalValue = (float)curve.Interpolate(localFootProjection.z);

        newGlobalPosition = matrix.MultiplyPoint3x4(new Vector3(0, newYlocalValue, localFootProjection.z));
        // newGlobalPosition = currentPosition;
        // // float yVar = Mathf.Lerp(currentPosition.y, newYGlobalValues.y, 0.5f);

        // newGlobalPosition.y = newYGlobalValues.y;


        var yVar = Mathf.MoveTowards(currentPosition.y, newGlobalPosition.y, step);

        newGlobalPosition.y = yVar;
        _animator.SetIKPositionWeight(goal, 1);
        _animator.SetIKPosition(goal, newGlobalPosition);

        // var currentGlobalPosition = _animator.GetBoneTransform(foot).position;
        // var newYlocalValue = (float)_curve.Interpolate(localFootProjection.z);
        // var newYGlobalValues = matrix.MultiplyPoint3x4(new Vector3(0, newYlocalValue, localFootProjection.z));
        //
        // float yVariable = Mathf.Lerp(prevPositionY, newYGlobalValues.y, 0.5f);
        // currentGlobalPosition.y += yVariable;
        // prevPositionY = yVariable;
        //
        // newGlobalPosition = currentGlobalPosition;
        // newGlobalPosition.y = newYGlobalValues.y;
        // _animator.SetIKPositionWeight(goal, 1);
        // _animator.SetIKPosition(goal, currentGlobalPosition);
    }
Пример #3
0
        private decimal PlotValue(decimal[] DataPoints, decimal Position)
        {
            CubicSpline oCs = CubicSpline.InterpolateNatural(

                DataPoints.Select((s, i2) => new { i2, s })
                .Select(t => Convert.ToDouble(t.i2)).ToArray(),

                DataPoints.Select(s => Convert.ToDouble(s)).ToArray());

            return(Convert.ToDecimal(oCs.Interpolate(Convert.ToDouble(Position))));
        }
Пример #4
0
        public double GetYPoint(double xPoint)
        {
            double y = _interpolator.Interpolate(xPoint);

            if (y > 255)
            {
                return(255);
            }
            if (y < 0)
            {
                return(0);
            }
            return(y);
        }
Пример #5
0
        public void InterpolateCurvePchip()
        {
            List <SensitivityPoint> smoothCurve = new List <SensitivityPoint>();

            double[]    timestamp   = sensCurve.Select(sensCurve => sensCurve.timeStamp).ToArray();
            double[]    randomsense = sensCurve.Select(sensCurve => sensCurve.sensitivity).ToArray();
            CubicSpline spline      = CubicSpline.InterpolatePchip(timestamp, randomsense);

            for (double timecode = 0; timecode < this.lenght; timecode += timestep)
            {
                SensitivityPoint sensPoint = new SensitivityPoint(timecode, spline.Interpolate(timecode));
                smoothCurve.Add(sensPoint);
            }
            sensCurve = smoothCurve;
        }
Пример #6
0
        private void FitSpline(FreeformPointLineSeries fpls)
        {
            m_chart.BeginUpdate();

            int iMarkerCount = fpls.SeriesEventMarkers.Count;

            double[] aMarkerValuesX = new double[iMarkerCount];
            double[] aMarkerValuesY = new double[iMarkerCount];

            for (int i = 0; i < iMarkerCount; i++)
            {
                SeriesEventMarker marker = fpls.SeriesEventMarkers[i];
                aMarkerValuesX[i] = marker.XValue;
                aMarkerValuesY[i] = marker.YValue;
            }

            //One solved point for each pixel in X-dimension

            double[] aXValues = new double[100];
            double   dXMin    = aMarkerValuesX[0];
            double   dXMax    = aMarkerValuesX[iMarkerCount - 1];
            double   dXStep   = (dXMax - dXMin) / (double)(100 - 1);

            for (int i = 0; i < 100; i++)
            {
                aXValues[i] = dXMin + dXStep * (double)i;
            }
            int iOrder = iMarkerCount - 1;

            //double[] aYValues = MathRoutines.PolynomialRegression(aMarkerValuesX, aMarkerValuesY, aXValues, iOrder);


            double[]    aYValues      = new double[100];
            CubicSpline naturalSpline = CubicSpline.InterpolateNatural(aMarkerValuesX, aMarkerValuesY);

            for (int i = 0; i < 100; i++)
            {
                aYValues[i] = naturalSpline.Interpolate(aXValues[i]);
            }
            if (aYValues != null)
            {
                fpls.Clear();
                fpls.AddPoints(aXValues, aYValues, false);
            }
            m_chart.EndUpdate();
        }
Пример #7
0
 /// <summary>Interpolates the specified x.</summary>
 /// <param name="x">The x.</param>
 /// <returns></returns>
 private double Interpolate(double x)
 {
     return(spline.Interpolate(x));
 }
Пример #8
0
 public float GetDragCoefficient(float angleOfAttack)
 {
     return((float)selectedDragInterpolation.Interpolate((double)angleOfAttack));
 }
Пример #9
0
        static double[][] emd(double[] signal, double[][] mods, int calls, int countOfMods)
        {
            if (originalSignal == null)
            {
                originalSignal = signal;
            }
            //int calls = 0;
            double[] mod = new double[signal.Length];
            //  while (calls<=21)
            {
                double[] localMaximums;
                double[] localMinimums;
                double[] indexesOfLocalMaximums;
                double[] indexesOfLocalMinimums;


                FindExtremums(signal, out localMinimums, out localMaximums, out indexesOfLocalMinimums, out indexesOfLocalMaximums);

                if (calls == 100)
                {
                    GC.Collect();
                }
                if (calls > 150 || indexesOfLocalMaximums.Length <= 1 || indexesOfLocalMinimums.Length <= 1)
                {
                    mods[countOfMods] = originalSignal;
                    return(mods);
                }
                double[]  interpMinimums = new double[signal.Length];
                double[]  interpMaximums = new double[signal.Length];
                Stopwatch sss            = new Stopwatch();
                sss.Start();

                // ToFile(localMinimums);
                // ToFile(localMaximums);
                CubicSpline interp = new CubicSpline();
                interp.BuildSpline(indexesOfLocalMinimums, localMinimums, indexesOfLocalMinimums.Length);

                int min = (int)(indexesOfLocalMinimums[0] < indexesOfLocalMaximums[0]
                    ? indexesOfLocalMaximums[0]
                    : indexesOfLocalMinimums[0]);

                int max = (int)(indexesOfLocalMinimums[indexesOfLocalMinimums.Length - 1] > indexesOfLocalMaximums[indexesOfLocalMaximums.Length - 1]
                    ? indexesOfLocalMaximums[indexesOfLocalMaximums.Length - 1]
                    : indexesOfLocalMinimums[indexesOfLocalMinimums.Length - 1]);
                double[] difference = new double[max - min];
                for (int interpolatedX = min; interpolatedX < max; interpolatedX++)
                {
                    interpMinimums[interpolatedX] = interp.Interpolate(interpolatedX);
                }
                // ToFile(interpMinimums);

                interp.BuildSpline(indexesOfLocalMaximums, localMaximums, indexesOfLocalMaximums.Length);
                for (int interpolatedX = min; interpolatedX < max; interpolatedX++)
                {
                    interpMaximums[interpolatedX] = interp.Interpolate(interpolatedX);
                }

                // ToFile(interpMaximums);
                sss.Stop();

                for (int i = min; i < max; i++)
                {
                    difference[i - min] = signal[i] - (interpMaximums[i] + interpMinimums[i]) / 2;
                }

                int    countOfNulls = 0;
                double mean         = 0;
                for (int i = 0; i < difference.Length - 1; i++)
                {
                    if (difference[i] * difference[i + 1] < 0)
                    {
                        countOfNulls++;
                    }
                    mean += difference[i];
                }
                mean /= difference.Length;
                FindExtremums(difference, out localMinimums, out localMaximums, out indexesOfLocalMinimums, out indexesOfLocalMaximums);
                if (Math.Abs(mean) <= 0.009 && Math.Abs(indexesOfLocalMaximums.Length + indexesOfLocalMinimums.Length - countOfNulls) <= 1)
                {
                    mods[countOfMods] = difference;
                    countOfMods++;
                    var backupLink = originalSignal;
                    originalSignal = new double[max - min];
                    for (int i = min; i < max; i++)
                    {
                        originalSignal[i - min] = backupLink[i] - difference[i - min];
                    }
                    calls++;

                    /* difference = null;
                     * localMinimums = null;
                     * localMaximums = null;
                     * indexesOfLocalMinimums = null;
                     * indexesOfLocalMaximums = null;
                     * interpMaximums = null;
                     * interpMinimums = null;*/
                    return(emd(originalSignal, mods, calls, countOfMods));
                }
                calls++;
                return(emd(difference, mods, calls, countOfMods));
            }
        }
 /// <summary>
 /// Returns the speed value of a given spline
 /// </summary>
 /// <param name="t"></param>
 /// <returns></returns>
 public double Speed(double t)
 {
     return(Math.Round(_speedSpline.Interpolate(t), 4));
 }
Пример #11
0
        private List <Wave> GetListOfWavesFromRange(DateTime StartDate, DateTime EndDate)
        {
            List <double> oPriceData = GetRangeOfDataAsDoubleIncludingLowHigh(StartDate, EndDate);

            if (oPriceData.Count < 5)
            {
                return(new List <Wave>());
            }

            CubicSpline oCSTotalData = CubicSpline.InterpolateAkimaSorted(

                oPriceData.Select((s, i2) => new { i2, s })
                .Select(t => Convert.ToDouble(t.i2)).ToArray(),

                oPriceData.Select(s => Convert.ToDouble(s)).ToArray());


            //create list of Waves
            List <Wave> oWaves = new List <Wave>();

            var FirstVarDiff = oPriceData.Select((s, i2) => new { i2, s })
                               .ToList().Select(f => oCSTotalData.Differentiate(Convert.ToDouble(f.i2))).ToArray();

            int           i                   = 0;
            Momentum      Current             = Momentum.Neutral;
            Momentum      Old                 = Momentum.Neutral;
            List <double> oCalcDoublesForWave = new List <double>();
            bool          bFirst              = true;

            foreach (var fvd in FirstVarDiff)
            {
                if (fvd < 0)
                {
                    Current = Momentum.Negative;
                }
                else if (fvd == 0)
                {
                    Current = Momentum.Neutral;
                }
                else
                {
                    Current = Momentum.Positive;
                }

                if (bFirst)
                {
                    oCalcDoublesForWave.Add(oCSTotalData.Interpolate(i));
                    bFirst = false;
                }
                else
                {
                    if (Current != Old && oCalcDoublesForWave.Count > 1)
                    {
                        oWaves.Add(new Wave
                        {
                            End         = oCalcDoublesForWave.Last(),
                            Start       = oCalcDoublesForWave.First(),
                            Length      = oCalcDoublesForWave.Count,
                            Momentum    = Old,
                            SourceIndex = i
                        });
                        oCalcDoublesForWave.Clear();
                    }
                    else if (Current != Old && oCalcDoublesForWave.Count <= 1)
                    {
                        oCalcDoublesForWave.Clear();
                    }
                    oCalcDoublesForWave.Add(oCSTotalData.Interpolate(i));
                }
                Old = Current;

                i++;
            }
            return(oWaves);
        }
 /// <summary>
 /// Returns the latitude value of a given spline
 /// </summary>
 /// <param name="t"></param>
 /// <returns></returns>
 public double Latitude(double t)
 {
     return(_latitudeSpline.Interpolate(t));
 }
 /// <summary>
 /// Returns the z coordinate of a given spline
 /// </summary>
 /// <param name="t"></param>
 /// <returns></returns>
 public double Z(double t)
 {
     return(Math.Round(_zSpline.Interpolate(t), 4));
 }
 /// <summary>
 /// Returns the thrust value of a given spline
 /// </summary>
 /// <param name="t"></param>
 /// <returns></returns>
 public double Thrust(double t)
 {
     return(Math.Round(_thrustSpline.Interpolate(t), 4));
 }
 /// <summary>
 /// interpolates the Y-value at the given point
 /// </summary>
 /// <param name="point">the point to interpolate</param>
 /// <returns>the interpolated value</returns>
 public double Interpolate(double point)
 {
     return(spline.Interpolate(point));
 }
Пример #16
0
        public Collection <DataPoint> GeneratePointsFromBitmap(string filename)
        {
            filename = Path.ChangeExtension(filename, "png");
            if (File.Exists(filename))
            {
                double fmax    = 19000.0;
                double fmin    = 20.0;
                double dbrange = 16.0;
                double dbmax   = 1;

                double sampleRate = 48000;
                int    sampleSize = 16384;

                // Create a Bitmap object from an image file.
                Bitmap iBitmap = new Bitmap(filename);
                Bitmap oBitmap = new Bitmap(iBitmap.Width, iBitmap.Height);

                int    first = 0;
                int    last  = 0;
                int    size  = 0;
                double min   = iBitmap.Height;
                double max   = 0;
                double mag   = 0;

                // Get the color of a pixel within myBitmap.
                Collection <KeyValuePair <int, double> > points = new Collection <KeyValuePair <int, double> >();
                for (var x = 0; x < iBitmap.Width; x++)
                {
                    List <int> list = new List <int>();
                    for (var y = 0; y < iBitmap.Height; y++)
                    {
                        Color pixelColor = iBitmap.GetPixel(x, y);
                        if ((pixelColor.R > 200) && (pixelColor.G < 25) && (pixelColor.B < 25))
                        {
                            if (first == 0)
                            {
                                first = x;
                            }
                            else
                            {
                                last = x;
                            }
                            oBitmap.SetPixel(x, y, Color.FromArgb(255, 0, 0));
                            list.Add(y);
                        }
                    }
                    if (list.Count > 0)
                    {
                        var a = iBitmap.Height - list.Average();
                        points.Add(new KeyValuePair <int, double>(x, a));
                        if (a < min)
                        {
                            min = a;
                        }
                        if (a > max)
                        {
                            max = a;
                        }
                    }
                }

                size = last - first + 1;
                mag  = max - min + 1;

                //calculate gain & offset
                double scale = dbrange / mag;
                double shift = dbmax - max * scale;

                //check
                double n_min = min * scale + shift;
                double n_max = max * scale + shift;

                //convert bitmap to frequency spectrum
                Collection <double> ex = new Collection <double>();
                Collection <double> ey = new Collection <double>();
                for (var x = 0; x < points.Count; x++)
                {
                    double df = Math.Log10(fmax / fmin);                      //over aproximately 3 decades
                    double f  = 20.0 * Math.Pow(10.0, df * x / points.Count); //convert log horizontal image pixels to linear frequency scale in Hz
                    double y  = points[x].Value * scale + shift;              //scale and shift vertical image pixels to correct magnitude in dB

                    ex.Add(f);
                    ey.Add(Math.Pow(10.0, y / 20.0));
                }

                //interpolate frequency spectrum to match Audyssey responseData length
                double[]               frequency        = Enumerable.Range(0, sampleSize).Select(p => p * sampleRate / sampleSize).ToArray();
                CubicSpline            IA               = CubicSpline.InterpolateAkima(ex, ey);
                Collection <DataPoint> frequency_points = new Collection <DataPoint>();
                foreach (var f in frequency)
                {
                    if (f < fmin)
                    {   // exptrapolate
                        frequency_points.Add(new DataPoint(f, double.NegativeInfinity));
                    }
                    else
                    {
                        if (f > fmax)
                        {   // exptrapolate
                            frequency_points.Add(new DataPoint(f, double.NegativeInfinity));
                        }
                        else
                        {   //interpolate
                            frequency_points.Add(new DataPoint(f, 20 * Math.Log10(IA.Interpolate(f))));
                        }
                    }
                }

                oBitmap.Save(Path.ChangeExtension(filename, "jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);

                return(frequency_points);
            }
            else
            {
                return(null);
            }
        }
Пример #17
0
        public static List <OsuMovement> ExtractMovement(OsuHitObject obj0, OsuHitObject obj1, OsuHitObject obj2, OsuHitObject obj3,
                                                         Vector <double> tapStrain, double clockRate)
        {
            var movement = new OsuMovement();

            double t12 = (obj2.StartTime - obj1.StartTime) / clockRate / 1000.0;

            movement.RawMT = t12;
            movement.Time  = obj2.StartTime / 1000.0;

            if (obj2 is Spinner || obj1 is Spinner)
            {
                movement.IP12           = 0;
                movement.D              = 0;
                movement.MT             = 1;
                movement.Cheesablility  = 0;
                movement.CheesableRatio = 0;
                return(new List <OsuMovement>()
                {
                    movement
                });
            }

            if (obj0 is Spinner)
            {
                obj0 = null;
            }

            if (obj3 is Spinner)
            {
                obj3 = null;
            }

            var pos1 = Vector <double> .Build.Dense(new[] { (double)obj1.Position.X, (double)obj1.Position.Y });

            var pos2 = Vector <double> .Build.Dense(new[] { (double)obj2.Position.X, (double)obj2.Position.Y });

            var    s12  = (pos2 - pos1) / (2 * obj2.Radius);
            double d12  = s12.L2Norm();
            double IP12 = FittsLaw.CalculateIP(d12, t12);

            movement.IP12 = IP12;

            var s01 = Vector <double> .Build.Dense(2);

            var s23 = Vector <double> .Build.Dense(2);

            double d01 = 0;
            double d23 = 0;
            double t01 = 0;
            double t23 = 0;

            double flowiness012    = 0;
            double flowiness123    = 0;
            bool   obj1InTheMiddle = false;
            bool   obj2InTheMiddle = false;


            // Correction #1 - The Previous Object
            // Estimate how obj0 affects the difficulty of hitting obj2
            double correction0 = 0;

            if (obj0 != null)
            {
                var pos0 = Vector <double> .Build.Dense(new[] { (double)obj0.Position.X, (double)obj0.Position.Y });

                s01 = (pos1 - pos0) / (2 * obj2.Radius);
                d01 = s01.L2Norm();
                t01 = (obj1.StartTime - obj0.StartTime) / clockRate / 1000.0;

                if (d12 != 0)
                {
                    double tRatio0 = t12 / t01;

                    if (tRatio0 > tRatioThreshold)
                    {
                        if (d01 == 0)
                        {
                            correction0 = correction0Still;
                        }
                        else
                        {
                            double cos012             = Math.Min(Math.Max(-s01.DotProduct(s12) / d01 / d12, -1), 1);
                            double correction0_moving = correction0MovingSpline.Interpolate(cos012);

                            double movingness = SpecialFunctions.Logistic(d01 * 2) * 2 - 1;
                            correction0 = (movingness * correction0_moving + (1 - movingness) * correction0Still) * 1.5;
                        }
                    }
                    else if (tRatio0 < 1 / tRatioThreshold)
                    {
                        if (d01 == 0)
                        {
                            correction0 = 0;
                        }
                        else
                        {
                            double cos012 = Math.Min(Math.Max(-s01.DotProduct(s12) / d01 / d12, -1), 1);
                            correction0 = (1 - cos012) * SpecialFunctions.Logistic((d01 * tRatio0 - 1.5) * 4) * 0.3;
                        }
                    }
                    else
                    {
                        obj1InTheMiddle = true;

                        var    normalized_pos0 = -s01 / t01 * t12;
                        double x0 = normalized_pos0.DotProduct(s12) / d12;
                        double y0 = (normalized_pos0 - x0 * s12 / d12).L2Norm();

                        double correction0Flow = calcCorrection0Or3(d12, x0, y0, k0fInterp, scale0fInterp, coeffs0fInterps);
                        double correction0Snap = calcCorrection0Or3(d12, x0, y0, k0sInterp, scale0sInterp, coeffs0sInterps);
                        double correction0Stop = calcCorrection0Stop(d12, x0, y0);

                        flowiness012 = SpecialFunctions.Logistic((correction0Snap - correction0Flow - 0.05) * 20);

                        correction0 = Mean.PowerMean(new double[] { correction0Flow, correction0Snap, correction0Stop }, -10) * 1.3;

                        //Console.Write(obj2.StartTime + " ");
                        //Console.Write(correction0Flow.ToString("N3") + " ");
                        //Console.Write(correction0Snap.ToString("N3") + " ");
                        //Console.Write(correction0Stop.ToString("N3") + " ");
                        //Console.Write(correction0.ToString("N3") + " ");
                        //Console.WriteLine();
                    }
                }
            }

            // Correction #2 - The Next Object
            // Estimate how obj3 affects the difficulty of hitting obj2
            double correction3 = 0;

            if (obj3 != null)
            {
                var pos3 = Vector <double> .Build.Dense(new[] { (double)obj3.Position.X, (double)obj3.Position.Y });

                s23 = (pos3 - pos2) / (2 * obj2.Radius);
                d23 = s23.L2Norm();
                t23 = (obj3.StartTime - obj2.StartTime) / clockRate / 1000.0;

                if (d12 != 0)
                {
                    double tRatio3 = t12 / t23;

                    if (tRatio3 > tRatioThreshold)
                    {
                        if (d23 == 0)
                        {
                            correction3 = 0;
                        }
                        else
                        {
                            double cos123             = Math.Min(Math.Max(-s12.DotProduct(s23) / d12 / d23, -1), 1);
                            double correction3_moving = correction0MovingSpline.Interpolate(cos123);

                            double movingness = SpecialFunctions.Logistic(d23 * 6 - 5) - SpecialFunctions.Logistic(-5);
                            correction3 = (movingness * correction3_moving) * 0.5;
                        }
                    }
                    else if (tRatio3 < 1 / tRatioThreshold)
                    {
                        if (d23 == 0)
                        {
                            correction3 = 0;
                        }
                        else
                        {
                            double cos123 = Math.Min(Math.Max(-s12.DotProduct(s23) / d12 / d23, -1), 1);
                            correction3 = (1 - cos123) * SpecialFunctions.Logistic((d23 * tRatio3 - 1.5) * 4) * 0.15;
                        }
                    }
                    else
                    {
                        obj2InTheMiddle = true;

                        var    normalizedPos3 = s23 / t23 * t12;
                        double x3             = normalizedPos3.DotProduct(s12) / d12;
                        double y3             = (normalizedPos3 - x3 * s12 / d12).L2Norm();

                        double correction3Flow = calcCorrection0Or3(d12, x3, y3, k3fInterp, scale3fInterp, coeffs3fInterps);
                        double correction3Snap = calcCorrection0Or3(d12, x3, y3, k3sInterp, scale3sInterp, coeffs3sInterps);

                        flowiness123 = SpecialFunctions.Logistic((correction3Snap - correction3Flow - 0.05) * 20);

                        correction3 = Math.Max(Mean.PowerMean(correction3Flow, correction3Snap, -10) - 0.1, 0) * 0.5;
                    }
                }
            }

            // Correction #3 - 4-object pattern
            // Estimate how the whole pattern consisting of obj0 to obj3 affects
            // the difficulty of hitting obj2. This only takes effect when the pattern
            // is not so spaced (i.e. does not contain jumps)
            double patternCorrection = 0;

            if (obj1InTheMiddle && obj2InTheMiddle)
            {
                double gap = (s12 - s23 / 2 - s01 / 2).L2Norm() / (d12 + 0.1);
                patternCorrection = (SpecialFunctions.Logistic((gap - 0.75) * 8) - SpecialFunctions.Logistic(-6)) *
                                    SpecialFunctions.Logistic((d01 - 0.7) * 10) * SpecialFunctions.Logistic((d23 - 0.7) * 10) *
                                    Mean.PowerMean(flowiness012, flowiness123, 2) * 0.6;
                //patternCorrection = 0;
            }

            // Correction #4 - Tap Strain
            // Estimate how tap strain affects difficulty
            double tapCorrection = 0;

            if (d12 > 0 && tapStrain != null)
            {
                tapCorrection = SpecialFunctions.Logistic((Mean.PowerMean(tapStrain, 2) / IP12 - 1.34) / 0.1) * 0.25;
            }

            // Correction #5 - Cheesing
            // The player might make the movement of obj1 -> obj2 easier by
            // hitting obj1 early and obj2 late. Here we estimate the amount of
            // cheesing and update MT accordingly.
            double timeEarly         = 0;
            double timeLate          = 0;
            double cheesabilityEarly = 0;
            double cheesabilityLate  = 0;

            if (d12 > 0)
            {
                double t01Reciprocal;
                double ip01;
                if (obj0 != null)
                {
                    t01Reciprocal = 1 / (t01 + 1e-10);
                    ip01          = FittsLaw.CalculateIP(d01, t01);
                }
                else
                {
                    t01Reciprocal = 0;
                    ip01          = 0;
                }
                cheesabilityEarly = SpecialFunctions.Logistic((ip01 / IP12 - 0.6) * (-15)) * 0.5;
                timeEarly         = cheesabilityEarly * (1 / (1 / (t12 + 0.07) + t01Reciprocal));

                double t23Reciprocal;
                double ip23;
                if (obj3 != null)
                {
                    t23Reciprocal = 1 / (t23 + 1e-10);
                    ip23          = FittsLaw.CalculateIP(d23, t23);
                }
                else
                {
                    t23Reciprocal = 0;
                    ip23          = 0;
                }
                cheesabilityLate = SpecialFunctions.Logistic((ip23 / IP12 - 0.6) * (-15)) * 0.5;
                timeLate         = cheesabilityLate * (1 / (1 / (t12 + 0.07) + t23Reciprocal));
            }

            // Correction #6 - Small circle bonus
            double smallCircleBonus = SpecialFunctions.Logistic((55 - 2 * obj2.Radius) / 3.0) * 0.3;

            // Correction #7 - Stacked notes nerf
            double stackedThreshold = 0.8;
            double d12StackedNerf;

            if (d12 < stackedThreshold)
            {
                d12StackedNerf = Math.Max(1.4 * (d12 - stackedThreshold) + stackedThreshold, 0);
            }
            else
            {
                d12StackedNerf = d12;
            }

            // Apply the corrections
            double d12WithCorrection = d12StackedNerf * (1 + smallCircleBonus) * (1 + correction0 + correction3 + patternCorrection) *
                                       (1 + tapCorrection);

            movement.D              = d12WithCorrection;
            movement.MT             = t12;
            movement.Cheesablility  = cheesabilityEarly + cheesabilityLate;
            movement.CheesableRatio = (timeEarly + timeLate) / (t12 + 1e-10);

            var movementWithNested = new List <OsuMovement>()
            {
                movement
            };

            // add zero difficulty movements corresponding to slider ticks/slider ends so combo is reflected properly
            int extraNestedCount = obj2.NestedHitObjects.Count - 1;

            for (int i = 0; i < extraNestedCount; i++)
            {
                movementWithNested.Add(GetEmptyMovement(movement.Time));
            }

            return(movementWithNested);
        }
Пример #18
0
 private double NonPerturbative_ITP(
     double energy_MeV
     )
 {
     return(AlphaInterpolator.Interpolate(energy_MeV));
 }