Mapping exported DXF entities with Revit elements in linked models

Mapping exported DXF entities with Revit elements in linked models

jmorris03
Enthusiast Enthusiast
2,450 Views
12 Replies
Message 1 of 13

Mapping exported DXF entities with Revit elements in linked models

jmorris03
Enthusiast
Enthusiast

We have an application that exports DXF through the Revit API, and as part of a post-process, applies other data that is associated with the Revit element. 

 

The mapping is straight forward and works well when the Revit elements are part of the main model, but not so well when the elements are part of a linked model.

 

When an element originates from the main model, the Revit Id value maps directly to that value contained in the XData of the AutoCAD entities.   

e.g. 

Revit Id = 318170

AutoCAD XData: 

(-3 ("REVIT" (1002 . "{") (1070 . 1) (1000 . "318170") (1002 . "}") (1002 . "{") (1070 . 5) (1000 . "131610") (1002 . "}") (1002 . "{") (1070 . 2) (1000 . "-2000080") (1002 . "}")

 

But if the element originates from a linked model, the XData will contain some other Id value:

e.g.  

AutoCAD XData: 

(-3 ("REVIT" (1002 . "{") (1070 . 2) (1000 . "315181_-2000011") (1002 . "}")

 

Is there any way of mapping an AutoCAD entity that originates from a Revit linked model?

0 Likes
Accepted solutions (3)
2,451 Views
12 Replies
Replies (12)
Message 2 of 13

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Thank you for your interesting query.

 

Yes, I would expect there to be some way to determine that mapping for linked files as well.

 

I cannot tell off-hand, though, or guarantee anything whatsoever.

 

What research have you performed so far yourself?

 

What are the element ids and unique ids in the project file and the linked model versus the info reflected in the AutoCAD Xdata?

 

Here is all I know about the DWG and DXF Export Xdata Specification so far:

 

https://thebuildingcoder.typepad.com/blog/2010/08/dwg-and-dxf-export-xdata-specification.html

 

It says nothing about linked files.

 

I would be overjoyed to add that information.

 

Let's research further together and find out.

 

I can check our results with the development team as soon as we have any, or we can provide them with a complete minimal reproducible case:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#1b

 

Would you like to supply one?

 

I guess it just needs one element each in the main project and the linked file.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 13

jmorris03
Enthusiast
Enthusiast

Hi Jeremy,

 

Thanks for the reply.

 

Given:

Our application makes use of the Revit Unique Id value to map Revit elements to other data, e.g. in code: v.UniqueId

 

But the DXF export functionality does not push the UniqueId value, it pushes the element Id values instead.

 

So the only way we have of identifying an AutoCAD entity in the DXF is per that element Id value.

 

The issue is that elements that reside in a linked model are pushing out an element Id value that is not the same as the Revit .NET API provides to us.  I'm assuming that it  is some internally generated Id value that is used by Revit itself with the linked models, but not exposed through the Revit API.

 

In the attached .zip file, there are 2 Revit 2018 models:

liteArch.rvt

litMep. rvt

 

liteArch model is linked into liteMep.

 

The exported DXF is also included for reference, and was generated from the standard Revit UI for exporting DXF.

 

No code is needed to see the discrepancies between the Revit Id and the values in AutoCAD XDATA.

 

The Element Id values can easily be obtained using the Revit Lookup Snoop Current Selection Addin.

 

In this simple example, both the main model and the linked in model contain 1 table each.

The Xdata chunks displayed here are from the exported dxf loaded into AutoCAD.

 

Main Model Table Object Id: 318170

AutoCAD XData:

(-3 ("REVIT" (1002 . "{") (1070 . 1) (1000 . "318170")

    (1002 . "}") (1002 . "{")

    (1070 . 5) (1000 . "131610") (1002 . "}")

    (1002 . "{") (1070 . 2) (1000 . "-2000080") (1002 . "}")

 

Linked Model Table Object Id:  320121

AutoCAD Xdata:

(-3 ("REVIT" (1002 . "{") (1070 . 2) (1000 . "318408_-2000011") (1002 . "}")

 

You can see the mismatch in the xdata 1000 grouping for the linked model.

We aren't concerned about the different contents of each of the Xdata lists, as our code expects this and handles it.

e.g.

(1000 . "318170")

(1000 . "318408_-2000011")

 

The issue is that because we do not have the expected Revit Element Id => AutoCAD Entity Xdata identifier, there is no way for us to correctly identify the entity in the model.

 

Ideally, I would have thought that the export DXF functionality would push the Unique Id values, but it doesn't.

 

Hopefully what I've described here is clear.

And I am definitely looking for a way to support this mapping in our application.

 

As an aside to this issue, but related, any idea why the DXF Export called from the .NET API  is about 50% slower than when Exporting DXF from the Revit UI?

 

 

Thanks,

Joe

0 Likes
Message 4 of 13

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Thank you for your update and detailed explanation.

 

That is just what I need.

 

I logged the issue REVIT-141310 [Invalid element ids in DWG and DXF export Xdata -- 14864463] with our development team for this on your behalf as it requires further exploration and possibly a modification to our software. Please make a note of this number for future reference.

 

You are welcome to request an update on the status of this issue or to provide additional information on it at any time quoting this change request number.

 

This issue is important to me. What can I do to help?

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 5 of 13

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Thank you for your patience.

 

The development team have taken a look at the issue REVIT-141310 [Invalid element ids in DWG and DXF export Xdata -- 14864463].

 

Their initial take on this is that this behaviour is (obviously) not API related, and therefore a product issue which needs to be discussed at a higher level.

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 6 of 13

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Thank you for your patience.

 

The development team resolved the issue REVIT-141310 [Invalid element ids in DWG and DXF export Xdata -- 14864463] as 'By Design' and explain why things are as they are:

 

This is by design.

 

Let's suppose the we have a rvt document with one wall. We have another rvt document and link the original one (with the wall).

 

When we export in AutoCAD, we will see a block reference which is containing four lines (the result of exporting the wall).

 

Now, in xdata of the block reference, we will find the id of the RevitLinkInstance element.

 

In the xdata of each line,  we will find the wall's id which is the id from the linked document.

 

Now, with the id of stored in block reference you can obtain the RevitLinkInstance element.

 

With this you can do the following to obtain the UniqueId:

 

 

  int idInteger = ...; // element id in the linked document (the wall's id which can be obtained from line's xdata)
  ElementId id = new ElementId(idInteger);
  Element elemFromLink = revitLinkInstanceElem.GetLinkDocument().GetElement(id); // this element is the wall
  string uniqueId = elemFromLink.UniqueId; // obtain the unique id

 

I hope this solves the issue for you.

 

Please let us know how you end up using this.

 

Thank you!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 7 of 13

jmorris03
Enthusiast
Enthusiast

Hi Jeremy,

 

Unfortunately the proposed solution does not work.

 

Let me describe what I have here in a different way, based on the info previously sent...

liteArch.rvt is linked into liteMep.rvt

liteArch contains:
    FamilyInstance of a table : 318170 (Revit Id in the linked in Arch model)

Export to DXF and loaded into AutoCAD

Drawing contains:
    BlockReference (what originated as the linked in model liteArch.rvt)
    I Explode the liteArch block reference

Drawing now contains:
    BlockReferernce of a table: 318408 (Revit id from the xdata in the AutoCAD entity)

Note that the 2 id values are not the same.

In Revit, using those 2 different Revit id values, I get the following results:

int idInteger = 318170; // element id in the linked document
ElementId id = new ElementId(idInteger);
Element elemFromLink = revitLinkInstanceElem.GetLinkDocument().GetElement(id);
// elemFromLink is non-null


int idInteger = 318408; // element id in the linked document (the familyInstance id which is obtained from blockReference's xdata)
ElementId id = new ElementId(idInteger);
Element elemFromLink = revitLinkInstanceElem.GetLinkDocument().GetElement(id);
// is NULL

 

In other words, the id value in the XDATA does not represent a valid revit id in the linked model.

Hope what I've described is clear enough, and the attachment that I provided before demonstrates this problem.

Thanks again for your assistance with this,
Joe

0 Likes
Message 8 of 13

jmorris03
Enthusiast
Enthusiast

Hi Jeremy,

 

The following image, which is also attached, clearly shows the discrepancy that I'm talking about.

The left side shows the Revit Id values in Revit.

The right side shows the Revit Id values contained in the AutoCAD xdata.

IdDiscrepancy.jpgThe Revit Id for the Room element does come across correctly in the AutoCAD xdata, but the id value for the Table (Family Instance) element does not.

 

The Revit Id 320121 is not found with a text search in the DXF file, i.e.  it just isn't in there.

 

FYI:  This DXF functionality that we are using here is nothing more than a work around to the fact that the Revit API doesn't provide a method for determining if elements in a linked model are visible in a given view or not.  Per a discussion I have had with Revit development in the past, this is a known limitation.  If we had that working, this DXF workaround that we have implemented would be a moot point.

 

Thanks again,

Joe

 

0 Likes
Message 9 of 13

jeremytammik
Autodesk
Autodesk

Dear Joe,

 

Thank you for your update and clarification.

 

I didn't think it was solved either  🙂

 

I reopened the issue REVIT-141310 [Invalid element ids in DWG and DXF export Xdata -- 14864463] and added your explanation to it.

 

I guess it is still by design, and not an API issue anyway, but maybe this will still help move forward in some way.

 

Have you submitted a wish list item for better access to the linked elements based on DWG and DXF export xdata info yet?

 

If not, I would suggest you do so and collect as many votes as possible for it.

 

Meanwhile, I look forward to their response to your detailed explanation.

 

Thank you!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes
Message 10 of 13

jeremytammik
Autodesk
Autodesk
Accepted solution

Dear Joe,

 

The development point understand the issue now and responded again to the issue REVIT-141310 [Invalid element ids in DWG and DXF export Xdata -- 14864463], saying:

 

I can confirm that this is an issue. I don't have any workaround for obtaining elementId from DXF file.

 

The only thing that I have in mind is to use DWG export with DWGExportOptions.MergedViews = false (option "Export views on sheets and links as external references checked" ).

 

In this case, each RevitLinkInstance will create a separate dwg file and the family instances will have the correct id.

 

I believe that the customer is interested about 2d views.

 

For 3d views, he can used a CustomExporter (derive a class from IExportContext) that provides callbacks which inform when a rvt link or an element is exported.

 

These kinds of workarounds are ugly, keeping in mind he just want to see if an element from RevitLink is visible in a view.

 

I think that we should understand better this requirement (maybe a business case) and solve the real request.

 

I'll close this issue REVIT-141310 now as 'code fix needed'.

 

We should analyse what we should set in xdata - the id from linked document, and also specify somehow that it was from a linked document, or we should set the UniqueId, but in this case maybe we should do for all the elements that are exporting, including ones in the current rvt.

 

Do you happen to know whether the string representation of a stable reference includes information about the whole hierarchy of linked files and nested element ids at each level?

 

Would you like to provide a business case for this?

 

I hope the problem description is clear enough as it stands now.

 

The rest of a business case provides motivation to address the task at hand:

 

This issue needs to be assessed by our engineering team and prioritised against all other outstanding change requests. Any information that you can provide to influence this assessment will help. Please provide the following where possible:

 

  • Impact on your application and/or your development.
  • The number of users affected.
  • The potential revenue impact to you.
  • The potential revenue impact to Autodesk.
  • Realistic timescale over which a fix would help you.
  • In the case of a request for a new feature or a feature enhancement, please also provide detailed Use cases for the workflows that this change would address.

 

This information is extremely important. Our engineering team have limited resources, and so must focus their efforts on the highest impact items. We do understand that this will cause you delays and affect your development planning, and we appreciate your cooperation and patience.

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 11 of 13

jmorris03
Enthusiast
Enthusiast
Accepted solution

Hi Jeremy,

 

Thanks for the update.

In the meantime I have been able to come up with an acceptable workaround to this RevitId => AutoCAD XDATA mapping issue.

 

The workaround:

Instead of relying on the Revit Id value that originates in a Linked model to be correctly pushed to AutoCAD XDATA, I've implemented a different and simple way of being able to correctly identify an AutoCAD BlockReference associated with the originating Revit FamilyInstance element. Which is to just identify an AutoCAD BlockReference entity by the X,Y in the drawing which does appear to be an identical match to a FamilyInstance Location in the model. It seems to work very well, and gets us to where we need to be, which is what counts at this point in time.

 

Background info of this particular bit of functionality:

Our core applications, which are distributed globally, are Browser/Mobile device interfaces.

Some of the core functionality we deliver is to support Space Management, Asset Management, etc.

Our users expect a graphical interface in the Browser/Mobile that display both 2D floor plans as well as 3D models.

(I'm very aware of Autodesk's Forge based APIs, but for a huge part of our client base, for many different legitimate reasons are not either ready or planning on moving to the cloud).
The building/floor plan graphics originate from Revit/AutoCAD, which we push to different output file formats to satisfy our core applications.  In particular, this issue is in regards to publishing the 2D floor plans.

 

The overall flow of this functionality looks like this:

Revit/AutoCAD => Intermediate Format => Targeted Output formats

 

In the above flow, DXF was not even part of the equation until we discovered that it is not possible with the Revit API to determine if an element in a linked model is visible in a view in the main model. Meaning it was not possible to push the correct linked graphics to our Intermediate Format.

 

So we shoehorned in the DXF process into our overall process something like this:

Revit/AutoCAD => DXFShoehornedIn => Intermediate Format => Targeted Output formats

 

The following is an example of the Revit code for getting at list of elements to work with from the main model (pretty standard logic):

 

FilteredElementCollector collector = new FilteredElementCollector(document, view.Id);
IEnumerator enumerator = collector.WherePasses(
new LogicalOrFilter(
new ElementIsElementTypeFilter(false),
new ElementIsElementTypeFilter(true))).GetElementIdIterator();

 

But the above is not able to get the elements in the linked models. Of course there are ways of getting the elements and the associated graphics from the linked models, but there is no way to determine if an element in a linked model is visible in the current model's view. Per a discussion I had at Forge last year with Revit development, it is not exposed in the Revit API. e.g.  no such capability as:

    GetVisibleElementsContainedInLinkedModelPerViewInMainModel(mainModelView);

 

Based on that limitation with not being able to correctly identify which elements are visible in the linked model, we were able to determine that DXF would solve this problem for us. That is, it does a very nice job of pushing all of the geometry, whether originating from the main model or one of the linked models, into a single and nicely packaged DXF file. And the bonus was that the Revit => DXF process conveniently also provided a way of mapping the generated AutoCAD entity back to the originating Revit element, via the Revit Id. But that then lead us to discover, it doesn't push the Revit Id from a linked model correctly, which is what lead to this discussion in the first place.

 

The workaround, based on the DXF logic that now maps the X,Y values:

       private void DXFToIntermediateLogicPsuedoCode()
        {
            // Create a list of the linked in model identifiers
            List<string> linkedModelIds = GetLinkedModelIds();

            // Create a list of Asset information to be passed to the DXF process
            List<Asset> assets = new List<Asset>();
            assets.AddRange(GetElementsInMainModelWeAreInterestedIn().Select(e => ToAsset(e)));     
            assets.AddRange(GetLinkedElementsWeAreInterestedIn().Select(e => ToAsset(e)));

            // Call the Revit API for exporting to DXF
            ExportDXF();

            // The DXF process
            var dxfModel = LoadDXF();
            foreach (var entity in dxfModel.Entities)
            {
                if (entity is BlockReference && linkedModelIds.Contains(entity.Name))
                    ProcessEntities(assets, entity.Entities);
                else
                    ProcessEntity(assets, entity);
            }
        }

        private void ProcessEntity(IEnumerable<Asset> assets, Entity entity)
        {
            int RevitId = entity.GetRevitId();
            var asset = assets.FirstOrDefault(a => a.Id == RevitId);

            // The logic that will now test per X,Y
            if (asset == null)
                asset = assets.FirstOrDefault(a => a.Point == entity.Point);

            if (asset != null)
                PushAssetGraphics(asset);
        }

        public class Asset
        {
            public int Id;      // The Revit ElementId
            public Point Point; // The Revit Location

            //  Other data we keep track of
        }

        private Asset ToAsset(Element element)
        {
            // If from a linked model, get the X,Y values
            //  + taking into consideration the revitLinkInstance.GetTotalTransform() values
            return new Asset();
        }

The above code is obviously a lightweight description of the process, but you get the basic idea.

 

Based on this workaround, we are good to go.

 

Thanks again for your time with this,

Joe

0 Likes
Message 12 of 13

jeremytammik
Autodesk
Autodesk
Accepted solution

Dear Joe,

 

Thank you for your update and sharing your workaround.

 

Congratulations on solving the problem cleanly and efficiently.

 

Is the following a correct summary of your approach, in a nutshell?

 

  • You export information from Revit to DXF.
  • Later, from the DXF data, you wish to relocate the Revit element.
  • This is easy for Revit elements in the main file, since the DXF Xdata contains the element id.
  • For Revit elements in a linked file, the element id is not available.
  • In that case, you use the element XY location to retrieve it instead.

 

Correct?

 

I like the idea very much.

 

I described something similar and more generic in my suggestion to create your own key:

 

https://thebuildingcoder.typepad.com/blog/2012/03/great-ocean-road-and-creating-your-own-key.html#2

 

Thank you!

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 13 of 13

jmorris03
Enthusiast
Enthusiast

Hi Jeremy,

 

Yes, you did a very good job of summarizing what I described in a much more verbose way.

 

The important thing here is that we are now able to make this required mapping from Revit linked elements to their equivalent in DXF.

 

Thanks for your support on this.

Joe

 

0 Likes