About transforming envelopes in the display
Understanding how rotation is implemented within display objects is important since it affects all displayed entities. Rotation happens below the transformation level so clients of DisplayTransformation always deal with un-rotated shapes. For example, when you get a shape from one of the transform routines, it is in un-rotated space. When you specify an extent to the transform, the extent is also in un-rotated space. There are no issues with rotation when working with polygons. However, it is more complicated when working with envelopes, because rotated rectangles cannot be represented. The following sections demonstrate these complications.
Getting a rectangle from the transform
For example, you want a rectangle representing the client area of the window. Since the user is seeing rotated space on the display, it is not possible to represent the requested area as an envelope. The four corners of the rectangle have unique x,y values in map space. The internal representation of the Envelope class assumes shared x,y values for the sides. As a result, the envelope returned by DisplayTransformation.FittedBounds is not what you want because a rectangular polygon is needed to accurately represent the client area in un-rotated map space. Most clients avoid using an envelope when there is rotation and implement code to find the rectangular polygon that matches a rectangle on the user's display. See the following code example:
[VB.NET]
Private Sub ToUnrotatedMap(ByVal r As tagRECT, ByVal geomBounds As IGeometry, ByVal dispTransform As IDisplayTransformation)
Dim mapPoints() As WKSPoint = New WKSPoint(5)
Dim rectCorners() As tagPOINT = New tagPOINT(4)
rectCorners(0).x = r.Left
rectCorners(0).y = r.bottom
rectCorners(1).x = r.Left
rectCorners(1).y = r.top
rectCorners(2).x = r.Right
rectCorners(2).y = r.top
rectCorners(3).x = r.Right
rectCorners(3).y = r.bottom
'Transform all four points.
dispTransform.TransformCoords(mapPoints(0), rectCorners(0), 4, 4 | 1)
dispTransform.TransformCoords(mapPoints(1), rectCorners(1), 4, 4 | 1)
dispTransform.TransformCoords(mapPoints(2), rectCorners(2), 4, 4 | 1)
dispTransform.TransformCoords(mapPoints(3), rectCorners(3), 4, 4 | 1)
' Build polygon from mapPoints.
mapPoints(4) = mapPoints(0)
Dim boundsPointCollection As IPointCollection
Dim boundsTopologicalOperator2 As ITopologicalOperator2
boundsPointCollection = CType(geomBounds, IPointCollection)
boundsTopologicalOperator2 = CType(geomBounds, ITopologicalOperator2)
boundsPointCollection.SetWKSPoints(1, ref mapPoints(0))
boundsPointCollection.SetWKSPoints(1, ref mapPoints(1))
boundsPointCollection.SetWKSPoints(1, ref mapPoints(2))
boundsPointCollection.SetWKSPoints(1, ref mapPoints(3))
boundsPointCollection.SetWKSPoints(1, ref mapPoints(4))
boundsTopologicalOperator2.IsKnownSimple_2 = True
End Sub
[C#]
private void ToUnrotatedMap(tagRECT r, IGeometry geomBounds, IDisplayTransformation
dispTransform)
{
WKSPoint[] mapPoints = new WKSPoint[5];
tagPOINT[] rectCorners = new tagPOINT[4];
rectCorners[0].x = r.left;
rectCorners[0].y = r.bottom;
rectCorners[1].x = r.left;
rectCorners[1].y = r.top;
rectCorners[2].x = r.right;
rectCorners[2].y = r.top;
rectCorners[3].x = r.right;
rectCorners[3].y = r.bottom;
//Transform all four points.
dispTransform.TransformCoords(ref mapPoints[0], ref rectCorners[0], 4, 4 | 1);
dispTransform.TransformCoords(ref mapPoints[1], ref rectCorners[1], 4, 4 | 1);
dispTransform.TransformCoords(ref mapPoints[2], ref rectCorners[2], 4, 4 | 1);
dispTransform.TransformCoords(ref mapPoints[3], ref rectCorners[3], 4, 4 | 1);
// Build polygon from mapPoints.
mapPoints[4] = mapPoints[0];
IPointCollection boundsPointCollection;
ITopologicalOperator2 boundsTopologicalOperator2;
boundsPointCollection = (IPointCollection)geomBounds;
boundsTopologicalOperator2 = (ITopologicalOperator2)geomBounds;
boundsPointCollection.SetWKSPoints(1, ref mapPoints[0]);
boundsPointCollection.SetWKSPoints(1, ref mapPoints[1]);
boundsPointCollection.SetWKSPoints(1, ref mapPoints[2]);
boundsPointCollection.SetWKSPoints(1, ref mapPoints[3]);
boundsPointCollection.SetWKSPoints(1, ref mapPoints[4]);
boundsTopologicalOperator2.IsKnownSimple_2 = true;
}
Specifying a rectangle to the transform
The client needs to work in un-rotated space and let the transform handle the rotation before displaying. In the case of dragging a zoom rectangle, this means the user sees rotation space. The dragged rectangle is in rotation space. The tool needs to convert the rectangle to un-rotated space before specifying it to the transform. The following code example shows how to do this (rotatedExtent is a rectangular polygon that exactly matches the dragged rectangle):
[VB.NET]
Dim area As IArea = rotatedExtent
Dim center As IPoint = area.Centroid
Dim trans As ITransform2D = rotatedExtent
trans.Rotate(pCenter, (90 * (3.1416 / 180)))
[C#]
IArea area = rotatedExtent;
IPoint center = pArea.Centroid;
ITransform2D trans = rotatedExtent;
trans.Rotate(pCenter, (90 * (3.1416 / 180)));
See Also:
Working with the map displayTo use the code in this topic, reference the following assemblies in your Visual Studio project. In the code files, you will need using (C#) or Imports (VB .NET) directives for the corresponding namespaces (given in parenthesis below if different from the assembly name):
ESRI.ArcGIS.Display ESRI.ArcGIS.Geometry ESRI.ArcGIS.System (ESRI.ArcGIS.esriSystem)
Development licensing | Deployment licensing |
---|---|
ArcGIS for Desktop Basic | ArcGIS for Desktop Basic |
ArcGIS for Desktop Standard | ArcGIS for Desktop Standard |
ArcGIS for Desktop Advanced | ArcGIS for Desktop Advanced |
Engine Developer Kit | Engine |