Create a letter 'B' by using rotating lines

edited November 2016 in Questions about Code

Hi guys! I've just started learning Processing. Maybe my question will be too obvious for someone, but I would appreciate if you could help me to figure out how to create a shape of a letter (ex. 'B') by using only line. I already managed to create a background by using rotating lines. The tricky thing for me is to create the shape of a letter 'B' with the same lines.

Also I attached the image of what I am trying to achieve below. Thanks in advance for any thoughts!

Screen Shot 2016-11-29 at 22.26.43

Here is a code that I wrote so far.

float angle;
float radius;

void setup() {
  size(400, 400, P2D);
  smooth(5);
}

void draw () {
  background (255);
  for (int x = 0; x < width; x += 40) {
    lineRotate(x, height);
    for (int y = 0; y < height; y += 40) {
      lineRotate(x, y);
    }
  }
}
void lineRotate(float x, float y) {
  pushMatrix();

  translate(x, y);

  strokeWeight(1);
  radius = 20;
  x = radius * cos(angle);
  y = radius * sin(angle);
  line(x + radius, y + radius, radius - x, radius - y);
  angle = PI/ 4 * second();

  popMatrix();
}

Answers

  • Please edit your post (click the upper-right gear icon )and format your code correctly (highlight the code and press CTRL-o to indent four spaces).

    Once you do there are related rotation-based sketch discussions that might help you.

  • edited November 2016

    thanks, jeremydouglass! Hope now it reads better:-))

  • Answer ✓

    How many letters are you planning to draw?

    Before drawing lines, it is important to generate the coordinates of the center of each line inside each letter. The code above only draws the background so far. I will suggest you post next an array of points describing the center of each line for each letter. This is a tedious task but it has to be done only once. To make things easier, do it for a single letter (example B) to prove the concept.

    Or what thoughts do you have to approach your challenge?

    Kf

  • edited December 2016 Answer ✓

    Thanks @yura.

    Recently there was another thread about mapping rotated objects (images, or drawn lines) based on analyzing the per-pixel values of an underlying image.

    You can find that discussion here:

    https://forum.processing.org/two/discussion/18443/svg-rotation-based-on-pixel-value

    Good luck, and let us know what you come up with!

  • thanks @kfrajer and @jeremydouglass for your advises. For now, I'll focus on only one letter ("B"). There are already enough challenges for me as a beginner;I'll try follow your recommendations and I'll let you know about my result. Thanks again!

  • edited December 2016

    see also here but not connected to your problem immediately

    https://forum.processing.org/two/discussion/comment/79932/#Comment_79932

    you can derive from here this approach. It takes the invisible image pg and reads the pixels of D there :

    // https://forum.processing.org/two/discussion/comment/79932/#Comment_79932
    
    PFont f;
    PGraphics pg;
    
    void setup() {
    
      size(700, 700);
      background(255);
    
      f=createFont("Arial", 300);
      fill(0);
      textFont(f);
    
      pg = createGraphics(width, height);
      pg.noSmooth();  
      pg.beginDraw();
      pg.background(255);
      pg.fill(0);
      pg.textFont(f);
      pg.text("D", 270, 400);
      pg.endDraw();
    }
    
    void draw() {
    
      background(2);
    
      stroke(0, 225, 0);
    
      for (int x=0; x < pg.width; x+=2) {
        for (int y=0; y < pg.height; y+=3) {
          if (pg.get(x, y) < color(1)) 
            point(x, y) ;
        }
      }
    }
    //
    
  • edited December 2016

    thank you @Chrisir

  • edited December 2016

    Hi guys @jeremydouglass @kfrajer @Chrisir ... it is me again...I feel that I stuck and I don't know how to move forward with my project. I thought that it won't be so hard to draw and rotate a letter 'B' with an array. But it is hard task. Initially, my plan was 1/ create a background with rotating lines; 2/ create array for a line. 3/ to map/affect some arrays which form letter 'B' and to give them different parameters than other arrays lines have.

    There is a second sketch where I tried to create arrays for line which will rotate like in the 1st sketch.

    Maybe I am doing something wrong...I'd appreciate for some practical advise! Thanks!

    float angle;
    float x;
    float y;
    
    int [] line = new int [width];
    
    void setup() { 
      size(400, 400, P2D);
      smooth();
    }
    
    void draw() {
      background(255);
      strokeWeight(1);
      fill(0);
    
    
      for (int x = 0; x < line.length; x ++) {
        line(x*10 +10, 10, x*10+15, 10);
        for (int y = 0; y < line.length; y ++) {
          line(x*10 +10, y*10, x*10+15, y*10);
        }
      }
    
       float radius = 5;
      float x = radius * cos(angle);
      float y = radius * sin(angle);
      line(radius + x, radius + y, radius - x,  radius - y);
      angle = PI / 4 * second();
    
    }
    
  • edited December 2016

    @yura -- I think you are on the right track.

    One approach might be to use a big graphical "B" as input. Here is a big "B":

    void setup(){
      size(200, 300);
      textSize(350);
      textAlign(CENTER,CENTER);
    }
    void draw(){
      translate(width/2.0,height/2.0 - 40);
      text("B",0,0);
    }
    

    Try drawing the B into a PGraphics object or copying it into a PImage. Then, when you loop through your grid of lines, check that pixel values inside the image with get(). If the pixel is white, rotate your line before drawing it to the canvas -- if it isn't white, just draw a flat line.

    In other words, you are combining image data generated like in the simple sketch above with a simple grid/checkerboard sketch of point-sampling and drawing, like here:

    int xsteps, ysteps;
    float xunit, yunit;
    void setup() {
      size(200, 300);
      xsteps = 20;
      ysteps = 26;
      xunit = width/(float)xsteps;
      yunit = height/(float)ysteps;
    }
    
    void draw() {
      for (int y=0; y<ysteps; y++) {
        for (int x=0; x<xsteps; x++) {
          // check something, draw something!
          point(x*xunit,y*yunit);
        }
      }
    }
    

    Keep in mind that the more complex sketch at https://forum.processing.org/two/discussion/18443/svg-rotation-based-on-pixel-value turns any image into any set of subimages. It could turn a map into a bunch of hands or arrow; it could also turn a picture of a "B" into a bunch of slashes just by changing the map image to a B image and the hand image to a slash image. It is really about taking any image and turning it into a bunch of small images or small drawings.

  • thank you @jeremydouglass putting me on the right track. I'll try to do this way...

  • edited December 2016

    Hey guys! Thanks for all your time and advises you gave me. It seems like all parts in this puzzle start to work together and with your help I made this letter 'B' with rotating lines. I copied the code below.

    Only one question left; is it possible to read data outside a shape of the letter and manipulate with them (let's say to rotate the same lines with slight delay)?

    //   ![sketch-letter](https://forum.processing.org/two/uploads/imageupload/235/U8FGUIEE23EZ.jpg "sketch-letter")
    
    PImage letter;
        float radius;
        float angle;
    
        void setup() {
          size (600, 600);
          background(255);
          letter = loadImage("letter-b.png");
        }
    
        void draw() {
    
          loadPixels();
          letter.loadPixels();
          for ( int x = 0; x < width; x ++) {
            for (int y = 0; y < height; y ++) {
              int loc = x + y * width;
              float b = brightness(letter.pixels[loc]);
              pixels[loc] = color(b);
              if (b > 0) {
                pixels[loc] = color (255);
              }
            }
          }
          updatePixels();
    
          for (int x=0; x < width; x+=25) {
            for (int y=0; y < height; y+=25) {
              if (letter.get(x, y) < color(150)) {
                lineRotate(x, y);
              }
            }
          }
        }
        void lineRotate(float x, float y) {
          pushMatrix();
          translate(x, y);
          strokeWeight(1);
          stroke(0);
          radius = 10;
          x = radius * cos(angle);
          y = radius * sin(angle);
          line(x + radius, y + radius, radius - x, radius - y);
          angle = PI/ 4 * second();
          popMatrix();
        }
    
  • read data outside a shape of the letter and manipulate with them (let's say to rotate the same lines with slight delay)?

    You can layout the background first and manipulate it as a whole. Then you draw on top of your background using your letter algorithm.

    Another option is this:

    lineRotate() modified:

    void lineRotate(float x, float y, color c, int wt,float angleOffset) {
      pushMatrix();
      translate(x, y);
      strokeWeight(1);
      stroke(c);
      strokeWeight(wt);
      radius = 10;
      x = radius * cos(angle);
      y = radius * sin(angle);
      line(x + radius, y + radius, radius - x, radius - y);
      angle = PI/ 4 * second()+angleOffset;
      popMatrix();
    }
    

    Now your a section of your draw() needs to be modified:

      if (letter.get(x, y) < color(150)) {
        lineRotate(x, y,color(0),3,0);
      }
      else{
        lineRotate(x, y,color(68),1,-PI/2);
      }
    

    Try PI/2,PI/3,PI/6 for 90,60 or 30 degree delays. Remember the offset angle can also be positive. One last question. What is the relation between your letter image and your canvas? I will suggest adding letter.resize(width,height); right after you load your letter figure, in case your letter is bigger than your sketch. That is only a suggestion.

    Kf

  • Answer ✓

    An alternative to above, instead of using an offset in the function, use that value as the actual angle:

    void lineRotate(float x, float y, color c, int wt,float anAngle) {
      (................)   SKIPPED LINES
      angle = anAngle * second();
      popMatrix();
    }
    

    Kf

  • thanks @kfrajer, I'll try your way.

  • edited December 2016

    @kfrajer everything works perfectly!

    Thanks to everyone for their time and help!!! :)

Sign In or Register to comment.