【问题标题】:Sierpinski carpet in processing正在加工的谢尔宾斯基地毯
【发布时间】:2017-05-12 10:47:56
【问题描述】:

所以我在处理中使用Square 数据类型制作了谢尔宾斯基地毯分形,该数据类型绘制一个正方形并具有一个函数generate(),它从自身生成9 个相等的正方形并返回一个ArrayList (9 -1)=8 去除中间的方块(它不会添加到返回的ArrayList)以生成谢尔宾斯基地毯。

这里是 Square 类 -

class Square {

  PVector pos;
  float r;

  Square(float x, float y, float r) {
    pos = new PVector(x, y);
    this.r = r;
  }
  void display() {
    noStroke();
    fill(120,80,220);
    rect(pos.x, pos.y, r, r);
  }
  ArrayList<Square> generate() {

    ArrayList<Square> rects = new ArrayList<Square>();

    float newR = r/3;

    for (int i=0; i<3; i++) {
      for (int j=0; j<3; j++) {
        if (!(i==1 && j==1)) {
          Square sq = new Square(pos.x+i*newR, pos.y+j*newR, newR);
          rects.add(sq);
        }
      }
    }

    return rects;
  }
}

这是通过鼠标单击向前生成的主要草图 -

ArrayList<Square> current;

void setup() {
  size(600, 600);
  current = new ArrayList<Square>();

  current.add(new Square(0, 0, width));
}

void draw() {
  background(255);
  for (Square sq : current) {
    sq.display();
  }
}

void mousePressed() {
  ArrayList<Square> next = new ArrayList<Square>();

  for(Square sq: current) {
    ArrayList<Square> rects = sq.generate();
    next.addAll(rects);
  }
  current = next;
}

问题:

我得到的输出有很细的白线,不应该在那里:

第一代 -

第二代 -

第三代 -

我的猜测是,这些线条只是由于generate() 中的计算偏离一两个像素而出现的白色背景。但是我不确定如何摆脱这些。任何帮助将不胜感激!

【问题讨论】:

  • 我注意到您在显示正方形时调用了noStroke()。我不使用处理,但我在其他需要描边和填充正方形的情况下看到了类似的问题。
  • 您说您对正在发生的事情有所猜测。这意味着是时候debug 你的程序来确认你的怀疑了。尝试将其缩小到一个正方形。它的坐标和大小是多少?它们是如何绘制的?如果您在将其缩小到一个正方形后仍然无法弄清楚,那么请发布minimal reproducible example,仅显示该正方形而不是您的整个草图,我们将从那里开始。祝你好运。
  • @KevinWorkman 我证实了我的怀疑,这正是正在发生的事情!现在,画布是 600x600,只能被 3 整除一次,如果我们再次划分,我们会进入小数,并且在第 2 代出现白线。现在,我将大小更改为 900x900,它可以被 3 整除两次,因此这次白线出现在2代之后,即第三代!但是,我无法弄清楚如何准确解决此问题。
  • @KevinWorkman 一个快速解决方法是删除noStroke() 并使笔触与填充颜色相同,它会删除线条但会弄乱后代中的较小方块并使它们看起来不合适这是不希望的。

标签: processing fractals


【解决方案1】:

这是一个演示您的问题的较小示例:

size(1000, 100);
noStroke();
background(0);

float squareWidth = 9.9;
for(float squareX = 0; squareX < width; squareX += squareWidth){
 rect(squareX, 0, squareWidth, height); 
}

请注意,黑色背景通过方块显示。请尝试在将来发布这种最小的示例而不是您的整个草图。

无论如何,有三种方法可以解决这个问题:

选项1:调用noSmooth()函数。

默认情况下,Processing 使用抗锯齿功能使您的绘图看起来更平滑。通常这是一件好事,但它也会给形状的边缘添加一些模糊性。如果您禁用抗锯齿,您的形状将更加清晰,您将看不到伪影。

选项 2:使用与填充颜色相同的笔触。

正如您已经发现的那样,这会在形状周围绘制轮廓。

选项 3: 使用 int 值而不是 float 值。

您将坐标和大小存储在 float 值中,其中可以包含小数位。问题是,屏幕(显示器上的实际像素)没有小数位(没有半个像素之类的东西),所以它们由int 值表示。因此,当您将 float 值转换为 int 时,小数部分会被丢弃,这可能会导致您的形状出现小间隙。

如果您只是切换到使用 int 值,问题就会消失:

size(1000, 100);
noStroke();
background(0);

int squareWidth = 10;
for(int squareX = 0; squareX < width; squareX += squareWidth){
 rect(squareX, 0, squareWidth, height); 
}

【讨论】:

  • 选项 1 与选项 2 一样,使白线消失但使较小的正方形变形,选项 3 仍然留下白线,但在最终图像中有所不同。 Here are some pictures for each case.
  • @MasterYushi int 转换必须从一开始就发生。您无法从 float 转换为 int。您必须将所有内容存储为int
  • 我就是这么做的,用int重写了整个课程
  • @MasterYushi PVector 在内部使用float
猜你喜欢
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-09
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多