Creating Revit View Set from Scope Boxes

Creating Revit View Set from Scope Boxes

hammad_haroon
Contributor Contributor
1,865 Views
7 Replies
Message 1 of 8

Creating Revit View Set from Scope Boxes

hammad_haroon
Contributor
Contributor

I need to create view sets of multiple areas in a model each with a plan, 2 sections and a section box 3D view. I intend to do this using scope boxes placed/copied manually, and do the rest with Revit API.

 

The first hurdle I've run into is that when I use the CreateSection on the boundingbox retrieved from the Scope Box, it points upward from below. I'm not sure why this is happening

 

hammad_haroon_0-1716386012302.png

 

Here is the code snippet I've used to create this: 

 

public void CreateSection()
		{
			FilteredElementCollector scopeBoxes = new FilteredElementCollector(Document).OfCategory(BuiltInCategory.OST_VolumeOfInterest);
			var scopeBoxList = scopeBoxes.ToList();
			
			ViewFamilyType vft
      = new FilteredElementCollector(Document)
        .OfClass( typeof( ViewFamilyType ) )
        .Cast<ViewFamilyType>()
        .FirstOrDefault<ViewFamilyType>( x =>
          ViewFamily.Section == x.ViewFamily );
			
			using (Transaction tx = new Transaction(Document)) {
				tx.Start("Create Section");
				foreach (Element e in scopeBoxList) 
				{
					BoundingBoxXYZ bbox = e.get_BoundingBox(null);

					ViewSection section1 = ViewSection.CreateSection(Document, vft.Id, bbox);
					
					
				}
				tx.Commit();
			}
						
		}

 

I've tried creating a new bounding box, and assigning a new maximum and minimum point, intending to change the orientation while maintaining the dimensions, as below:

 

public void CreateSection()
		{
			FilteredElementCollector scopeBoxes = new FilteredElementCollector(Document).OfCategory(BuiltInCategory.OST_VolumeOfInterest);
			var scopeBoxList = scopeBoxes.ToList();
			
			ViewFamilyType vft
      = new FilteredElementCollector(Document)
        .OfClass( typeof( ViewFamilyType ) )
        .Cast<ViewFamilyType>()
        .FirstOrDefault<ViewFamilyType>( x =>
          ViewFamily.Section == x.ViewFamily );
			
			using (Transaction tx = new Transaction(Document)) {
				tx.Start("Create Section");
				foreach (Element e in scopeBoxList) 
				{
					BoundingBoxXYZ bbox = e.get_BoundingBox(null);

					/*ViewSection section1 = ViewSection.CreateSection(Document, vft.Id, bbox);*/
					
					XYZ max1 = bbox.Max;
					XYZ min1 = bbox.Min;					
					
					XYZ max2 = new XYZ(max1.X, max1.Y, min1.Z);
					XYZ min2 = new XYZ(min1.X, min1.Y, max1.Z);
					
					XYZ mid = bbox.Max.Add(bbox.Min)/2;
				
					BoundingBoxXYZ ebbox = new BoundingBoxXYZ();
					
					ebbox.Enabled = true;
					ebbox.Max = max2;
					ebbox.Min = min2;
					
					ViewSection section2 = ViewSection.CreateSection(Document, vft.Id, ebbox);
				}
				tx.Commit();
			}	
		}

 

However I get this error 

hammad_haroon_1-1716386717196.png

 

 

0 Likes
1,866 Views
7 Replies
Replies (7)
Message 2 of 8

Moustafa_K
Advisor
Advisor

One important factor you might have overlooked is the orientation of the scope boxes. If the bounding box direction points toward the world XY plane (toward the earth), you'll end up with a section that appears as a plan view.

 

To achieve the desired section view, you need to transform the bounding box that is extracted from the scope box, to get an aligned version with the section direction you want.

 

For example, let's assume you have a scope box oriented along the +Z axis, but you want to create a section that looks in the direction of the X axis. In this case, you would need to rotate the Z vector around the Y axis to align it with the X vector.

 

Here are the steps to accomplish this:

  1. Define the vector direction for your section view.
  2. Create a rotation transform based on this direction.
  3. Apply this rotation transform to the bounding box.
  4. Construct your section based on the transformed bounding box.

To translate this into code, consider the following example:

