Message 1 of 7
Get Transform of viewport that was changed by modifying its crop region
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
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);
}
}