CreateLinkReference Sample Code

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

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
.


Comments

4 responses to “CreateLinkReference Sample Code”

  1. Richard Cleveland Avatar
    Richard Cleveland

    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!

  2. 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.

  3. Richard Cleveland Avatar
    Richard Cleveland

    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

  4. Dear Richard,
    That makes sense. Congratulations on finding a way. My pleasure entirely.
    Cheers, Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading