Random 在随机坡度上的点处查找切线

Random 在随机坡度上的点处查找切线,random,processing,calculus,Random,Processing,Calculus,我得到了一段处理代码,似乎正在设置一个。不幸的是,尽管我努力提高自己的数学技能,但我不知道它在做什么,而且我发现的方法也没有多大帮助 我试图扩展这段代码,这样我就可以在下面的代码创建的斜坡上画一条与点相切的直线。我能找到的最接近于回答这个问题的答案是。不幸的是,我真的不明白正在讨论什么,或者它是否真的与我的情况有关 如果能帮助我计算曲线上某一点的切线,我将不胜感激 自2013年6月17日起更新 我一直在尝试玩这个,但没有太大的成功。这是我能做的最好的了,我怀疑我是否正确地应用导数来找到切线(或者

我得到了一段处理代码,似乎正在设置一个。不幸的是,尽管我努力提高自己的数学技能,但我不知道它在做什么,而且我发现的方法也没有多大帮助

我试图扩展这段代码,这样我就可以在下面的代码创建的斜坡上画一条与点相切的直线。我能找到的最接近于回答这个问题的答案是。不幸的是,我真的不明白正在讨论什么,或者它是否真的与我的情况有关

如果能帮助我计算曲线上某一点的切线,我将不胜感激

自2013年6月17日起更新

我一直在尝试玩这个,但没有太大的成功。这是我能做的最好的了,我怀疑我是否正确地应用导数来找到切线(或者即使我在点上正确地找到了导数)。此外,我开始担心,即使我的其他一切都是正确的,我也没有正确地画出这条线。如果有人能提供这方面的意见,我将不胜感激

final int w = 800;
final int h = 480;
double[] skyline;
PImage img;
int numOfDeriv = 800;
int derivModBy = 1; //Determines how many points will be checked
int time;
int timeDelay = 1000;
int iter;
double[] derivatives;

void setup() {
  noStroke();
  size(w, h);
  fill(0,128,255);
  rect(0,0,w,h);
  int t[] = terrain(w,h);
  fill(77,0,0);
  for(int i=0; i < w; i++){
    rect(i, h, 1, -1*t[i]);
  }
  time = millis();
  timeDelay = 100;
  iter =0;
  img = get();
}

void draw() {
  int dnum = 0; //Current position of derivatives
  if(iter == numOfDeriv) iter = 0;
  if (millis() > time + timeDelay){
        image(img, 0, 0, width, height);
        strokeWeight(4);
        stroke(255,0,0);        
        point((float)iter*derivModBy, height-(float)skyline[iter*derivModBy]);
        strokeWeight(1);
        stroke(255,255,0);
        print("At x = ");
        print(iter);
        print(", y = ");
        print(skyline[iter]);
        print(", derivative = ");
        print((float)derivatives[iter]);
        print('\n');
        lineAngle(iter, (int)(height-skyline[iter]), (float)derivatives[iter], 100);
        lineAngle(iter, (int)(height-skyline[iter]), (float)derivatives[iter], -100);
        stroke(126);
        time = millis();
        iter += 1;
    }
}

void lineAngle(int x, int y, float angle, float length)
{
  line(x, y, x+cos(angle)*length, y-sin(angle)*length);
}

int[] terrain(int w, int h){

    width = w;
    height = h;

    //min and max bracket the freq's of the sin/cos series
    //The higher the max the hillier the environment
    int min = 1, max = 6;

    //allocating horizon for screen width
    int[] horizon = new int[width];
    skyline =  new double[width];
    derivatives = new double[numOfDeriv];

    //ratio of amplitude of screen height to landscape variation
    double r = (int) 2.0/5.0;

    //number of terms to be used in sine/cosine series
    int n = 4;

    int[] f = new int[n*2];

    //calculating omegas for sine series
    for(int i = 0; i < n*2 ; i ++){
      f[i] = (int) random(max - min + 1) + min;
    }

    //amp is the amplitude of the series
    int amp =  (int) (r*height);
    int dnum = 0; //Current number of derivatives    
    for(int i = 0 ; i < width; i ++){
      skyline[i] = 0;
      double derivative = 0.0;
      for(int j = 0; j < n; j++){
         if(i % derivModBy == 0){
            derivative += ( cos( (f[j]*PI*i/height) * f[j]*PI/height) - 
                        sin(f[j+n]*PI*i/height) * f[j+n]*PI/height);
         }

        skyline[i] += ( sin( (f[j]*PI*i/height) ) +  cos(f[j+n]*PI*i/height) );
        }
      skyline[i] *= amp/(n*2);
      skyline[i] += (height/2);
      skyline[i] = (int)skyline[i];
      horizon[i] = (int)skyline[i];
      derivative *= amp/(n*2);
      if(i % derivModBy == 0){
        derivatives[dnum++] = derivative;
        derivative = 0;
      }
    }

    return horizon;
}

void reset() {
  time = millis();
}
final int w=800;
最终int h=480;
双[]天际线;
皮马杰;
int numOfDeriv=800;
int-derivModBy=1//确定要检查的点数
整数时间;
int-timeDelay=1000;
国际热核实验堆;
双[]衍生工具;
无效设置(){
仰泳();
尺寸(w,h);
填充(0128255);
rect(0,0,w,h);
int t[]=地形(w,h);
填充(77,0,0);
对于(int i=0;i时间+延时){
图像(img,0,0,宽度,高度);
冲程重量(4);
冲程(255,0,0);
点((浮动)iter*derivModBy,高度-(浮动)天际线[iter*derivModBy]);
冲程重量(1);
中风(255255,0);
打印(“在x=”);
印刷(国际热核实验堆);
打印(,y=);
印刷(天际线[iter]);
打印(“,派生=”);
印刷((浮动)衍生品[iter]);
打印('\n');
线性角(iter,(int)(高度天际线[iter]),(浮动)导数[iter],100);
线性角(iter,(int)(高度天际线[iter]),(浮动)导数[iter],-100);
中风(126);
时间=毫秒();
iter+=1;
}
}
空心线角(整数x,整数y,浮动角度,浮动长度)
{
线(x,y,x+cos(角度)*长度,y-sin(角度)*长度);
}
int[]地形(int w,int h){
宽度=w;
高度=h;
//最小值和最大值将正弦/余弦系列的频率括起来
//最大值越高,环境越恶劣
最小积分=1,最大积分=6;
//为屏幕宽度分配地平线
int[]地平线=新的int[宽度];
天际线=新的双[宽度];
导数=新的双[numOfDeriv];
//屏幕高度振幅与景观变化的比率
双r=(int)2.0/5.0;
//正弦/余弦系列中使用的术语数量
int n=4;
int[]f=新的int[n*2];
//正弦级数的ω气计算
对于(int i=0;i
在这种特殊情况下,你似乎不需要对傅里叶级数有太多的了解,只是它的形式是:

    A0 + A1*cos(x) + A2*cos(2*x) + A3*cos(3*x) +... + B1*sin(x) + B2*sin(x) +...
通常,你会得到一个函数
f(x)
,你需要找到
An
Bn
的值,这样傅里叶级数(当你添加更多项时)在某个区间
[a,b]
收敛到你的函数

然而,在这种情况下,他们想要一个看起来像不同的块和坑(或山和谷,如上下文所示)的随机函数,因此他们从最小值和最大值之间的傅里叶级数中选择随机项,并将其系数设置为1(否则概念上为0)。它们还满足于4个正弦项和4个余弦项的傅里叶级数(这当然比无穷多的项更容易管理)。这意味着它们的傅里叶级数最终看起来像是不同频率的不同正弦和余弦函数加在一起(并且都具有相同的振幅)

如果您还记得以下内容,则很容易找到其导数:

    sin(n*x)' = n * cos(x)
    cos(n*x)' = -n * sin(x)
    (f(x) + g(x))' = f'(x) + g'(x)
因此,计算导数的循环如下所示:

    for(int j = 0; j < n; j++){
        derivative += ( cos( (f[j]*PI*i/height) * f[j]*PI/height) - \
                        sin(f[j+n]*PI*i/height) * f[j+n]*PI/height);
    }
for(int j=0;j
在某个点,
i
(请注意,导数是针对
i
进行的,因为这是表示x位置的变量)

有了它,您应该能够计算点
i
处的切线方程

更新
在你做
skyline[i]*=amp/(n*2)的点上您还必须相应地调整您的导数
导数*=amp/(n*2)但是,当你做
天际线[i]+=he时,你的导数不需要调整
final int w = 800;
final int h = 480;
float[] skyline;
PImage img;
int numOfDeriv = 800;
int derivModBy = 1; //Determines how many points will be checked
int time;
int timeDelay = 1000;
int iter;
float[] tangents;

public void setup() {
  noStroke();
  size(w, h);
  fill(0, 128, 255);
  rect(0, 0, w, h);
  terrain(w, h);
  fill(77, 0, 0);
  for (int i=0; i < w; i++) {
    rect(i, h, 1, -1*(int)skyline[i]);
  }
  time = millis();
  timeDelay = 100;
  iter =0;
  img = get();
}

public void draw() {
  if (iter == numOfDeriv) iter = 0;
  if (millis() > time + timeDelay) {
    image(img, 0, 0, width, height);
    strokeWeight(4);
    stroke(255, 0, 0);        
    point((float)iter*derivModBy, height-(float)skyline[iter*derivModBy]);
    strokeWeight(1);
    stroke(255, 255, 0);
    print("At x = ");
    print(iter);
    print(", y = ");
    print(skyline[iter]);
    print(", derivative = ");
    print((float)tangents[iter]);
    print('\n');
    lineAngle(iter, (int)(height-skyline[iter]), (float)tangents[iter], 100);
    lineAngle(iter, (int)(height-skyline[iter]), (float)tangents[iter], -100);
    stroke(126);
    time = millis();
    iter += 1;
  }
}

public void lineAngle(int x, int y, float angle, float length) {
  line(x, y, x+cos(angle)*length, y-sin(angle)*length);
}

public void terrain(int w, int h) {      
  //min and max bracket the freq's of the sin/cos series
  //The higher the max the hillier the environment
  int min = 1, max = 6;
  skyline =  new float[w];
  tangents = new float[w];
  //ratio of amplitude of screen height to landscape variation
  double r = (int) 2.0/5.0;
  //number of terms to be used in sine/cosine series
  int n = 4;
  int[] f = new int[n*2];
  //calculating omegas for sine series
  for (int i = 0; i < n*2 ; i ++) {
    f[i] = (int) random(max - min + 1) + min;
  }
  //amp is the amplitude of the series
  int amp =  (int) (r*h);
  for (int i = 0 ; i < w; i ++) {
    skyline[i] = 0;
    for (int j = 0; j < n; j++) {
      skyline[i] += ( sin( (f[j]*PI*i/h) ) +  cos(f[j+n]*PI*i/h) );
    }
    skyline[i] *= amp/(n*2);
    skyline[i] += (h/2);
  }
  for (int i = 1 ; i < w - 1; i ++) {
    tangents[i] = atan2(skyline[i+1] - skyline[i-1], 2);
  }
  tangents[0] = atan2(skyline[1] - skyline[0], 1);
  tangents[w-1] = atan2(skyline[w-2] - skyline[w-1], 1);
}

void reset() {
  time = millis();
}