Get Solid for Linked Element with Duplicate Id

Get Solid for Linked Element with Duplicate Id

Anonymous
Not applicable
12,453 Views
30 Replies
Message 1 of 31

Get Solid for Linked Element with Duplicate Id

Anonymous
Not applicable

I'm running into a frustrating problem when trying to get a solid for an element that lives in a linked file. Right now I'm using the custom exporter to get all the elements in a 3d view and then using Revit's get_Geometry method on certain ones in order to do a type of overlap detection.

 

Solid solid = element.get_Geometry(opts).FirstOrDefault() as Solid;

 

This seems to work fine for anything in the current file, and it seems to work fine for most elements in linked files. But if the linked element happens to share an id with an element in the active file, then doing the above returns the solid information for the element in the active file instead. This is the case, even though the element is clearly the correct element.

 

In a sample file, I have a linked file with a wall that has the same id as a window in the active file. When I debug the code at the line above, even without getting the firstordefault or converting it to a solid, I can clearly see the element is a wall but the solid the method returns is for the window. It seems that Revit's method is just using the id alone.

 

I've tried changing the View value in the Options object fed into the method, but I don't have an active view for the linked document and no other view I could find made sense. I've also tried changing the ComputeReference value, just to try. It changed nothing.

 

I've gone looking online and in the forums for other ways to get at the solid information for a linked document. This link  (https://forums.autodesk.com/t5/revit-api-forum/linked-file-element-intersection-solid-geometry/m-p/7...) suggests there is a method with the line in the accepted answer:

 

Open the linked project Q and retrieve the solid Sb of B.

 

Sadly, I can find no more information about how to do that. Can anyone point me to a way to do that, or find some other way to work around the bug in get_Geometry?

0 Likes
Accepted solutions (1)
12,454 Views
30 Replies
Replies (30)
Message 2 of 31

jeremytammik
Autodesk
Autodesk

Dear Nate,

 

Thank you for your query.

 

The strangeness you describe sounds very strange indeed.

 

I can hardly believe that. I am pretty sure the development team will not believe it either.

 

If indeed that is the case, it definitely needs to be looked at.

 

Can you please provide a minimal reproducible case demonstrating that effect?

 

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

 

For this situation, the following should be sufficient:

 

  • A host file containing a macro reproducing the problem
  • A linked file
  • Just a very few elements in each file, preferably one each
  • One of elements in each file sharing the same element id but with different geometry solid

 

I would be very surprised indeed if we can reproduce the behaviour you describe.

 

I would not be surprised at all if putting together the reproducible sample leads to you discovering a programming error or other misunderstanding that leads to this strange the result.

 

You might be surprised how often the implementation of the reproducible case (or attempt to do so) ended up solving the problem.

 

Maybe the call to FirstOrDefault is doing something unexpected? Have you tried unrolling that?

 

I can easily explain the suggestion in the thread you point to:

 

Open the linked project Q and retrieve the solid Sb of B.

 

It basically means something like this, which you are already doing:

 

Document Q; // obtained and opened somehow
ElementId id;
Element B = Q.GetElement(id);
Solid Sb obtained from B.get_Geometry

 

I hope this helps.

 

Best regards,

 

Jeremy

 



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

0 Likes
Message 3 of 31

Anonymous
Not applicable

Thanks, Jeremy. I will work on getting a sample around today, or as soon as I can.

0 Likes
Message 4 of 31

Anonymous
Not applicable

Hi Jeremy,

I've spent today pruning down the model and the code to just the bare minimum that will show the issue. It wasn't clear how you wanted me to submit it, so I've attached a zip to this reply. Hope that works for you.

 

