Shorthand version of For Loops

I am wondering how to write this piece of code in normal syntax. I understand the version supplied here is shorthand.

I want to be able to tease apart the pieces so I can see what it is doing (still learning) and I am not sure how to devolve the syntax so-to-speak. How could I write this out in full?

    beginShape();
    for (PVector point : contour.getPolygonApproximation().getPoints()) {
      vertex(point.x, point.y);
    }
    endShape();

From the full version of the FindContours example in OpenCV for Processing by Greg Borenstein

import gab.opencv.*;

PImage src, dst;
OpenCV opencv;

ArrayList<Contour> contours;

void setup() {
  src = loadImage("test.jpg"); 
  size(src.width, src.height/2, P2D);
  opencv = new OpenCV(this, src);

  opencv.gray();
  opencv.threshold(70);
  dst = opencv.getOutput();

  contours = opencv.findContours();
  println("found " + contours.size() + " contours");
}

void draw() {
  scale(0.5);
  image(src, 0, 0);
  image(dst, src.width, 0);

  noFill();
  strokeWeight(3);

  for (Contour contour : contours) {
    stroke(0, 255, 0);
    contour.draw();

    stroke(255, 0, 0);
    beginShape();
    for (PVector point : contour.getPolygonApproximation().getPoints()) {
      vertex(point.x, point.y);
    }
    endShape();
  }
}

