在Processing中嵌套问题

时间:2014-03-01 16:09:45

标签: java processing hierarchy nested

我正在制作动画的问题。主要思想是6个等边三角形围绕中心点旋转,同时也绕自己的自身旋转。

当我运行代码时,三角形的每个实例都使用前一个实例作为参考点,而不是中心。这会产生很酷的螺旋效果,但这不是我想要的。

代码如下:

//Declare
tri myTri1;
tri myTri2;
tri myTri3;
tri myTri4;
tri myTri5;
tri myTri6;

void setup() {
  size(600, 600);
  smooth();

  //Initialise
  myTri1 = new tri();
  myTri2 = new tri();
  myTri3 = new tri();
  myTri4 = new tri();
  myTri5 = new tri();
  myTri6 = new tri();
}

void draw() {
  background(0);

  //Call Functions
  myTri1.run();
  translate(width/2,height/2);
  rotate(PI/3);
  translate(-width/2,-height/2);
  myTri2.run();
  translate(width/2,height/2);
  rotate(PI/3);
  translate(-width/2,-height/2);
  myTri3.run();
  translate(width/2,height/2);
  rotate(PI/3);
  translate(-width/2,-height/2);
  myTri4.run();
  translate(width/2,height/2);
  rotate(PI/3);
  translate(-width/2,-height/2);
  myTri5.run();
  translate(width/2,height/2);
  rotate(PI/3);
  translate(-width/2,-height/2);
  myTri6.run();
}

第二个标签:

class tri {
  //Variables
  float ax, ay, bx, by, cx, cy; //triangle point coordinates
  float theta; //triangle angle
  float pi = PI; //pi reference

  //Construct
  tri() {
    theta = PI/6;
    ax = 0;
    ay = 0;
    bx = -50*(sin(theta));
    by = +50*(cos(theta));
    cx = +50*(sin(theta));
    cy = +50*(cos(theta));
  }

  //Functions
  void run() {

    translate(width/2, height/2);
    revolve(); //revolve triangle about centre
    spin(); //spin triangle about itself
    pulse(); //move triangle in/out
    display(); //show triangle
    translate(-width/2, -height/2);
  }

  void spin() {
    translate(0, by/2); //sets rotation axis to centre of triangle
    rotate(millis()*-0.0005*pi);
    translate(0, -by/2); //resets axis to centre of window
  }

  void revolve() {
    translate(-2*by, 0);
    ax = ax + 2*sin(millis()*0.005);
    ay = ay + 4*cos(millis()*0.005);
    bx = bx + 2*sin(millis()*0.005);
    by = by + 4*cos(millis()*0.005);
    cx = cx + 2*sin(millis()*0.005);
    cy = cy + 4*cos(millis()*0.005);
    translate(2*by, 0);
  }

  void pulse() {
    ay = ay + 5*sin(millis()*0.005);
    by = by + 5*sin(millis()*0.005);
    cy = cy + 5*sin(millis()*0.005);
  }

  void display() {
    fill(255);
    strokeWeight(0.8);
    triangle(ax, ay, bx, by, cx, cy);
  }
}

如果有人能够指出我在哪里出错,那就太棒了,如果你可以建议任何优化RE六边形的形成(而不是翻译的混乱),我会非常高兴。

1 个答案:

答案 0 :(得分:1)

Franchesca的建议很好。您应该知道原点在哪里以及您应用的坐标空间变换如何影响它,至少在您感觉到它并且您完全可以控制之前。

我也热烈推荐这个Processing tutorial on 2d transformations

现在,回到你的代码:)

你可以改进的第一件事是习惯于循环和数组。 起初他们可能看起来很可怕,但是一旦掌握了它们,它们就会非常容易。 无论您何时想到需要重复的情况,您都可以使用for循环来让您的生活更轻松。 在您的情况下,生成三角形并存储它们可以使用循环和数组完成。

For循环具有以下语法:

for keyword (3 elements: a start point,an end point(condition) and an increment,(separated by the ; character)

假设你想一次从一个步骤(0)移动到b(10):

for(int currentPos = 0 ; currentPos < 10; currentPos++){
  println("step: " + currentPos);
}

如果你可以走路,你也可以跳过:)

