Get Transform of viewport that was changed by modifying its crop region

Get Transform of viewport that was changed by modifying its crop region

DanielKP2Z9V
Advocate Advocate
366 Views
6 Replies
Message 1 of 7

Get Transform of viewport that was changed by modifying its crop region

DanielKP2Z9V
Advocate
Advocate

Code below remaps lines from viewport space into sheet space. However, Transform returned by viewport.GetProjectionToSheetTransform doesn't seem to account for changes made by moving/rotating viewport by its crop region. That is if user shifts or rotates the viewport by clicking on its crop region and performs move/rotate command the new position won't be accounted for by the command below and the lines won't be drawn in correct place on the sheet.

 

Is there a way in Revit API to look up this extra "crop region" transformation?

 

using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using System.Collections.Generic;
using System.Linq;

[Transaction(TransactionMode.Manual)]
public class MapLinesToSheet : IExternalCommand
{
    public Result Execute(
        ExternalCommandData commandData,
        ref string message,
        ElementSet elements)
    {
        UIDocument uidoc = commandData.Application.ActiveUIDocument;
        Document doc = uidoc.Document;
        View activeView = uidoc.ActiveView;

        // Find the viewport that contains this active view
        Viewport viewport = GetViewportForActiveView(doc, activeView);
        if (viewport == null)
        {
            message = "No viewport found for the active view.";
            return Result.Failed;
        }

        // Get the sheet that contains the viewport
        ViewSheet sheet = doc.GetElement(viewport.SheetId) as ViewSheet;
        if (sheet == null)
        {
            message = "No sheet found for the active view.";
            return Result.Failed;
        }

        // Use the existing selection
        ICollection<ElementId> selectedIds = uidoc.Selection.GetElementIds();
        if (selectedIds.Count == 0)
        {
            message = "No elements selected. Please select some lines first.";
            return Result.Failed;
        }

        // Get the scale of the viewport
        double viewportScale = activeView.Scale;

        // Begin transaction
        using (Transaction trans = new Transaction(doc, "Map Lines to Sheet Space"))
        {
            trans.Start();

            foreach (ElementId id in selectedIds)
            {
                Element element = doc.GetElement(id);
                if (element is CurveElement curveElement)
                {
                    Curve curve = curveElement.GeometryCurve;

                    // Get the transformation from the viewport to the sheet, including crop region rotation
                    Transform transform = GetViewportToSheetTransform(viewport);

                    // Scale the curve manually by dividing its coordinates by the viewport scale
                    Curve scaledCurve = ScaleCurve(curve, 1 / viewportScale);

                    // Apply the transform to the scaled curve
                    Curve transformedCurve = scaledCurve.CreateTransformed(transform);

                    // Project the transformed curve to the sheet plane
                    Curve projectedCurve = ProjectCurveToSheetPlane(transformedCurve);

                    // Create the new curve on the sheet
                    if (projectedCurve != null)
                    {
                        doc.Create.NewDetailCurve(sheet, projectedCurve);
                    }
                    else
                    {
                        message = "Failed to project curve to sheet plane.";
                        return Result.Failed;
                    }
                }
            }

            trans.Commit();
        }

        return Result.Succeeded;
    }

    private Viewport GetViewportForActiveView(Document doc, View activeView)
    {
        // Find the viewport that displays the active view
        FilteredElementCollector collector = new FilteredElementCollector(doc).OfClass(typeof(Viewport));
        foreach (Viewport vp in collector.Cast<Viewport>())
        {
            if (vp.ViewId == activeView.Id)
            {
                return vp;
            }
        }

        return null; // No matching viewport found
    }

    private Curve ScaleCurve(Curve curve, double scaleFactor)
    {
        // Scale each point in the curve by multiplying the coordinates by the scaleFactor
        Transform scaleTransform = Transform.Identity.ScaleBasis(scaleFactor);
        return curve.CreateTransformed(scaleTransform);
    }

    private Curve ProjectCurveToSheetPlane(Curve curve)
    {
        // Define the XY plane of the sheet (Z = 0)
        Plane sheetPlane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero);

        // Project each point of the curve onto the sheet plane
        XYZ start = ProjectPointToPlane(curve.GetEndPoint(0), sheetPlane);
        XYZ end = ProjectPointToPlane(curve.GetEndPoint(1), sheetPlane);

        // Return a new line or arc based on the projected points
        if (curve is Line)
        {
            return Line.CreateBound(start, end);
        }
        else if (curve is Arc arc)
        {
            XYZ mid = ProjectPointToPlane(arc.Evaluate(0.5, true), sheetPlane);
            return Arc.Create(start, end, mid);
        }

        return null; // If the curve type is not supported
    }

    private XYZ ProjectPointToPlane(XYZ point, Plane plane)
    {
        // Project a point onto a plane
        XYZ originToPt = point - plane.Origin;
        double distance = originToPt.DotProduct(plane.Normal);
        XYZ projection = point - distance * plane.Normal;

        return projection;
    }

    private Transform GetViewportToSheetTransform(Viewport viewport)
    {
        // Get the basic projection transform
        Transform projectionTransform = viewport.GetProjectionToSheetTransform();

        // Get the rotation of the viewport (this is a double representing radians)
        double rotationAngle = (double)viewport.Rotation;  // Cast rotation to double

        // Create a rotation transform around the center of the viewport
        XYZ center = viewport.GetBoxCenter();
        Transform rotationTransform = Transform.CreateRotationAtPoint(XYZ.BasisZ, -rotationAngle, center);

        // Combine the projection and rotation transforms
        return rotationTransform.Multiply(projectionTransform);
    }
}

 

367 Views
6 Replies
Replies (6)
Message 2 of 7

jeremy_tammik
Alumni
Alumni

Congratulations! You seem to have solved your first issue that you raised:

  

  

Would you like to add your solution to that thread to make it easier for posterity to discover it? Thank you!

   

The new issue sounds a bit tricky... don't know off-hand, I'm afraid... sorry!

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 7

DanielKP2Z9V
Advocate
Advocate

Sorry for duplicate post, I forgot that this has been posted already. This code isn't much different from the previous example, it still doesn't work in elevations and I can't seem to get it to work with viewports, which had their views modified by editing crop region.

 

I'm exploring this problem actively now, so if I find a solution I will update both posts - alternatively I can close the previous one?

 

> The new issue sounds a bit tricky... don't know off-hand, I'm afraid... sorry!

 

No worries, I'm sure that it must have something to do with the transform in View.CropBox.Transform - I'm just not sure how to apply it now (not enough experience in computer graphics unfortunately ;/)

Message 4 of 7

ianpM59BG
Contributor
Contributor

I'm having a very similar issue! Did you ever find an answer to this?

Thanks!

0 Likes
Message 5 of 7

baleti3266
Advocate
Advocate

@ianpM59BG yes, but it got integrated into this "DrawRevisionCloudAroundSelectedElementsInSheets" command. I'll see if I can distill what portion does that exactly.

0 Likes
Message 6 of 7

baleti3266
Advocate
Advocate

@ianpM59BG got chatgpt to extract it for me, sorry: https://pastebin.com/eYb6fA3i

0 Likes
Message 7 of 7

ianpM59BG
Contributor
Contributor

INCREDIBLE! Did exactly what I needed it to do. Thanks so much!