Jump to content

learning foreach loop in vex


MadMax50

Recommended Posts

Hello,

I am trying to understand the foreach loop in vex. I want to loop over my boxes and assign a random color to it. 

So if the structure of the foreach loop is like this:

foreach( element; array) {
     // do things to element
 }

So if I were to apply this to my example of randomizing color on boxes:

the "array" should be the class attribute stored in a custom array... and the "element" should be the iteration of each class right ?

I'm stuck on storing the class attribute into an array. I know how to make a custom array like this:

float myclass[]={1,2,22,3,45};

but how would I store an attribute into an array?

If anyone can give me a simple example of how this works. It would be much appreciated.

Thank you.

Link to comment
Share on other sites

Attribute Array declaration is slightly different than standard array.

f[]@myclass = {1,2,22,3,45};
float val = f[]@myclass[3];

Apparently this syntax disturbs more than one (me the first). I Already respond to this question three days ago :rolleyes:.
It must be said that this particular sintax is not really easy to find in the doc.
It's in the array section of the Using VEX expressions chapter, but not in the declare attibutes section and not in the array chapter !

Check the Mestela Wiki for more infos
http://www.tokeru.com/cgwiki/?title=HoudiniVex#Arrays

Edited by flcc
Link to comment
Share on other sites

@flccThank you for the response. I understand how to create array attributes manually. My issue is that I don't no how to get an existing attribute like @class created by the connectivity sop and store those values in an array. 

All the documentation I read up on does not explain this even on Mestelas Wiki or Joy of VEX. 

Perhaps I am thinking about arrays differently than they are supposed to be used? Would love to get any insight.

Thanks again.

 

Link to comment
Share on other sites

To accumulate an array of all your class attributes it is my understanding that you would have to loop over every prim, check to see if that prim's class is already in your array and if it isn't then append it.

Then if you wanted to loop over each object like you said you could use

for (int i:array)

which is something vex picked up from c++

then you would have to loop over each prim again to see if it has a matching class attrib and only then could you assign a random value

 

instead you could loop over each primitive in a detail and assign it a random colour based on the class attribute.

for (int primitive=0;prim<nprimitives(0);prim++)

{

       vector randCd=rand(prim(0,"class",primitive));

       setprimattrib(0,"Cd",primitive,randCd,"set");

}

 

 

Link to comment
Share on other sites

15 hours ago, MadMax50 said:

how to get an existing attribute like @class created by the connectivity sop and store those values in an array

This, in a detail wrangle, will do it; although as you'll see it's quite a roundabout way to work:

// Construct `class` array from the prim attribute.
int class[], primclass;
for(int primnum = 0; primnum < nprimitives(0); primnum++) {
    primclass = prim(0, 'class', primnum);
    push(class, primclass);
}

// Construct `class_uniques` array from `class` without duplicates.
int class_uniques[], count = 0;
if (len(class)) {  // Proceed only if the array is non-empty.
    class = sort(class);
    
    // Add the first element, so we have something to compare against below.
    push(class_uniques, class[0]);
    count++;
    
    foreach(int elem; class[1:]) {  // For each, leaving the first element out.
        // If the current element is different from the preceding one, add it.
        if (elem != class_uniques[count-1]) {
            push(class_uniques, elem);
            count++;
        }
    }
}

i[]@class_uniques = class_uniques;

Instead of doing this, I would suggest using a For-Each SOP block. It's much simpler, and I assume also more efficient. If you want to have a look, the attached file shows both approaches for setting color by connectivity class.

class_to_array__forum.hiplc

Link to comment
Share on other sites

@flcc @pabcou @ColecloughGeorge @ikoon

Thank you everyone for the help. I will definitely be reading through those links you sent me. 

@ColecloughGeorgeThank you for the file. I didn't realize that doing something so simple would be that complicated with a foreach in vex.

My follow up question with your code would have to be this:

1. What is the difference between a "for" and a "foreach". Aren't both doing pretty much the same thing ?

Link to comment
Share on other sites

A for loop requires you to control the variable you're iterating, do your own comparison, and extract the element of an array yourself.

A foreach does all that for you.

These are functionally equivalent:

int myarray[] = {2345,3456,234,34,6,8,567,34,5,346,45};


for (int i = 0; i < len(myarray); i++) {
   @P.x += myarray[i];
}


// vs...

foreach(int element; myarray) {
   @P.x += element; 
}

 

  • Like 1
Link to comment
Share on other sites

