Show Element Relative to Model in View3D

Show Element Relative to Model in View3D

Anonymous
Not applicable
4,337 Views
8 Replies
Message 1 of 9

Show Element Relative to Model in View3D

Anonymous
Not applicable

Hi,

I’m having trouble finding a way to adjust a perspective 3D view to show the region that is already showing as well as a specific element. I have this working for 2D because all I have to do is make a new BoundingBoxXYZ that includes both the current CropBox and the BoundingBoxXYZ of my element, then set view.CropBox = newBox. I've attached pictures to show this operation in a 2D view.

 

I want to mimic this behavior with 3D views. My ideas was to orient the view facing down then do the same crop box union but set the eye of the view to the center of the XY plane of the new box and at a Z value high enough to see everything.

 

The problem I’m running into is that I can’t find a good way to get or set the corners of the crop box as it is projected onto a specific plane (such as the plane defined by the height of the element). From what I can tell from this source: https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2017/ENU/Revit-API/files/GUID-... the CropBox of a perspective view basically just gives corners of the front clipping plane and the distance to the back clipping plane. I’m not sure how to tell what region is currently visible, or how to predict what region will be made visible by setting the CropBox to a new BoundingBoxXYZ.

 

 I’m also not sure how to figure out what Z value to place the eye at since I can’t find a field of view angle or anything else to find the relationship between the dimensions of the projection plane and the distance from the plane to the eye.

 

I’m wondering if I’ve missed anything that already exists to do this, or if anyone has any ideas. I’ve been stuck on this for a while now and it is entirely possible that I’ve been staring at my code too long to see the obvious solution. I would also appreciate any alternative suggestions if someone has a different, hopefully less complicated way to show the element in relation to the model.

 

For context, I’m making an add-in that includes a visual representation of a particular point in 3D, such as the base point, the survey point, or any other point the user wants to be able to reference easily. I place a family instance of the "Diagnostic Tripod-1 point" at the reference point. Right now I can use UIDocument.ShowElement but that doesn’t give any context for where the point is relative to the rest of the model. If I have a survey point 700 ft. from a building and I zoom in and show just that point then it can be difficult to find the rest of the model again, which usually defeats the purpose of showing the point in the first place.  

 

Thanks for your time!

0 Likes
4,338 Views
8 Replies
Replies (8)
Message 2 of 9

jeremytammik
Autodesk
Autodesk
0 Likes
Message 3 of 9

Anonymous
Not applicable

Thanks for providing the link. I did try using that method before but I wasn’t able to make it work. Originally, I assumed the API had changed too much since 2009 so I didn’t spend much time on it. I’ve gone back and tested more but I still can’t make it work. Maybe you can help me identify my mistakes. I’ve simplified my goal for testing purposes to mimic the example you linked as closely as possible by using a view which already shows the element and cropping to that element the way your example crops to a room. Note that I had to use GetOriginalGeometry because using get_Geometry caused vertices to be an empty list. I don’t know if that is related to the problem I’m having or not. I use the following code.

 

