Solid.GetBoundingBox() is different from Element.get_BoundingBox(View myview) how to convert solid bounding box?

Solid.GetBoundingBox() is different from Element.get_BoundingBox(View myview) how to convert solid bounding box?

ahmed.elhawary73
Advocate Advocate
1,544 Views
11 Replies
Message 1 of 12

Solid.GetBoundingBox() is different from Element.get_BoundingBox(View myview) how to convert solid bounding box?

ahmed.elhawary73
Advocate
Advocate

After getting BoundingBox from Soild How I Transform its Values to comply with 3d view because as mentioned in revit API docs "The bounding box information is stored as bounds in local coordinates and a transform. So the transform is to be taken in to account when using the bounds. This is different from the bounding box returned by Element.BoundingBox in that the bounding box returned by that routine stores the bounds in modeling coordinates with an identity transform." all I need is to C transform bounding box got from solid geometry to bounding box I can use in 3dview

0 Likes
Accepted solutions (3)
1,545 Views
11 Replies
Replies (11)
Message 2 of 12

jeremy_tammik
Alumni
Alumni

It depends on your element. For a wall, for instance, the transform is identity. For a family instance, the local coordinate system depends on the family definition.

   

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

ahmed.elhawary73
Advocate
Advocate

Hello Dear, let's take an example to explain what I mean if I get a solid of a specific element and get the bounding box from this solid through solid.GetBoundingBox(); then used this bounding box to set the 3dview section box I'm getting a section box that does not include my element. 
After Searching within Revit API Docs I got this remarks:

Remarks

"The bounding box information is stored as bounds in local coordinates and a transform. So the transform is to be taken in to account when using the bounds. This is different from the bounding box returned by Element.BoundingBox in that the bounding box returned by that routine stores the bounds in modeling coordinates with an identity transform."
 
So I want an example of converting a Solid bounding box so it can be used to get a section box in the 3d view to just include my solid bounds.
 
 
 
0 Likes
Message 4 of 12

jeremy_tammik
Alumni
Alumni
Accepted solution

I searched this forum for "transform element coordinates to model" for you:

  

    

One of the first hits is this that looks likely to answer your question:

   

   

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

ahmed.elhawary73
Advocate
Advocate

Dear Jeremey, I've browsed the mentioned posts. Now I can get all the bounding boxes I need from solids, for example, if I set the 3d view section box to one of them directly it works well,  but here is a new problem when I try to combine all the bounding boxes by getting min & max points (x,y,z) and create a new bounding box to include all wanted solids then I miss the transform of each bounding box how can I combine bounding box without losing transform?

 

 

public void SetSectionBox()
		{
			UIDocument uidoc = Application.ActiveUIDocument;
			Document doc = Application.ActiveUIDocument.Document;
			var myview = uidoc.ActiveView as View3D;
			
			//pick elements
			var refs = uidoc.Selection.PickObjects(ObjectType.Element);
			var elements = refs.Select(x => doc.GetElement(x.ElementId)).ToList();
//get all solids it worked
			var solids = getallsolids(elements,myview);
			var bbs = solids.Select(x=>x.GetBoundingBox()).ToList();
			

			BoundingBoxXYZ bb =  OuterBox(bbs);
			
					
			 Transaction trn = new Transaction(doc, "sd");
             trn.Start();
             myview.SetSectionBox(bb);
             trn.Commit();
			
			
		}

 

 

 

 

public BoundingBoxXYZ OuterBox(List<BoundingBoxXYZ> bbs)
		{
			var x1 = bbs.Select(x=>x.Min.X).Min();
			var y1 = bbs.Select(x=>x.Min.Y).Min();
			var z1 = bbs.Select(x=>x.Min.Z).Min();
			
			var x2 = bbs.Select(x=>x.Max.X).Max();
			var y2 = bbs.Select(x=>x.Max.Y).Max();
			var z2 = bbs.Select(x=>x.Max.Z).Max();
			
			var min = new XYZ(x1,y1,z1);
			var max = new XYZ(x2,y2,z2);
			
			var bb = new BoundingBoxXYZ(){Min=min,Max=max};
			
			return bb;
			
		}

 

then I need to set a transform to the new bounding box so it'll show all selected elements in the view section box

 

0 Likes
Message 6 of 12

jeremy_tammik
Alumni
Alumni

