Hello everyone. I am fairly new to Dynamo and I am trying to figure out a way of automatically populating a parametric roof I created with PV panels.
I have more or less the idea of what I have to do, but not the knowledge of how to implement it. So I have a roof with some kind of obstacle (any geometry I add on the surface - HVAC or exhausters) on it and what I would like to happen is that the script automatically creates the biggest rectangle possible on the roof avoiding the obstacle(s), and within that rectangle, add the maximum number of smaller geometries representing the PV panels.

Thatâs more or less a diagram of what I would like to happen:

Any direction on how to proceed would be greatly appreciated!

I suspect you want to look at âBin Packingâ hereâs a link which discusses some optionsâŚ

Though if your example is as simple as you describe ie. a rectangle with some other rectanglesâŚ Itâs possible you could extract the roof geometry, subtract the clash cuboid, use the void edges to split the roof into rectangles and populate those with your grid of PV rectangles?

Thank you so much for your comment. It actually helped me get started with this script.
So yes, everything is meant to be really simple since I am moving from Rhino GH to Dynamo and I am still learning the basics.
From the information I got from your comment, I started by creating my surface (my roof geometry), adding points + circles to my geometry to represent the âobstaclesâ, and then subtracting them (I selected only two of them to subtract).
This is the result:

But I am kind of lost on the next stepsâŚ How can I use the void edges to split the surface roof? Ideally now, I would like to split the roof into two sides, the left and right side of the clash cuboid, and select the bigger side to populate with my PV rectangles.
(https://1drv.ms/u/s!AlORhB2zZdFxgptQ1ZfZtQSWNBCqjQ?e=3pc6AU) link with my really basic script, I cant upload files into this forum yet.

Again, thank you so much for your help. This forum is proving fundamental to my learning experience!

Just an idea, but how about if you create a rectangle instead of a circle? Perhaps you could extract the sides and extend those until they hit the edge of the roof? The created sub-rectangles might be useful?

I guess an alternative method might be to create a grid across the roof and check whether the âcirclesâ intersect each grid square? that would maybe let you build a yes / no kind of option for whether a PV could live there?

Sorry I canât be of more help, itâs not my specialism!

I wouldnât use a solid here - stick to the abstracted surface instead. Simpler shapes process faster and are more comprehend-able.

Generally speaking it helps to sketch the steps you want to take when building a geometric process. I personally prefer the sketchbook app on my iPad for this as it has a recording feature to generate a video which thereby captures my sequence so I know what has to happen in what order, but any sketching tool will do.

Iâd go a similar route to @Mark.Ackerley, but you neednât limit yourself to orthogonal penetrations - just build the shape you want. My thoughts on how that might be managed are in the collapsed list below:

Possible Process

First Iâd shift my surface (not an entire solid) to be as close to orthogonaly aligned as possible. Read the vectors of each edge, take the average, and rotate the form by the angles formed with the global X axis (if youâre already orthogonal youâll rotate by 0). No need to âflattenâ this - you wonât gain any added speed in doing so. This will allow you to utilize bounding boxes for the other shapes, which will quickly âsquare things offâ.

Next pull the perimeter curves from the rotated surface, and group them. I believe that there is a handy node in archi-lab package for this called âGroup Curvesâ. Turn each of the groups into a polycurve, which will represent the âperimeter polygonâ, and all the interior obstruction polygons.

Sort the polycurves by the inverse of the area of the surface formed by each, so that the âlargestâ polycurve (the one which contains all the rest) is the first item in the list. List.SortByKey will help here - remember you want to sort the polycurves not the surfaces or their areas). Then use a List.Deconstruct to pull the âsurfaceâ out from the list of obstructions.

Build a bounding box for each of the obstrucitons (Boundingbox.ByGeometry), convert the Bounding Boxes into a solid (Boundingbox.ToCuboid), and then merge the solids into one with a Solid.ByUnion node.

Build a surface from the roof polycurve (the one which was taken out with the deconstruct), and remove the combined solid from the roof surface. Pull the vertices from the surface (Topology.Vertices) a get the associated point geometry. Convert the points to UV parameters (Surface.UVParameterAtPoint), and pull the U and V values into lists (UV.U and UV.V). Get the unique UV values (List.Unique) and use those create two lists of Isocurves (Curve.ByIsoCurveOnSurface node) on the U and V axis.

Extrude each group of Isocurves on the Z axis to create a group of surfaces, and combine them into two polysurfaces (one for the U axis, and one for the V). Split the roof surface with the obstruction voids (previous paragraph) using the U, and the the V polysurfaces. You now have a series of rectangles which make up the larger rectangle.

The next step will be the hard part - I recommend looking into the use of topology to get adjacent âsetsâ of rectangular cells from the matrix. Face.AdjacentEdges and Edge.AdjacentFaces will help here - use of that on cell X will get you the four adjacent Cells, if they exist. Where there is an obstruction you wonât have a face. Remember that to use all four faces on a cell you need to catch the corner as well. In the matrix of [ [1,2,3], [4,X,6], [7,8,9] ], where X is the âstartingâ cell, you need to gather 9 if you gather both 6 and 8 - if 9 doesnât exist, youâre no longer a rectangle, but an L and you should go with the larger of the two (6 or 8), and try to capture 2 or 4 with it to maximize area. Generative design might help you quickly iterate this if youâre struggling with ensuring you âgrab the biggest possibleâ due to iterations.

Once you have the combination sets youâll want to generate a bounding box of the shape, convert that into a cuboid, and intersect the cuboid with the complete (no-voids) roof surface to get a rectangle.That rectangle can act as a host for your solar panels, (coordinate system at parameter), which can then be rotated into position by using the inverse of the angle from the first bullet point.

What may feels like a simple task by hand is in no way simple - this is because our brains are quite adept at solving this stuff as we have a TON of practice. We start the âmake the shape fit in the openingâ very early, and we learn over time, well usually) and the number of edge cases for a task like this is very high. Hopefully your grasshopper background has prepared you a good bit and the terms I used above arenât too foreign. While itâs ambitious, it will prepare you to do some really high level stuff and can pay dividends.