Double loop with anemone

Hello,

I’m very new to Grasshopper. I was wondering if someone could help me with anemone.

Here is my problem:
I want to place balconies on a building façade. I created the façade using Isotrim, so I have a grid of rectangular modules.

I would like to generate balconies with a length between X and Y modules, defined by the user. I also want to avoid balconies being too close to each other, so there must be at least Z modules of distance between two balconies.

My idea is to iterate through the modules using an index-based logic:

  • Starting at index 0, there is a 33% chance to create a balcony.

  • If a balcony is created, I randomly generate its length A between X and Y.

  • Then I jump directly to index (current index + A + Z) to keep the required distance.

  • If no balcony is created, I move to the next index and repeat the same 33% test.

The important part is that my data is structured by floors:
I have a list of floors, and inside each floor a list of modules (each floor can have a different number of modules).

Therefore, I want to use a loop inside another loop:

  • One loop to iterate through the floors

  • One loop to iterate through the modules of each floor

I want to avoid flattening all modules into a single list, because this would cause balconies to be split across floors (for example, a balcony starting near the end of one floor could incorrectly continue on the floor above, resulting in very short balconies).

My question is:
What is the correct way to implement this logic using Anemone (nested loops and index jumping) while preserving the floor structure?

Thank you very much for your help.

Travail archi emu version 18decembre2025.gh (50.2 KB)

what i already did might not be optimized but it works

you state that the probability of a balcony to exist is always 33%, regardless of other balconies being previously generated, the only thing that changes is that if a balcony is generated, then its length and the distances between that and the next position where a future-balcony might exist are also variables

if that is correct, then I don’t think you need a loop or nested loop, because you don’t need to take decisions based on previous iterations

you can just generate a list of random numbers Domain [0, 1], count how many of those are <= to 0.33 and for each of those generate abalcony length A (as a Random number with Domain [X, Y] ) then apply distances between those

how could i do that in grasshopper ?

This doesn’t help you with your problem in any way, but does clean up the messy scripting that gets you your building geometry:


Double loop with anemone VR 01.gh (40.5 KB)

this is the first theoretical approach that comes to my mind (it has some Flatten here and there so it won’t work on data trees)

True means there’s a Balcony there
False means there’s no Balcony there

it has the very same downsides the loop you described would have, meaning that it does not know when a facade will end: let’s say you have 30 modules, have set a balcony to have minimum length = 3 modules, and are computing module index 29 (the last one) → if that module happens to roll the 33% probability to be a balcony, its minimum length will be 3 modules, which you don’t have in that facade because you are already computing the last available module…

balconies.gh (17.8 KB)

thank you it will help me to optimize my projects !!

Thank you very much for your help! I really appreciate it.
I’m having some trouble understanding how the True/False list works in detail, and I’d be very curious to learn more about it.
I also have one more question: how could I use this list to create the balconies? I tried to figure it out on my own, but it seems a bit too complex for me at the moment. Any tips or insights would be wonderful

the T/F list would be “Yes/No” to the presence of a Balcony on each given Module

for instance here some points are arrayed along X axis, they represent Module centers, and a rectangle is drawn if in that position there’s a corresponding True value:


balconies_2.gh (18.1 KB)

the rules you have listed have some flaws that are present also in this definition, regardless if you use a loop or just populate a list of random values:
→ the loop/list_of_values increments module-by-module, one-by-one
but
→ when a Balcony should be created, it will occupy “many” of the following modules, “overwriting” the original timeline of events, or -as I have proposed in my definition- extending it

in particular, let’s say I initially ask the definition to evaluate 10 modules in total, with a 33% probability to have a Balcony there, it tells me I should have a Balcony at index 2, 4 and 7:

the “situation” is that a Balcony will be longer than one module (balcony length is X to Y modules) then it’s followed by Z modules where a Balcony cannot exist by definition

so, for instance, this is the whole thing that has to be generated starting at index 2, the first balcony: it’s six-modules long

here you can approach the thing in two different ways, but neither of them grants a solution that respects your initial rules:

→ the way I have done it is, when a Balcony is created, the List locally expands in such a way a single True value becomes a whole_balcony_array:


this means that for 10 initial evaluation you have requested, you get many more results, because values are always added to the list

→ a different approach might be to overwrite existing original values, instead of locally expanding the list, something like the following, but still, despite the final result containing for sure less extra members, it does not guarantee there won’t be extra members:

and if you just trim the list to the wanted length, you will end up with the original rules not being respected:

I don’t understand this fetish of not doing things via Anemone loops. Just because they are not native Grasshopper components? The coding under the hood uses loops anyhow. And, invariably, any problem that naturally lends itself to be solved through iteration will otherwise be solved by creating a large matrix of data from which the solution is then culled. Which means more overhead.

Consider the problem above. For each row of modules, the number of times you will have to roll for balconies is the number of modules in the row given the very improbable (but possible) scenario, that each module fails the balcony roll. You then generate a boolean mask for the balconies which you trim to the length of the largest grouping of balconies and that fit in the row of modules, calculate the number of falses needed to complete the row and disperse these between the balconies.