Congratulations on your good progress. I suggest you apply the transform individually to each bounding box first, retrieve the resulting min and max corners of each in the global coordinate system, and then unify the GPS corners into one single new GPS bounding box. Here are some methods from The Building Coder samples to expand a bounding box to contain new points:

   

    public static class JtBoundingBoxXyzExtensionMethods
    {
        /// <summary>
        ///     Make this bounding box empty by setting the
        ///     Min value to plus infinity and Max to minus.
        /// </summary>
        public static void Clear(
            this BoundingBoxXYZ bb)
        {
            var infinity = double.MaxValue;
            bb.Min = new XYZ(infinity, infinity, infinity);
            bb.Max = -bb.Min;
        }

        /// <summary>
        ///     Expand the given bounding box to include
        ///     and contain the given point.
        /// </summary>
        public static void ExpandToContain(
            this BoundingBoxXYZ bb,
            XYZ p)
        {
            bb.Min = new XYZ(Math.Min(bb.Min.X, p.X),
                Math.Min(bb.Min.Y, p.Y),
                Math.Min(bb.Min.Z, p.Z));

            bb.Max = new XYZ(Math.Max(bb.Max.X, p.X),
                Math.Max(bb.Max.Y, p.Y),
                Math.Max(bb.Max.Z, p.Z));
        }

        /// <summary>
        ///     Expand the given bounding box to include
        ///     and contain the given points.
        /// </summary>
        public static void ExpandToContain(
            this BoundingBoxXYZ bb,
            IEnumerable<XYZ> pts)
        {
            bb.ExpandToContain(new XYZ(
                pts.Min<XYZ, double>(p => p.X),
                pts.Min<XYZ, double>(p => p.Y),
                pts.Min<XYZ, double>(p => p.Z)));

            bb.ExpandToContain(new XYZ(
                pts.Max<XYZ, double>(p => p.X),
                pts.Max<XYZ, double>(p => p.Y),
                pts.Max<XYZ, double>(p => p.Z)));
        }

        /// <summary>
        ///     Expand the given bounding box to include
        ///     and contain the given other one.
        /// </summary>
        public static void ExpandToContain(
            this BoundingBoxXYZ bb,
            BoundingBoxXYZ other)
        {
            bb.ExpandToContain(other.Min);
            bb.ExpandToContain(other.Max);
        }
    }

  

   

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

ahmed.elhawary73
Advocate
Advocate
Dear Jeremy, Thanks for your support as usual, I didn't understand how I could apply the transform individually to each bounding box first, from which object I can get the transform to apply for all bounding boxes, excuse me but not understanding.
0 Likes
Message 8 of 12

jeremy_tammik
Alumni
Alumni
Accepted solution

Given two bounding boxes B1 and B2 with transforms T1 and T2 and min and max points Mn1, Mx1, Mn2 and Mx2, I suggest creating a new bounding box B in GPS coordinates by setting B.min = Min(T1 x Mn1, T2 x Mn2) and B.max = Max( T1 x Mx1, T2 x Mx2).

     

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

ahmed.elhawary73
Advocate
Advocate
B.min = Min(T1 x Mn1, T2 x Mn2) >>>>>>>>>>> what do you mean by x between T1 and Mn1
0 Likes
Message 10 of 12

jeremy_tammik
Alumni
Alumni

The standalone 'x' with spaces around it means 'apply the transform'.

   

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

ahmed.elhawary73
Advocate
Advocate

ahmedelhawary73_0-1725621098378.png

 

Invalid expression

0 Likes
Message 12 of 12

ahmed.elhawary73
Advocate
Advocate
Accepted solution

Dear Jeremy, Finally I got it I have to use Transform.Ofpoint(XYZ) method when adding min and max points of the bounding Box. 

Much Thanks for help

 

	var solids = getallsolids(elements,myview);
			var bbs = solids.Select(x=>x.GetBoundingBox()).ToList();
			BoundingBoxXYZ bb = new BoundingBoxXYZ();
			Clear(bb);
			foreach (var B in bbs) 
			{
				var newbb = new BoundingBoxXYZ();
				var min = B.Min;
				var max = B.Max;
				var trans = B.Transform;
				
				ExpandToContain(bb,new BoundingBoxXYZ(){Min=trans.OfPoint( B.Min) , Max = trans.OfPoint( B.Max ) });
			}

Much 

0 Likes