Create new View3D that just displays wall layers of "Structure" function

Create new View3D that just displays wall layers of "Structure" function

evidalpe
Contributor Contributor
1,030 Views
9 Replies
Message 1 of 10

Create new View3D that just displays wall layers of "Structure" function

evidalpe
Contributor
Contributor

 

I have a list of Walls and I want to create a new View3D with the same walls but containing only the "Structure" function layers. I've implemented the code below.

 

I've realized that I need to duplicate the WallTypes and copy a new wall with just the filtered layers in the same location, because otherwise the original Walls & WallTypes will be modified. The code below works, but it's extremely slow for big models. Is there any way to optimize the process?

 

 

 

 

...
/* Create new View3D and make it active */
...

ICollection<ElementId> visibleIds = new List<ElementId>();                    

foreach(Wall wall in wallList)
{
	// Get WallType and CompoundStructure
	WallType wallType = wall.WallType;
	CompoundStructure compoundStructure = wallType.GetCompoundStructure();

	// Copy wall in the same position
	ICollection<ElementId> newWallId = ElementTransformUtils.CopyElement(ViewModel.CurrentDocument, wall.Id, new XYZ(0, 0, 0));

	// Duplicate WallType
	Wall newWall = ViewModel.CurrentDocument.GetElement(newWallId.ElementAt(0)) as Wall;
	WallType newWallType = newWall.WallType.Duplicate(newWall.WallType.Name + GenerateRandomSuffix()) as WallType;
	CompoundStructure newCompoundStructure = newWallType.GetCompoundStructure();
	IList<CompoundStructureLayer> newWallLayers = newCompoundStructure.GetLayers();
	
	// Filter just Structure layers and assign to new WallType
	IList<CompoundStructureLayer> filteredLayers =
		(from o in newWallLayers where o.Function.ToString() == "Structure" select o).ToList();
	newCompoundStructure.SetLayers(filteredLayers);
	newWallType.SetCompoundStructure(newCompoundStructure);
	newWall.WallType = newWallType;

	// Add walls to visible elements list
	visibleIds.Add(newWallId.ElementAt(0));
}

...
/* Hide all elements in View3D and just make "visibleIds" visible */
...

 

 

 

 

 

 

 

 

0 Likes
Accepted solutions (1)
1,031 Views
9 Replies
Replies (9)
Message 2 of 10

RPTHOMAS108
Mentor
Mentor

It may be slow due to wall joins i.e. the new walls are going to try and interact with the adjacent existing walls to those copied from. Generally (always) that kind of workflow is not a good idea (duplicating elements in same location to change presentation).

 

Have you considered copying walls to new project and linking them back in, perhaps the other option is by utilising design options.

Message 3 of 10

harrymattison
Advocate
Advocate
Message 4 of 10

evidalpe
Contributor
Contributor

@harrymattison that's a great idea for visualization, I'll have a look and see if I can implement that in my add-in.

But at the end, if I want to have both the original and the new wall types available at the same time, I'd need to find another way. @RPTHOMAS108 is right, due to wall joins the process is slow, so there's not an easy way to do this.

0 Likes
Message 5 of 10

harrymattison
Advocate
Advocate
Accepted solution

Not sure why you want to duplicate wall types and have both original and new wall types in your project. Is your end goal something different than what I show here? https://boostyourbim.wordpress.com/2023/12/04/create-a-3d-view-showing-only-revit-wall-structural-la...

Message 6 of 10

jeremy_tammik
Alumni
Alumni

Dear Harry,

  

Thank you for your very nice solution! 

  

I summarised the functionality that you implement and thought my list of steps might be of interest to other as well, so here goes:

  

  • Create a new 3D isometric view
  • Set parts visibility PartsVisibility.ShowPartsOnly
  • Create parts from all walls
  • For each part, retrieve its built-in parameter DPART_LAYER_INDEX
  • Convert from string to wall compound structure layer index
  • Hide part if its compound structure layer function differs from MaterialFunctionAssignment.Structure

  

Cheers,

  

Jeremy

  

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

evidalpe
Contributor
Contributor

Yeah, I do need to have both available somehow, it's a difficult use case. So somehow the first response fits better for my needs.

In any case, it makes much more sense to accept your response as the valid one, you've done a great work. And congrats on the super blog too 🙂

Just one thing before accepting the response, I think the transaction must be committed

t.Commit();

after the 

PartUtils.CreateParts

call. Otherwise the collector

FilteredElementCollector(doc, view.Id).OfClass(typeof(Part))

will be empty, since the Parts won't be available yet.

Could you have a look to that? I've tried with several examples and that's the only way I made it work.
Then of course you have to create another transaction for 

view.HideElements(toHide);

 

0 Likes
Message 8 of 10

harrymattison
Advocate
Advocate
Thanks. Glad this was helpful. Yesterday it seemed to work fine without
committing that transaction after creating the parts, but when I look at it
today, we do need to add doc.Regenerate() there. This is often
sufficient to get the document to update without committing the transaction.
0 Likes
Message 9 of 10

jeremy_tammik
Alumni
Alumni

... cf. 

 

 

thank you and cheers,

 

jeremy

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

evidalpe
Contributor
Contributor

Cool, I saw you already updated it in your blog. Response accepted!
Thanks @jeremy_tammik for all the work you do too, always a reference for Revit API devs 🙂

0 Likes