You supply for loops with a variable to iterate over, a condition that if not true will stop the loop and something that happens to the variable each loop. For example you could have:

for (int i=5; i>1; i/2)

You can also have for loops that iterate over array members such as

for (int i:array)

foreach (int i;array)

Functionally these both do the same thing to my knowledge.

 

Also I believe the above answer is wrong as those two for loops will have different results. E.g.

int array[]={5,9,2,8};

foreach(int i; array)

      printf i;

//This would return 5,9,2,8

for (int i=0; i<len(array); i++)

      printf i;

//This would return 0,1,2,3

There is a great website for some nice syntax hints

http://www.cplusplus.com/doc/tutorial/control/

Link to comment
Share on other sites

16 hours ago, pabcou said:

Instead of doing this, I would suggest using a For-Each SOP block

you can easily remove your For Each Loop, Prim Wrangle with @Cd = rand(i@class); is enough to randomize color per class

Link to comment
Share on other sites

@mestela Thank you for the reply. That makes sense to me now. 
I guess the reason for my original question of this thread was to get as many examples as I can to understand for loops in vex. I went through the examples on Joy of Vex talking about loops in relation to the nearpoints function but I think I need to see even more examples of how they work. That is why I thought my randomize color based of @class idea was going to be a fairly basic example but apparently not haha. 

I already started a master file for all the for loop examples I came across so far.

Thank you .

Link to comment
Share on other sites

On 6/29/2019 at 12:09 PM, anim said:

you can easily remove your For Each Loop

Thank you for pointing this out, Tomas.

On 6/28/2019 at 8:33 PM, MadMax50 said:

I didn't realize that doing something so simple would be that complicated with a foreach in vex.

It turns out it can be simplified. I've just learned about the `uniquevals` function, which, per the docs, "returns the set of unique values across all values for an int or string attribute." So it seems like a direct answer to your original question. Using it, you can get rid of all the code in my previous post, and instead put this in a Detail Wrangle:

int class[] = uniquevals(0, 'prim', 'class');

foreach(int elem; class) {
    vector Cd = rand(elem);
    int prims[] = findattribval(0, 'prim', 'class', elem);
    foreach(int prim; prims) {
        setprimattrib(0, 'Cd', prim, Cd);
    }
}

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 4 weeks later...

we are testing out how to find min max of a attribute in a point geo. (1 million points)

attrib promoting to detail as min and max using two nodes took  196.23 ms

and 

float test[];

for (int point=0;point<npoints(0);point++)
{
 float getval = point(0,'test',point);
 push(test,getval);
}
@min_val = min(test);
@max_val = max(test);

above wrangle code took 355.94 ms

setdetailattrib(0, 'attrib_set_min', @test, "min");
setdetailattrib(0, 'attrib_set_max', @test, "max");

this one took 176.36 ms

 

Edited by kris
  • Like 2
Link to comment
Share on other sites

Hi kris, nice test. You might also test to resize() the array before the loop. Then, instead of push(), use the index test[point]. It is faster (but not as fast as the Promote SOP or the setdetailattrib())

 

float test[];
int npoints = npoints(0);
resize(test, npoints);

for (int point=0; point<npoints; point++)
{
    float getval = point(0,'test',point);
    test[point] = getval;
}

@min_val = min(test);
@max_val = max(test);

 

  • Like 1
Link to comment
Share on other sites

  • 2 years later...
On 6/30/2019 at 1:14 PM, pabcou said:

Thank you for pointing this out, Tomas.

It turns out it can be simplified. I've just learned about the `uniquevals` function, which, per the docs, "returns the set of unique values across all values for an int or string attribute." So it seems like a direct answer to your original question. Using it, you can get rid of all the code in my previous post, and instead put this in a Detail Wrangle:


int class[] = uniquevals(0, 'prim', 'class');

foreach(int elem; class) {
    vector Cd = rand(elem);
    int prims[] = findattribval(0, 'prim', 'class', elem);
    foreach(int prim; prims) {
        setprimattrib(0, 'Cd', prim, Cd);
    }
}

 

Hi fellas! I'm still new to Houdini and love this thread. It's helped me understand a lot.
Using from what I learned from all of you, I would like set color or remove a group of primitives that are intersecting another geometry.
I was able to get rid of the affected primitives but not the whole set. In the image, anything that has a color or mask value > 0.001 should be deleted. Ultimately I'd be left with the one strip below the collider. Any help is very much appreciated. Thank you.

Screenshot_1.png

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...