public static Result Focus3DViewOnInstance(View3D view3D, 
            FamilyInstance instance)
        {

            if (view3D == null)
            {
                return Result.Failed;
            }

            BoundingBoxXYZ box = view3D.CropBox;
            Transform transform = box.Transform.Inverse;
            
            ISet<XYZ> vertices = new HashSet<XYZ>();

            foreach (GeometryObject o in 
                instance.GetOriginalGeometry(new Options()))
            {
                if (o is Solid)
                {
                    Solid solid = o as Solid;
                    foreach (Edge edge in solid.Edges)
                    {
                        foreach (XYZ p in edge.Tessellate())
                        {
                            vertices.Add(transform.OfPoint(p));
                        }
                    }
                }
            }

            double xMin = 0, yMin = 0, xMax = 0, yMax = 0;
            bool first = true;
            foreach (XYZ p in vertices)
            {
                if (first)
                {
                    xMin = p.X;
                    yMin = p.Y;
                    xMax = p.X;
                    yMin = p.Y;
                    first = false;
                }
                if (xMin > p.X)
                    xMin = p.X;
                if (yMin > p.Y)
                    yMin = p.Y;
                if (xMax < p.X)
                    xMax = p.X;
                if (yMax < p.Y)
                    yMax = p.Y;
            }
            box.Max = new XYZ(xMax, yMax, box.Max.Z);
            box.Min = new XYZ(xMin, yMin, box.Min.Z);

            view3D.CropBox = box;

            view3D.CropBoxActive = true;
            view3D.CropBoxVisible = true;

            return Result.Succeeded;

This doesn’t crop to the element though. It distorts the view and stretches it out. I’ve included screenshots of the view before and after running the above code. I also tried getting vertices by manually finding the 8 corners of the BoundingBoxXYZ of the element and I had the same result. I've also tried view3D.ResetCameraTarget() when possible at the end of the function, but it doesn't seem to make a different. 

0 Likes
Message 4 of 9

jeremytammik
Autodesk
Autodesk

GetOriginalGeometry may be returning the geometry in the family definition coordinates, not in project coordinates, so obviously the view will end up showing the wrong thing.

 

In that case, you should maybe retrieve the geometry instance and determine the insertion transformation from that:

 

https://apidocs.co/apps/revit/2019/fe25b14f-5866-ca0f-a660-c157484c3a56.htm

  

Better still, get the bounding box from your element and use that to determine the view crop box.

 

That would be much simpler than going through all the geometry stuff.

 



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

0 Likes
Message 5 of 9

Anonymous
Not applicable

I've tried every method I could think of to get the corners and transform them but unfortunately I haven't been able to get this working. I have to move on to another project so for now we'll just zoom into the element. I'll come back to work on this if I get free time and I'll post if I find a solution or explanation.

 

Thanks for your time and assistance.

0 Likes
Message 6 of 9

jeremytammik
Autodesk
Autodesk

I once implemented a sample that sets up a 3D view to exactly display a given 3D bounding box:

 

https://thebuildingcoder.typepad.com/blog/2009/12/crop-3d-view-to-room.html

 

Does that not fulfil your needs?

 

Cheers,

 

Jeremy

 



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

0 Likes
Message 7 of 9

Anonymous
Not applicable

Thank you, but you already provided that link. I outlined the issues I was having with that method in message 3 of this forum post.

 

My best guess is that the method is perfectly sound, but there is something somewhere in my code that transforms some coordinate system in a way I wasn't expecting. I just don't have time to hunt down the issue right now, nor do you I would imagine.

 

Thanks again, I'll post an update if I figure out what's causing the issue. 

0 Likes
Message 8 of 9

jeremytammik
Autodesk
Autodesk

Yep, busy we are all.

 

Still, out of interest and the kindness of my heart, if you provide a minimal sample model including a handful of elements and a 3D view which needs cropping to those elements, I can try running the existing CmdCropToRoom on that and see whether it works out of the box or anything needs adapting:

 

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

 

Cheers,

 

Jeremy

 



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

0 Likes
Message 9 of 9

Anonymous
Not applicable

I threw together a quick model for you, but I figured I might as well include the relevant sections of my code for testing just in case. In the process, I noticed that it sort of works as expected (still needs a lot of tweaking and doesn't seem to work on all views) if I just pass the view as is, but that requires changing the user's existing view which is not what I want to do. Things only consistently break into strange warped versions of views if I duplicate the view and apply the function to the duplicate view, which is what I've been doing so far. 

 

I have no idea why this happens, but on the upside I now know that the code I've been reworking over and over again is actually perfectly find, and the reason I can't find a solution is because I've been asking entirely the wrong question. I'll do a bit of searching tomorrow and see if I can find why duplicating the view is breaking everything.

 

I included the .zip file with the .rvt file as well as the visual studio project in case you still want to test either one. The .dll and .addin are in the Debug folder. The project has two commands: One which duplicates the view and then adjusts it, and the other which adjusts the existing view.

0 Likes