Answers

  • edited February 2015 Answer ✓

    it depends from the methods of contour, but in general, something like this.

    (it would be like this if it were an ArrayList)

    for (int i=0; i < contour.getPolygonApproximation().count(); i++) {
        PVector point = contour.getPolygonApproximation().getPoint(i); 
        vertex(point.x, point.y);
    }
    
  • edited February 2015

    this

     for (Contour contour : contours) {
    

    just means "loop over all elements in the list contours and bring each element into the var (object) contour one after another.

    var contour being of type (class) Contour."

    ;-)

  • When you use an "enhanced for" like that, you're actually using an Iterator behind the scenes. So this code:

    for (PVector point : contour.getPolygonApproximation().getPoints()) {
      vertex(point.x, point.y);
    }
    

    Is actually doing this:

    Iterator<PVector> iter = contour.getPolygonApproximation().getPoints().iterator();
    while(iter.hasNext()){
       PVector point = iter.next();
       vertex(point.x, point.y);
    }
    
  • edited February 2015 Answer ✓

    Addendum:

    • Indeed Java uses an Iterator instance behind the scene.
    • Any class which implements Iterable interface is illegible for the "enhanced" for ( : ) loop.
    • But let's not forget that regular Java arrays also work in such "enhanced" for ( : ) loops.
    • Diff. is that w/ regular arrays there's no Iterator. And thus it's faster:

    for (PVector dot : vecs) vertex(dot.x, dot.y);

    if vecs happens to be a PVector[], it's internally transpiled into:

    for (int i = 0; i < vecs.length; ++i) {
      PVector dot = vecs[i];
      vertex(dot.x, dot.y);
    }
    

    Otherwise, if it's a class which implements Iterable, like an ArrayList for example, it's as what was said by other answerers:

    import java.util.List;
    import java.util.Iterator;
    
    final List<PVector> vecs = new ArrayList<PVector>();
    Iterator<PVector> iter = vecs.iterator();
    
    while (iter.hasNext()) {
      PVector dot = iter.next();
      vertex(dot.x, dot.y);
    }
    

    Of course never use Iterator. Just let Java do that behind the scenes w/ those nice for ( : ) loops! ;-)

  • Thank you very much for the thorough explanation everyone. I see that there are a few different ways and a few different layers going on here.

    I am going to try a few of these in the code and see about finding which one works for the sketch and re-post that.

    I think I'll start with the post by Chrisir and then dig deeper.

    for (int i=0; i < contour.getPolygonApproximation().count(); i++) {
        PVector point = contour.getPolygonApproximation().getPoint(i); 
        vertex(point.x, point.y);
    }
    

    Cheers!

  • edited February 2015 Answer ✓

    I think I'll start with the post by @Chrisir and then dig deeper.

    Take notice that this long condition expression within the for ( ; ; ) loop:

    i < contour.getPolygonApproximation().count(); is re-tested at each iteration! =;

    For better performance I advise you to pre-cache that before the loop:

    // Pre-caching the List's reference before loop for better performance.
    // Assuming method getPoints() returns an ArrayList of PVector objects:
    
    ArrayList<PVector> vecs = contour.getPolygonApproximation().getPoints();
    
    for (int i = 0, len = vecs.size(); i != len; ++i) {
      PVector p = vecs.get(i);
      vertex(p.x, p.y);
    }
    

    But don't forget that everything above can be shortened to 1-line statement via "enhanced" for ( : ): *-:)

    for (PVector p : contour.getPolygonApproximation().getPoints())  vertex(p.x, p.y);
    

    Read more about the diffs. between the 2 for () loop styles here: :-B
    http://processing.org/reference/for.html

  • I started with the line of code above but frankly I think I have just confused myself more and it doesn't work within the context of the sketch.

    I am not sure what's doing what. There are too many things named similar to "contour". I'll be working through it this afternoon.

    Here is my current sketch:

    import gab.opencv.*;
    
    PImage src, dst;
    OpenCV opencv;
    ArrayList<Contour> contours;
    
    PVector [] pj;
    int numPoints;
    
    
    void setup() {
      src = loadImage("test.jpg"); 
      size(src.width, src.height, P3D);
      opencv = new OpenCV(this, src);
    
      pj = new PVector[numPoints];
    
      opencv.gray();
      opencv.threshold(70);
      dst = opencv.getOutput();
    
      contours = opencv.findContours();
      println("found " + contours.size() + " contours");
    }
    
    void draw() {
      image(src, 0, 0);
    
    
      noFill();
      strokeWeight(3);
    
    
      for (int i=0; i < contour.getPolygonApproximation ().count(); i++) {
        PVector point = contour.getPolygonApproximation().getPoint(i); 
        vertex(point.x, point.y);
      }
    
    }
    
  • edited February 2015

    Dunno if it's any help but here's your program using the "enhanced" for () loop.
    Since I dunno the library nor have the image, couldn't test it though: :-??

    // forum.processing.org/two/discussion/9555/shorthand-version-of-for-loops
    
    import gab.opencv.*;
    import java.util.List;
    
    OpenCV opencv;
    List<Contour> contours;
    PImage src, dst;
    
    void setup() {
      if (!isGL())  src = loadImage("test.jpg"); 
      size(src.width, src.height, OPENGL);
    
      smooth(8);
      frameRate(60);
    
      noFill();
      strokeWeight(3);
      stroke(0);
    
      opencv = new OpenCV(this, src);
      opencv.gray();
      opencv.threshold(70);
    
      dst = opencv.getOutput();
    
      contours = opencv.findContours();
      println("Found " + contours.size() + " contours.");
    }
    
    void draw() {
      background(src);
      for (PVector p : contours.getPolygonApproximation().getPoints())  vertex(p.x, p.y);
    }
    
  • I really appreciate you taking a moment to help me through this.

    When I run the code you just posted I get the error of "The function getPolygonApproximation() does not exist" on the last line of code.

    Is it calling it outside or inside of the scope of the function?

  • edited February 2015
    • As mentioned I've got no idea about that OpenCV library! :@)
    • From your own code, you use contour variable in your loop.
    • However contour doesn't exist. Instead it's contours w/ "s".
    • And it's a reference for an ArrayList of Contour objects.
    • So it seems we're gonna need a loop to iterate over that ArrayList.
    • Only then we can call getPolygonApproximation() over each of those extracted Contour objects.

    for (Contour c : contours) // iterates over ArrayList of Contour objects.
      for (PVector p : c.getPolygonApproximation().getPoints()) // ArrayList of PVector objects.
        vertex(p.x, p.y);
    
  • Yeah, I am just learning the library as well. Thank you for the help once again. I was hoping these misunderstandings would be common enough for others not into OpenCV to help with.

    The last line gave me an error but still ran.

    "No uv texture coordinates supplied with vertex() call"

    I am thinking I'll just try out some other examples and see if I can work it out. I've started to tease apart the naming of the code. Some is arbitrary and some is not (especially with the three derivatives of "contour" present.)

  • edited February 2015

    I'm not versed w/ vertex() either. Better take a look at it for yourself then: 8-X

    Seems like some beginShape() & endShape() are needed too...
    If that's so, perhaps this might work now: :(|)

    for (Contour c : contours) { // iterates over List of Contour objects.
      beginShape();
    
      for (PVector p : c.getPolygonApproximation().getPoints()) // List of PVector objects.
        vertex(p.x, p.y);
    
      endShape();
    }
    
  • Yes, that one does work. Thank you.

Sign In or Register to comment.