Made a new 3DView. It's empty. Why?

Made a new 3DView. It's empty. Why?

0001des
Enthusiast Enthusiast
1,525 Views
11 Replies
Message 1 of 12

Made a new 3DView. It's empty. Why?

0001des
Enthusiast
Enthusiast

What is going on?  here's my code:

 

                ViewFamilyType viewFamilyType = (from v in new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType)).Cast<ViewFamilyType>()
                                                 where v.ViewFamily == ViewFamily.ThreeDimensional
                                                 select v).First();
                View3D view;
                using (Transaction t = new Transaction(doc, "Create Issues View"))
                {
                    t.Start();
                    view = View3D.CreateIsometric(doc, viewFamilyType.Id);

                    
                    t.Commit();
                }

It makes the new 3D view.  But there isn't anything in it.  Any help would be greatly appreciated.  

 

(NOTE! When I iterate through all the objects found using a FilteredElementCollector on that specific 3d View, it returns over 9000 elements with their respective ElementID's.  That means there is geometry in that view, but for some reason it's not visible in 3D.)

 

 

 

0 Likes
1,526 Views
11 Replies
Replies (11)
Message 2 of 12

BIM.Frankliang
Collaborator
Collaborator

Hi Friend,

 

     Here is the Link you may need:

https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2017/ENU/Revit-API/files/GUID-...

     Wish it is helpful for you 🙂

 

Best Regards,

Frank Liang

名片2.png

 

 

0 Likes
Message 3 of 12

0001des
Enthusiast
Enthusiast

I would assume that regardless of the 3dView clipping plane and bounding box settings, it would allow me to zoom-to-fit on the objects in the view once the script has finished, right?  

 

However, when I orbit around the 3D View, there is still nothing in the view for me to find or select.  Perhaps I am mistaken about the clipping plane values, and the geometry is there, however, for some reason, i cannot see it.  I'll try to mess with these methods in the link you sent, and see what happens.  

0 Likes
Message 4 of 12

BIM.Frankliang
Collaborator
Collaborator

Hi Friend,

 

     Here is the key code in link that could solve your question:

 view3D.SetOrientation(viewOrientation3D)

 

Wish it is helpful for you 🙂

 

Yours sincerely,

Frank Liang

名片2.png

 

 

0 Likes
Message 5 of 12

0001des
Enthusiast
Enthusiast

I tried various ViewOrientations and nothing appears in my view.  

 

Nothing is working.

 

                ViewFamilyType viewFamilyType = (from v in new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType)).Cast<ViewFamilyType>()
                                                 where v.ViewFamily == ViewFamily.ThreeDimensional
                                                 select v).First();
                View3D view33 = null;
                using (Transaction tran2 = new Transaction(doc))
                {
                    if (tran2.Start("Make View") == TransactionStatus.Started)
                    {
                        view33 = View3D.CreateIsometric(doc, viewFamilyType.Id);
                        
                        

                        XYZ eye = new XYZ(10, 10, 10);
                        XYZ up = new XYZ(0, 0, 1);
                        XYZ forward = new XYZ(0, 1, 0);
                        

                        ViewOrientation3D viewOrientation3D = new ViewOrientation3D(eye, up, forward);
                        view33.SetOrientation(viewOrientation3D);
                        tran2.Commit();
                    }
                }

This seems really dumb and simple.  Does anyone have a simple portion of Revit API code that makes a 3D view, and has objects in it?  No links to someone else's site or distractions.  Just letters and words and semi-colons showing the proper way to make a 3D View in these API's?   

 

I've coded in CATIA, Rhino, AutoCAD, and Maya for years without any issues, but I've never had such trouble than when I want to do the simplest things in Revit.

 

 

 

 

0 Likes
Message 6 of 12

cwaluga
Advocate
Advocate

Did you check the visibility settings of your view? You use any view type you find to create the view, so it might well be that you use a template where the things that matter to you are hidden. Type VV in the created view to check what is visible.

0 Likes
Message 7 of 12

0001des
Enthusiast
Enthusiast

I've been able to show all objects, but through a rather convoluted way.

 

Here's how I did it.  

 

I run my script.  It collects the ID's of every object that causes the an error.  With that collection, I do the following:

 

Make a transaction, make a CreateIsometric 3D view, name it.  (Code mentioned above).

Then I unhide all the elements in my "error" collection.

 

view33.UnhideElements(PILIDList);

Then I commit the transaction.

 

Just to make this work for now, I use the visibilityCategory method to turn on all the Walls.  I want this to turn on all BIC's, but for now, I just have it for walls to get this dumb script done.

 

