Improving code which simulates harmonograph drawings

Hi everyone,

So inspired by the extremely incredible perfection of a Harmonograph drawing machine and using some of the basic principles of how it works I came down to the following code:

import processing.pdf.*;
import java.util.Calendar;

boolean savePDF = false;

float ax1 = 150;//width * 0.9 * (random(1) + random(1));
float ax2 = 150;//width * 0.9 * (random(1) + random(1));
float ay1 = 150;//height * 0.9 * (random(1) + random(1));
float ay2 = 150;//height * 0.9 * (random(1) + random(1));
float fx1 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
float fx2 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
float fy1 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
float fy2 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
float px1 = random(TWO_PI);
float px2 = random(TWO_PI);
float py1 = random(TWO_PI);
float py2 = random(TWO_PI);
float dx1 = random(0.005) + random(0.005);
float dx2 = random(0.005) + random(0.005);
float dy1 = random(0.005) + random(0.005);
float dy2 = random(0.005) + random(0.005);
float t = 0.0;

ArrayList<PVector> points = new ArrayList<PVector>();

void setup () {

  size (1080, 720, P3D);
  colorMode(HSB);
  smooth();
}

void draw() {

  if (savePDF) beginRecord(PDF, timestamp()+".pdf");

  background(0);

  float x = ax1 * sin(t * fx1 + px1) * exp(-dx1 * t) 
    + 
    ax2 * sin(t * fx2 + px2) * exp(-dx2 * t);

  float y = ay1 * sin(t * fy1 + py1) * exp(-dy1 * t)
    +
    ay2 * sin(t * fy2 + py2) * exp(-dy2 * t);

  points.add(new PVector(x, y));

  translate(width/2, height/2);


  noFill();

  float hu = 0;

  beginShape();
  for (PVector v : points) {
    stroke(hu, 255, 255);
    vertex(v.x, v.y);

    hu += 0.1;
    if (hu > 255) {
      hu = 0;
    }
  }

  endShape();

  t = t + 0.05;

  if (savePDF) {
    savePDF = false;
    endRecord();
  }
}

void mousePressed() {
  noLoop();
}

void keyPressed() {
  if (key=='s' || key=='S') saveFrame(timestamp()+"_##.jpeg");
  if (key=='p' || key=='P') savePDF = true;
}

// timestamp
String timestamp() {
  Calendar now = Calendar.getInstance();
  return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}

As long as I am satisfied with the overall output there are few things which I struggle with, like:

  • when exporting either .pdf or .jpeg/.png file it looks really bad, somehow pixelated;
  • exporting is working only while the sketch is running and it doesn't after stoping the drawing with mousePressed() function;
  • when exporting to .pdf file it always shows the drawing in one color (blue).

It will be really appreciated if someone can help me out with fixing the above.

Thx

Answers

  • .pdf shouldn't look pixelated, try enlarging it a bit and viewing.

  • Well the .pdf doesn't but it is only one color even though the code is drawn with rainbowish colors. Any suggestions how to fix that?

  • That must be a problem with using colorMode(HSB).

  • You could try using the createGraphics() method.
    See the last part in this page.

  • Or, don't bother. It doesn't work either.

  • For whatever stupid reason, it always saves the whole figure to the same color.

  • Exactly. Quite frustrating right.

  • Don't know how, but this works:

    import processing.pdf.*;
    import java.util.Calendar;
    
    boolean savePDF = false;
    
    float ax1 = 150;//width * 0.9 * (random(1) + random(1));
    float ax2 = 150;//width * 0.9 * (random(1) + random(1));
    float ay1 = 150;//height * 0.9 * (random(1) + random(1));
    float ay2 = 150;//height * 0.9 * (random(1) + random(1));
    float fx1 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
    float fx2 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
    float fy1 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
    float fy2 = int(5 * random(1) * random(1)) + 1 + 0.01 * randomGaussian();
    float px1 = random(TWO_PI);
    float px2 = random(TWO_PI);
    float py1 = random(TWO_PI);
    float py2 = random(TWO_PI);
    float dx1 = random(0.005) + random(0.005);
    float dx2 = random(0.005) + random(0.005);
    float dy1 = random(0.005) + random(0.005);
    float dy2 = random(0.005) + random(0.005);
    float t = 0.0;
    
    ArrayList<PVector> points = new ArrayList<PVector>();
    
    void setup () {
    
      size (1080, 720, P3D);
      //colorMode(HSB);
      smooth();
      strokeWeight(2);//just for thicker lines.
    }
    
    void draw() {
    
      if (savePDF) beginRecord(PDF, timestamp() + ".pdf");
    
      background(0);
    
      float x = ax1 * sin(t * fx1 + px1) * exp(-dx1 * t) 
        + 
        ax2 * sin(t * fx2 + px2) * exp(-dx2 * t);
    
      float y = ay1 * sin(t * fy1 + py1) * exp(-dy1 * t)
        +
        ay2 * sin(t * fy2 + py2) * exp(-dy2 * t);
    
      points.add(new PVector(x, y));
    
      translate(width/2, height/2);
    
      float hu = 0;
      PVector pv,v;
      for (int i = 1; i < points.size(); i++) {
        stroke(HSBtoRGB(hu, 255, 255));
        pv = points.get(i-1);
        v = points.get(i);
        line(v.x, v.y, pv.x, pv.y);
    
        hu += 0.1;
        if (hu > 255) {
          hu = 0;
        }
      }
    
      t = t + 0.05;
    
      if (savePDF) {
        savePDF = false;
        endRecord();
      }
    }
    
    void mousePressed() {
      noLoop();
    }
    
    void keyPressed() {
      if (key=='s' || key=='S') saveFrame(timestamp()+"_##.jpeg");
      if (key=='p' || key=='P') savePDF = true;
    }
    
    // timestamp
    String timestamp() {
      Calendar now = Calendar.getInstance();
      return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
    }
    
    color HSBtoRGB(float hue, float sat, float bri){
      color RGBVal = java.awt.Color.HSBtoRGB(hue/256, sat/256, bri/256);
      return RGBVal;
    }  
    
  • That's just poetry :) Thanks mate, you made my day

  • @Vankata, @Lord_of_the_Galaxy, is this something that seems like it might be a bug?

    For example, is there a way of creating a very simple sketch based on your first example that draws two lines of different colors to the screen, but saves two lines of the same color to the PDF? If so, it might be reported to Processing Issues.

  • edited November 2016

    Oh, wait, I see the problem.

    From the beginRecord() reference:

    Note that beginRecord() will only pick up any settings that happen after it has been called. For instance, if you call textFont() before beginRecord(), then that font will not be set for the file that you're recording to.

    So, @Vankata set colorMode() before calling beginRecord. The recording was not in HSB -- it was in RGB. That was the whole problem. The simplest possible fix (untested) is to add colorMode(HSB); to line 36 of the original sketch. @Lord_of_the_Galaxy 's fix is a more general approach -- convert everything to RGB and you never need to worry about how your mode is set when you start / stop recording to PDF.

  • @jeremydouglass there is just one more problem- if you saw that final part of the page, there is an option to use createGraphics and a PGraphics object to create a PDF. I set the colorMode seperately for the PGraphics object, but to no avail. The whole figure is the same color(generally blue, sometimes whitish or purplish).

Sign In or Register to comment.