The Revit 2014 API introduced a whole bunch of linked RVT document interaction enhancements:
- Identifying links
- Obtaining linked documents
- Link creation
- Link load and unload
- Link path type
- Conversion of geometric references
- Room tag creation from linked rooms
- Picking in links
They all provide important and useful functionality.
Let's take a look at one of them in particular as well as another issue that just cropped up:
- Conversion of a geometric reference in a linked RVT model
- Triggering a dynamic model updater by specific element ids
Conversion of a Geometric Reference in a Linked RVT Model
As stated in What's New in the Revit 2014 API, "these methods enable conversion between Reference objects that reference the contents of the link and the host, respectively:
- Reference.LinkedElementId
- Reference.CreateLinkReference
- Reference.CreateReferenceInLink
This allows an application, for example, to look at the geometry in the link, find the needed face, and convert the reference to that face into a reference in the host suitable for use to place a face-based instance. Also, they enable you to obtain a reference in the host (e.g. from a dimension or family) and convert it to a reference in the link, suitable for use in Element.GetGeometryObjectFromReference."
This functionality raised some questions, though, e.g. in the recent comments on selecting a face in a linked file by Rolando and Paul Marsland:
Question: Could you please give some example code about the use of Reference.CreateLinkReference(RvtLink) to place a face based family in a linked model.
Question: Like Rolando, I have been toying (unsuccessfully) with CreateLinkReference since it appeared in the API, documentation and examples of how this is implemented are virtually non existent. I would greatly appreciate a code example showing how a face based family can be attached to a face in a linked file.
Answer: Here is a sample code snippet from the development team exercising this functionality. Note that it includes hard-coded element ids from a specific sample model that you obviously need to modify to suit your own context:
public void AddFaceBasedFamilyToLinks( Document doc ) { ElementId alignedLinkId = new ElementId( 125929 ); // Get symbol ElementId symbolId = new ElementId( 126580 ); FamilySymbol fs = doc.GetElement( symbolId ) as FamilySymbol; // Aligned RevitLinkInstance linkInstance = doc.GetElement( alignedLinkId ) as RevitLinkInstance; Document linkDocument = linkInstance .GetLinkDocument(); FilteredElementCollector wallCollector = new FilteredElementCollector( linkDocument ); wallCollector.OfClass( typeof( Wall ) ); Wall targetWall = wallCollector.FirstElement() as Wall; Reference exteriorFaceRef = HostObjectUtils.GetSideFaces( targetWall, ShellLayerType.Exterior ) .First<Reference>(); Reference linkToExteriorFaceRef = exteriorFaceRef.CreateLinkReference( linkInstance ); Line wallLine = ( targetWall.Location as LocationCurve ).Curve as Line; XYZ wallVector = ( wallLine.GetEndPoint( 1 ) - wallLine.GetEndPoint( 0 ) ).Normalize(); using( Transaction t = new Transaction( doc ) ) { t.Start( "Add to face" ); doc.Create.NewFamilyInstance( linkToExteriorFaceRef, XYZ.Zero, wallVector, fs ); t.Commit(); } }
How to Trigger a Dynamic Model Updater by Specific Element Ids
Question: Is it possible to create an IUpdater triggered by changes to specific elements? Or, in other words, is there a way to make an ElementFilter that only passes a predefined list of element ids?
Answer: This query is actually answered by a brief glance at the basic IUpdater documentation:
All updaters are activated based on triggers, defined by calling one of the overloads of the UpdaterRegistry.AddTrigger method.
They all take an ElementFilter argument specifying what criteria the modified elements need to fulfil in order to trigger the event.
The element filter can be as specific as you like, e.g. be based on a list of element ids, a single element id, etc., as you can see from the list of ElementFilter constructors.
The situation where an updated is triggered by changes to one single specific element defined by its element id is illustrated by the DynamicModelUpdate AssociativeSection SDK sample.
Here is an overview of other discussions on the Dynamic Model Updater framework.
Hi Jeremy,
Great application to Revit Links and families.
I've got a wall reference in terms of the Revit link (through a selection and filtering linked elements), which I've converted to an Element ID in hopes that there is an easy way to work backwards from the element to the link instance. Unfortunately I haven't found a way to do it.
Is there an easy way to pick up the Element ID of the Link Instance from the wall reference?
Thanks!
Posted by: Richard Cleveland | December 04, 2014 at 22:48
Dear Richard,
Does this help?
http://thebuildingcoder.typepad.com/blog/2012/05/selecting-a-face-in-a-linked-file.html
There may be something newer and better, however...
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 04, 2014 at 23:04
Hmm a bit! I was considering using this when we were on 2013, but we're moving to 2015 so I was hoping there was another way. Quickly glancing at it I don't know how I would take the link unique ID and convert it into something that I could use.
My thought now is to just use an element collector and assume that there is only one link instance (which is usually the case). It's kind of quick and dirty but it will get me what I need. I suppose if you have multiple links you can pick up all the links and test to see which one has the object (wall in this case) and use that checked link.
Thanks for the insight
Posted by: Richard Cleveland | December 05, 2014 at 16:41
Dear Richard,
That makes sense. Congratulations on finding a way. My pleasure entirely.
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 08, 2014 at 18:41