for(int currentPos = 0 ; currentPos < 10; currentPos+=2){
  println("step: " + currentPos);
}
如果你愿意,甚至倒退:

for(int currentPos = 10 ; currentPos > 0; currentPos--){
  println("step: " + currentPos);
}

当遍历所有类型的数据(场景中的三角形,三角形中的顶点等)时,这非常有用。

您如何整理数据?您将它放在列表或数组中。 数组包含相同类型的元素并具有设置长度。 声明数组的语法如下:

ObjectType[] nameOfArray;

你可以初始化一个空数组:

int[] fiveNumbers = new int[5];//new keyword then the data type and length in sq.brackets

或者您可以使用值初始化数组:

String[] words = {"ini","mini","miny","moe"};

使用方括号和要访问的列表中对象的索引访问数组中的元素。数组具有长度属性,因此您可以轻松计算对象。

background(255);
String[] words = {"ini","mini","miny","moe"};
for(int i = 0 ; i < words.length; i++){
   fill(map(i,0,words.length, 0,255));
   text(words[i],10,10*(i+1));
}

现在回到你原来的问题。 这是使用for循环和数组简化的主要代码:

//Declare
int numTri = 6;//number of triangles
tri[] triangles = new tri[numTri];//a list/an array of tri objects (currently empty)
float angleIncrement = TWO_PI/numTri;
float radius = 100;
void setup() {
  size(600, 600);
  smooth();

  //Initialise
  for(int i = 0 ; i < numTri; i++){
    triangles[i] = new tri();//allocate/initialise each tri object into it's 'slot' in the list/array
  }
}

void draw() {
  background(0);
  translate(width * .5, height * .5);//move everything to the centre
  for(int i = 0 ; i < numTri; i++){
    pushMatrix();
      rotate(angleIncrement * i);//rotate from the last offset(centre)
      translate(radius,0);//move on (rotated) X axis away from the centre
      triangles[i].run();
    popMatrix();
  }
}
void drawAxes(int size){
  pushStyle();
  stroke(255,0,0);
  line(0,0,size,0);
  stroke(0,255,0);
  line(0,0,0,size);
  popStyle();
}

注意我在push/pop matrix次调用中缩进了代码。 这没有必要,但我已经补充说,这样你就可以了解坐标空间是如何嵌套的。 这些调用非常有用,因为它们可以为您处理幕后的细节数学部分。注意我是如何将符号放在一个圆圈中而不使用极坐标到笛卡尔的转换公式(cos(角度)*半径,sin(角度)*半径)。

您可以使用其他标签中的代码对其进行测试:

class tri {
  //Variables
  float ax, ay, bx, by, cx, cy; //triangle point coordinates
  float theta; //triangle angle
  float pi = PI; //pi reference

  //Construct
  tri() {
    theta = PI/6;
    ax = 0;
    ay = 0;
    bx = -50*(sin(theta));
    by = +50*(cos(theta));
    cx = +50*(sin(theta));
    cy = +50*(cos(theta));
  }

  //Functions
  void run() {
    pushMatrix();
    revolve(); //revolve triangle about centre
//    pulse(); //move triangle in/out
    display(); //show triangle
    popMatrix();
  }

  void revolve() {
    translate(-2*by, 0);
    float angle = millis()*0.005;
    float cos = cos(angle);
    float sin = sin(angle);
    ax = ax + 2*sin;
    ay = ay + 4*cos;
    bx = bx + 2*sin;
    by = by + 4*cos;
    cx = cx + 2*sin;
    cy = cy + 4*cos;
    translate(2*by, 0);
  }

  void pulse() {
    ay = ay + 5*sin(millis()*0.005);
    by = by + 5*sin(millis()*0.005);
    cy = cy + 5*sin(millis()*0.005);
  }

  void display() {
    fill(255);
    strokeWeight(0.8);
    triangle(ax, ay, bx, by, cx, cy);
  }
}

另请注意我添加了drawAxes功能。这只是一个实用工具,可以让您更容易理解绘图的坐标空间。

再次回到数组和for循环,这是代码的修改版本:

