Processing+代码本色 chap3 振荡

弹力

介绍

在这里插入图片描述
弹簧的弹力可以根据胡克定律计算得到,胡克定律以英国物理学家罗伯特·胡克命名,他在1660年发明了这个公式。胡克最初是用拉丁文描述这个公式的——“Ut tensio,sic vis”, 这句话的意思是“力如伸长(那样变化)”。我们可以这么理解它:弹簧的弹力与弹簧的伸长量成正比。

先用胡克定律计算弹力的大小。我们需要知道k和x的值:k很简单,它只是一个常量,我们可以随意选择一个数。

float k = 0.1;

x可能会更复杂,我们需要知道“当前长度和静止长度的差”。可以用restLength表示静止长度,

PVector dir = PVector.sub(bob,anchor); 由枢轴点指向摆锤的向量,它告诉我们弹簧的当前长度
float currentLength = dir.mag();
float x = restLength - currentLength;

方向计算
在这里插入图片描述

float k = 0.1; 按照胡克定律计算得到的弹力
PVector force = PVector.sub(bob,anchor);
float currentLength = dir.mag();
float x = restLength - currentLength;
force.normalize(); 弹力的方向(单位向量)
force.mult(-1 k x); 把方向和大小放在一起!

下面两个类不做过多介绍,可以参考书本第三章的介绍

Spring类的实现

class Spring { 
  PVector anchor;

  // 静止长度和弹簧常数
  float len;
  float k = 0.2;
  
  Bob a;
  Bob b;

  // 
  Spring(Bob a_, Bob b_, int l) {
    a = a_;
    b = b_;
    len = l;
  } 

  // Calculate spring force
  void update() {
    // Vector pointing from anchor to bob position
    PVector force = PVector.sub(a.position, b.position);
    // What is distance
    float d = force.mag();
    // Stretch is difference between current distance and rest length
    float stretch = d - len;

    // Calculate force according to Hooke's Law
    force.normalize();
    force.mult(-1 * k * stretch);
    a.applyForce(force);
    force.mult(-1);
    b.applyForce(force);
  }


  void display() {
    strokeWeight(2);
    stroke(0);
    line(a.position.x, a.position.y, b.position.x, b.position.y);
  }
}

控制小球的类(Bob类)

class Bob { 
  PVector position;
  PVector velocity;
  PVector acceleration;
  float mass = 12;
  
  // Arbitrary damping to simulate friction / drag 
  float damping = 0.95;

  // For mouse interaction
  PVector dragOffset;
  boolean dragging = false;

  // Constructor
  Bob(float x, float y) {
    position = new PVector(x,y);
    velocity = new PVector();
    acceleration = new PVector();
    dragOffset = new PVector();
  } 

  // Standard Euler integration
  void update() { 
    velocity.add(acceleration);
    velocity.mult(damping);
    position.add(velocity);
    acceleration.mult(0);
  }

  // Newton's law: F = M * A
  void applyForce(PVector force) {
    PVector f = force.get();
    f.div(mass);
    acceleration.add(f);
  }


  // Draw the bob
  void display() { 
    stroke(0);
    strokeWeight(2);
    fill(175);
    if (dragging) {
      fill(50);
    }
    ellipse(position.x,position.y,mass*2,mass*2);
  } 

  // The methods below are for mouse interaction

  // This checks to see if we clicked on the mover
  void clicked(int mx, int my) {
    float d = dist(mx,my,position.x,position.y);
    if (d < mass) {
      dragging = true;
      dragOffset.x = position.x-mx;
      dragOffset.y = position.y-my;
    }
  }

  void stopDragging() {
    dragging = false;
  }

  void drag(int mx, int my) {
    if (dragging) {
      position.x = mx + dragOffset.x;
      position.y = my + dragOffset.y;
    }
  }
}

网格设计

在这里插入图片描述
根据上面两个类对网进行实现

int Bobnum = 10;
Bob[][] b = new Bob[Bobnum][Bobnum];
Spring[] s = new Spring[2*Bobnum*(Bobnum-1)];

Bobnum:网的长度(即每一行的点的个数,宽度和长度相等)
b:存储网的点的数组
s:存储点之间连线的数组

对数组进行初始化,连线方式参考上图

void setup() {
  size(1000, 800);
  // 在起始位置创建对象
  //请注意,Spring构造函数中的第三个参数是"rest length"
  int Springnum = 0;
  for(int i=0;i<Bobnum;i++)
    for(int j=0;j<Bobnum;j++)
      b[i][j] = new Bob(width*j/(Bobnum-1),height*i/((Bobnum-1)));
    
  
  for(int i=0;i<Bobnum;i++)
    for(int j=0;j<Bobnum;j++)
    {
      if(j<Bobnum-1&&i<Bobnum-1){
        s[Springnum] = new Spring(b[i][j],b[i][j+1],int(width/(Bobnum-1)));
        s[Springnum+1] = new Spring(b[i][j],b[i+1][j],int(height/((Bobnum-1))));
        Springnum +=2;
      }
      else
      {
        if(j==Bobnum-1 &&i<Bobnum-1){
          s[Springnum] = new Spring(b[i][j],b[i+1][j],int(height/((Bobnum-1))));
          Springnum+=1;
        }else if(j<Bobnum-1&&i==Bobnum-1)
        {
          s[Springnum] = new Spring(b[i][j],b[i][j+1],int(width/(Bobnum-1)));
          Springnum +=1;
        }else
        {
        }
      }
    }
}

在draw()函数中进行实现

void draw() {
  background(255); 
  for(int a=0;a<2*Bobnum*(Bobnum-1);a++)
    s[a].update();
  
  for(int a=0;a<2*Bobnum*(Bobnum-1);a++)
    s[a].display();

    
  for(int i=0;i<Bobnum;i++)
    for(int j=0;j<Bobnum;j++)
    {
      b[i][j].update();
      b[i][j].display();
    }
  b[int(Bobnum/2)][int(Bobnum/2)].drag(mouseX, mouseY);
  fill(255,0,0);
  ellipse(b[int(Bobnum/2)][int(Bobnum/2)].position.x,b[int(Bobnum/2)][int(Bobnum/2)].position.y,
    b[int(Bobnum/2)][int(Bobnum/2)].mass*2,b[int(Bobnum/2)][int(Bobnum/2)].mass*2);
    
  fill(0);
  text("点击鼠标右键重置", 10, 30);
}

点击鼠标右键进行网的初始位置重现,鼠标左键点击红色的球可以进行拖动。

void mousePressed() {
  if (mouseButton == RIGHT){
    setup();
  }
  b[int(Bobnum/2)][int(Bobnum/2)].clicked(mouseX, mouseY);
}

void mouseReleased() {
  b[int(Bobnum/2)][int(Bobnum/2)].stopDragging();
}

运行效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了20 篇原创文章 · 获赞 7 · 访问量 7066

猜你喜欢

转载自blog.csdn.net/YCSDNG/article/details/103808574