Line drawing from image beautiful sketch from p5.js to processing 3

good afternoon i try to migrate this beautiful sketch https://www.openprocessing.org/sketch/486307 from p5js to processing 3.

Till now i have the following code that is “somehow” works but the lines doesn’t seem to be as “curly” and beautiful as the original.
What do you think is the matter?
excuse my english.
main tab

PImage img;


Paint paint;
//var paint;
int subStep = 400; //800;
float z = 0;  // noise
boolean isStop = false;
int count = 0;

void settings() {
  img = loadImage("aj4.jpg");
    //img = createImage(width, height,RGB);
  size(img.width,img.height);

}

void setup() {
  paint = new Paint(width/2,height/2);
  background(255, 255, 255);
  colorMode(RGB, 255, 255, 255, 255);
  img.loadPixels();
  //println(img.pixels.length);
  //paint.reset();
   // frameRate(1);
}

void draw() {
  if (!isStop) {
    for (int i = 0 ; i < subStep ; i++) {
      paint.update();
      paint.show();
      z+= 0.01;
    }
  }
  count++;
  if (count > width) {
    isStop = true;
  }
  //background(255);
  //image(img, 0, 0, width, height);
}



void keyPressed() {

  if (key == 's' || key == 'S') {
    isStop = !isStop;
  } 
}

and Paint class

class Paint {
  float x, y; 
  PVector ppos;
  PVector pos;
  Paint (float x, float y) { 
    //ppos.x = x;
    //ppos.y = y;
    ppos = new PVector(x,y);
    pos = new PVector(x,y);
    //PVector pos = new PVector(x,y);

  } 
  
  PVector vel = new PVector(0,0);
  PVector force = new PVector(0,0);

  
  float maxSpeed = 3.0; // κάνει μικρότερες γραμμές ο μικρότερος αριθμός def 3
  int perception = 5;   // def 5 
  float bound = 60; // def 60;  όριο από τις άκρες
  float boundForceFactor = 0.16; //def .16
  float noiseScale = 100.0;
  float noiseInfluence = 1 / 20.0; // def 1/20
  
  float dropRate = 0.004;  // κάθε πότε τελεία //.004
  float dropRange = 40.0;
  float dropAlpha = 150.0;
  float drawAlpha = 50.0;
  color drawColor = color(0, 0, 0, drawAlpha);
  float drawWeight = 1.0;
  int count = 0;
  int maxCount = 100;
  
  void update(){
    ppos = pos.copy();
    force.mult(0); 
    // Add pixels force
    PVector target = new PVector(0,0);
    
    int count = 0;
    for (int i = -floor(perception/2) ; i < perception/2 ; i++ ) {  // μια μήτρα από 5/2 =-2 μέχρι 2
      for (int j = -floor(perception/2) ; j < perception/2 ; j++ ) {
        if (i == 0 && j == 0)
          continue; // skip to next iteration
        int x = floor(pos.x+i);
        int y = floor(pos.y+j);
        if (x <= img.width - 1 && x >= 0 && y < img.height-1 && y >= 0) {
          int pxx = int(y) * img.width + int(x);
          color c = img.pixels[pxx];
          float b = brightness(c);
          b = 1 - b/100.0;           
          PVector p = new PVector(i, j);
          target.add(p.normalize().copy().mult(b).div(p.mag())); 
          count++;
        }
      }
    }
    if (count != 0) {
      force.add(target.div(count));
    }
    
    // Add noise force
    float n = noise(pos.x/noiseScale, pos.y/noiseScale, z);
    n = map(n, 0, 1, 0, 5*TWO_PI);
    //var p = p5.Vector.fromAngle(n);
    PVector p = PVector.fromAngle(n); //  Calculates and returns a new 2D unit vector from the specified angle value (in radians). 
    if(force.mag() < 0.01)
      force.add(p.mult(noiseInfluence * 5));
    else
      force.add(p.mult(noiseInfluence));
    
    // Add bound force
    PVector boundForce = new PVector(0,0);
    //var boundForce = createVector(0, 0);
    if (pos.x < bound) {
      boundForce.x = (bound-pos.x)/bound;
    } 
    if (pos.x > width - bound) {
      boundForce.x = (pos.x - width)/bound;
    } 
    if (pos.y < bound) {
      boundForce.y = (bound-pos.y)/bound;
    } 
    if (pos.y > height - bound) {
      boundForce.y = (pos.y - height)/bound;
    } 
    force.add(boundForce.mult(boundForceFactor));
    
    
    vel.add(force);
    vel.mult(0.9999);
    if (vel.mag() > maxSpeed) {
      vel.mult(maxSpeed/vel.mag());
    }
    
    pos.add(vel);
    if (pos.x > width || pos.x < 0 || pos.y > height || pos.y < 0) {
      reset();
    }
    
  }

  void reset() {
    img.updatePixels();
    img.loadPixels();

    count = 0;
    //maxCount = 200;
    boolean hasFound = false;
    while (!hasFound) {
      pos.x = random(1)*width;
      pos.y = random(1)*height;
      int pxx = int(pos.y) * img.width + int(pos.x);
      color c = img.pixels[pxx];
      //float c = fget(floor(pos.x), floor(pos.y));
      float b = brightness(int(c));
      if(b < 35)
        hasFound = true;
    }
    int pxx = int(pos.y) * img.width + int(pos.x);
    drawColor = img.pixels[pxx];
    drawColor = color(red(drawColor),green(drawColor),blue(drawColor),drawAlpha);
    ppos = pos.copy();
    vel.mult(0);
  }

  void show() {
    count++;
    if (count > maxCount)
      reset();
    stroke(drawColor);
    strokeWeight(drawWeight);
    if (force.mag() > 0.1 && random(1) < dropRate) {
      //drawColor.setAlpha(dropAlpha);
      stroke(drawColor);
      float boldWeight = drawWeight+random(5);
      strokeWeight(boldWeight);
      //drawColor.setAlpha(drawAlpha);
    }
    line(ppos.x, ppos.y, pos.x, pos.y);
    // doesn't seem to do much from what i saw
   // fadeLineFromImg(ppos.x, ppos.y, pos.x, pos.y);
  }
  

  
}
1 Like

In Paint class,
int perception = 5, should be float perception = 5.

Maybe the sketch can work better

1 Like

indeed it is a lot better. I though i declared everything except the counters as variables, but the perception was a problem that tended the vectors to “flow” in one direction as int.

I guess the only thing left is something with alpha values ( even with a lot of fewer steps) that leads the java - processing sketch to be more shadowed than the original. I guess it is the b variable (brightness) that returns different values for some reason

Thank you

1 Like

can anyone maybe explain the code a bit? found it hard for me to understand. thx :pray: