C# 随机光滑图

C# 随机光滑图,c#,math,graph,C#,Math,Graph,我想要一个类似下图的图。我想实现类似于cos/sin的图形,但带有一点随机性。图表不得超过(100)或低于(0)极限。 如果没有随机性,我们可以编写如下函数: f(x)=cos(x)*50+50 我正在寻找任何语言的实现或只是一个简单的解释 您可以简单地用随机系数和周期求几个正弦/余弦的和 实现示例: internal struct SineWave { internal readonly double Amplitude; internal readonly double

我想要一个类似下图的图。我想实现类似于cos/sin的图形,但带有一点随机性。图表不得超过(100)或低于(0)极限。 如果没有随机性,我们可以编写如下函数:

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


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

您可以简单地用随机系数和周期求几个正弦/余弦的和

实现示例:

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;
    } 
}
内部结构正弦波
{
内部只读双振幅;
内部只读双序号频率;
内部只读双角度频率;
内部只读双相;
内部只读双移位;
内部正弦波(双振幅、双频率、双相位、双位移)
{
振幅=振幅;
普通频率=普通频率;
角度频率=2*Math.PI*普通频率;
相位=相位;
ShiftY=ShiftY;
}
}
公共类随机曲线
{
专用正弦波[]m_正弦波;
公共随机曲线(整数分量、双最小值、双最大值、双平坦度)
{
m_正弦波=新正弦波[分量];
双倍总峰值振幅=最大-最小;
双平均峰值振幅=总峰值振幅/分量;
int素数=1;
随机r=新随机();
对于(int i=0;i
对于函数,可以使用类和方法

对于图形解决方案,您可以查看以下主题


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

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

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

希望这有帮助

      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;
    }
private static Random rnd=new Random();
专用双[]RAIN(整数长度、整数正弦、整数余弦、双amplsin、双amplcos、双噪声)
{
如果(长度忘记了这个

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

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


看一看,一种向图形添加随机噪声并使其平滑的方法,使其看起来像手绘的,模仿的样式。虽然这并不完全是您想要的,但我认为只需将输入图形设置为零(例如y=0)将噪声平滑参数调整为更大的噪声幅度和更大的平滑距离可能会产生您正在寻找的那种随机图形。

为什么?这有点太开放了…@RBarryYoung为一个简单的游戏生成随机地形。啊,好的。我记得,随机地形最好以f(0)和f(1)过程的组合…你想要a)生成一组点,b)一个分析函数,c)一个绘图工具吗?我想也是随机周期?我想你误解了这个问题。他不是问如何绘制那个函数,而是问如何使那个函数更随机。这是什么意思“使函数更随机”?函数可以清晰地输入和输出。一个更随机的函数怎么可能只在一个名为
cos(x)*50+50
的表达式中工作?请告诉我..他想要一个类似于该函数的函数,但它有一些随机性。
      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;
    }