Here are a couple of threads from the Revit API discussion forum related to MEP and connectors from the past few weeks that seem worth taking note of:
- Traversing an MEP system and retrieving connected elements
- Reproducing the MEP electrical system browser hierarchy
- Creating a conduit between two connectors
- Dealing with the read-only transition diameter
The discussion on connector neighbours brought up a number of aspects of and solutions for traversing an MEP system and retrieving connected elements:
Question: Connectors seems like a pretty powerful system. It started to give me some ideas for other Connector uses regarding mechanical systems. I was hoping to be able to do something like the following:
- Get an element
- Get its connectors
- Find the connector ends
- Use the ends to "climb" down the system branch by finding the neighbouring element and repeating the process
The issues that have been arising are the following:
An element can have more than two ends
- I'm not sure how to get a reference to a neighbouring element using connected Connectors.
- Branching through systems in this fashion could cause you to essentially get lost in the branches unless you map N number of forks.
- The directions of the connectors are often bi-directional, so how does one know you're progressing in the correct direction even if you could get the neighbours?
Essentially, if you wanted to grab piece A on a duct, and iterate through the neighbouring ducts to Piece B, what would be the correct method to do this? You don't have to get super detailed with source, I'm just looking for the high-level approach.
Answer: Nice task!
Maybe these discussions and other ones they point to will help:
I work on pipes, but maybe it is not that different from ducts.
- First, RevitLookup will help you with what is reference to what, so I suggest installing it, if you didn't already.
- All pipes have connector manager with connectors, connectors have all ref (that show to what there are connected), with pipe there is this little thing that you have to check: is connector from all refs is not the second connector from connector manager.
- You need to check if connector is right kind (physicalConn).
- Usually the neighbour connector has the same origin and opposite direction (this is not always the rule, like in placeholders).
In family, you can check which connector is prime and which is secondary and go with this link.
With branches, you can always make a list of points to look at to detect if you make a full loop, not the best solution, but for big project.
In my case, I only needed to go through all connectors until I will find pipe (I had like 4 or 5 families connected with each other).
Here are some additional pinpointed leads to answer your questions that should help in accompaniment with Jeremy's posts:
- An element can have more than two ends
– Check if the
connector.connectortype == connectortype.end.
- I'm not sure how to get a reference to a neighbouring element using connected Connectors
Connector.AllRefswill return connectors connected to the one you're looking at, then you can look at their hosts
- Branching through systems in this fashion could cause you to essentially get lost in the branches unless you map N number of forks – Yup. But this is why you're a programmer, you're the bad ass that will get this licked ;)
- The directions of the connectors are often bi-directional, so how does one know you're progressing in the correct direction even if you could get the neighbours? –
Connector.CoordinateSystem.BasisZwill help you make sure you're facing OUT from the fitting if airflow is not the concern.
I've had to do this for a couple different tools, so I thought I'd just create a quick Revit API SystemSearch repo for you to check it out.
It's a pretty basic bit of source that I threw together real quick, but the general idea is there. You'll definitely need to tweak it to meet your needs, but I hope it helps:
You also need to be aware of the Revit SDK TraverseSystem sample. It determines the correct order of the individual system elements in the direction of the flow and stores the entire directed graph in XML.
Here are some discussions of it:
- The Revit MEP 2010 API
- The Revit MEP API and some Revit MEP sample applications
- Revit MEP API Samples
Question: Another high-level question regarding these branching systems:
Considering the potential for loops to be present, am I right in assuming that finding the shortest/all routes from a given start and end is non-trivial?
My workflow intention was something like:
- Select start and end point in a given system.
- Find the user's intended route through the system (likely the shortest one).
- Do a calculation on the given run using connectors and their references.
I'm wondering if at step two the intended route could be ambiguous, and if so, how do you handle it?
I'm also wondering how you use the map once you map the system to proceed from the start in a direction that brings you closer to the end. This can't really be done with spacial location because to assume the end is specially further from the start than the middle may be a false assumption.
At the moment I'm considering making the user select the entire run, but the original intent would be a lot simpler (for the user...).
Answer: So, it seems to me that you have a couple options on your hand. You can:
- Let the user pick their own route.
- Offer the most direct route.
- Offer the shortest route (not necessarily the same as #2).
- Take a path that passes points (like if you have some kind check system everything needs to pass).
Based on that, you'll have to do some math & logic on the search process. Check out the image below (it's pipes - not ductwork... but same principle):
You'll encounter tons of systems that have an infinite number of ways of laying them out. In the drawing above, if you were to go from start to finish taking the "direct route", which may be the least amount of turns, you'd go straight down south, the east - covering 300' of pipe/ductwork in your case. If you wanted the shortest route, you could take the top route (follow the most northern pipes) and you would only pass through 296' 1/12" of pipe...
Never presume to know what the user wants... Most users will all have different ways of doing things - from East Coast to West Coast; North to South America and Europe... If you want to give them options (which I would always recommend for enhanced UX), give them options. Otherwise just build what you can, and add to it later.
If you really want to explore this and make a powerful tool, look at the differences between depth-first vs breadth-first searches, which are intended for graph systems like this:
- When is it practical to use Depth-First Search (DFS) vs Breadth-First Search (BFS)?
- Breadth First Vs Depth First
- 10-minute video on Graph Traversals – Breadth First and Depth First
- Graph searching: Breadth-first vs. depth-first
- Depth First Traversal or DFS for a Graph
- Breadth First Traversal or BFS for a Graph
There really isn't a 'right' answer for this.
It's got to be a balanced combination of what the users want and what you can reasonably create in a timely manner. What's important is that whatever you create, make it scalable so you can always come back and build on it later! So, if you start by making them select their entire path, make it so that you can make edits and build on it without having to rewrite the whole thing... I've had to do that. It's not fun.
Many thanks to MarryTookMyCoffe, r.singleton and Geoff Overfield, Software Engineer at FabPro1, LLC, for sharing all these useful suggestions!
I am not sure which of the approaches is best.
It can't hurt to check them out and compare them.
Please let me know what you think and how well they suit your needs.
A related, simpler question was raised on getting the tree view from the Revit MEP system browser:
Question: How can I get tree view in the System Browser in Revit?
I need it to create a form has tree view like this:
Answer: My AdnRme HVAC sample does that.
I implemented two different methods to reproduce the MEP Electrical System Browser Hierarchy structure.
- Before the advent of any MEP specific functionality in the Revit API, I made use of generic parameter values stored on the respective system elements.
- After the introduction of the Revit MEP API, I implemented a simpler and safer solution making use of that and the connector information it provides.
We also discussed how to create a conduit between two connectors:
Question: I have conduit connectors on junction box family instances and I'd like to connect two boxes using a conduit.
I couldn't find any method to achieve this.
Answer: In general, Revit will automatically and happily connect everything that can be connected.
Of course, in order to achieve this, I assume that the boxes need to be equipped with connector elements.
Furthermore, have you tested and verified that the connection you wish to achieve works as expected when you drive it manually through the user interface?
In general, if a feature is not available in the Revit product manually through the user interface, then the Revit API will not provide it either.
You should therefore research the optimal workflow and best practices to address your task at hand manually through the user interface first.
To do so, please discuss and analyse it with an application engineer, product usage expert, or product support.
Once you have got that part sorted out, it is time to step into the programming environment.
Assuming you have (or can get) the connector points, simply substitute the
Autodesk.Revit.DB.Electrical.Conduit.Create( pDoc, type.Id, new XYZ(0, 0, 0), new XYZ(10, 0, 0), level.Id );
Response: Yes. I have created a conduit connector in the box. I can manually connect 2 boxes with conduit.
Conduit.Create, and this method only requests coordinates as parameter.
I successfully created a conduit between two boxes, but they are not connected.
I used this method, but the conduit didn't connect to the boxes.
Answer: What happens if you ask the connector on one of the boxes to connect to the connector on the other box?
Does it automatically create a conduit between them?
Please study the series of research articles on rolling offset creation.
Response: Yes, it worked.
Thank you again.
Finally, a question on transitions between different pipe diameters:
Question: In a pipe transition the parameters defining the diameter are read-only; does anyone know how to walk around this?
I think I can create small dummy pipes on both sides, but I would like to avoid this.
Answer: You can use dummy pipes for creating transitions.
- Create two pipes of the desired diameters somewhere far away from all other elements.
- Connect them by calling
- Delete the dummy pipes.
The remaining transition
FamilyInstance will retain the correct diameter parameter values.
Move it to the desired location.
Many thanks to Revitalizer for this hint!