BoundingBoxXYZ bbox = e.get_BoundingBox(null);
var centerPoint = (bbox.Max+bbox.Min)/2;
var rotateTrans= Transform.CreateRotation(XYZ.BasisY, Math.PI / 2);
bbox.Transform = rotateTrans * bbox.Transform;
ViewSection section1 = ViewSection.CreateSection(Doc, vft.Id, bbox);

 

I hope this simple briefed explanation fits.

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes
Message 3 of 8

hammad_haroon
Contributor
Contributor

Thanks Moustafa, I tried that solution as well. The issue I ran into was that bounding box isn't a cube, it may be tall with a smaller square base, so when it's rotated, the section isn't the correct size, its short in heigh t& width but looks further than it needs to. I was hoping to have the same dimensions of the bounding box but only change the orientation.

0 Likes
Message 4 of 8

Moustafa_K
Advisor
Advisor

one possible solution is to create the bounding since now you confirmed you know the orientation, and you already have the scope box, then you can extract the width and height and assign it a new boundingbox with a rotation and translation vector

 

see this Pseudo  code sample:

 

 

 

BoundingBoxXYZ bbox = e.get_BoundingBox(null);
var rotatedBbx = new BoundingBoxXYZ();
rotatedBbx.Max = new XYZ( bbox.Width(), bbox.Height(), bbox.Length());

var rotaTrans = Transform.CreateRotation(XYZ.BasisY, Math.PI / 2);
var transla = Transform.CreateTranslation(bbox.Transform.Origin);
rotatedBbx.Transform = rotaTrans .Multiply(transla);

 

 

 

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes
Message 5 of 8

TripleM-Dev.net
Advisor
Advisor

Hi @hammad_haroon,

 

See this link:

http://thebuildingcoder.typepad.com/blog/2012/06/create-section-view-parallel-to-wall.html 

 

This sample helpt me a lot with creating a addin that can use any scopebox to create 2 section in it's center in X and Y direction.

You need to create a new "BoundingBoxXYZ" with the correct transform value that matches the section you need.

 

For instance see this piece below. The values of origin and right depends on the position and direction of the section needed.

See the full post in the link above on how to calculate them.

Transform transform = Transform.Identity;
  transform.Origin = origin;
  transform.BasisX = right;
  transform.BasisY = up;
  transform.BasisZ = viewdir;
 
  BoundingBoxXYZ sectionBox = new BoundingBoxXYZ();
  sectionBox.Transform = transform;

 

- Michel

 

0 Likes
Message 6 of 8

hammad_haroon
Contributor
Contributor

Thank you! I managed to make it work exactly as needed in an empty test file, with the sections intersecting at the center of the scope box.

 

However when I applied the same macro to the file (File B) i wanted to use it in, the sections are out of the scope box. The scope boxes are the same sizes in both files but in File B, the sections appear like this:

hammad_haroon_0-1717097619887.png

 

// get current selected scope box and bounding box
			UIDocument uidoc = this; 
        	Reference myRef = uidoc.Selection.PickObject(ObjectType.Element);
        	Element scopeBox = Document.GetElement(myRef);
        	string scopeBoxName = scopeBox.Name;
			BoundingBoxXYZ bbox = scopeBox.get_BoundingBox(null);
			
			XYZ max1 = bbox.Max;
			XYZ min1 = bbox.Min;	
			XYZ centerpoint = (bbox.Max + bbox.Min)/2;
			
			//Creates section box in center looking east
			Transform transformv = Transform.Identity;
			transformv.Origin = centerpoint;
			transformv.BasisX = XYZ.BasisY;
			transformv.BasisY = XYZ.BasisZ;
			transformv.BasisZ = XYZ.BasisX;			

			BoundingBoxXYZ sectionBoxv = new BoundingBoxXYZ();
			sectionBoxv.Transform = transformv;
			sectionBoxv.Min = min1;
			sectionBoxv.Max = max1;
			
			//Creates section box in center looking north
			Transform transformh = Transform.Identity;
			transformh.Origin = centerpoint;
			transformh.BasisX = XYZ.BasisX.Negate();
			transformh.BasisY = XYZ.BasisZ;
			transformh.BasisZ = XYZ.BasisY;
			
			BoundingBoxXYZ sectionBoxh = new BoundingBoxXYZ();
			sectionBoxh.Transform = transformh;
			sectionBoxh.Min = min1;
			sectionBoxh.Max = max1;
			
				
			using (Transaction tx = new Transaction(Document)) {	
				tx.Start("Create Section");
				
				//Create Plan by duplicating current view and assigning scope box
				View plan = Document.GetElement(ActiveView.Duplicate(ViewDuplicateOption.Duplicate)) as View;
				plan.Name = scopeBoxName + " Plan";
				plan.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(scopeBox.Id);
				plan.ViewTemplateId = viewTemplatePlanId;
				
				//Create vertical section
				ViewSection sectionv = ViewSection.CreateSection(Document, vft.Id, sectionBoxv);
				sectionv.Name = scopeBox.Name + " Section N-S";
				sectionv.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(scopeBox.Id);
				sectionv.ViewTemplateId = viewTemplateSection.Id;
				
				//Create horizontal section
				ViewSection sectionh = ViewSection.CreateSection(Document, vft.Id, sectionBoxh);
				sectionh.Name = scopeBox.Name + " Section E-W";
				sectionh.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(scopeBox.Id);
				sectionh.ViewTemplateId = viewTemplateSection.Id;
				
				tx.Commit();
				}

 