If you did this with loops, the method looks much the same, only instead of creating a mask that exceeds the number of modules in a row, you would check after each looped roll, if the mask you are about to create is going to extended past the row module length. If yes, you exit the loop.

I assume this would be computationally more efficient. But I don’t know. I would have to test it to find out.

the thing is, in both scenarios let’s say the last module (or 1-but-last, or 2-but-last… depending on XYZ variables amplitude) of a given row rolls to have a Balcony, then it won’t be possible to follow the initial rules as they are stated, loop or not loop

the problem can for sure be attacked with a loop :slight_smile: but because of the very rules listed by OP, a loop -in my opinion- is just not necessary and it doesn’t allow for shortcuts neither simplify the problem

this is similar to what OP stated, but not the same :slight_smile:
he said he rolls 1/3rd probability for each module, and as soon as one hits the jackpot then a “package of modules” representing a Balcony is generated, which is a whole set of Random[X,Y]=A modules + Z empty ones

so the probability of getting a Balcony is 33% per module, but when a Balcony is generated it will last X-to-Y modules, which will probably result in a very different overall destribution than 33% of the moduls being balconies: it mainly depends on X, Y, Z values

your approach is more like to calculate how many balconies we’ll get in total for a given row by rolling 33% for each of those, and then aggregate them in such a way they respect the X-to-Y number of consecutive ones, and distribute each group along the row in such a way there are always Z empty spaces among them :+1:

for me it’s more like I’m willing to use explicit loops if and only if there’s some sort of decision-making that make the current step dependant on the -impossible to forecast- result of the previous one, or external variables that could appear and disappear

but I personally don’t like to use loops if there’s no external variables to the system :face_with_monocle: (like here, where probability of Balconies is a flat 33% period)

for instance, if you want a random walker that moves on XY plane, you could of course Anemone it and create a nice loop chosing between +/- X/Y steps at each iteration

that will work fine

but why using that if there’s no decision making? :smiley: I prefer creating a random list with domain [0, 3] and pick from a list of +1/-1 X/Y vectors, then Mass addition them and use partial results… it yelds the very same output, there are no “unforecastable” external forces/variables acting on the system… but of course it will just work both ways!

I don’t say this to be recalcitrant, but no. What he said is:

which, of course, was said in the context of an assumed loop-based solution, but will not produce a mask exceeding the count of row modules as your “package of modules” solution does.

What I described here:

is not intended as a description of an alternate solution, but a description of the very solution you lay out with added steps to fix spacing.

Not true. It will always be possible to follow the initial rules because while there is a minimal number of modules spacing the balconies there is no maximum:

Thanks for the Christmas Greetings.

I’m not following this thread but people often use loops (Anemone) when they don’t know any better (“The Grasshopper Way”).

https://discourse.mcneel.com/search?q=nested%20loop%20order%3Alatest

Hi Joseph!

Yes. True. But I think what I am trying to argue is the point that there are situations where the “Grasshopper way” is less efficient the equivalent “Anemone way” because of the bloated data to get to the solution.

Hope all is well!

Thank you,

this helps me a lot with the Grasshopper logic, this is a solution I hadn’t thought about. As you explain it, I understand that I can’t just trim the list afterwards, because then the rule is no longer respected. What I’m wondering now is how this solution could be adapted to my case so that it actually works: how would you make sure the list ends up with the right length while still respecting the balcony rules ?

I think this also shows a limitation of a purely linear approach. Even if it works in many cases, when we operate on a list of façade modules some operations can unintentionally spill over to the next floor. If that happens at the wrong moment, we can still end up with balconies that are cut short or behave strangely.

This is why I was thinking about a floor by floor, module-by-module approach in the first place. Conceptually it makes sense to me, but I’m realizing that translating this into a working Grasshopper definition is still quite difficult at my level.

But I’m still left with one last question: once this logic is in place, how would you actually use Grasshopper to turn it into balconies?

Sorry if I’m missing something obvious, I’m still getting a bit overwhelmed by the complexity of the project.

@inno

I took me a while, but I finally understand what you are saying. Clearly, I am not good at math.

In the end, the balconies will not reflect a perfect 33% distribution. My approach does serve well as a practical solution though, I feel. You could, in fact, ditch the whole 33% thing. I assume it was intended to provide uneven spacings between the balconies, but you will get these by randomly distributing the remaining space anyhow. The whole thing is a bit bunk. In reality, the spacing of the balconies will be given by the floor planning behind the facades, not some random distribution of modules.

yeah, after this exchange I also think OP strategy for rolling probability was indeed not stated as “stricht set of rules” to follow as a generative diagram, but more to hint to the flavor or randomness he wanted to imbue the facade with :+1:

it’s one of those situation where you have an “almost-clear-view” of the final result you want to get… but instead of stating that result, you carefully describe the step-by-step process you believe will get you there… until it doesn’t… sort of…

:smiley: I also do that all the time :smiley: