Most efficient method to draw building elements

Hi all,

I’m currently writing a program to design a mass timber building. As part of that effort, one section of my python code is needed to build a 3D model of the building, which is essentially a series of various cuboids representing the beams, columns, and slabs, and looks as below:

image

My question is - what would be the most efficient way to draw such a structure? The data is generated within a Python node, so it might be preferable to keep the drawing within Python. Alternatively, I could output the data required and then use standard GH components to create the 3D view.

Currently I’m drawing this by creating a Python function which draws a mesh cuboid (mesh with 6 faces) and then looping over all the elements in a list to draw them all. Function is as follows:

> def DrawCube(c,x,y,z,Capped=True):
>     ErrorText = 'c should be a list or tuple of (x,y,z) coordinates'
>     if not isinstance(c,list) and not isinstance(c,tuple):
>         print ErrorText
>     if isinstance(c,list) or isinstance(c,tuple):
>         if len(c) != 3:
>             print ErrorText
>     dim = [x/2,
>            y/2,
>            z/2]
>     d = [[1,1,-1],
>         [-1,1,-1],
>         [-1,-1,-1],
>         [1,-1,-1],
>         [1,1,1],
>         [-1,1,1],
>         [-1,-1,1],
>         [1,-1,1]]
>     if Capped:
>         Faces = ((0,1,2,3),
>                  (0,1,5,4),
>                  (1,2,6,5),
>                  (2,3,7,6),
>                  (3,0,4,7),
>                  (4,5,6,7))
>     else:
>         Faces = ((0,1,2,3),
>                  (0,1,5,4),
>                  (1,2,6,5),
>                  (2,3,7,6),
>                  (3,0,4,7))
>     Corners = []
>     for i in d:
>         V = [(i[j]*dim[j]+c[j]) for j in range(3)]
>         Corners.append(V)
>     Mesh = rs.AddMesh(Corners,Faces)
>     return Mesh

I then essentially loop over all building elements as below:

> Elements = [DrawCube(col) for col in columns]

I used a mesh rather than surfaces as I believed this would be faster, however not so sure anymore. Any advice greatly appreciated!

I’ve attached a vastly reduced version of the file which only deals with the rendering process if this will help.

Optimiser - Brief.gh (30.3 KB)

Yes, that’s true. If you were using surfaces/breps, other than more complex objects, rhino/grasshopper would need to do the “meshing” of every box object every time the script is executed.
In your case of a thousand of objects, that would probably make rhino freeze for some second every time.
It’s wise to avoid that, as you did.


I don’t know python, but it seems you did non multithread it … ?
Also, inside the “DrawCube” definition you create the faces list “Faces” every time a new box is created.
Maybe making two lists “FacesCapped” and “FacesUncapped” outside “def DrawCube()” and then just using them inside the loop will speed up things?

1 Like

Also you can override DrawViewPortMeshes if you dont need to output the geometry. This will be much quicker as well. Would also be worth to cache all your geo in a hash table or similar so you dont need to recreate your data if you don’t really have to. And finally creating a compiled c# in visual studio would also help to increase performance by a lot.

Hello,

It looks like you are only ever going to draw several thousand cuboids so operating speed is not likely to be your main worry : I suggest you try to write code which is easy for you to understand and explain to others, and easy to modify for your different use cases.

If you call rs.EnableRedraw(False) before your code and rs.EnableRedraw(True) afterwards then it should be fast enough for you.

Happy coding !

Graham

How do I override DrawViewPortMeshes?

top marks sir - this has boosted speeds massively - thanks!

I’m still curious to know any better ways of creating the volumes in the first place so will leave the post open, but this is real winner.

1 Like

Upon closer inspection this solution isn’t ideal as it forces a redraw every time the solution expires when I’m running Galapagos. Will have to find a way to switch the behaviour on and off in such a way that doesn’t make it redundant in the first place.

You shouldn’t have to call EnableRedraw when you’re targeting the Grasshopper document (which GHPython does by default). A few more things that might help:

All that said, I wouldn’t expect this (i.e. making and outputting many mesh boxes) to be super expensive.

Also, here’s an example of how to override DrawViewPortMeshes from GHPython.

Edit: Just realised we’d already discussed some suggestions (e.g. profiling, input/output cost).