Util.visibilityCategory(doc, categories, view33, BuiltInCategory.OST_Walls);

(While I have you, how can I include all categories, not just the walls, without making some sort of loop?)

 

Onward,

I set the new 3D View as active:

 

uiApp.ActiveUIDocument.ActiveView = view33;

Then I make a new transaction.  

 

Then I collect all the elements in the view:

 

                        FilteredElementCollector CGM = new FilteredElementCollector(doc, view33.Id);
                        ICollection<ElementId> hh2 = CGM.ToElementIds();
                        List<ElementId> hh2List = (List<ElementId>)hh2;

Then I go through all the elements in a loop to determine if any object in the main view object collection is in my error loop.  If it is, I have a subroutine to return if it exists, and to skip it.  If it doesn't, then it hides the object using the HideElements method.  Since HideElements only takes a collection or list, then I have to make a temporary list in the loop to perform the hide operation.

 

                            if (IsInListElementID(PILIDList, hh2List[jkl]) == false)
                            {
                                //hide
                                try
                                {
                                    List<ElementId> hh2ListPre = new List<ElementId>();
                                    hh2ListPre.Add(hh2List[jkl]);
                                    view33.HideElements(hh2ListPre);
                                    hh2ListPre.Clear();
                                }
                                catch { }
                            }
                            else
                            {
                                //show
                                
                            }

Perhaps I could make a "RemoveOffendingIDsFromList()" subroutine so I could do the HideElements method, but for now, this works.

 

After all this, I use the UnhideElements to "show" all the objects that were in my "error" list.

 

view33.UnhideElements(PILIDList);

I commit this and it shows all the elements in the 3D View.  Or, it hides all the elements. 

 

Either way, all or nothing doesn't help me.  I need a 3D view showing ONLY the objects in my "error" list.  Using these API's is like pulling teeth.

 

Here are my questions:

 

Could my "error" objects be sub-objects, which when you hide/show the parent object, it hides everything underneath it regardless if the sub-object is "unhided?"  

 

Why isn't UnhideElements showing my objects? 

 

Could my "error" objects not be able to hide/show via the API?  They are "error" objects because it does not allow me to modify parameters on them.

 

My error objects happen to be parts of walls.  When I "show" the category of OST_Walls, does that "show" all the elements under a 3D wall, or does it just show parts of a wall, thus my "error" objects won't show up regardless?

 

 

 

 

 

 

0 Likes
Message 8 of 12

0001des
Enthusiast
Enthusiast

Most of my objects are parts of a wall.  I have the ElementID of the "part" of the wall, but how do I get the parent wall ElementID?

0 Likes
Message 9 of 12

FAIR59
Advisor
Advisor

first of all, you might make a list of the error elements. We can then see the Revit classes to which the elements belong.

			List<ElementId> errorIds ;
			StringBuilder sb = new StringBuilder();
			foreach( ElementId id in errorIds)
			{
				Element e = doc.GetElement(id);
				sb.AppendLine(string.Format("<{0}> {1}  [{2}]",id, e.Name, e.GetType()));
			}
			TaskDialog.Show("debug", sb.ToString());

 

I think you should make your own ViewFamilyType, without ViewTemplate so all elements are Visible on creation.

You can then hide all elements (that can be hidden) except the error elements.

			List<ElementId> errorIds ;
            ViewFamilyType viewFamilyType = (from v in new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType)).Cast<ViewFamilyType>()
                                                 where v.ViewFamily == ViewFamily.ThreeDimensional
                                                 select v).First();
            View3D view;
            using (TransactionGroup tg = new TransactionGroup(doc, "create Error View"))
            {
            	tg.Start();
		        using (Transaction t = new Transaction(doc, "Create Issues View"))
        	    {
            	    t.Start();
            	    // create new ViewFamilyType without ViewTemplate
            	    ViewFamilyType my_type = viewFamilyType.Duplicate("Error_View") as ViewFamilyType;
					my_type.get_Parameter(BuiltInParameter.DEFAULT_VIEW_TEMPLATE).Set(ElementId.InvalidElementId);
            	 
					view = View3D.CreateIsometric(doc, my_type.Id);

					// Hide DWG , Analytical Categories, Annotaion
            	    view.AreImportCategoriesHidden = true;
            	    view.AreAnalyticalModelCategoriesHidden = true;
            	    view.AreCoordinationModelHandlesHidden = true;
            	    view.AreAnnotationCategoriesHidden = true;
            	    // Hide RVT Links
            	    view.SetCategoryHidden(new ElementId(BuiltInCategory.OST_RvtLinks),true);
            	    // show Parts
            	    view.get_Parameter(BuiltInParameter.VIEW_PARTS_VISIBILITY).Set(2);
            	    t.Commit();
            	}
		        IEnumerable<Element> elemsInView = new FilteredElementCollector(doc,view.Id)
		        	.WhereElementIsNotElementType()
		        	.Excluding(errorIds);
		        List<ElementId> elemsToHide = new List<ElementId>();
		        foreach(Element e in elemsInView)
		        {
		        	if (e.CanBeHidden(view) ) elemsToHide.Add(e.Id);
		        }
		        using  (Transaction t = new Transaction(doc, "hide elements"))
		        {
		        	t.Start();
		        	view.HideElements(elemsToHide.ToList());
		        	t.Commit();
		        }
		        tg.Assimilate();
            }
            this.ActiveUIDocument.ActiveView = view;
            this.ActiveUIDocument.ShowElements(errorIds);