class tri {
  //Variables
  float ai = TWO_PI/3;//angle increment
  float r  = 50;
  float sr = r * 1.5;//spin radius
  float vt = 5;//vertical translation(for pulse)
  PVector[] verts = new PVector[3];

  boolean rotateAroundCentre = true;
  boolean translateAroundCentre = false;
  boolean translateVertically = false;
  //Construct
  tri() {
    for(int i = 0 ; i < 3; i++){
      verts[i] = new PVector(cos(ai * i) * r,sin(ai * i) * r);
    }
  }

  //Functions
  void run() {
    pushMatrix();
      float angle = millis()*0.0005;
      if(rotateAroundCentre) rotate(angle);
      if(translateVertically) translate(sin(angle)*vt,0);
      if(translateAroundCentre){
//        translate(cos(angle) * sr,sin(angle) * r);
//        or          
          rotate(angle);
          translate(sr,0);   
      }
    display(); //show triangle
    popMatrix();
  }
  void display() {
    fill(255);
    strokeWeight(0.8);
    triangle(verts[0].x, verts[0].y, verts[1].x, verts[1].y, verts[2].x, verts[2].y);
    drawAxes(10);
  }
}

随意使用布尔值rotateAroundCentre,translateAroundCentre,translateVertically变量,玩得很开心玩坐标和几何:)

例如,这是草图的一个版本,您可以使用键盘上的1/2/3键切换上面的3个选项:

//Declare
int numTri = 6;//number of triangles
tri[] triangles = new tri[numTri];//a list/an array of tri objects (currently empty)
float angleIncrement = TWO_PI/numTri;
float radius = 100;
boolean[] options = {false,false,false}; 
void setup() {
  size(600, 600);
  smooth();

  //Initialise
  for(int i = 0 ; i < numTri; i++){
    triangles[i] = new tri();//allocate/initialise each tri object into it's 'slot' in the list/array
  }
}

void draw() {
  background(0);
  translate(width * .5, height * .5);//move everything to the centre
  for(int i = 0 ; i < numTri; i++){
    pushMatrix();
      rotate(angleIncrement * i);//rotate from the last offset(centre)
      translate(radius,0);//move on (rotated) X axis away from the centre
      drawAxes(20);
      triangles[i].run();
    popMatrix();
  }
}
void drawAxes(int size){
  pushStyle();
  stroke(255,0,0);
  line(0,0,size,0);
  stroke(0,255,0);
  line(0,0,0,size);
  popStyle();
}
void keyReleased(){
  for(int i = 0 ; i < 3; i++) if(key == (49+i)) options[i] = !options[i];//quick'n'dirty option toggling
  for(int i = 0; i < numTri; i++) {
    triangles[i].rotateAroundCentre = options[0];
    triangles[i].translateAroundCentre = options[1];
    triangles[i].translateVertically = options[2];
  }
}
class tri {
  //Variables
  float ai = TWO_PI/3;//angle increment
  float r  = 50;
  float sr = r * 1.5;//spin radius
  float vt = 5;//vertical translation(for pulse)
  PVector[] verts = new PVector[3];

  boolean rotateAroundCentre = false;
  boolean translateAroundCentre = false;
  boolean translateVertically = false;
  //Construct
  tri() {
    for(int i = 0 ; i < 3; i++){
      verts[i] = new PVector(cos(ai * i) * r,sin(ai * i) * r);
    }
  }

  //Functions
  void run() {
    pushMatrix();
      float angle = millis()*0.0005;
      if(rotateAroundCentre) rotate(angle);
      drawAxes(30);

      if(translateVertically) translate(sin(angle)*vt,0);
      drawAxes(40);

      if(translateAroundCentre){
//        translate(cos(angle) * sr,sin(angle) * r);
//        or          
          rotate(angle);
          drawAxes(40);

          translate(sr,0);   
      }
    display(); //show triangle
    popMatrix();
  }
  void display() {
    fill(255);
    strokeWeight(0.8);
    triangle(verts[0].x, verts[0].y, verts[1].x, verts[1].y, verts[2].x, verts[2].y);
    drawAxes(10);
  }
}