Message 1 of 3
Map lines from viewport space to sheet space
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Does anyone know how to map elements from viewport space to sheet space on which viewport is placed? I've had initial success with this code, it worked on a simple plan, but when running it on a rotated plan or on an elevation it either placed lines incorrectly (rotated) or threw an exception altogether (elevation).
If anyone knows a good example to follow that would be much appreciated.
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
Transform transform = viewport.GetProjectionToSheetTransform();
// 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;
}
}