Last thing to check (if needed) Visibility of Worksets, turn on all worksets. [ view.SetWorksetVisibility() ]

0 Likes
Message 10 of 12

0001des
Enthusiast
Enthusiast

Thank you for your detailed answer.  I like your approach.  I'll see if I can port it over to my code, and make this work.  I have a few questions.

 

What does this line mean:

 

 

// create new ViewFamilyType without ViewTemplate
            	    ViewFamilyType my_type = viewFamilyType.Duplicate("Error_View") as ViewFamilyType;
					my_type.get_Parameter(BuiltInParameter.DEFAULT_VIEW_TEMPLATE).Set(ElementId.InvalidElementId);

 

I looks like we are duplicating the "first" view found via the filter criteria further up the code, so the file is basically taking an existing view and duplicating it.  Is that better than the "Create" method?

 

Then you are getting a parameter  and setting it to an ElementId enumeration of invalid element?  Why?  Is ElementId.InvalidElementId not an enumeration?  

 

 

view.get_Parameter(BuiltInParameter.VIEW_PARTS_VISIBILITY).Set(2);

What is this line doing exactly?  Why "2?"

 

 

 

I like this line:

 

		        IEnumerable<Element> elemsInView = new FilteredElementCollector(doc,view.Id)
		        	.WhereElementIsNotElementType()
		        	.Excluding(errorIds);

I see what you do later with checking the elements to make sure they are eligible for "hiding."  Too bad the filter can't have a ".CanBeHidden()" suffix to eliminate that.  But I'm sure it doesn't require a lot resources.

 

 

 

 

All of this is really good.  I'll try it out.  Aside from the "view.get_Parameter(BuiltInParameter...." coding, I have seen most of what you are providing, but never employed it in that way.  Much smarter looping and filtering in your suggestion than my original code, but I'm still negotiating how Revit works.

 

 

 

 

 

 

 

 

0 Likes
Message 11 of 12

FAIR59
Advisor
Advisor

Why duplicate?

It is not duplicating a existing view, but duplicating a existing ViewFamilyType.

Because I don't know which elements are on the errorId list, I want to make sure that all elements are visible. A view has a ViewFamilyType. The ViewFamilyType can have a ViewTemplate (which regulates visibility / non-visibility of categories)  assigned to it, that will be applied to newly created views. As I want all elements visible, I want to use a ViewFamilyType without a ViewTemplate. To avoid messing with the model, I duplicate the first ViewFamilyType found, and remove the ViewTemplate from it.  [my_type.get_Parameter(BuiltInParameter.DEFAULT_VIEW_TEMPLATE).Set(ElementId.InvalidElementId);]  where ElementId.InvalidElementId is the equivalent to null for an ElementId-value. (== do not assign ViewTemplate)

Then I use this ViewFamilyType to create the 3D view.

 

BuiltInParameter.VIEW_PARTS_VISIBILITY

Revit has the possibility to divide (system) families into Parts http://help.autodesk.com/view/RVT/2018/ENU/?guid=GUID-DA150C6B-996C-4C70-9E8C-3C536C232851 

A view can show either the original element, the parts or both. By setting the BuiltinParameter to 2, I set the view to show the original element and the parts.

0 Likes
Message 12 of 12

jeremytammik
Autodesk
Autodesk

Thank you for the interesting discussion, and especially @FAIR59 for his very illuminating answer.

 

I summarised it for posterity here:

 

http://thebuildingcoder.typepad.com/blog/2018/09/floor-area-above-room-and-mysterious-hide.html#3

 

Cheers,

 

Jeremy

 



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

0 Likes