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: 

Modify CropBox of Elevation View

20 REPLIES 20
Reply
Message 1 of 21
grahamcook
7468 Views, 20 Replies

Modify CropBox of Elevation View

I am having difficulty in modifying the cropbox of an elevation view.  The extract code below will place an elevation marker in a room and then create an elevation off index 0 of the marker.  I then get the existing cropbox and attempt to reduce the height by 3 feet (just as an example).  The code runs successfully (within a transaction) but the result is as per the original cropbox, ie, no change.  When an elevation marker is placed in a room using the User Interface Revit will automatically find the extents of the room and set the crop box accordingly.  I'm wondering if this behavior is overwriting the changes I make via the API?

 

ElevationMarker elevMarker = 
ElevationMarker.CreateElevationMarker(doc, vft.Id, roomCenter, scale);

ViewSection sv = elevMarker.CreateElevation(doc, viewPlan.Id, 0);
doc.Regenerate();

// get the bounding box of the section
BoundingBoxXYZ bb = sv.CropBox;

// by way of example reduce the section height by 3 foot
XYZ max = bb.Max;
max = new XYZ(max.X, max.Y - 3, max.Z);
bb.Max = max;

// set the new bounding box
sv.CropBox = bb;

 

20 REPLIES 20
Message 2 of 21
Joe.Ye
in reply to: grahamcook

 

It is likely that Revit overwrite the cropbox when the transaction is submitted. However not sure, as I didn't test this.

 

This idea just came to my mind. 

Can you use two transactions to do this?

Start the first transaction to create the section marker and the section view, then commit the transaction.

Start the second transaction to change the crop box.

 

 



Joe Ye
Contractor
Developer Technical Services
Autodesk Developer Network
Message 3 of 21
grahamcook
in reply to: grahamcook

Joe, thanks for your suggestion.

 

I tried the idea of creating a second transaction to carry out the cropbox resize but unfortunately didn’t make any difference.  I must clarify though that this issue relates to elevations created using the new 2013 class.  I have created the attached graphic to illustrate some weird behaviour though:

 

As we go through the code in the graphic you will see that I set BoundingBoxXYZ bb to equal the cropbox of my testView. (1)

I then modify bb by reducing the height by 3 feet.

I then set the cropBox to equal bb, see 2 and 3 in the image.  At this point an unexpected change in the boundingBox values takes place.  You will see that even though we set the cropBox to equal bb both of the Z values seem to have reversed in the new cropBox (3).

After regenerating I checked the cropBox value again and you will see that the Y value we reduced by 3 feet has reverted to the original value but the incorrect Z values have remained.  This has the effect of the elevation looking back on itself.

 

Message 4 of 21
Joe.Ye
in reply to: grahamcook

 

The Z value of the CropBox Max and Min is not so important. In the elevation view, the Z coordinate is vertical to the elevation view. The X is horizontal to  the right, and Y is vertical up. Probably Revit change the CropBox max and min Z value automatically. This doesn't affect the appearance of the elevation view.

 

After assign the bb back to the elevation view, I cannot reproduce the issue you reported. "Y value we reduced by 3 feet has reverted to the original value "

 

I also wrote a command like yours. I cannot reproduce the Y value reduced back to the original value issue.

 

here is the code I used.

 

<code>


[TransactionAttribute(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class RevitCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string messages, ElementSet elements)
{

UIApplication app = commandData.Application;
Document doc = app.ActiveUIDocument.Document;
Transaction trans = new Transaction(doc, "ExComm");
trans.Start();

FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(ViewFamilyType));


var viewFamilyTypes = from elem in collector
let type = elem as ViewFamilyType
where type.ViewFamily == ViewFamily.Elevation
select type;

ElementId viewtypeId;
if (viewFamilyTypes.Count() > 0)
viewtypeId = viewFamilyTypes.First().Id;
else
return Result.Cancelled;

ElevationMarker marker = ElevationMarker.CreateElevationMarker(doc, viewtypeId, new XYZ(0, 10, 0), 100);

ViewSection sv = marker.CreateElevation(doc,doc.ActiveView.Id, 1);

trans.Commit();

//chang the cropbox.
Transaction trans2 = new Transaction(doc,"test2");
trans2.Start();

doc.Regenerate();

// get the bounding box of the section
BoundingBoxXYZ bb = sv.CropBox;

// by way of example reduce the section height by 3 foot
XYZ max = bb.Max;
max = new XYZ(max.X+ 3, max.Y - 3, max.Z);
bb.Max = max;

// set the new bounding box
sv.CropBox = bb;

trans2.Commit();

return Result.Succeeded ;
}
}

 

 

