Reference

Conversion of Revit Coordinates and Screen Coordinates

Prerequisite

Record of Issues and Solutions for Generation of Vertical Stair Dimensions in Revit

Style

![Image Description](https://cdn.bimath.com/blog/pg/Snipaste_2026-01-04_17-15-57.png)
![Image Description](https://cdn.bimath.com/blog/pg/Snipaste_2026-01-04_17-16-01.png)

Content

The linked file above provides a method for converting screen coordinates to project coordinates. The principle is calculated by converting the proportion of the point in the screen and the boundary to the project, but the blogger’s method is only applicable to the XY plane case. If applied to a section, it cannot be satisfied. Sections will have orthogonal sections and parallel XY axis cuts or oblique sections, so the following uses the blogger’s ideas to modify the method.

  1. First analyze the section view, which can be seen as horizontal and vertical. Vertical only represents the Z value, and horizontal represents the (X, Y) value, but the horizontal plane will have rotation offset. You can think of this as the bamboo-copter turned when you were a child. Secondly, the section view we see in Revit is actually the projection of the oblique section on the screen.
  2. When we obtain the clicked screen coordinates, we will get the screen’s (X, Y) point, and then obtain the screen Rectangle of the Revit workspace, thereby calculating the proportion of XY in space.
    • Here are two situations. Record it. I first wanted to use UV conversion here, but there is a problem. I cannot get the BoundingBoxUV of the View, so forget it.
    • Later, I used proportional calculation directly, but it was still the problem of oblique sections. At this time, the two ZoomCorns of the oblique section represent a cube, so it cannot be directly converted by proportion.
    • Afterwards, I wanted to convert coordinates through Transform, but we cannot get the converted 3D point because the 2D point of the screen can only provide us with an accurate Z value.
  3. At this time, because the 3D is reduced to XY plane operation, only consider left or right. Because of Revit’s characteristics, Corns[0] represents the left side, 1 represents the right side. This is when we can connect two points with the same Z value into a vector, and bring the horizontal X proportion into the Vector calculation to obtain the horizontal XY value. Combined, it is an accurate 3D coordinate.
  4. Through the first three steps plus a transparent window click interface, the function of automatically generating stair dimensions by user selecting vertical dimension position can be realized. This is not complicated to say, just that I got into the solution of matrix operation at the beginning and took a detour.

Coding a modern tutorial, with a clear explanation of matrices. Reading this will give you a deeper understanding of matrix operations.
Linear Algebra Course: The Essence of Linear Algebra

Code

Screen coordinates to Revit coordinates, only applicable to sections, planes can use the blogger above.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/// <summary>
/// Convert screen coordinates to project coordinates
/// </summary>
/// <param name="screenPoint"></param>
/// <returns></returns>
private XYZ Screen2ViewPlan(UIView uiView,System.Drawing.Point screenPoint)
{
/*
* Due to the uncertainty of the section direction, XY coordinates cannot be simply returned
* The coordinates of the upper left corner can be calculated through the coordinates of the screen working area, returning the screen coordinates and comparing with the clicked window screen coordinates
* Calculate the actual comparison through the comparison of screen values
* Reference link: https://blog.csdn.net/w051108/article/details/107723510
*/

//Screen coordinates
var rect = _uiView.GetWindowRectangle();
//Screen ratio
double sWidth = rect.Right - rect.Left;
double sHeight = rect.Bottom - rect.Top; // Y value increases from top to bottom

double widthScale = (screenPoint.X - rect.Left) / sWidth;
double heightScale = (rect.Bottom - screenPoint.Y) / sHeight;
//Here, if it is an oblique section view, you need to use a normal interface to receive the corresponding position
//Here only need to distinguish left and right, not all views are bottom left and top right corners
var corners = _uiView.GetZoomCorners();
XYZ wRight = corners[1];
XYZ wLeft = corners[0];
//var referVector = (corners[0] - corners[1]).Normalize();
//var referAngle = referVector.AngleTo(XYZ.BasisX);
//if ((referAngle >= 0 && referAngle < 0.5 * Math.PI) ||
// (referAngle >= 1.5 * Math.PI && referAngle <= 2 * Math.PI))
//{
// wRight = corners[1];
// wLeft = corners[0];
//}
//else
//{
// wRight = corners[0];
// wLeft = corners[1];
//}

//Three-dimensional rotation algorithm similar to a plunger style
var fakeTransform = Transform.Identity;
/*
* First reduce dimensions and then calculate separately and combine to become 3D coordinates
* This algorithm applies to all section areas. By unifying Z values, two 3D focus points become a 2D plane
* After connecting two points into a line, find the point on the 2D XY plane through the horizontal proportion of the working plane and the clicked point
* Vertical proportion can calculate Z value, combination can calculate XYZ 3D coordinates
*/
//First degrade Z, degrade to unified Z value
var MoveReferPoint = new XYZ(wRight.X,wRight.Y,wLeft.Z);
var referLine = Line.CreateBound(wLeft, MoveReferPoint);
var referNormalVector = referLine.Direction;
var sPoint = wLeft + (MoveReferPoint - wLeft) * widthScale;
var baseHeight = wRight.Z - wLeft.Z > 0 ? wLeft.Z : wRight.Z;
var referHeight = Math.Abs(wRight.Z - wLeft.Z);

var rPoint = new XYZ(sPoint.X,sPoint.Y,baseHeight + referHeight*heightScale);


// double wWidth = wRightTop.X - wLeftBottom.X;
//double wHeight = wRightTop.Y - wLeftBottom.Y;

//double widthDis = wWidth * widthScale;
//double heightDis = wHeight * heightScale;

//var pointXY = new XYZ(wLeftBottom.X + widthDis, wLeftBottom.Y + heightDis, 0);


return rPoint;
}