Align viewports by their cropbox using new API methods

Align viewports by their cropbox using new API methods

pieter7
Advisor Advisor
420 Views
1 Reply
Message 1 of 2

Align viewports by their cropbox using new API methods

pieter7
Advisor
Advisor

I am trying to align views on a sheet using their cropbox, and not their 'viewport extents' as those are influenced by annotations.

 

Prior to Revit 2023, the trick was to hide all the annotations, so that the 'viewport extents' matches the cropbox, align the viewports and then re-able the annotations again.

 

But Revit 2023 got two new methods (https://thebuildingcoder.typepad.com/blog/2022/04/whats-new-in-the-revit-2023-api.html#4.2.6.2) that look like they should allow us to do this more efficiently. 

 

This is what I have so far:

 

AlignViewPortsVertically:

 

        public void AlignViewPortsVertically(List<View> viewsToAlign, View referenceView )
        {
            BoundingBoxXYZ referenceBoundingBox = RevitUtility.GetProjectedCropBoxOnSheet(referenceView);
            
            foreach ( View view in viewsToAlign )
            {
                BoundingBoxXYZ viewBoundingBox = RevitUtility.GetProjectedCropBoxOnSheet(view);

                double deltaX = referenceBoundingBox.Max.X - viewBoundingBox.Max.X;
                double deltaXScaled = deltaX;
                Viewport viewport = RevitUtility.GetViewPortOfView(view.Id);
                RevitUtility.MoveViewPort(viewport, deltaXScaled, 0);
            }
        }

 

 

GetProjectedCropBoxOnSheet:

 

        static public BoundingBoxXYZ GetProjectedCropBoxOnSheet(View view)
        {
            Viewport viewport = GetViewPortOfView(view.Id);
            XYZ referenceMin = view.CropBox.Min;
            XYZ referenceMax = view.CropBox.Max;
            
            Transform transform = viewport.GetProjectionToSheetTransform();
            XYZ minProjected = transform.OfPoint(referenceMin);
            XYZ maxProjected = transform.OfPoint(referenceMax);

            BoundingBoxXYZ boundingBoxXYZ = new BoundingBoxXYZ();
            boundingBoxXYZ.Min = minProjected / view.Scale; 
            boundingBoxXYZ.Max = maxProjected / view.Scale;

            return boundingBoxXYZ;
        }

 

 

However, the views don't exactly align. See the image attached. Anyone have any ideas what I am doing wrong?

Accepted solutions (1)
421 Views
1 Reply
Reply (1)
Message 2 of 2

pieter7
Advisor
Advisor
Accepted solution

I think I found a solution. My problem seemed to be with using:

 

            XYZ referenceMin = view.CropBox.Min;
            XYZ referenceMax = view.CropBox.Max;

 

It seems  view.Cropbox does not return reliable values for the cropbox (?).

 

This is my new code that seems to work:

 

Projecting crop boxes onto the sheet coordinate space:

 

        static public BoundingBoxXYZ GetProjectedCropBoxOnSheet(View view)
        {
            IList<TransformWithBoundary> transformList = view.GetModelToProjectionTransforms();
            TransformWithBoundary transformWithBoundary = transformList[0];
            CurveLoop boundaryLoop = transformWithBoundary.GetBoundary();

            //extract first point of each line curve
            List<XYZ> corners = new List<XYZ>();
            foreach (Line line in boundaryLoop)
            {
                if (line != null)
                {
                    corners.Add(line.GetEndPoint(0));
                }
            }

            //project each point from model space to sheet
            List<XYZ> projectedCorners = new List<XYZ>();
            foreach (XYZ corner in corners)
            {
                projectedCorners.Add(ProjectModelPointOnSheet(view, corner));
            }

            //create bounding box that fits all points (z is non-sensical)
            BoundingBoxXYZ boundingBox = new BoundingBoxXYZ();
            boundingBox.Clear();
            foreach (XYZ projectedCorner in projectedCorners)
            {
                boundingBox.ExpandToContain(projectedCorner);
            }
            return boundingBox;
        }

 

 

Projecting points from model space to sheet coordinate space

 

static public XYZ ProjectModelPointOnSheet(View view, XYZ pointInModel)
{
    Viewport viewport = GetViewPortOfView(view.Id);

    IList<TransformWithBoundary> transformList = view.GetModelToProjectionTransforms();
    TransformWithBoundary transformWithBoundary = transformList[0];
    Transform transform1 = transformWithBoundary.GetModelToProjectionTransform();
    XYZ pointInViewCoordinateSpace = transform1.OfPoint(pointInModel);

    Transform transform2 = viewport.GetProjectionToSheetTransform();
    XYZ pointInSheetCoordinateSpace = transform2.OfPoint(pointInViewCoordinateSpace);

    return pointInSheetCoordinateSpace;
}

 

 

Right-aligning viewports based on their crop boxes

 

      static public void RightAlignViewPorts(List<View> viewsToAlign, View referenceView)
      {
          BoundingBoxXYZ referenceBox = GetProjectedCropBoxOnSheet(referenceView);

          foreach (View view in viewsToAlign)
          {
              BoundingBoxXYZ viewCorner = GetProjectedCropBoxOnSheet(view);
              double deltaX = referenceBox.Max.X - viewCorner.Max.X;
              Viewport viewport = GetViewPortOfView(view.Id);
              MoveViewPort(viewport, deltaX, 0);
          }
      }