随机平滑图

时间:2012-12-25 17:02:41

标签: c# math graph

我想在下图中找到类似于图表的图表。我想实现类似cos / sin的图形,但有一点随机性。图表不应超过(100)或低于(0)限制。 没有随机性,我们可以编写这样的函数:

f(x)=cos(x)*50+50

Random graph

我正在寻找任何语言的实施或只是一个简单的解释。

5 个答案:

答案 0 :(得分:2)

你可以简单地用随机系数和周期来计算一些sin / cos。

实施示例:

internal struct SineWave
{
    internal readonly double Amplitude;
    internal readonly double OrdinaryFrequency;
    internal readonly double AngularFrequency;
    internal readonly double Phase;
    internal readonly double ShiftY;

    internal SineWave(double amplitude, double ordinaryFrequency, double phase, double shiftY)
    {
        Amplitude = amplitude;
        OrdinaryFrequency = ordinaryFrequency;
        AngularFrequency = 2 * Math.PI * ordinaryFrequency;
        Phase = phase;
        ShiftY = shiftY;
    }
}

public class RandomCurve
{
    private SineWave[] m_sineWaves;

    public RandomCurve(int components, double minY, double maxY, double flatness)
    {
        m_sineWaves = new SineWave[components];

        double totalPeakToPeakAmplitude = maxY - minY;
        double averagePeakToPeakAmplitude = totalPeakToPeakAmplitude / components;

        int prime = 1;
        Random r = new Random();
        for (int i = 0; i < components; i++)
        {
            // from 0.5 to 1.5 of averagePeakToPeakAmplitude 
            double peakToPeakAmplitude = averagePeakToPeakAmplitude * (r.NextDouble() + 0.5d);

            // peak amplitude is a hald of peak-to-peak amplitude
            double amplitude = peakToPeakAmplitude / 2d;

            // period should be a multiple of the prime number to avoid regularities
            prime = Utils.GetNextPrime(prime);
            double period = flatness * prime;

            // ordinary frequency is reciprocal of period
            double ordinaryFrequency = 1d / period;

            // random phase
            double phase = 2 * Math.PI * (r.NextDouble() + 0.5d);

            // shiftY is the same as amplitude
            double shiftY = amplitude;

            m_sineWaves[i] =
                new SineWave(amplitude, ordinaryFrequency, phase, shiftY);
        }
    }

    public double GetY(double x)
    {
        double y = 0;
        for (int i = 0; i < m_sineWaves.Length; i++)
            y += m_sineWaves[i].Amplitude * Math.Sin(m_sineWaves[i].AngularFrequency * x + m_sineWaves[i].Phase) + m_sineWaves[i].ShiftY;

        return y;
    }
}

internal static class Utils
{
    internal static int GetNextPrime(int i)
    {
        int nextPrime = i + 1;
        for (; !IsPrime(nextPrime); nextPrime++) ;
        return nextPrime;
    }

    private static bool IsPrime(int number)
    {
        if (number == 1) return false;
        if (number == 2)  return true;

        for (int i = 2; i < number; ++i)
            if (number % i == 0) return false;

        return true;
    } 
}

答案 1 :(得分:2)

所以这是一个用C#编写的代码,它可以随机输入值随机化。 我只是给你一些带有值的输出,看看它是否适合你。可以针对余弦和窦值修改Amplite。最后添加偏移量(因此最小值始终为0)并进行缩放以确保最大值为100.您可以看到可以添加噪声(图3,图4)。

  

terr1:RandomTerrarain(1000,4,1,10,5,0);   Figure 1

     

terr2:RandomTerrarain(1000,2,3,-10,5,0);   Figure 2

希望这有帮助!

      private static Random rnd = new Random();
    private double[] RandomTerrarain(int length, int sinuses, int cosinuses, double amplsin, double amplcos, double noise)
    {
        if (length <= 0)
            throw new ArgumentOutOfRangeException("length", length, "Length must be greater than zero!");
        double[] returnValues = new double[length];

        for (int i = 0; i < length; i++)
        {
            // sin
            for (int sin = 1; sin <= sinuses; sin++)
            {
                returnValues[i] += amplsin * Math.Sin((2 * sin * i * Math.PI) / (double)length);
            }
            // cos
            for (int cos = 1; cos <= cosinuses; cos++)
            {
                returnValues[i] += amplcos * Math.Cos((2 * cos * i * Math.PI) / (double)length);
            }
            // noise
            returnValues[i] += (noise * rnd.NextDouble()) - (noise * rnd.NextDouble());
        }
        // give offset so it be higher than 0
        double ofs = returnValues.Min();
        if (ofs < 0)
        {
            ofs *= -1;
            for (int i = 0; i < length; i++)
            {
                returnValues[i] += ofs;
            }
        }
        // resize to be fit in 100
        double max = returnValues.Max();
        if (max >= 100)
        {
            double scaler = max / 100.0;
            for (int i = 0; i < length; i++)
            {
                returnValues[i] /= scaler;
            }
        }
        return returnValues;
    }

答案 2 :(得分:0)

对于您的功能,您可以使用Math类和Cos()方法。

public static double GetCosFunction(double d)
{
     return Math.Cos(d) * 50 + 50;
}

对于图解决方案,您可以查看这些主题;

答案 3 :(得分:0)

忘了这个......

  

terr3:RandomTerrarain(1000,5,5,-2,5,2);   Figure 3

     

terr4:RandomTerrarain(1000,4,1,5,-20,1);   Figure 4

答案 4 :(得分:0)

看一下xkcd-style graphs,一种向图形添加随机噪声并将其平滑以使其看起来像手绘的方法,模仿xkcd cartoons的样式。虽然这不是你想要的,但我认为简单地将输入图设置为零(例如y = 0)并将噪声平滑参数调整为更大的噪声幅度和更大的平滑距离可能会导致这种随机图形你在寻找。