Hello, I am sure this is a simply question, but how do I set a 3d Views Cropbox to match (to the outer corners) that of a Sectionbox?
Regards
Chris
Hi Chris,
Have you looked at this post on setting the view section box to match its scope box?
http://thebuildingcoder.typepad.com/blog/2012/08/set-view-section-box-to-match-scope-box.html
That might help.
Cheers,
Jeremy
Is there already a solution for this problem, set the 3d view cropbox to match roughly the 3d view sectionbox?
I have been searching and only found references to a bug that was fixed in rvt2018.1
The two boxes have different coordinate systems so one has to transformed into the other. Also consider below that the maximum and minimum points of the section box are not enough alone to properly frame the section box with a crop box. If you transformed P1 and P2 below from the coordinate space of the section box into the coordinate space of the view you would end up with the red box. You need to know the missing corners and then you can transform all of the eight corner points into the coordinate space of the view. You then find the max/min xyz from those and set crop box to green rectangle.
I wrote this extension method:
<Extension()>
Public Sub AdjustCropToSectionBox(View3D As View3D)
'View3D crop can't have a shape assigned and can't be split
If View3D.CropBoxActive = False Then
View3D.CropBoxActive = True
End If
If View3D.IsSectionBoxActive = False Then
Exit Sub
End If
Dim CropBox As BoundingBoxXYZ = View3D.CropBox
Dim SectionBox As BoundingBoxXYZ = View3D.GetSectionBox
Dim T As Transform = CropBox.Transform
Dim Corners As XYZ() = BBCorners(SectionBox, T)
Dim MinX As Double = Corners.Min(Function(j) j.X)
Dim MinY As Double = Corners.Min(Function(j) j.Y)
Dim MinZ As Double = Corners.Min(Function(j) j.Z)
Dim MaxX As Double = Corners.Max(Function(j) j.X)
Dim MaxY As Double = Corners.Max(Function(j) j.Y)
Dim MaxZ As Double = Corners.Max(Function(j) j.Z)
CropBox.Min = New XYZ(MinX, MinY, MinZ)
CropBox.Max = New XYZ(MaxX, MaxY, MaxZ)
View3D.CropBox = CropBox
End Sub
Private Function BBCorners(SectionBox As BoundingBoxXYZ, T As Transform) As XYZ()
Dim Btm_LL As XYZ = SectionBox.Min 'Lower Left
Dim Btm_LR As New XYZ(SectionBox.Max.X, SectionBox.Min.Y, SectionBox.Min.Z) 'Lower Right
Dim Btm_UL As New XYZ(SectionBox.Min.X, SectionBox.Max.Y, SectionBox.Min.Z) 'Upper Left
Dim Btm_UR As New XYZ(SectionBox.Max.X, SectionBox.Max.Y, SectionBox.Min.Z) 'Upper Right
Dim Top_UR As XYZ = SectionBox.Max 'Upper Right
Dim Top_UL As New XYZ(SectionBox.Min.X, SectionBox.Max.Y, SectionBox.Max.Z) 'Upper Left
Dim Top_LR As New XYZ(SectionBox.Max.X, SectionBox.Min.Y, SectionBox.Max.Z) 'Lower Right
Dim Top_LL As New XYZ(SectionBox.Min.X, SectionBox.Min.Y, SectionBox.Max.Z) 'Lower Left
Dim Out As XYZ() = New XYZ(7) {Btm_LL, Btm_LR, Btm_UL, Btm_UR, Top_UR, Top_UL, Top_LR, Top_LL}
For i = 0 To Out.Length - 1
'Transform bounding box corords to model coords
Out(i) = SectionBox.Transform.OfPoint(Out(i))
'Transform bounding box coords to view coords
Out(i) = T.Inverse.OfPoint(Out(i))
Next
Return Out
End Function
It is also worth considering that the extents of the section box may not be appropriate for how you wish to crop the view. The section box below is relatively tight on the wall elements but due to the viewing angle there is a lot of spare space to the right. When you print that on a sheet it will not be evident why the view content is off centre and what the extra space is for:
RP Thomas, I thank you.
This solution worked great, I translated to C# so I have posted here for C# coders.
public static void AdjustCropToSectionBox(this View3D View3D)
{
if (View3D.CropBoxActive == false)
{
View3D.CropBoxActive = true;
}
if (View3D.IsSectionBoxActive == false)
{
return;
}
BoundingBoxXYZ CropBox = View3D.CropBox;
BoundingBoxXYZ SectionBox = View3D.GetSectionBox();
Transform T = CropBox.Transform;
var Corners = BBCorners(SectionBox, T);
double MinX = Corners.Min(j => j.X);
double MinY = Corners.Min(j => j.Y);
double MinZ = Corners.Min(j => j.Z);
double MaxX = Corners.Max(j => j.X);
double MaxY = Corners.Max(j => j.Y);
double MaxZ = Corners.Max(j => j.Z);
CropBox.Min = new XYZ(MinX, MinY, MinZ);
CropBox.Max = new XYZ(MaxX, MaxY, MaxZ);
View3D.CropBox = CropBox;
}
private static XYZ[] BBCorners(BoundingBoxXYZ SectionBox, Transform T)
{
XYZ Btm_LL = SectionBox.Min; // Lower Left
var Btm_LR = new XYZ(SectionBox.Max.X, SectionBox.Min.Y, SectionBox.Min.Z); // Lower Right
var Btm_UL = new XYZ(SectionBox.Min.X, SectionBox.Max.Y, SectionBox.Min.Z); // Upper Left
var Btm_UR = new XYZ(SectionBox.Max.X, SectionBox.Max.Y, SectionBox.Min.Z); // Upper Right
XYZ Top_UR = SectionBox.Max; // Upper Right
var Top_UL = new XYZ(SectionBox.Min.X, SectionBox.Max.Y, SectionBox.Max.Z); // Upper Left
var Top_LR = new XYZ(SectionBox.Max.X, SectionBox.Min.Y, SectionBox.Max.Z); // Lower Right
var Top_LL = new XYZ(SectionBox.Min.X, SectionBox.Min.Y, SectionBox.Max.Z); // Lower Left
var Out = new XYZ[8] { Btm_LL, Btm_LR, Btm_UL, Btm_UR, Top_UR, Top_UL, Top_LR, Top_LL };
for (int i = 0, loopTo = Out.Length - 1; i <= loopTo; i++)
{
// Transform bounding box corords to model coords
Out[i] = SectionBox.Transform.OfPoint(Out[i]);
// Transform bounding box coords to view coords
Out[i] = T.Inverse.OfPoint(Out[i]);
}
return Out;
}
}
That's amazing you guys! I just needed this functionality and after translating it to python, voila! It worked like a freaking charm.
Here is the python version of the code:
def crop_axo(view3d):
if view3d.IsSectionBoxActive == False: return
if view3d.CropBoxActive == False:
view3d.CropBoxActive = True
crop_box = view3d.CropBox
section_box = view3d.GetSectionBox()
trans = crop_box.Transform
corners = bb_corners(section_box, trans)
minX = min(corners, key=lambda x: x.X).X
minY = min(corners, key=lambda x: x.Y).Y
minZ = min(corners, key=lambda x: x.Z).Z
maxX = max(corners, key=lambda x: x.X).X
maxY = max(corners, key=lambda x: x.Y).Y
maxZ = max(corners, key=lambda x: x.Z).Z
crop_box.Min = DB.XYZ(minX, minY, minZ)
crop_box.Max = DB.XYZ(maxX, maxY, maxZ)
view3d.CropBox = crop_box
def bb_corners(box, transform):
b_ll = box.Min #lower left
b_lr = DB.XYZ(box.Max.X, box.Min.Y, box.Min.Z) # lower right
b_ul = DB.XYZ(box.Min.X, box.Max.Y, box.Min.Z) # upper left
b_ur = DB.XYZ(box.Max.X, box.Max.Y, box.Min.Z) # upper right
t_ur = box.Max # upper right
t_ul = DB.XYZ(box.Min.X, box.Max.Y, box.Max.Z) # upper left
t_lr = DB.XYZ(box.Max.X, box.Min.Y, box.Max.Z) # lower right
t_ll = DB.XYZ(box.Min.X, box.Min.Y, box.Max.Z) # lower left
out = [b_ll, b_lr, b_ul, b_ur, t_ur, t_ul, t_lr, t_ll]
for index, o in enumerate(out):
out[index] = box.Transform.OfPoint(out[index])
out[index] = transform.Inverse.OfPoint(out[index])
return out
Thanks again
Can't find what you're looking for? Ask the community or share your knowledge.