Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Set View Cropbox to a Section Box

5 REPLIES 5
Reply
Message 1 of 6
chris.j.mckeown
2063 Views, 5 Replies

Set View Cropbox to a Section Box

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

5 REPLIES 5
Message 2 of 6

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



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

Message 3 of 6

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

Message 4 of 6

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.

 

200624.PNG

 

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:

 

200624a.PNG

 

 

 

Message 5 of 6

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;
}
}

Message 6 of 6

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.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community