I am doing some intersections of Room centre Perpendicular lines with Floors and the thing is intersection tests are quite computative and take up quite some time to run.
If I do the same thing floor by floor the run is much faster since it has much lower elements to check each round.
Now my question is wether we can run a script multiple times on each level rather than it running on all elements.
Note. I do want all elements to run through but level by level rather than as a whole.
Hard to help you improve without seeing more of your work, but I’m assuming you’re using nodes like “all elements of category” or “all elements of type” and aren’t ever reducing your data set on a larger project. If this is the case I can think of a few options on the fly.
The first is to reduce the dataset by switching out the initial collector for something with less scope and reach, such as all elements in active view, and then filter out to just the categories you want and then proceed with the rest of the graph. You can even isolate the categories in the view prior to running to remove the need to filter here, which while not very computation can save you some time in the short term or on ‘one time use’ graphs.
The next method would be to keep global collector method I’m assuming you’re using, and use a List.GroupByKey node to group each element by it’s level. Once they are grouped you can use a list.getitematindex node in combination with a datashapes UI++ node to allow for selection of level via user input, and faster runtime by running the graph with Dynamo Player instead of regular Dynamo. Just be certain to remember what level you just ran so you don’t duplicate runs. Since the levels of rooms and floors are pretty straightforward so this may be your best bet in the short term. Depending on dataset size you might even be able to just sort the sublists by the unique keys and test level 1 rooms against level 1 floors and so on, still utilizing a single run.
The last off the top of my head option is to skip the level by level idea and look into more efficient testing - if a bounding box doesn’t contain the lines or points than it can’t physically intersect so no need to do the more involved geometry intersection test. Reducing the dataset with that type of “pre-test” can shave a lot of time off the overall effort. You may also want to look into the Bimorph package as the geometry intersection nodes in that package are faster than the native dynamo ones (though I still haven’t had time to test this myself).
Likely the ‘right way’ is to use a combination of the 2nd and 3rd choice, but again without seeing more of your work no one can really be sure what’s best here. If you post a camera export of your graph and any relevant sample files such as the DYN and/or RVT file I can try to help more in the coming days - generally speaking the more you post the more you get back.
Yes, start by implementing a better list management system.
If you have 1500 floors and 100 rooms and do a cross-check, you’ll end up doing 150k comparison operations.
However, let’s say you have 10 levels and on average 150 floors and 10 rooms per level. That means you only have to do 10 * (150 * 10), or 15k comparison ops. That’s an order of magnitude less work and doing less work is always going to be faster…
Thanks for the Input.
Let me explain you the current situation. I am trying to get the FFL and SFL info of the floors at the centre of the rooms into the Room info for tagging purpose. Now my Floors are Composite floors, meaning I have multiple layers in them so I Am looking into the top Finish Layer only.
The snapshot will probably explain you what I am trying to do.
Now let me go point wise for each of the Solutions
1.Reducing the Data set would definitely helping me out. But eventually I would be running this same script in some 16 odd broken down and link files so I also kind of wanna be foolproof and include everything.
2.The List.GroupByKey is the method to drive it level by level one by one. But what happens when I am working on a 40 storey tower. I effectively want it to run each floor test one after the other. back in the day we had something like a grafting tree in Grasshopper to do something similar. (Not exactly it though)
The Dynamo Player option I would eventually want definietly but for this project I am stuck with Revit 2016. SO instad I am using Dyno and getting prettymuch the same result. And yes I can definitely have it run level by level No issues.
3. The issue with bounding boxes is it doesn’t take the shape of the floor all right. Imagine small toilets in the building and having a large L shaped Floor just outside in the corridor. The bounding box of the floor outside would intersect with the bounding box of the floor of the Bathroom as well right!
That said have a look at the script. I know I could definitely streamline the process in the later part of the script dealing with nos. But what takes up the most time is finding the intersections for me.
Yes absolutely, I do understand the reason why it is slowing down and the amount of calculations it is doing increases exponentially. That is primarily the reason I want to run something level by level.
But the idea is to run it level by level on its own.
So for example if I had just 3 levels in my floor. I would have just Filtered or listed out everything based on levels and ran it manually changing the input levels. Or maybe I would have copied the nodes thrice in the same file and kept one level for each group of nodes. But things change dramatically when I have like 40 storeys.
The idea is to automate and make things faster. So essentially I was just looking into ways to get a script run in a cyclic loop changing a certain input by a given range. (If that makes sense)
By any chance do you use volumetric calculation on your rooms, and if so are your floors room bounding? Because Room.Boundaries would return the bounding floors at a much faster rate than a geometry test.
While bounding box containment won’t provide a correct solution in most cases, it certainly can be used to narrow down your data set faster. the way I think of it is that it performs the first common sense check the same way your brain does. That is if you were doing this by hand you wouldn’t even consider the geometry of the floor in the north janitor’s closet when attempting to get the ffl and ssl of the club room on the south side of the building, which actually has several finish floors in it so you need to review all of that geometry more closely. You instead look at it for the briefest moment and instantly discard it as data useless relative to your task at hand - all of this happens in a fraction of a fraction of an instant. Bounding boxes can serve as this level of “generalized shape” test, to tell your computer to discard stuff that’s WAY outside the scope for the issue at hand.
The reason they are so much faster than actual geometry intersection is because bounding boxes are defined as only two points - a minimum point and a maximum point, so they are really easy to test - in fact you can write down the math to check the elements against each other on the back of the receipt the next time you buy coffee. Now if you tried to use the actual geometry of the floors, who’s boundaries are defined by multiple sketch lines against the cylinders you’re using for the room (a fairly good choice geometry wise by the way, but not as good as a line or a point), you’re going to have to get out a much bigger piece of paper as you have to test every line of the sketch, at the top and the bottom of every floor, for every floor on the level. Remember that even after filtering down to the level you’re still testing the floor of the janitor’s closet on the north side of the building against the club room, so don’t forget to write down all those lines as well. Even thinking of how much effort and time that would take has me going batty.
So the bounding box test isn’t saying to do ONLY a bounding box test, but instead use it as a preliminary test - if bounding box for element A intersects with bounding box for element in list b, than do a real geometry test, otherwise return null. This will further reduce the number of difficult calculations by a great deal. Let’s say each floor has 10 rooms with a bounding box intersection. Extrapolating on @Dimitar_Venkov’s example, instead of doing 150,000 in depth geometry tests for all rooms against all floors, or 15,000 in depth geometry tests for all rooms on this level against all floors on this level, you’re doing 15,000 coffee receipt calculations which quickly leads to 13,500 false values and 1500 in depth geometry tests. Still a lot of paper but better than 150,000 big tests right?
Now seeing the scope of your problem and understanding more of what you’re after, I would look into first grouping all floors and rooms by level, then sorting the sublists by level, and then using either the boundingbox and then geometry intersection method, or go straight to the bimorph nodes for the clash detection. Your dataset is small enough that you can then run with level by level and then you can likely do the entire building in one go - just make sure that the unique keys for the groups align - if you have floors on level 6 but rooms on level 6a you’re going to be cursing yourself for awhile.
I do now understand what you meant the bounding box for… Its basically removing the 90% of the false checks that dynamo might have to do later and also it is much more robust and foolproof then using levels cause as you said as I can’t really control or make sure that if the rooms and floors were hosted on the same levels.
The bounding box way of things to first make the data set more viable is the idea I think which I will be going for.
Thank you so much for all the explanation and taking all the time in the world to explain a noob like me everything so clearly.
Glad I c oils help out! If you get stuck feel free to post back!