Transcription
Hey everybody. So, in this video, we're gonna talk about its spaces from rooms. We're gonna create those spaces from a linked model. And the reason why I'm creating this video is because recently, John Atkinson, which is from DLR Group, and I developed this script because he had been working with an engineer that didn't want to have to deal with spaces. And because of all the changes the architect would make, it would force them to always have to keep up with them, re-creating those spaces, placing new spaces, re-annotating views with those spaces in them. And it would just cause a lot of a headache for that user. So John Atkinson thought that, hey, you know, if that's the case, then maybe we can make it easier through Dynamo or an add-in of such.
So we essentially went into Dynamo, built that tool out. So I'll go ahead and show you what that is. We'll start with this PowerPoint, then we'll jump straight into Dynamo and kind of build out the entire script from from scratch. So the goal, I kind of stated, was to develop, create the spaces from the rooms, pulling all the parameters and whatnot from the rooms, and then tag them, not just in some one view, but all the views that would be important to that user or that project. In this example, we're attacking two different floor plans. The script would be applied to ceiling plans as well, and we'll talk a little bit more about that when we get into the script and we get to that portion of it.
To break down this script, we're gonna start off with getting the rooms from the link. So we need to get those rooms from that linked file. So we'll be using an R key lamp node. We'll go into that and get an item at index, which will just grab that specific link that we want, which is the architectural one. On this instance, its index is zero. Then we use a Clockwork node to pass through one. Now, we'll talk a little bit more about that when we get to the end of this PowerPoint, and then I'll show you what we're doing there. Then the next one is Data Shapes. We're getting all the elements from the links. So we're getting into rooms. We're using the rooms category to grab those. Then from there, what we do is we we get all the.
So, I, so we've now got all the rooms. So now we're going to place those spaces since we've already got the room location. And then we're going to apply the parameters that are necessary. So we get the name parameter up here from the room, we get the number parameter from the room, and then we get the room location from the room. So just a point where that room is sitting. And then we use this node from Dynamo MEP to place that this space at that point. So we create those spaces where those rooms are. And then these two nodes over here are just setting the name parameter and the number parameter. Down here, then what we do is before we move to annotating it, we first need to get two views.
So here, what we do is use a Code Bracket floor plan, ceiling plan. We give you because this is asking for a string value, so we can tie in these string values into it. Get the views, get by type. So we'll get all those types. This relay was put there on accident, so ignore that. We just do a quick list join. And then we come over here, get parameter value by name, which will give us a list of the names for that are from the model, so that we can essentially filter through them. So here we do a string starts with, and then we filter by if it starts with any of these. We mess with levels a little bit so that we can actually lacing so that we make sure that we're running the the boolean against multiple, you know, multiple views. So we don't just, we want to look at every, we want to look at the views independently and then run all the, all the string values against it. So everything over here, so we say, you know, this first view, you know, this first element, so W underscore, is it's in this list? If not, false, false, of views. And then we go to the next element and say, is HV and this list of views? And then for this example, true, and then false for the other view. And it keeps going through until it finishes all the string values and then outputs us a list of true and false. Is that we can use a filter by mask to filter out the non-true items from the true items, which gives us the endless here that we eventually tie into the annotation portion of this.
You can see here, our room, our when we got this, when we created the spaces, we used the room location. We can use that room location here as well, and actually place them from our, use those points to place the tag location. Then we use family types and we find the space tag. We do a list flatten for the space rooms in there are the spaces. You can see here what their names are, so one in our space, one room one. And then down here, let's flatten for the views that we get. We tie all that in. We do lacing on this as well. So we do a lacing method on there along with some levels, some level configuration because again, we wanted it to not essentially place one tag per room, but to place all the tags for every single room. If you don't configure the lacing in this manner, then what would happen is would go through and create one tag per room because it's essentially pairing up the list of elements and just running a tag for each point and then separating that from each view that you may have. So you may get, depending on your views, you may get one one tag per view, up to four views in this instance because there's four spaces. Or you may get, you know, only two tags for both rooms. So definitely make sure that the levels are created, excuse me, created correctly, and then make sure that you have cross lacing set up so that it applies it against every single room and then tags some appropriately, our tags every view appropriately.
So here I mentioned in the filtering, so that is part of it. We will be filtering, but if that doesn't apply to you, you can actually just dump this out and purely tie in views that you get from the view types and then just tie that in. It's the views that you want to apply this to. And then finally, there's a leave spaces from the model. Now, we do this because, as I mentioned before, the architect just kind of going in and out, changing a bunch of stuff. So if you start fresh, what we do is we delete them spaces, then reapply them. But first, we use that pass-through node to say, you know, delete them first. If that's true, go ahead and create the spaces. So let's go ahead and close this, and we'll just jump straight into Dynamo and we'll start to knock this out.
So starting off, what we need to get is those links, as I mentioned in the first, the first slide. So we're gonna use an R key lab node. So we can come over here and do select dot get documents. There goes, sorry for the lag. So now we've got the document, or we can get the document from the model now. So you can see here, this is set to automatic currently, so we can see the list. What we want is link doc. We can see those instances for each of these outputs down here, link path, link instance, link name, and link doc list, which is what we need. And then you can see the index of all of those. For this one, we need index zero, so that's why we're doing a get item at index. So we're doing get item. Now, what we can do is simply use a code block and then just a number, but I think a slider is sometimes more useful, especially for users that aren't too familiar with Dynamo. They can simply come in here and change the slider, you know, maybe adding a good note to describe what's going on, such as like, hey, you know, zero would be the first link in there, and then, you know, kind of so on. But, you know, it mostly you wouldn't need to verify that by looking at this drop-down list here to make sure that you're grabbing the correct instance. You could verify that by going to link name list and kind of seeing it there. So maybe you could put a watch node out to show show that for the name list. So link and then watch node and then describe, hey, you know, go to this specific link, you know, slide to the number to the specific link that you want to get your spaces out of or create your spaces from. In this instance, it's going to be zero. So we'll drop this down and make it easier for users. We could just set it to four or depending on what your general sizes or a typical size of how many links you have. We'll say step of one. And now if they scroll, they only have these options. Now we can see that we only have that one element from link doc, the Autodesk Revit DB document, index zero.
Let's quickly use this pass-through node. But before we do that, what I'm going to do is set this to manual. So when you'll have any hiccups or anything happening while we do this. Again, this is a node from Clockwork. Now, we'll want to make sure to give it something to actually pass. So we'll come down here, search for element type. Now, typically, when I'm working in in Revit or in Dynamo, I'll search for items instead of, especially now in the latest Dynamo, it's quite a bit easier in comparison to the older versions of Dynamo. Where searching is quite a bit more difficult, it just has a lot more lag to it. Now, that's not the case now. Currently, it is since I'm recording for some reason, it just lags up quite a bit. Okay, I did leave the other node, that's not what we needed. What we need is all elements of type. And I'm going to be pausing the video on and off just while I just to kind of mitigate the lag for you guys. So if you see it jumping around a little bit, just keep that in mind. Now, what we'll do is delete those elements. So we can just simply use, there's there's other nodes that we can use. This one's pretty useful. So it's from R key lab. It's going to give us a true/false list. So we can just come in here, run this, have that, wait for it. It'll give us a list of true saying that it did delete those spaces. Now, what we need to do is move on to the next bit, which is setting the parameters and, you know, placing the spaces in the model.
So first, actually, before we do that, let's jump back into, let's jump into Revit and delete everything. So we can come in here, just grab everything in the model, filter, oops, I think I left the links on. Yep, all right. So filter, delete the spaces. We'll jump into a room schedule, our space schedule real quick. Come over here, we'll do a new schedule, jump down to spaces. All right, so the model's cleaned up. So the idea is that we're going to place those spaces and name and number them correctly, pulling that information from the architectural model. Currently, no spaces have been placed. We could see the spaces in their architectural model, and that's it. So now we'll jump back into Dynamo, and when we come back and look at Revit after we run this script, we should then see all our spaces and tags within the Revit model.
All right, first, let's get the rooms. So we'll get that by using the Data Shapes node, and that'll be called get all elements from links plus plus. All right, sorry about that, the lag on there. So with those placed, we've also placed the categories node, and then we'll just tie that directly into there. We'll tie this over here. I've frozen this just so that it doesn't mess with anything, and then I've unplugged it from the pass-through node so it doesn't freeze everything else. And now what we'll do is start to set those parameters. So let's do a few different nodes. What we need to get is the room location, and then we'll place the spaces. But before we can really set the parameters, we'll need to get the parameters and also the spaces. So we'll kind of move through those all at the same time. So first, we'll get the elements, get parameter value by name. Okay, now what we're gonna do is copy this down. We're going to search for the room location node, which will give us the location for those rooms. Plug that in there, and then this node here will give us a list of elements. So we can tag that up here and then input that down here to get those parameters set. And now to create our space, we're gonna look for this space by point node, which will actually place the spaces, and that's a Dynamo MEP node. This one will take those room points and then actually place them.
So, so now we've essentially got our rooms from the links model and essentially placed those spaces already. So the rest of it's really setting the parameters and then applying the correct annotation to those spaces. We're going to do a code block up here, and this is going to be the parameter name one that we're looking for in those rooms are named. And then we'll copy this one down here and number. We'll input that there. Now, what we'll need to do is set those parameters. So we need a, instead of an element I get, we'll need an element set parameter by name. So we'll do element dot set right here. So the value, which is what this node is going to get out for us out of the rooms, that needs to be placed here. Now, we need to copy this down because we need to place them for both. So we'll pull this down here, we'll have that set right there. And this node here will place the spaces, but it'll also, when it places those spaces, give us a list of elements. So those list of elements, which is in, which are spaces, can be plugged in here as the elements that we're going to set the parameter to. And then from here, we'll plug in the name to the parameter name, and then here the number to the parameter name for this. So this is going to reach into the spaces that we just created, set the correct parameter or set that parameters per those spaces, pulling that information from the rooms.
Now, let's move on to the next bit, which is going to be getting the views, and then finally, what we'll do is actually annotate this, annotate the the elements or annotate the spaces per each view. In this example, we have two views that we're going to end up dating. If everything works correctly, so down here, what we have, what we're going to start off with is a code block because we need to get the room names, are the rooms for the room types, which is the floor plan and the ceiling plan views. So we need all those view types. So we'll use that code block just to as an input for the views that we're going to get. So we'll do views dot. It's these nodes are the nodes that we're going to place our from our key lamp as well. So we do views get by type. And a cool tip is you can actually click the Help button and they'll tell you. So that's a nice improvement to the latest Dynamo. Also, there's an extension that you can access if you go up to the view and then you can show graph package dependencies. So if you get into this and find that, hey, I can't find this node, or if you've taken this script and then you have some troubles, you can troubleshoot it that way. So we'll need two of these, one for for plan, one for ceiling plan. And there also may be a nice way, and I haven't tried it, and I'm not going to do it while I'm recording, but to take a list, so a list of strings on this example for our plane and ceiling, take that list, tie into one of these, which will give us a list of views. I'm not gonna do that right now because I just don't want it to break on me. So we're gonna stick to what I know, and we'll do the separates string values and the separate nodes.
So now we have our two strings. We can come in there, tie them into this. Now, we could also use a type, which I actually, you know, be it drop down that we can choose things from. I try to avoid those when I can because what happens is when anything changes in Dynamo's API and or into the Revit API, we open the Dynamo script in a later version, those drop downs may be out of whack. As you see here, I use a drop down, this input value for this get by type is a string input. You can see if we hover over it, it says string. This one is a little bit different, this categories is a different type, so it's a different data type. I, if I can at some point, getting into Python, see how I see how that's done, but, you know, try to keep that in mind where you can use string values where you can't use the dropdowns, but, you know, there's always an option to code it out. You just have to know where to look, which is something I'm going to try to do for those. But as a tip, just try to avoid them. So now we're just gonna do a quick list join. And as I mentioned before, if we could tie a list of strings into the view, views that get by type, we could avoid maybe having to do this. But again, in this instance, I'm going to avoid that just because I don't want nothing to go wrong. So we'll come down here, click the little plus symbol, tag these two lists, which essentially was going to give us a list of, if you two, we're gonna have a list of floor plans and a list of ceiling plans.
Now, what we're gonna do is another get parameter value by name, which we can come up here and grab this one, set this one down here, and all this is going to do is because give us a list of the view names, so that we can do some filtering to them. Now, this is avoidable if this isn't something you want to do. If you simply want to apply this annotation to every single view, that's fine. This only has to do with the annotation portion of it. So, you know, you can totally skip filtering if that works for you and simply tie in this join list into the annotation node that we'll get to at the end of this. So here, what we're gonna look at is the parameters, the parameter name. So we'll need that parameter name, which is called view name. We'll create that code block and then tie that up here. Now, there's some lacing and some level configuration going on in this, this portion of it. So bear with me, I won't dive too much into it because frankly, I'll do a bad job explaining it. But what we essentially want to do is be able to run each of those independent values, so each of the items that we're going to be filtering it with independently, running again, running those against every single view. So that we don't get a list of just a single true and false and and also we don't get a list of just fault, you know, either a bunch of falses or a bunch of trues. We want the each value, each string value to be ran against every single view. So that we know for sure that that view doesn't exist or that view exists or doesn't exist in that list of views. So we're going to do a string, string starts with. So the strings that we're going to be working with are the strings from the view names, the ones that we're going to search for in this example, which is which is going to be in our Revit model. So you can see here, the two that we're looking for is HV and PI. So we can just type those out and, you know, you can type whatever, whatever views that, you know, you're filtering for. And this list, when those don't need to be in brackets, comma separated. And then we'll do the last one, HV, and then we'll put a bracket at the end there. So now we have a list of PI and HV, which should filter through. Now, in this example, we only have two views, but it should go through and get a, get us, it should have those two views as true. It'll output that out of our bull mask.
So now we're gonna do a search for, and just to make sure, I want this set to false, which it is, so we can ignore that true. If you do want it to be space or case-specific, if it needs to be uppercase, you can come in here and say true, it'll, um, make sure that filter out that stuff that doesn't have the, the specific case that you have set up in here. So now what we're going to do is that filter by the bull mask. And this node will take that input of true/false against the list over here. This list join, which will, you know, give it'll give us an output of actual elements that we can work with, whereas this list will only give us a list of truths and false. It's not until it runs through this spool mask that it gives us something that we can work with. So in this list here, it'll have trues and falses, false is for the, the views that don't actually apply, and then true for the, the ones that do. And here, and this input, this is all items that have been identified as true, which in this instances are the elements that we need to use to create our annotations on. Now, and the output list is the ones that are false, the ones that we're going to ignore in this system. So this is a really powerful node that you'll probably use quite a bit now.
Now we need to come in here and set the level. So we're going to turn on levels. We're gonna leave it as two for that one. This is essentially should have a list, should have a list of a list of each view type. So lists, so within a list, there should be two more lists, one list for the floor plan types, on one list for the ceiling plan line types. We're drilling into the second level, which should be the sub list underneath the overall list, if that makes any sense. And then we're gonna set this to level one. You can see here, this is one list, and within that list is these two elements. Level one just says, hey, this overall list, run against the individual list in there, and it kind of runs per elements in, in that model art with against each of those views. So it runs each of these, each of these strings against each view, and it creates its own list time it runs through it. So we should have two lists. And if we had another string added to this, well, it would have created a third list of of trues and falses. Now we'll need cross lacing applied to this. We'll right-click it, right now, set to auto, but we'll come down here and set it to cross product. You'll see those triple X's. And now we'll also have to do the same for the list filter by mask. And we're doing it in there so that we can match up the list. So because this creates a bunch of sub lists, and we want the list to match up with the lists over there. So we'll use levels, set that the level two, and then our list join should filter out correctly.
Now we can jump up here and finish out this script. So we're going to create or use the create annotation tag, which is from the R key Lam package. All right, so we'll pull this over here. Now, the first thing we'll need is the tag location. Now, what we can use is the room location for that. So that'll give us the tag location of each of those spaces. And now we'll need the tag type. So we'll do a family type real quick. Now, this would be your space tag. So if, so whatever your space tag is, use that one and then plug that into the tag type. And then we'll do elements, or we'll need the elements. So we're gonna need this spaces, which are going to be right right here. And first, we'll do a list flatten. I can't remember since we're not actually running this script right now, if it, if it, I think equates sub-lists from the space point by now, but I'm not entirely sure. So we're gonna do a list flatten just to make sure that those elements are flattened. But we want to tag in those spaces into the elements input, which are going to be elements we're actually tagging.
All right, now we need our views. So we've already filtered everything, so we can just simply tag that directly into here. And that's it, mostly for the, for this node, except for the levels. Oh, and one more input. So down here, we'll just need to see if run it is set to true, which it's not, set to false by default. So we can just create a code block and then come down here and type in true, plug that directly in there. We don't need any things, we're link instance. Now we need to configure the levels again. I probably didn't do the best job before describing this, but we don't want it to essentially go through each element, so like put a tag at point A, point B, point C, point, you know, D, and then and then essentially separate that by the views. So, you know, if you don't have any levels or anything set up, it's gonna go in, if it's set to a single view, it works perfectly. But if it's set to multiple views, what's gonna happen? It's just gonna create a tag per each view. It's gonna use the point as the point to place it for, you know, the first point index zero against index zero of view, and then go on through that list. And in this instance, we may only get two tags, one tag per view. That's not what we want. So we're using some some levels to just make sure everything kind of gets aligned, or well, more or less, we want it to create all the tags for every single view. So place a tag every space on every view, not one. So we're using levels to kind of help that through. On this one, needs to be set it to, and then this last one, views needs to be set at one. I would say, you know, for me, I've gotten used to levels and dealing with them. It's still sometimes a kinda run it and see what happens. I've gotten to a point where I can kind of guess what needs to be done a little bit quicker. But to really get good at levels, I think it's just a try, you know, keep trying and failing, eventually you'll get the hang of how they work. There's also some good information out on the Dynamo website that you can check out if you want to learn more. But all right, but now that we have everything set up, it should be good to go.
So, oh, one more thing, we need to change the lacing to cross-product for this one as well. So as you saw before, in our model, there was only, there was only the link, nothing else. So what this should do is create everything for us. Now, currently, we'll leave this node off, or actually, sorry, we, I think we can turn this on, but we may get some issues. So for this first run, what we can do is just come over here, tag that directly into there, just so that we don't have any issues with this pass-through node while we're testing it. And now we'll run it and then see if the spaces get created. So we'll come down here, run, and then wait.
All right, so that was really quick. It created that in about a second. So it was funny because when we were testing us out, I'm working through some of the levels, we got it done pretty quickly. But when we were filtering out some of those sheets, or the views, it was taking an incredibly long time to run until we got the levels and order things, starts to run a lot quicker. So you could see it ran in just a second. And what's cool is we did test this on some large projects, and it ran, and it ran just as quick. So it's a very quick script, you know, doesn't get, it doesn't get lagged up for 20 minutes, it does it pretty quickly. So even if you have us a place or a building with, you know, a hundred spaces, it shouldn't have any issues dealing with that. So we'll go ahead and minimize this, and then we'll take a look at the Revit model.
So originally, you saw that we only had the link. Now we have the rooms, and then we have the room tags. So room one, room two, room three, and then room four. Those tags are, I'm correct, it's pulling it from the link model of the rooms in there, and those are called room one, two, and three, and four. You can see that in a space schedule. Now, let's see if it tagged the other space, or the other sheet. So you can, so now we can see in here and tagged everything appropriately. Oops, let's open up Revit again, and then real quick, we'll take a look at the Dynamo script. We'll take a look at this output. So we can see it gave us a list of space tags. These space tags are applied to each room. So you can see the subway. So that's kind of why we had to create levels and stuff, and you'll see when you're messing with that, how this gets configured, how it changes, and, you know, how sometimes you'll see a list with one tag, and that'll give you an idea that maybe you need to apply some type of lacing to it, you know, either cross product or another lacing method. So again, it was just a trial, you know, just keep trying it until you you get to what you need.
So here we did a list flatten. I'm not entirely sure if that was necessary. I can't remember. Yeah, it was. So this created a list with the sub list of spaces. We wanted a list flatten, which just flattens it down to one list, like you see here. So now, if we, since everything worked the way that we wanted it to, we can use this pass-through node, tie that in there, come over to this element type, right-click it, unfreeze it, and then now if we rerun this, what it's going to do is run, delete the spaces, which you just did, and then we apply those spaces. So if we drop this down, we can see then it read true that it deleted those spaces, and then if we pan over here, we can see the new spaces that were created, and then the parameters that were pulled over up here. So the room parameters, and then one, two, three, four for these parameters. So everything does what it's supposed to do, which is great.
So give this a try. Let me know if you have any questions or you're getting stuck anywhere. I'll share this script. I'll go ahead and save it as it is right now. I'll use the one that that already has some groups and stuff applied to it, and list what each node, what package it comes from, so it's a little bit easier. I'll save that. You'll find the link below to the OneDrive. If you don't know where that is, just reach out and I'll point you to it. But you can take the script from there and then use it however way you want, or you can just go through this step-by-step guide and kind of build it yourself. But if you have any troubles, reach out to me. Let me know. I'm happy for any questions. But thanks a lot for watching, and I'll see in the next one.