isn't stroke strange?

First time i noticed and i really don't care :)

But isn't it strange that a stroke starts on the inside and ends on the outside?

stroke(255, 0, 0); rect(0, 0, width, height);

Answers

  • edited May 2014

    Coordinates width & height are outside canvas already! Why? B/c 1st coordinate is 0!
    Let's say that canvas is size(800, 600);. It means coordinate x is from 0 to 799 & y is from 0 to 599!
    To prove that correctly, turn off anti-aliasing: noSmooth(); or smooth(0);before issuing rect()! ;)

  • Yeah but a rect width a width of 100 with noStroke has a width of 100. A rect width a width of 100 with a stroke has a width of 101. Wouldn't it make more sense if it had a width of either 100 (inner stroke) or 102 (outer stroke) like indesign also works.

    I don't follow your smooth thing: Like this?

    noSmooth();
    stroke(255, 0, 0); 
    rect(0, 0, width, height);
    
  • edited May 2014

    Like you said: perhaps the rect()'s algorithm only takes into consideration the dimensions w/o the outline stroke()!? :-/
    In the example below, rect(0, 0, width - 1, height - 1); actually fails to fill up whole canvas: @-)

    // forum.processing.org/two/discussion/4928/isnt-stroke-strange
    
    noLoop();
    noSmooth();
    clear();
    
    noStroke();
    //stroke(#FF0000);
    fill(#008000);
    
    //rect(0, 0, width, height);
    rect(0, 0, width - 1, height - 1);
    
    /**
     * Searches for color #000000 existence.
     * Negative means not found!
     */
    
    loadPixels();
    println(java.util.Arrays.binarySearch(pixels, #000000));
    
  • It's logic it fails fill up the whole canvas. Yo draw smaller then the width without a stroke. Nice thing with the binarySearch, good to know :) I remember programming a method like that in the book of ben fry.

  • edited May 2014

    It's logic it fails fill up the whole canvas.

    But rect(0, 0, width - 1, height - 1); wouldn't fail if stroke(#FF0000) is uncommented! :P

    Nice thing with the binarySearch()...

    It's still very exotic for me! Even though it's the 3rd time I use it! /:)

  • I don't follow your sketch anymore :) What are you trying to do / show?

  • edited May 2014 Answer ✓

    The idea behind doing this is probably consistency with multiple objects.

    If you have a rect() at x position 0, its width is 100, and then you have another rect() at x position 100 then they will share a stroke() boundary. If this was not the case then there would be a stroke() of double thickness. The case is the same on the y axis:

    void setup() {
      size(300, 300);
      rect(0, 0, 100, 100);
      rect(100, 0, 100, 100);
      rect(0, 100, 100, 100);
      rect(100, 100, 100, 100);
    }
    

    What is more typical for filling the entire screen is background()

    Edit: Perhaps another design choice was that this way the only special case is when an object is at the far right or bottom rather than every time objects are near each other

  • edited May 2014

    What are you trying to do / show?

    Exactly what u had pinpointed: w/ noStroke(), rect()'s coords go from 0 to (width & height) - 1. Which is correct!
    W/ stroke() active, it's from 0 to width & height. Which is 1 pixel more beyond canvas! 3:-O

    And consequently, rect() is lying to us about its dimension parameters!
    We coulda asked for a 100x100, but it ends up rendering 101x101!!! :-w

  • Good answer asimes. never thought of it that way :)

  • edited January 2018

    I work on a algorithm at the moment and this thing is driving me nuts. If processing was made by me I would fix the damn thing...

    Maybe it makes sense:

    void setup() {
      size(32, 32, JAVA2D);
    }
    
    void draw() {
    
    
      stroke(0, 255, 0);
      beginShape();
      // Exterior part of shape, clockwise winding
      vertex(4, 4);
      vertex(24, 4);
      vertex(24, 24);
      vertex(4, 24);
      //stroke(0, 255, 0);
      // Interior part of shape, counter-clockwise winding
      beginContour();
      vertex(8, 8);
      vertex(8, 16);
      vertex(16, 16);
      vertex(16, 8);
    
      endContour();
      //stroke(0, 0, 255);
      //noStroke();
      endShape(CLOSE);
    
      if (mousePressed) {
        stroke(255, 0, 0);
        line(4, 4, 24, 4);
        line(24, 4, 24, 24);
        line(24, 24, 4, 24);
        line(4, 24, 4, 4);
      }
    
      //saveFrame();
      //exit();
    }
    
  • the thing asimes describes has a technical name. things like this are described as "half-open" and it is to stop coincident edges being rendered twice - think what would happen if something with 50% alpha was drawn twice

  • @koogs can you elaborate on that?

  • it's something i remember from reading sunos graphics manuals in the 1980s (lol, old) but couldn't find a decent link last week when it came up. there's some talk about it here:

    https://en.wikibooks.org/wiki/Cg_Programming/Rasterization

    specifically

    "There are certain rules for cases when the center of a pixel is exactly on the boundary of a primitive. These rules make sure that two adjacent triangles (i.e. triangles that share an edge) never share any pixels (unless they actually overlap) and never miss any pixels along the edge; i.e. each pixel along the edge between two adjacent triangles is covered by either triangle but not by both. This is important to avoid holes and (in case of semitransparent triangles) multiple rasterizations of the same pixel. The rules are, however, specific to implementations of GPUs. Moreover, other APIs than OpenGL may specify different rules. Thus, they won't be discussed here."

  • as for this bit

    think what would happen if something with 50% alpha was drawn twice

    the first drawing would use 50% of the existing background colour and 50% of the new colour. the second iteration would use 50% of the new background colour (which includes the 50% of the new colour drawn on the first pass) and another 50% of the new colour. so the edge would look different from the rest of the polygon.

  • Thanks.

    void setup() {
      size(300, 300);
    }
    
    void draw() {
       background(255, 0, 0);
       fill(50, 50);
       stroke(0, 50);
       triangle(20, 200, 150, 50, 150, 200);
       triangle(150, 50, 150, 200, 290, 200);
    }
    

    Screen Shot 2018-01-24 at 20.54.41

    It seems to be more about avoiding double edges. So 2 adjacent 1px stroke triangles don't form a 2 pixel edge. Cause the problem you describe with the 50% is happening atm cause processing is drawing outside the shape on the right and the bottom...

Sign In or Register to comment.