2

作为进入处理的一个小作业,我不得不编写一些代码来获得以下内容: 任务

使用

public void setup() {
   size(300,200);
   noFill();
   rect(100, 20, 40, 80);
   ellipseMode(CENTER);
   fill(#000000);
   ellipse(width/2, height/2, 5,5);
   
   noFill();
   translate(width/2, height/2);
   rotate(radians(65));
   rect(-20, -40, 40, 80);
}
public void draw() {
}

到目前为止,这非常有效。但我不喜欢我必须更改底部rect指令内的坐标才能正确旋转。我知道通过旋转您不会旋转单个元素,而是旋转整个坐标系。我不知道将哪些值放入translate指令中以使输出如上图所示,同时在rect命令中仍使用相同的坐标。

任务已经用我使用的代码完成了,我只是不太喜欢它。所以这不仅仅是要求别人做我的功课,而是纯粹的兴趣。

编辑:一个问题的更一般化的尝试:我如何知道在旋转之前要翻译哪些值以获得我想要的任何结果?有没有办法计算它们?当然,这不仅仅是尝试,不是吗?

4

3 回答 3

6

处理中的很多混淆是坐标系。在处理中,原点 (0,0) 位于屏幕的左上角,屏幕上仅显示正坐标。对此非常常见的解决方法是调用:

translate(width/2, height/2);

在您的void draw()方法开始时。这样 0,0 现在位于草图的中心,任何后续调用的方法rotate(radians(65))都将从草图的中心执行操作。

这也很好,因为使用P3DOPENGL渲染器的草图通常会调用 translate 以将坐标系更改为更易于使用的东西。例如,位于 0,0 或 0,0,0 的对象位于中心,这使得相机更容易围绕对象旋转或让对象围绕其中心旋转。

另一种绘制对象的流行方法是如上所述设置原点,而不是给出每个对象的坐标,即rect(-100, -50, 50, 50)在平移之前使用 popMatrix() 和 pushMatrix,然后在 0,0 处绘制每个对象,如下所示:

translate(width/2, height/2);
pushMatrix();
  translate(-100, -50);
  rect(0,0,50,50);
popMatrix();

如果您认为最终可能会迁移到 3d 渲染器,这是在 2d 渲染器中使用的好方法,因为您可以轻松替换rect()box()创建sphere()自己的方法或对象,假设原点位于 0,0 处绘制几何图形。

如果您将 x 和 y 坐标替换为变量或在 for 循环中遍历数组,则可以非常轻松地在 2d 或 3d 中绘制数百或数千个形状,而只需最少的工作量和最少的代码重写。


更新:根据他们的评论添加了对原始海报的说明。


我稍微改变了这个问题,向您展示我将如何解决这个问题。我正在使用推送和弹出矩阵展示我上面描述的翻译/旋转方法。我只是在猜测这些值,但如果您想要精确的像素,您可以在 Photoshop 或预览等图像编辑程序中进行测量。

矩形1

translate(180, 150);
rect(0, 0, 180, 80);

矩形2

translate(185, 170);
rotate(radians(65));
rect(0, 0, 180, 80);

椭圆

translate(180, 250);
ellipse(0, 0, 8, 8);

pushMatrix()将它们与和放在一起popMatrix()

void setup(){
  size(400,400);
}

void draw(){
  // rect1
  noFill();
  pushMatrix();
    translate(180, 150);
    rect(0, 0, 180, 80);
  popMatrix();
  // rect2
  pushMatrix();
    translate(185, 170);
    rotate(radians(65));
    rect(0, 0, 180, 80);
  popMatrix();
  // ellipse
  fill(0);
  pushMatrix();
    translate(180, 250);
    ellipse(0, 0, 8, 8);
  popMatrix();
}
于 2012-11-20T03:28:34.447 回答
3

旋转远离应用于原点 (0,0),因此您要绘制轴以在原点旋转。或将坐标系原点移动到您的轴。这确实令人困惑。使用转换时,我倾向于始终在原点绘制。试试这个,看看它是否让事情更清楚......或者更少:) 还有 push/popMatrix() 来控制转换的范围......

public void setup() {
  size(300, 380);
  smooth();
}
public void draw() {
  background(0);
  stroke(255);
  //use push/pop Matrix to control scope of translate and rotate
  pushMatrix();
  //move coordinates system origin to center of screen
  translate(width/2, height/2);
  // rotate with origin as axis
  rotate(radians(mouseY));
  //draw at origin (now temp moved to center of screen)
  // white line 
  line(0, 0, 150, 0);
  // here all coordinate system is back to normal
  popMatrix();

  //draw with normal system red line at origin
  stroke(255, 0, 0);
  line(0, 0, 150, 0);

    //draw with normal system blue line at centre
  stroke(0, 0, 255);
  line(width/2, height/2, width/2 + 150, height/2);
}
于 2012-11-20T02:41:35.253 回答
3

在我的特定示例中,知道如何在不更改矩形坐标的情况下平移和旋转以获得图片中的结果?

好吧,你需要在原点绘制才能正确使用旋转,所以你只是在处理矩形的原点......因为它在你的代码中,默认的原点是左上角,所以你做了一个关闭设置(从(0,0))在坐标(0,0)处绘制它的中心,而不是角,然后旋转中间。做得好。您找到的值是负半矩形宽度(-20)和负半矩形高度(-40)并非巧合。如果更改为 rectMode(CENTER),则只能在 (0,0) 处绘制。这同样适用于平移,您可以只平移到所需的点,即屏幕的中心,那里有椭圆。使用半宽和半高做什么...

看:

public void setup() {
  size(300, 200);
  smooth();
  ellipseMode(CENTER);
  rectMode(CENTER);
  noFill();
  // here converting the coordinates to work with CENTER mode
  //could have changed the rect mode just after this
  // but i kept as an illustration
  int rwidth = 40;
  int rheight = 80;
  int xpos = 100 + rwidth/2;
  int ypos = height/2 - rheight/2 ;

  rect(xpos, ypos, rwidth, rheight);

  fill(#000000);
  ellipse(width/2, height/2, 5, 5);

  noFill();
  pushMatrix();

  translate(width/2, height/2);

  //draw at origin gray
  stroke(150);
  rect(0, 0, 40, 80);
  // then rotate
  rotate(radians(65));
  // draw again black
  stroke(0);
  rect(0, 0, 40, 80);

  popMatrix();


  // here using the cordinates calculated before as a translate value 
  // we draw at origin, but it appears at same place
  stroke(230,230,100);
  // a bit to the left...
  translate(xpos-2, ypos-2);

  rect(0, 0, 40, 80);

}

于 2012-11-22T13:27:31.703 回答