I’m currently developing a parametric model in Grasshopper for modular CLT starter homes, and I’ve run into a challenge regarding spatial constraints within a site.
The Goal is:
I want to define a construction site boundary (imported as a free-form closed curve from Rhino) and use this boundary as a strict limit for placing and growing housing modules (boxes).
Within this boundary, I am generating modular housing units that can vary in size and position based on parameters (e.g. width, depth, spacing). The idea is that these modules should never exceed the site boundary. When the modules grow (for example when increasing width or shifting position), they can cross the boundary. What I want instead is:
If a module reaches the boundary, it should stop growing in that direction
Or alternatively: adapt its growth in the opposite direction where space is still available
These are the files I’m currently working on. I want to control the spacing between the different modules, and ensure that if a module extends beyond the plot boundary, it either gets trimmed or removed. Does anyone know how to achieve this?
. check whether the house profile curve intersects the plot boundary
. check if the house profile curve is outside the plot boundary
If one of those conditions is true, you cull that house. I’ve implemented a couple of ways to do that:
. check if the list of resulting points from curve|curve intersection has length zero + check if the house polygon center is outside the plot curve
. get the corners + the center of the house profile and check if all those points are inside the plot curve
One more thing: I don’t quite get why you generate a non-centered rectangle with explicit dimensions over a tessellation that is already rectangular. Why not use the tessellation rectangles in the first place and control size and proportions from the tessellation amounts? Yes, it’s less controllable in terms of measurements, but it ensures coherence and no overlaps. But of course, this is not necessarily a problem.
PS: using a grid is not exactly growing, rather placing houses. For growth, you need an iterative process and one or more criteria for how to place the next item at each iteration
Yes, I would like to generate at least one module that I can then duplicate and mirror, for example, so that I can create different types of blocks. It is important to me that I can determine the spacing between the modules, the size, and also that the module cannot cross the lot boundary. So perhaps a grid is not the solution. Maybe you know what a good solution for this is?
2e test model parametric housing moduls on site.gh (22.1 KB) this is my second model where i can move from a module from one point. But i dont know why the boundary does not work. If the module goes past the site boundary but the module is not being deleted. I also want to make a script where i can make multiple copies in a specific axis (x, y and z) Can someone help?
Hi @Jonathan23, here’s a simple script to start from if you want to go deeper into iterative logic.
It repeats a module on the X axis until it reaches the max extension of the plot area, then moves one span up in the Y axis and repeats, until it fills the area. Every new item is tentatively placed, and, if it’s outside the plot boundary (via the same kind of check I posted earlier), it is not added to the final list.
The script requires the Anemone plugin.
Of course, it is very simple and stupid, but it is a boilerplate to understand how to implement iterative logic of placement and filtering.
Thanks for the help Is it possible to place, for example, 3 modules and then place another 2 modules at a different position on the plot, but with a different spacing and size? I have tried to place a new module, but it is not working quite right.
Hi Jonathan, there are a few things to understand about iterative procedures:
You have to think in terms of what happens in a single iteration only (inside the Anemone loop in this case), and then repeat that n times (or as long as you reach a certain condition). This implies:
you can only think about the move(s) you want to be repeated every single time: you want to be able to place 3 modules and then 2? Then, you’ll have to code both parts for placing 3 or 2 pieces inside the loop, and a condition that, at each loop iteration, decides which one to apply
the inputs and the outputs of a loop must coincide (this is also a basic Anemone constraint): if you end an iteration with a list of boxes in an output, a list of boxes is what you will have from the corresponding input at the beginning of the next loop
You have to establish procedures (how to do something) and criteria (boundary conditions) for how every thing happens in the iteration. If you want to place items in a different position, with different spacing and size, you have to specify how to compute all those things (position, spacing, size) at each iteration. They can be fixed data (as in my example, X and Y increments are fixed), or create bits of code to do that (for example, picking a random point inside the perimeter at each iteration, or establishing more complex ways of computing those data)
So, first, you should clarify a lot of "how"s. My suggestion is to write pseudocode (a verbose list of operations expressed in natural language describing the mathematical and geometrical operations that need to happen in order) for what you want to perform inside the iteration, and then try to translate it into Grasshopper components bit by bit.
Indeed, I first have to come up with parameters beforehand that belong to a specific project and eventually add them to my model as sliders so that my colleagues can quickly create variants.
Fortunately for me, right now it’s just boxes with a specific dimension that I need to be able to drag along an x- and y-axis. I have now created a layout within this model with 2 individual modules that I can move and copy separately.
Thanks for the tips. For them, it is mainly about how to make good use of the lot with these boxes. What I am still struggling with, however, is how to ensure that these modules are not allowed to overlap.
placement strategy is overlap-free: for example, objects are placed using a regular grid sized so that ensures no overlap ever occurs > no need of iterative strategies
placement is decided at each iteration: you need to implement a collision/clash check. Place the new item > check if it collides/clashes with previously existing items > if yes, discard the new item; if not, add it to the list > go to the next iteration. This is easy enough if objects overlap compenetrating each other (see the Collision One to Many component), it gets tricky if objects are allowed to “touch” each other (share and edge or a face).
Thanks for the tip, I’ve tried to get the clashing to work properly, but I haven’t managed to get it to work yet. Maybe you can help me on the right track?
Some notes:
. you can have ONE Anemone loop active at a time, so all your processes for each iteration should be inside that single loop
. make sure you feed the right type to the input components: collision one to many does not accept groups (make sure you read the error balloons at the top-right of the component if you get an error)
. since you can now choose between 2 modules with different sizes, an incremental positioning by fixed steps makes no sense anymore. Instead, a new logic is necessary
The process starts by placing an initial module and a list of growth points; the corners of the rectangle curve of each module are the potential growth points.
At each iteration, the process:
. picks one of the modules (using a random choice index)
. picks one growth point from the list of potential growth points (using another random index) then considers
. places the chosen module at the chosen position
. checks for collisions with the already placed modules
. checks for boundary condition
. if both checks are ok:
. the new module is added to the list
. the corners of its rectangle curve are added to the list of growth points
. if checks are not ok, the chosen growth point is culled from the list (to avoid unnecessary future attempts)
There are also a few other things, like keeping track of what type is added so you can do statistics, and ending the loop if there are no more available growth points. To generate different configurations, other than changing the starting point, you should change the seed-related sliders.
For this to work, the number of iterations should be considerable (I used 200). Please note that the number of iterations DOES NOT EQUAL the number of placed modules. If you want control over that, you should come up with some condition inside the loop and an eventual additional exit condition. basic iterative housing v3_AE.gh (55.7 KB) basic iterative housing v3_AE.3dm (46.3 KB)
Hey, thanks again for all the effort you put into helping me — I really appreciate the time and thought you invested.
I wanted to clarify one thing about the approach. In my case (within the company I’m working at), the goal is actually a bit different: we’re not trying to generate random configurations across the plot. Instead, the idea is to work with a set of modules that can be repositioned in a more controlled way across the site.
The reason is that fully random placement tends to produce layouts that aren’t very usable or spatially coherent. So we’re aiming for something more guided, where the modules can still adapt and move, but within a logic that helps lead to a well-organized overall layout.
Your explanation really helped me understand the system better though — especially the logic with growth points and iteration — so thanks again for that!
To clarify, the example I provided is a template/blueprint aimed at giving you an entry point into the iterative growth logic, not an attempt to answer the specific design problem you have. Randomness is there exactly as a placeholder to be replaced by more stable and thoughtful criteria, but you have to come up with your own logic, which is specific to each design problem.
For example, when you say “that can be repositioned in a more controlled way across the site”, “more controlled” means nothing per se; you have to specify what “control” means and how you proceed to achieve that. You have to build up a logic for that, specifying how you pick a position for each new item you want to place.