How do I refer to the multiple objects in an array?

edited December 2014 in How To...

Hello guys, I am new to Processing. I hope that someone can help me. I have an array of objects (circles positioned randomly) and whenever any of them have the distance of 200px or less between each other they are connected with a line. The only way I found to connect them is by creating another array on top of that one but it doesn't seem right since another instance of circles is created and placed on top of the first one.
Here is the code:

    Bubble[] myBubble = new Bubble[20];

    void setup() {
      size(500, 500); 
      for (int i=0; i <myBubble.length; i++) {
        int s = 20;
        int x1 = int(random(500)); 
        int y1 = int(random(500)); 
        int z = int(random(2)); 
        color c1; 
        if ( z>=1) {
          c1 = color(255, 0, 0);
        } else {
          c1= color(0, 0, 255);
        } 
        myBubble [i] = new Bubble( x1, y1, c1, s);
      }
    }
    void draw() {
      background(255);
      for (int i = 0; i <myBubble.length; i++) {
        for (int j = 0; j <myBubble.length; j++) {    
          myBubble [i] .display(); 
          if (dist(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y) <= 100) {
            line(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y);
          }
        }
      }
    }
    class Bubble {
      int x;
      int y;
      int size;
      color cor;
      int count; 

      Bubble() {
        x=250;
        y=250;
        cor = color(255, 255, 0);
        size =20;
        count =0;
      }
      Bubble ( int _x, int _y, color _cor, int _size) {
        x= _x;
        y= _y;
        cor = _cor;
        size=_size;
      }
      void display() {
        ellipseMode(CENTER);
        fill(cor);
        ellipse(x, y, size+count, size+count);
      }
    }

Answers

  • Answer ✓

    Looks ok to me, but swap lines 22 and 23.

  • Thanks a lot!

  • ??

    1st check if i!=j before comparing dist

    2nd shouldn't we say for j=i.....? because it's enough to check a and b, no need to check ball b and a as well because dist is the same

    ;-)

  • or rather j= i+1 ?

    @gotoloop ...

  • edited December 2014

    @Chrisir? j = i + 1???

    for (int i = 0; i != NUM;) {
      final Bubble b = balls[i++].script(); // i has increased.
    
      for (int j = i; j != NUM;) {
        final Bubble p = balls[j++]; // j has increased.
    
  • edited December 2014

    i see

    but in bugsugly he wants j=i+1, right? because I wrote j=i first

    (you see how bad your code is)

  • edited December 2014

    (you see how bad your code is)

    • I don't get how my code is supposed to be "bad"? /:)
    • Iterator i is already increased before reaching for (int j = i;.
    • So it's equivalent to your for (int j = i + 1;.
    • Or that's too tough for ya to figure out? 8-}
  • edited December 2014

    Updated the double loop in order to be shorter & clever. O:-)
    This time I had to pre-increment ++ iterator j so it points to next Bubble: =P~

    http://studio.processingtogether.com/sp/pad/export/ro.989GaZC5t7EkE/latest

    for (int j, i = 0; i != NUM; stroke(Bubble.STROKE)) {
      Bubble p, b = balls[j = i++].script();
      stroke(Bubble.LINK);
    
      while (++j != NUM)
        if (b.isIntersecting(p = balls[j]))  b.linkToBubble(p);
    }
    
  • now it's even worse ;-)

  • "Or that's too tough for ya to figure out?"
    Bad code isn't necessarily non-working code. It is code we have to spend time on it to understand its intent. Condensing lines to get shorter code isn't considered a good practice, even less for code given to newbies. Today, good code is readable code, easy to maintain and to extend, not code where you saved (potentially) a nanosecond or two out of a 100 ns execution time...

    When I discovered C (after the verbose Pascal), I was glad to use tricks like balls[j = i++] as it seemed clever. Today, I just make two lines (or more) out of it.

    Note: when you write int j, i = 0;, j is uninitialized in Java. Idem for p in Bubble p, b = ...
    Not sure if you tested your code in the PDE.

  • edited December 2014

    When you write int j, i = 0;, j is uninitialized in Java. Idem for p in Bubble p, b = ...

    Java (at compile time) emits an error when local variables are used before initializing 'em.
    As every1 can see, both j @ [j = i++] & p @ (p = balls[j]) are initialized before being used l8er.

    Not sure if you tested your code in the PDE.

    This is a "perfect" Java-JS cross-mode sketch: :P
    http://studio.processingtogether.com/sp/pad/export/ro.989GaZC5t7EkE/latest

  • edited December 2014

    OK, but that proves your code is confusing, with unnecessarily complex logic flow. If such init isn't obvious at a glance, it makes the code too tricky (or too costly) to be maintained (and unusable for the usual target of this forum).

  • edited December 2014

    @Chrisir seems to be on the right track because the solution here is to modify the limits of the for loops

    i is iterated over all but the last bubble, then j iterates over all the bubbles after bubble i this way every bubble is tested against every other bubble just once.

    for (int i = 0; i <myBubble.length - 1; i++) {
        myBubble [i] .display();
        for (int j = i + 1; j <myBubble.length; j++) {   
            if (dist(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y) <= 100) {
                line(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y);
            }
        }
    }
    myBubble [myBubble.length - 1].display ();
    

    This technique is very common when testing for 'interaction' between objects held in an array e.g. collision detection. Because it is a common technique it is easily recognised so easier to maintain.

    Why make it more complex than it actually is?

    When answering novice programmers let's stick with the KISS principle. :D

  • edited December 2014

    Seems like every1 missed the point that I had simply pointed out an online version I've already got a very long time ago which used that very same "interaction" which was careful enough not to check out against same objects twice! :O)

    And all of my online examples got header links to their original forum threads too: :P
    http://forum.processing.org/two/discussion/3087/how-to-draw-lines-between-my-circles-where-they-overlap

    Yup, my 1st reply was just a complementary link! Which @Chrisir accused of not being optimized enough as he said:
    or rather j = i+1 ?

    I've just defended myself that it was actually over-the-top optimized more than every1 thought! \m/
    However @PhiLho started to blame the optimization's style itself rather than realize I was only worried about the previous accusation, not his! :-@

  • edited December 2014

    Why make it more complex than it actually is?

    Well, I'd say that: i < myBubble.length - 1;
    plus outta loop: myBubble[myBubble.length - 1].display();
    is unnecessarily more complex w/ no real speed gain! :>

    You're only averting 1 less final check for: for (int j = i + 1; j < myBubble.length; j++) {
    which would fail anyways when iterator i would otherwise reach myBubble.length - 1. L-)

    While at the same time checking against: i < myBubble.length - 1;
    rather than simply: i < myBubble.length;
    which may adversely affect "JS Mode" side's performance! ;;)

  • While at the same time checking against: i < myBubble.length - 1; rather than: i < myBubble.length;, which can adversely affect "JS Mode" part

    That is easily fixed

    int len_1 = myBubble.length - 1;
    for (int i = 0; i < len_1; i++) {
        myBubble [i] .display();
        for (int j = i + 1; j <myBubble.length; j++) {  
            if (dist(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y) <= 100) {
                line(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y);
            }
        }
    }
    myBubble [len_1].display ();
    

    I think this code (basically a slightly modified version of the OP's code) is easy to understand, easy to debug and easy to maintain, so why not use it?

  • edited December 2014
    if (dist(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y) <= 100) {
      line(myBubble[i].x, myBubble[i].y, myBubble[j].x, myBubble[j].y);
    }
    

    I still think if (b.isIntersecting(p = balls[j])) b.linkToBubble(p); is easier to read than yours.
    Mine reads like: "if b is intersecting p, link b to bubble p": =:)

    boolean isIntersecting(Bubble b) {
      return sq(b.x - x) + sq(b.y - y) < sq(b.r + r);
    }
    
    void linkToBubble(Bubble b) {
      line(x, y, b.x, b.y);
    }
    
  • edited December 2014

    I still think if (b.isIntersecting(p = balls[j])) b.linkToBubble(p); is easier to read than yours.

    Actually its the OPs code modified and he is not testing for intersection but for close proximity (because size = 20, dist = 100), but that's not important since the algorithm is basically the same.

    As to readability I must disagree with you since It is not valid to take a couple of lines out of context. In this case you have to look at the whole algorithm. To make a fair comparison you must compare your code (below) with the double for-loop shown in my last comment.

    for (int j, i = 0; i != NUM; stroke(Bubble.STROKE)) {
      Bubble p, b = balls[j = i++].script();
      stroke(Bubble.LINK);
    
      while (++j != NUM)
        if (b.isIntersecting(p = balls[j]))  b.linkToBubble(p);
    }
    
    boolean isIntersecting(Bubble b) {
      return sq(b.x - x) + sq(b.y - y) < sq(b.r + r);
    }
    
    void linkToBubble(Bubble b) {
      line(x, y, b.x, b.y);
    }
    

    As previously stated in this discussion "your code is confusing, with unnecessarily complex logic flow"

Sign In or Register to comment.