Why do i get "spikes" in these circles?

edited December 2017 in Questions about Code
// 4 circles intersecting at mouse pointer

//  to do
// make it a class

void setup() {
   size(840, 600, P3D);
   noFill();
   smooth();
}

void draw() {
   background(255);

   float lastX = mouseX;
   float lastY = mouseY;
   float lastW1= 2*sqrt(sq(lastX)+sq(lastY));
   float lastW2= 2*sqrt(sq(lastX-width)+sq(lastY));
   float lastW3= 2*sqrt(sq(lastX)+sq(lastY-height));
   float lastW4= 2*sqrt(sq(lastX-width)+sq(lastY-height));
   stroke(255,0,0,10);
   for (int i = 80 ; i> 1;i=i-8){  
     strokeWeight(lastW1/i);      
     ellipse(0, 0, lastW1, lastW1);
   }
   stroke(0, 255,0,10);
   for (int i = 80 ; i> 1;i=i-8){  
     strokeWeight(lastW2/i);  
     ellipse(width, 0, lastW2, lastW2);
   }
   stroke(0,0,255,10);
   for (int i = 80 ; i> 1;i=i-8){  
      strokeWeight(lastW3/i);  
      ellipse(0, height, lastW3, lastW3);
   }
   stroke(128,128,128,10);
   for (int i = 80 ; i> 1;i=i-8){  
      strokeWeight(lastW4/i);  
      ellipse(width, height, lastW4, lastW4);
   }
 }

Answers

  • What do you mean by spikes?

  • edited December 2017

    spikes

    those spikes (linux, processing 3.3.6)

    it's because the ellipses are draw in tiny bits and the transparency means the overlaps of those tiny bits look darker.

  • Answer ✓

    it's better if you don't use p3d

  • Without PD or with P2D they disappear!

  • edited December 2017

    Can you tell us what you're trying to do? What's your actual end goal? Do you have any example mock images?

  • edited December 2017

    @Eddybb3 -- If a 2D drawing method with alpha (transparency) causes artifacts -- such as darker areas of self-intersection -- one workaround is to draw without alpha to a PGraphics buffer, then apply the flat image with alpha (e.g. using tint()) to the main canvas.

  • I am trying to visualize triangulation where the the certainty of a distance to a source (4 with a "known" location) is given by the color depth and width of the source circle circumference. The "darkest" point would be the most probable location of the mouse pointer.

    Any help or pointers to a tutorial to make this into a "class" for each source would be nice as i am a newby in processing/programming!

    Old school: basic/fortran/pascal, trying to pick up again. (:))

  • class Ring {
      float cx, cy;
      Ring(float icx, float icy){
        cx = icx;
        cy = icy;
      }
      void draw(){
        float d = dist(cx,cy,mouseX,mouseY);
        noFill();
        stroke(255);
        ellipse(cx,cy,2*d,2*d);
      }
    }
    
    Ring[] rings;
    
    void setup(){
      size(800,800);
      rings = new Ring[5];
      rings[0] = new Ring(0,0);
      rings[1] = new Ring(width,0);
      rings[2] = new Ring(0,height);
      rings[3] = new Ring(width,height);
      rings[4] = new Ring(width/2,height/2);
    }
    
    void draw(){
      background(0);
      for( Ring r : rings ) r.draw();
    }
    

    You can add colors to it.

  • Thanks, but what if i dont know how many "rings" there are, and some may appear/disappear? I saw something about constructor/destructor for classes. But as i said i am a newbie, could use a good reference/tutorial for this topic

  • The constructor function for the Ring class is lines 3 to 6 - it's the function that shares the same name as the class and doesn't have a return type. This is the function that you call when you want to make an instance of this class. Notice I call it 5 times to create five Rings.

    Imagine the class is a blueprint for a thing. It also tells you how to make the thing. The constructor function is the directions to create a new thing. For example, your blueprint could describe the floor plan of a house. The constructor function would then be the directions to build the house, and the instance of the class - the actual object that results from making a new one - is the house itself.

    A destructor function is similar, except it is special directions for when you're getting rid of an object. You might need to take special care with some steps. The analogy is that you COULD just level the house with a bulldozer, sure, but it might be nicer if, before destroying the house, you made sure that it was empty, the water was shut off, and the power was disconnected. Generally, however, you won't need to worry about destructors for your objects in Processing.

  • Thankfully, now that we have a class that describes the object, it is much easier to write some more code to have a structure that stores an ever-changing number of them. The analogy is that you have a street that has space for several houses on it. The street starts with no houses, and you can add a bunch of houses by building them (by following the directions IE the constructor functions).

    The best structure for this is an ArrayList, which you can read all about if you search for it. Here's an example:

    class Ring {
      float cx, cy;
      int time;
      Ring(float icx, float icy){
        cx = icx;
        cy = icy;
        time = millis() + int(random(5000,20000));
      }
      boolean draw(){
        float d = dist(cx,cy,mouseX,mouseY);
        noFill();
        stroke(255);
        ellipse(cx,cy,2*d,2*d);
        return( millis() > time );
      }
    }
    
    ArrayList<Ring> rings;
    
    void setup(){
      size(800,800);
      rings = new ArrayList();
    }
    
    void draw(){
      background(0);
      for(int i = rings.size()-1; i >= 0; i--) if( rings.get(i).draw() ) rings.remove(i);
    }
    
    void mousePressed(){
      rings.add( new Ring(mouseX, mouseY) );
    }
    

    Now when you click, it adds a new Ring to the ArrayList. These rings now only last for some random amount of time.

Sign In or Register to comment.