<code>

 


When debuging, I kept watching  the CropBox value, and the bb value. The result is attached.

Not sure what's the problem in your side.

 



Joe Ye
Contractor
Developer Technical Services
Autodesk Developer Network
Message 5 of 21
grahamcook
in reply to: grahamcook

Joe

Thanks for trying to reproduce the problem.  If you add a doc.regenerate() between sv.CropBox = bb and trans2.Commit() you should see the modified X and Y values revert back.  I tested your code on the rac_basic_sample_project.rvt model and was able to reproduce the behaviour (see cropboxProblem_debug.jpg image attched).  I also attach an image cropboxProblem2.jpg that shows the effect of the max and min Z values being reversed and you will see it does infact make a significant difference to the resulting view.

I hope you are able to now reproduce the issue as i know this is fundamental in getting these things fixed.

 

Graham Cook

Message 6 of 21
Joe.Ye
in reply to: grahamcook

 

HI Graham,

 

Yes, i also reproduce the issue. If calling the regenerate() method, the cropbox value is reversed. 

This looks wield.

Then how about not calling the Regenerate() method. 

Since the transaction commit can automatically regenerate the model. 

 

 



Joe Ye
Contractor
Developer Technical Services
Autodesk Developer Network
Message 7 of 21
grahamcook
in reply to: grahamcook

Hi Joe

Glad you are now able to see the same issue!

Unfortunately, as you say the commit also performs a regenerate behind the scenes and it is at this point that Revit resets any changes to the cropbox back to the original values (and reverses min and max Z).  The cropbox can be modified no problem through the user interface so it looks to be a bug with the API.

 

I have also just tested the same code you provided but changed the XYZ location of the elevation marker to 0,0,0.  This puts the marker on the outside of the building (if run on the rac_basic_sample_project file).  When the elevation is outside and not within a room then the specified X and Y changes work OK.  But the Z still gets reversed.

 

Could this be logged as a bug with the development team?

 

Regards

 

Graham

Message 8 of 21
Joe.Ye
in reply to: grahamcook

 

I See, will let the engineering team know this issue soon.



Joe Ye
Contractor
Developer Technical Services
Autodesk Developer Network
Message 9 of 21
rodh257
in reply to: Joe.Ye

has there been any update on this issue? 

 

The reason I ask is in a command I do this on a Section:

 

					var section = (from v in new FilteredElementCollector(uiDoc.Document).OfClass(typeof(ViewSection)).Cast<ViewSection>()
								   where v.Name == viewName
								   select v).First();

					if (section != null)
					{
						var cropbox = section.CropBox;
						section.CropBox = cropbox;
					}

 

If I run it once and set a breadkpoint on the section I get:


+ Max {(39.920867142, 6.000000000, 0.000000000)} Autodesk.Revit.DB.XYZ
+ Min {(-36.346794904, -6.000000000, -10.000000000)} Autodesk.Revit.DB.XYZ

 

If I run it again I get:

 

+ Max {(39.920867142, 6.000000000, 10.000000000)} Autodesk.Revit.DB.XYZ
+ Min {(-36.346794904, -6.000000000, 0.000000000)} Autodesk.Revit.DB.XYZ

 

If I run it a third time, it goes back to what I got the first time, and so forth. It's very puzzling, I was trying to work out how to set the depth of a section, I'm guessing this means I won't be able to do that? 

 

 

Message 10 of 21
ari.monteiro
in reply to: grahamcook

Dear Joe, Recently I'm figure out the same problem when I found this post. I post my problem here and your colleague, Jeremy Tammik, tried to help me. I used the idea of one transaction for adjust the crop box, but not success. I saw in your last reply on this post that you sent the issue to analysis by engineering team. This issue persists in Revit 2014 API. Any suggestions to solve this issue? Regards, Ari Monteiro
Message 11 of 21
FRFR1426
in reply to: ari.monteiro

