I have a Layout created programatically using a CIMPage (LayoutFactory.Instance.CreateLayout(page)). This layout also has a MapFrame programatically added to it, and that MapFrame has its associated Map. I am trying to synchronize specific coordinates on that Map to points on the Page, so that they appear in the MapFrame in the appropriate locations.
It seems that if I had a Layout that was created with ItemFactory, I would be able to get at its Pane and LayoutView, and then I could pass that LayoutView into MapFrame.GetMapView() as the necessary argument. Then I might call something like MapView.MapToClient(mapPoint) to get the specific page coordinates I need for my render.
Since my Layout was created on the MCT and doesn't have a pane, however, I'm not sure how to go about this (using ESRI methods, at least). Would I have to instantiate a Pane with my new Layout just so I can get at the MapView of its already existing MapFrame?
Hello David, you ask a great question and I have a couple of comments.
First, the ArcGIS Pro software development is currently working on supporting map graphics. The plans are for 2.6. This might eliminate your need to attempt to build this map unit to page unit transformation. But ...
Second, I did make an attempt to try what you needed. It is not easy because a map frame has a camera and the camera has an XY center point (and scale). Extent is not persisted with the camera because the camera works for 3D as well where extents really don't make sense. So extents are derived from center point and scale. That along with your map frame width and height in page units you can do a proportional transformation.
Here is code where I have a hard coded targetX and targetY in map units and place those proportionally on a map frame using the appropriate math. What I learned from this is that we should at least have a helper function that returns the derived extent. This would eliminate the extra work of determining x/y min/max values.
////Convert map units to page units
Layout layout = LayoutView.Active.Layout;
await QueuedTask.Run(() =>
{
//Reference MapFrame
MapFrame mf = layout.FindElement("Map Frame") as MapFrame;
double camScale = mf.Camera.Scale;
//Build X in page unts at 995200 map units
double targetX = 995200;
double camX = mf.Camera.X; //Map feet
double mfWidth = mf.GetWidth(); //Page inches
double xMin = camX - (mfWidth / 2) * (camScale / 12);
double xMax = camX + (mfWidth / 2) * (camScale / 12);
double xPer = (targetX - xMin) / (xMax - xMin);
double xSpot = (mfWidth * xPer) + mf.GetX();
//Build Y in page unts at 604719 map units
double targetY = 604700;
double camY = mf.Camera.Y; //Map feet
double mfHeight = mf.GetHeight(); // Page inches
double yMin = camY - (mfHeight / 2) * (camScale / 12);
double yMax = camY + (mfHeight / 2) * (camScale / 12);
double yPer = (targetY - yMin) / (yMax - yMin);
double ySpot = (mfHeight * yPer) + mf.GetY();
//Build geometry
Coordinate2D coord2D = new Coordinate2D(xSpot, ySpot);
//Set symbolology, create and add element to layout
CIMPointSymbol pointSym = SymbolFactory.Instance.ConstructPointSymbol(ColorFactory.Instance.RedRGB, 25.0, SimpleMarkerStyle.Star);
GraphicElement ptElm = LayoutElementFactory.Instance.CreatePointGraphicElement(layout, coord2D, pointSym);
ptElm.SetName("New MapGraphic Point");
});
This was also submitted as an enhancement request (ENH-000126917). We are considering this for a future release. Thankyou for your feedback!
Jeff - Layout Team
Thanks Jeff Barrette. If you don't mind, I'd like to draw your attention to a related question I posted yesterday: https://community.esri.com/thread/254673-what-does-a-map-frame-cameras-scale-mean-in-the-context-of-...
Also, as for the above example - this assumes a specific combination of linear units, and that the map frame's camera's heading is 0 (no rotation). I've accounted for rotation successfully, but per the question referenced above, I'm not sure how to account for angular units. How can we something like translate between inches on a page and decimal degrees within a map frame, for instance?
Transformation functions have been added to LayoutView for the ArcGIS Pro 2.7 release.
Jeff - Layout / arcpy.mp Teams