0 Likes
Message 7 of 8

hammad_haroon
Contributor
Contributor

Thank you! I managed to make it work exactly as needed in an empty test file, with the sections intersecting at the center of the scope box.

 

However when I applied the same macro to the file (File B) i wanted to use it in, the sections are out of the scope box. The scope boxes are the same sizes in both files but in File B, the sections appear like this:

hammad_haroon_0-1717097619887.png

 

 

// get current selected scope box and bounding box
			UIDocument uidoc = this; 
        	Reference myRef = uidoc.Selection.PickObject(ObjectType.Element);
        	Element scopeBox = Document.GetElement(myRef);
        	string scopeBoxName = scopeBox.Name;
			BoundingBoxXYZ bbox = scopeBox.get_BoundingBox(null);
			
			XYZ max1 = bbox.Max;
			XYZ min1 = bbox.Min;	
			XYZ centerpoint = (bbox.Max + bbox.Min)/2;
			
			//Creates section box in center looking east
			Transform transformv = Transform.Identity;
			transformv.Origin = centerpoint;
			transformv.BasisX = XYZ.BasisY;
			transformv.BasisY = XYZ.BasisZ;
			transformv.BasisZ = XYZ.BasisX;			

			BoundingBoxXYZ sectionBoxv = new BoundingBoxXYZ();
			sectionBoxv.Transform = transformv;
			sectionBoxv.Min = min1;
			sectionBoxv.Max = max1;
			
			//Creates section box in center looking north
			Transform transformh = Transform.Identity;
			transformh.Origin = centerpoint;
			transformh.BasisX = XYZ.BasisX.Negate();
			transformh.BasisY = XYZ.BasisZ;
			transformh.BasisZ = XYZ.BasisY;
			
			BoundingBoxXYZ sectionBoxh = new BoundingBoxXYZ();
			sectionBoxh.Transform = transformh;
			sectionBoxh.Min = min1;
			sectionBoxh.Max = max1;
			
				
			using (Transaction tx = new Transaction(Document)) {	
				tx.Start("Create Section");
				
				//Create Plan by duplicating current view and assigning scope box
				View plan = Document.GetElement(ActiveView.Duplicate(ViewDuplicateOption.Duplicate)) as View;
				plan.Name = scopeBoxName + " Plan";
				plan.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(scopeBox.Id);
				plan.ViewTemplateId = viewTemplatePlanId;
				
				//Create vertical section
				ViewSection sectionv = ViewSection.CreateSection(Document, vft.Id, sectionBoxv);
				sectionv.Name = scopeBox.Name + " Section N-S";
				sectionv.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(scopeBox.Id);
				sectionv.ViewTemplateId = viewTemplateSection.Id;
				
				//Create horizontal section
				ViewSection sectionh = ViewSection.CreateSection(Document, vft.Id, sectionBoxh);
				sectionh.Name = scopeBox.Name + " Section E-W";
				sectionh.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(scopeBox.Id);
				sectionh.ViewTemplateId = viewTemplateSection.Id;
				
				tx.Commit();
				}

 

 

0 Likes
Message 8 of 8

TripleM-Dev.net
Advisor
Advisor

In File B, are the internal origin and the project base point both in 0,0,0 ?

0 Likes