Updates on this? Seems not resolved on 2016...

Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
Message 12 of 21
ken
Advocate
in reply to: FRFR1426

I'm going to add my voice to this issue.  It is, in fact, no small issue that the max/min Z values reverse, the result is that the section mark is now looking the wrong direction and is completely unacceptable.  This bug makes it impossible to set the crop box extents as well as revise the orientation of the cropbox/section.  There is a workaround for relocating/rotating the section by moving the section mark but resizing the crop box automatically is impossible in the current situation. 

 

As an additional note, a new section created with a new BBXYZ will be created at the proper location.  This may be a workaround for typical section views but assembly views can *only* be created by the AssemblyViewUitls class (which I think is too constraining: we should be able to create them normally.  If I can create a new one in the assembly view via the UI, then the API should be able to as well: important sections aren't always orthogonal to the assembly origin).

 

I would also like to say that, while I understand priorities, three to four releases later isn't really what I would hope for in terms of a bug-fix turn-around.  I have filed this as a new case and will try to communicate the need for this fix as best I can.

 

 

Message 13 of 21
Moustafa_K
in reply to: ken

WOHOOOO!!!.... Finally resolved in 2017 ... Thank you Autodesk team  Smiley Happy


-----------------------------------------------------
Moustafa Khalil
Message 14 of 21
ken
Advocate
in reply to: Moustafa_K

Nice Job Autodesk! This is absolutely HUGE for us.

Thanks Mostafa for verifying that it works now!
Message 15 of 21
LoginiMoon
in reply to: Moustafa_K

How do I change the Transform of the crop box of existing view?

Though Transform has set, it does not change.

 

I need to move and resize an existing elevation view (created using createDetail)

 

Resize works, but not move.

Message 16 of 21
FRFR1426
in reply to: LoginiMoon

Can we see your code, please?

Maxence DELANNOY
Manager
Add-ins development for Autodesk software products
http://wiip.fr
Message 17 of 21
LoginiMoon
in reply to: FRFR1426

private void CreateElevationView(BoundingBoxXYZ box)
{

   ElementId viewFamilyTypeId = Document.GetViewFamilyTypeId(ViewFamily.Detail);

 

   if (EditView == null) //static variable to maintain the same view
        EditView = ViewSection.CreateDetail(Document, viewFamilyTypeId, box);
   else
   {

        EditView.CropBox = box;

        EditView.CropBox.Transform = box.Transform;

   }

}

 

the min and max of box gets assigned, but not the transform values.

 

Whatever happens in CreateDetail passing the boundingbox, needs to be done to the exisitng ViewSection.

Typically, assigning a new bounding box to the same viewSection.

 

Any working code would be helpful.

Thank you.

Message 18 of 21
LoginiMoon
in reply to: FRFR1426

private void CreateElevationView(BoundingBoxXYZ box)
{

   ElementId viewFamilyTypeId = Document.GetViewFamilyTypeId(ViewFamily.Detail);

 

   if (EditView == null) //static variable to maintain the same view
        EditView = ViewSection.CreateDetail(Document, viewFamilyTypeId, box);
   else
   {

        EditView.CropBox = box;

        EditView.CropBox.Transform = box.Transform;

   }

}

 

the min and max of box gets assigned, but not the transform values.

 

Whatever happens in CreateDetail passing the boundingbox, needs to be done to the exisitng ViewSection.

Typically, assigning a new bounding box to the same viewSection.

 

Any working code would be helpful.

Thank you.

Message 19 of 21
LoginiMoon
in reply to: LoginiMoon

Any updates on this??

Message 20 of 21
Moustafa_K
in reply to: LoginiMoon

Hi

Apologies for my delayed response. i was extremely busy with a submission, you all know how Architecture world is. I have created this class to help you with this.

Please be aware this will work only on  Revit 2017 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;

namespace A4H_ArchMate
{
    [Transaction(TransactionMode.Manual)]
    class sectionme : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument m_uidoc = uiapp.ActiveUIDocument;
            Document m_doc = m_uidoc.Document;








            BoundingBoxXYZ bbx = new BoundingBoxXYZ();
            PickedBox pbox = m_uidoc.Selection.PickBox(PickBoxStyle.Directional);

            double minx, miny, maxx, maxy, maxz, minz;
            Transform trans = null;

            if (m_doc.ActiveView.ViewType == ViewType.Section || m_doc.ActiveView.ViewType == ViewType.Elevation)
            {

                var vx = m_doc.ActiveView as ViewSection;

                //Section view and Elevation must have Transform Inverse.
                trans = vx.get_BoundingBox(null).Transform.Inverse;

                pbox.Max = trans.OfPoint(pbox.Max);
                pbox.Min = trans.OfPoint(pbox.Min);

                ///we need to make sure that the bounding box initialized correctly
                ///we do not know if the user started clipping from top left to bottom right
                ///or from top right to bottom left
                ///or from bottom left to top right
                ///or from bottom right to top left
                ///all in all bounding box XYZ maximum point mustbe bigger than minimum point other wise you would get bounding box is empty.

                if (pbox.Max.Z > pbox.Min.Z)
                {
                    maxz = pbox.Max.Z;
                    minz = pbox.Min.Z;
                }
                else
                {
                    maxz = pbox.Min.Z;
                    minz = pbox.Max.Z;
                }


                if (Math.Round(pbox.Max.X, 4) == Math.Round(pbox.Min.X, 4))
                {
                    maxx = pbox.Max.X;
                    minx = minz;
                }
                else if (pbox.Max.X > pbox.Min.X)
                {
                    maxx = pbox.Max.X;
                    minx = pbox.Min.X;
                }

                else
                {
                    maxx = pbox.Min.X;
                    minx = pbox.Max.X;
                }

                if (Math.Round(pbox.Max.Y, 4) == Math.Round(pbox.Min.Y, 4))
                {
                    maxy = pbox.Max.Y;
                    miny = minz;
                }
                else if (pbox.Max.Y > pbox.Min.Y)
                {
                    maxy = pbox.Max.Y;
                    miny = pbox.Min.Y;
                }

                else
                {
                    maxy = pbox.Min.Y;
                    miny = pbox.Max.Y;
                }


            }
            else
            {
                if (pbox.Max.X > pbox.Min.X)
                {
                    maxx = pbox.Max.X;
                    minx = pbox.Min.X;
                }
                else
                {
                    maxx = pbox.Min.X;
                    minx = pbox.Max.X;
                }

                if (pbox.Max.Y > pbox.Min.Y)
                {
                    maxy = pbox.Max.Y;
                    miny = pbox.Min.Y;
                }
                else
                {
                    maxy = pbox.Min.Y;
                    miny = pbox.Max.Y;
                }

                if (pbox.Max.Z > pbox.Min.Z)
                {
                    maxz = pbox.Max.Z;
                    minz = pbox.Min.Z;
                }
                else
                {
                    maxz = pbox.Min.Z;
                    minz = pbox.Max.Z;
                }
            }

            bbx = new BoundingBoxXYZ();

            // after every thing is ok now setup the boundingbox
            bbx.Max = new XYZ(maxx, maxy, maxz);
            bbx.Min = new XYZ(minx, miny, minz);


            Transaction t = new Transaction(m_doc, "ArchMate");
            t.Start();


            //make sure scope box is set to none        
            m_doc.ActiveView.get_Parameter(BuiltInParameter.VIEWER_VOLUME_OF_INTEREST_CROP).Set(ElementId.InvalidElementId);

            //make sure FarClipping is set to none or at lease the far clipping distance contains the sectioned elements
            m_doc.ActiveView.get_Parameter(BuiltInParameter.VIEWER_BOUND_FAR_CLIPPING).Set(0);
            
            // set crop region active and visible
            m_doc.ActiveView.CropBoxActive = true;
            m_doc.ActiveView.CropBoxVisible = true;

            //regenerate the view to update data base with the above updates
            m_doc.Regenerate();

            m_doc.ActiveView.CropBox = bbx;

            t.Commit();


            return Result.Succeeded;

        }
    }
}

-----------------------------------------------------
Moustafa Khalil

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