These images from within a debugging session show the value returned from get_Geometry() from each of the two walls. The first, the wall in the primary file with a unique id, returns a solid (what I'd expect). The second, the wall in the linked file with the same id as the window in the first wall, returns a GeometryInstance for the window instead of a solid (not what I would expect).

 

FirstWallDebug-MacroVersion.jpgSecondWallDebug-MacroVersion.jpg

 

I'm actually still hopeful that I'm just doing something wrong, because I'd like to get past this issue as quickly as possible. Please let me know.

 

Thanks,

Nathan

0 Likes
Message 5 of 31

Anonymous
Not applicable

Oh, one last thing -- this is for Revit 2018. I think my company will be moving to 2020 sometime this year, but I'm looking for a solution that works with 2018.

 

Thanks!

Nathan

0 Likes
Message 6 of 31

jeremytammik
Autodesk
Autodesk

Dear Nate,

 

Thank you for your sample code.

 

There is something very strange in your sample code that probably explains the behaviour you see.

 

Your code says:

 

  //This will pull out the two walls, one in the primary document,
  //and one in the linked document.
  foreach (Document d in app.Documents)
  {
    walls.AddRange(new FilteredElementCollector(d)
      .OfCategory(BuiltInCategory.OST_Walls)
      .OfClass(typeof(Wall))
      .WhereElementIsNotElementType()
      .ToElements());
  }

 

I'm sorry to say this is impossible.

 

You cannot retrieve elements from two different documents using one single filtered element collector.

 

The sample code you provide retrieves elements from the document `d`.

 

You are not retrieving any element from the linked document at all.

 

Therefore, obviously, you are also not retrieving any geometry from any element in the linked document.

 

You are misunderstanding something very fundamental.

 

You can scrap this code, rethink, and start from scratch.

 

The good news is that there is no error in the Revit API, and you can fix this.

 

You will obviously be able to reuse almost everything you already have.

 

However, you will definitely need two separate filtered element collectors (or more), (at least) one for each document you process.

 

I hope this helps.

 

Best regards,

 

Jeremy

 



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

0 Likes
Message 7 of 31

Anonymous
Not applicable

Hi Jeremy,

Thanks for your response. I've attached another set of demo files and and a changed macro to show that getting the elements is not the problem, and that get_Geometry is still the issue. Here are the screencaps of running the macro, in which you will see there are two document being used to grab two sets of elements. This is correct and does not appear to be the real issue.

Primary document wall popup in new modelPrimary document wall popup in new modelLinked document walls popup in new modelLinked document walls popup in new model

While the code I attached previous is a vastly simplified version of the original just to demonstrate the bug, the full original code uses the recommended method to retrieve linked elements: the custom exporter. Using that definitely returns elements from the linked files (we use it all over the place with great success). Using custom exporter to get linked elements definitely shows the problem occurs when using get_Geometry on those elements to grab the geometry when an element shares an id with another element in the primary file.

 

Further, I'm pretty certain what you've said about the code I sent before is not correct. You said "You cannot retrieve elements from two different documents using one single filtered element collector." If you look at the code in the debugger or look at the output of the new code I attached you will see there are two documents under app.Documents (the main and the linked document), and when the foreach loop loops through each document it is creating a new filtered element collector for each one: 

new FilteredElementCollector(d)

You can see that code is not using one filtered element collector, but two (one for each document). If you step through the debugger for the previous code you will see this and that part is working correctly to retrieve both the main wall and the linked wall.

 

However, to attempt to prove that I am getting the correct elements and those elements can fail with get_Geometry, I have gone in and changed the structural (linked) file to add two more random walls. This way we can see that in one loop through app.Documents the code is picking up the one wall from the primary document and on the another pass it picks up the three walls from the linked document (see images above). This is only possible if the code is picking up elements from the linked document in two collectors, and not one that you said I was using. I have added a popup dialog as it steps through the documents getting the elements, so you can see this without even having to enter the debugger, but merely by running the macro. Please run the attached code or look at the images above to verify that it is correctly getting both the main and linked elements for you as well.

 

Given that getting the linked element isn't the issue, as it seems it's not, the initial issue with get_Geometry is still outstanding.

 

 

Thank you for your time.

Nathan

 

 

0 Likes
Message 8 of 31

jeremytammik
Autodesk
Autodesk

Very sorry, overlooked the loop  🙂

 



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

0 Likes
Message 9 of 31

Anonymous
Not applicable

Hi Jeremy,

No worries at all. So do you agree with my conclusion that this is a Revit API bug? Have the developers seen it? Is there a workaround for people like me that will have to deal with duplicate ids? Right now my team is looking at wrangling Revit elements into an external package just so we can replicate the logic of BooleanOperationsUtils.ExecuteBooleanOperation (which requires the solids we can't reliably get), which I would like to avoid if possible.

 

Thanks,

Nathan

0 Likes
Message 10 of 31

FAIR59
Advisor
Advisor
Accepted solution

If you remove the line:

            opts.View = doc.ActiveView;

from your code, you will find the geometry of all the walls.

 

Is this an option for you?

0 Likes
Message 11 of 31

Anonymous
Not applicable

Thank you! I could have sworn I tried that when I was playing with the options, but apparently I had not. That solved my problem!

0 Likes
Message 12 of 31

andremonteiro
Contributor
Contributor

I have a similar problem in that, I have a master model with linked models, and some of the links are copied several times on that master model. I am trying to achieve the same as the OP, however, I want to get the geometry of the copied elements as well, but what I'm getting are duplicates of the same element in their original position in the linked model.

 

Since the element IDs are the same for the copied elements, when I get their geometry, Revit does it from the original model and not the master model, hence I get a duplicate of the element on the same position. I thought the Options.View property was supposed to take care of that but apparently not.

Any thoughts?

Please see the image, models and code below. Thanks!!

 

Here's the code:

#Main code
view = UnwrapElement(IN[0])
viewId = view.Id

link_doc = []
links = FilteredElementCollector(doc).WhereElementIsNotElementType().ToElements()
for l in links:
	if "Link" in str(l):
		link_doc.append(l.GetLinkDocument())

views_doc = []
for l in link_doc:
	views = FilteredElementCollector(l).OfCategory(BuiltInCategory.OST_Views).WhereElementIsNotElementType().ToElements()
	for v in views:
		if v.Name == "{3D}":
			views_doc.append([l,v.Id])
			break

elements = []
for vd in views_doc:
	elems = FilteredElementCollector(vd[0],vd[1]).WhereElementIsNotElementType().ToElements()
	if elems:
		for e in elems:
			if not("Element" in str(e)):
				elements.append(e)

options = Options()
options.View = view

geometry = []
for e in elements:
	geo = e.get_Geometry(options)
	if geo:
		for g in geo:
			geometry.append(g.ToProtoType())	
OUT = geometry

 

0 Likes
Message 13 of 31

michael_weizmann
Participant
Participant

Hello,


I'm also facing a similar problem in Revit 2022.

I've got a door in a linked model, PlanView `ABC` in the site model, and an unrelated dimension in the site model that happens to have the same `ElementId` as the door.

So when I'm trying to do `door.get_Geometry()` with `View = ABC`, I'm getting the geometry of the dimension instead of the door.

If I remove the view from the options, as suggested by @FAIR59, I do get the geometry of the door, but that's a default geometry, that doesn't include the 2D geometry of the door in that specific view that I need.
I'd be glad to know if there are there any updates/workarounds for that issue? @jeremytammik 


Thanks,
Michael

0 Likes
Message 14 of 31

jeremy_tammik
Alumni
Alumni

If you are getting geometry from a dimension living in document A and the door lives in a different document B, then you are specifying the wrong document in your call to the Document.GetElement (ElementId) method. I would not expect the view to have anything to do with that problem. The view does not come into play until you call the element Geometry property with the appropriate Options. Before you do so, you need to ensure that you are working with the correct element to start with!

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 15 of 31

michael_weizmann
Participant
Participant

Thanks for quick reply Jeremy

 

I understand your assumption regarding the element I'm using, but I'm pretty sure it's the correct one.

It would be quite difficult for me to prepare a small example of a main and linked file that have elements with the same ids.

Assuming I'm using the correct element, or even if I'm not, I'm still wondering if there are any updates on the initial issue described in this post.

 

Message 16 of 31

jeremy_tammik
Alumni
Alumni

Yes, I understand the difficulty. If the situation is as you describe, it sounds like something the development team definitely need to take a look at. As you say, it may be tricky to hone it down to a minimal sample. On the other hand, it is probably more difficult still, or completely impossible, to reproduce, analyse, understand and fix the problem without such a reproducible case. Plus, it is just two files, and just two elements, possibly with some hosts and other stuff around to support them. Can't you just delete most of the unnecessary stuff?

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 17 of 31

michael_weizmann
Participant
Participant
Sure, I'll try to and will get back to you, thanks
Message 18 of 31

jeremy_tammik
Alumni
Alumni

There are no further updates on the original issue after Nate's confirmation:

  

Message 11 of 16 by Nate.Beeler on ‎2019-05-20 02:46 PM

  

> Thank you! I could have sworn I tried that when I was playing with the options, but apparently I had not. That solved my problem!

  

Why would you expect there to be?

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 19 of 31

michael_weizmann
Participant
Participant

Not providing a view in `Options` does work, but there are cases when I do need the geometry that is relevant to a specific view.
I'm attaching files with the example of the issue.
There is a wall in the linked ArchitectureModel_1.rvt and a opening cut in the SiteModel.rvt, both having the same ElementId.

With SiteModel.rvt as the active document, and LEVEL_1 ViewPlan as the active view I'm running the following code:

UIDocument uidoc = uiApplication.ActiveUIDocument;
Document siteDoc = uidoc.Document;
Document archDoc = uiApplication
    .Application
    .Documents
    .Cast<Document>()
    .ToList()
    .Find(d => d.PathName.Contains("Arch"));

ElementId id = new ElementId(4141128);
Element element = archDoc.GetElement(id);

if (element is Wall wall)
{
    Options options = new Options()
    {
        IncludeNonVisibleObjects = true,
        View = siteDoc.ActiveView
    };
    List<GeometryObject> geom = wall.get_Geometry(options).ToList();
}

 

With that, the geometry that I get in `geom` is the geometry of the opening cut, instead of the wall.

I can get wall geometry if I delete line 18, and that would be fine for this specific example, but there are other cases where I do need view-specific geometry.

Message 20 of 31

jeremy_tammik
Alumni
Alumni

So, maybe we should rephrase the problem and restart from scratch, then?

  

You have a document A and a linked document B. A contains a view V. B contains an element E. You wish to obtain the view-specific geometry for E in V.

  

is that correct?

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open