使用 Processing 生成图案并在偶数行图像之间的奇数行上渲染每个图像

Generate a pattern and render each image on the odd rows between the images of the even rows with Processing

在使用 Processing (Processing.org) 构建模式生成器方面寻求帮助。

我正在尝试使用这样的处理来生成模式:

- - - - -
 - - - - -
- - - - - 
 - - - - -
- - - - - 

目前我已经创建了这样一个模式:

- - - - - 
- - - - -  
- - - - -
- - - - -
- - - - - 

这是我在 build.pde 文件中的代码:

import processing.pdf.*;
HDrawablePool pool;
HColorPool colors;

void setup(){
    size(1000,1000);
    H.init(this).background(#ffffff);
    smooth();

    colors = new HColorPool(#111111);

    pool = new HDrawablePool(1000);
    pool.autoAddToStage()
                .add(new HShape("cv_bitter01.svg"))
                .add(new HShape("cv_bitter02.svg"))
                .add(new HShape("cv_bitter03.svg"))
                .add(new HShape("cv_bitter04.svg"))
                .add(new HShape("cv_bitter05.svg"))
                .add(new HShape("cv_bitter06.svg"))
                .add(new HShape("cv_bitter07.svg"))
                .add(new HShape("cv_bitter08.svg"))
                .add(new HShape("cv_bitter09.svg"))
                .add(new HShape("cv_bitter10.svg"))    

        .layout(
            new HGridLayout()
            .startX(25)
            .startY(25)
            .spacing(40,40)
            .cols(30)
        )

        .onCreate(
            new HCallback() {
                public void run(Object obj) {
                    HShape d = (HShape) obj;
                    d
                        .enableStyle(false)
                        .strokeJoin(ROUND)
                        .strokeCap(ROUND)
                        .strokeWeight(2)
                        .stroke(#000000)
                                                .rotation( (int)random(-15,15) )
                                                .anchorAt(H.CENTER)
                    ;
                    d.randomColors(colors.fillOnly());
                                
                }
            }
        )
        .requestAll()
  ;

  saveVector();
  noLoop();
}
 
void draw() {
  H.drawStage();
}

void saveVector() {
  PGraphics tmp = null;
  tmp = beginRecord(PDF, "render.pdf");

  if (tmp == null) {
    H.drawStage();
  } else {
    H.stage().paintAll(tmp, false, 1); // PGraphics, uses3D, alpha
  }

  endRecord();
}

HGridLayout是一个矩形网格。

对于您想要的模式,请改用 HHexLayout

看看下面的 HHexLayout 示例:

更新您可以使用十六进制布局,但是,仔细观察后,将绘制出屏幕外的元素。

该模式也称为 diagrid and you could generate it in multiple ways. One basic method is keep offset every other row on the x axis. You can check if a row is even or odd using the remainder of the integer division operation using the modulo(%) operator:

for(int i = 0; i < 10; i++){
  if(i % 2 == 0){
    println(i, "is even)");
  }else{
    println(i, "is odd)");
  }
}

如果您查看 HGridLayout source code,您会注意到 x、y 位置是如何根据行、列索引计算的。

您可以复制此 class,将其命名为 HDiagrid,并在相同的网格行为之上,添加一个额外的变量来跟踪 x 轴上要应用的额外偏移量另一排。在您的文本注释中,偏移量应用于奇数行,因此使用 row % 2 == 1 检查当前要计算的位置是否在奇数行,因此应应用对角线网格 x 偏移量。

这是一个基本示例,重新混合了 Hype 的 HGridLayout_001:

import hype.*;
import hype.extended.layout.HGridLayout;

HDrawablePool pool;

void setup() {
    size(640,640);
    H.init(this).background(#242424);

    pool = new HDrawablePool(192);
    pool.autoAddToStage()
        .add(new HRect(25).rounding(4))

        .layout(
            new HDiagridLayout()
      //new HGridLayout()
            .startX(28)
            .startY(21)
            .spacing(26 * 3, 26)
            .cols(8)
        )
        
        .onCreate(
             new HCallback() {
                public void run(Object obj) {
                    HDrawable d = (HDrawable) obj;
                    d.noStroke().fill(#ECECEC).anchorAt(H.CENTER);
                }
            }
        )
        .requestAll()
    ;

    H.drawStage();
    noLoop();
}

void draw() {

}

import hype.HDrawable;
import hype.interfaces.HLayout;
import processing.core.PVector;

// a modified copy of https://github.com/hype/HYPE_Processing/blob/master/src/main/java/hype/extended/layout/HGridLayout.java

public class HDiagridLayout implements HLayout {
  private int currentIndex, numCols, numRows;
  private float startX, startY, startZ, xSpace, ySpace, zSpace;
  // extra property to for diagonal grid horizontal offset
  private float diagridOffset;

  public HDiagridLayout() {
    xSpace = ySpace = zSpace = numCols = 16;
    // update horizontal offset
    diagridOffset = xSpace * 0.5;
    numRows = 0;
  }

  public HDiagridLayout(int numOfColumns) {
    this();
    numCols = numOfColumns;
  }

  public HDiagridLayout(int numOfColumns, int numOfRows) {
    this();
    numCols = numOfColumns;
    numRows = numOfRows;
  }

  public HDiagridLayout currentIndex(int i) {
    currentIndex = i;
    return this;
  }

  public int currentIndex() {
    return currentIndex;
  }

  public HDiagridLayout resetIndex() {
    currentIndex = 0;
    return this;
  }

  public HDiagridLayout cols(int numOfColumns) {
    numCols = numOfColumns;
    return this;
  }

  public int cols() {
    return numCols;
  }

  public HDiagridLayout rows(int numOfRows) {
    numRows = numOfRows;
    return this;
  }

  public int rows() {
    return numRows;
  }

  public PVector startLoc() {
    return new PVector(startX, startY, startZ);
  }

  public HDiagridLayout startLoc(float x, float y) {
    startX = x;
    startY = y;
    startZ = 0;
    return this;
  }

  public HDiagridLayout startLoc(float x, float y, float z) {
    startX = x;
    startY = y;
    startZ = z;
    return this;
  }

  public float startX() {
    return startX;
  }

  public HDiagridLayout startX(float x) {
    startX = x;
    return this;
  }

  public float startY() {
    return startY;
  }

  public HDiagridLayout startY(float y) {
    startY = y;
    return this;
  }

  public float startZ() {
    return startZ;
  }

  public HDiagridLayout startZ(float z) {
    startZ = z;
    return this;
  }

  public PVector spacing() {
    return new PVector(xSpace, ySpace, zSpace);
  }

  public HDiagridLayout spacing(float xSpacing, float ySpacing) {
    xSpace = xSpacing;
    ySpace = ySpacing;
    // update horizontal offset
    diagridOffset = xSpace * 0.5;
    return this;
  }

  public HDiagridLayout spacing(float xSpacing, float ySpacing, float zSpacing) {
    xSpace = xSpacing;
    ySpace = ySpacing;
    zSpace = zSpacing;
    // update horizontal offset
    diagridOffset = xSpace * 0.5;
    return this;
  }

  public float spacingX() {
    return xSpace;
  }

  public HDiagridLayout spacingX(float xSpacing) {
    xSpace = xSpacing;
    // update horizontal offset
    diagridOffset = xSpace * 0.5;
    return this;
  }

  public float spacingY() {
    return ySpace;
  }

  public HDiagridLayout spacingY(float ySpacing) {
    ySpace = ySpacing;
    return this;
  }

  public float spacingZ() {
    return zSpace;
  }

  public HDiagridLayout spacingZ(float zSpacing) {
    zSpace = zSpacing;
    return this;
  }

  @Override
  public PVector getNextPoint() {

    int layer = 0;
    int row = 0;
    int col = currentIndex % numCols;

    if (numRows > 0) {
      layer = (int) Math.floor( currentIndex / (numCols * numRows) );
      row = (int) Math.floor(currentIndex / numCols) - (layer * numRows);
    } else {
      row = (int) Math.floor(currentIndex / numCols);
    }

    ++currentIndex;
    // every other row the x value will be offset by an amount
    // on even rows it's 9
    float xOffset = 0;
    // if the row is odd (remainder of integer division by 2 is 1) (see % operator reference)
    if(row %  2 == 1){
      // apply the diagonal grid offset
      xOffset = diagridOffset;
    }
    // add xOffset (be it 0 on even rows or not
    if (numRows > 0) {
      return new PVector(col* xSpace + startX + xOffset, row* ySpace + startY, layer* zSpace + startZ);
    } else {
      return new PVector(col* xSpace + startX + xOffset, row* ySpace + startY);
    }
  }

  @Override
  public void applyTo(HDrawable target) {
    target.loc(getNextPoint());
  }
}

产生这个:

注意上面示例中的 diagridOffsetspacingX 的一半。 这只是一个例子:它可以是另一个比例,甚至可以独立于 spacingX。此外,您可以添加 getter 和 setter 方法(例如类似于 public float spacingX()public HDiagridLayout spacingX(float xSpacing))。

玩得开心!