English

How To: Compute the map extent based on a centerpoint and a scale for ArcGIS Server client application

Summary

ArcGIS Server .NET and Java APIs provide a CenterAndScale class to help zoom to an extent based on a centerpoint and a scale.

The user can get the map extent (MapExtent) from the result of a map export (MapImage).

To complete the map extent based on a centerpoint and a scale without having to get it from the output image, calculate the map extent on the client side. Instructions provided describe how to compute the map extent based on a centerpoint and a scale for ArcGIS Server client applications.

Procedure

Example #1 calculates the map extent using a centerpoint and a scale instead of using a CenterAndScale object in MapServer WSDL. Example #2 uses the DisplayTransformation object and requires access to ESRI’s Display Library. If it is not possible to access this library, use Example #1.

Example# 1 (C#): Compute map extent with a CenterAndScale object in WSDL:

/* The function requires MapServer WSDL’s MapServerInfo, ImageDisplay, CenterAndScale object and an already created EnvelopeN object (by ref) which will be modified */

private void ComputeExtent(MapServerWSDL.MapServerInfo pMSI, MapServerWSDL.ImageDisplay pImageDisplay, MapServerWSDL.CenterAndScale pCenterAndScale, ref MapServerWSDL.EnvelopeN pOutEnvelope)
{
  try
  {
    /* dividing image width by DPI to get it in Inch */
    double dblImgWidthInInch = pImageDisplay.ImageWidth / pImageDisplay.ImageDPI;
    double dblImgHeightInInch = pImageDisplay.ImageHeight / pImageDisplay.ImageDPI;

    /* converting Inch to meter (assume the map is in meter) */
    double dblImgWidthInMapUnit = dblImgWidthInInch * 0.0254;
    double dblImgHeightInMapUnit = dblImgHeightInInch * 0.0254;

    /* calculating half of map’s height & width at the specific scale */
    double dX = (dblImgWidthInMapUnit * pCenterAndScale.Scale) / 2;
    double dY = (dblImgHeightInMapUnit * pCenterAndScale.Scale) / 2;

    /* using the center point and width & height created before, it is computing map’s extent */
    MapServerWSDL.PointN pCtrPnt = pCenterAndScale.Center as MapServerWSDL.PointN;
    double minX = pCtrPnt.X - dX;
    double maxX = pCtrPnt.X + dX;
    double minY = pCtrPnt.Y - dY;
    double maxY = pCtrPnt.Y + dY;

    /* assigning values to the Envelope object passed by the caller function */
    pOutEnvelope.XMin = minX;
    pOutEnvelope.XMax = maxX;
    pOutEnvelope.YMin = minY;
    pOutEnvelope.YMax = maxY;

    /* printing out the extent */
    Debug.Print("ComputeExtent Result: " + pOutEnvelope.XMin.ToString() + ", " + pOutEnvelope.YMin.ToString() + ", " + pOutEnvelope.XMax.ToString() + ", " + pOutEnvelope.YMax.ToString());
  }
  catch (Exception exp)
  {
    MessageBox.Show(exp.Message, "Error in ComputeExtent", MessageBoxButtons.OK, MessageBoxIcon.Error);
  }
}
Note:
DCOM connection is no longer supported in ArcGIS for Server 10.1. If you need to use the following code in 10.1, do not use ServerContext.

Example# 2 (C#): Compute map extent with a CenterAndScale object:
/* ** esriDisplay library must be referenced.
   The function requires MapServerInfo, ImageDisplay, CenterAndScale
   object and returns IEnvelope
   ServerContext is optional, only required when your application works
   with ServerContext */

private IEnvelope ComputeExtent(IMapServerInfo pMapServerInfo, IImageDisplay pImageDisplay, ICenterAndScale pCenterAndScale, IServerContext pServerContex)
{
  try
  {
    /* aRect holds information about the client side’s map size in pixel */
    tagRECT aRect = new tagRECT();
    aRect.top = 0;
    aRect.left = 0;
    aRect.bottom = pImageDisplay.Height;
    aRect.right = pImageDisplay.Width;

    /* when application uses ServerContext, DisplayTransformation will be created in ServerContext */
    IDisplayTransformation pDT;
    if (pServerContex != null)
      pDT =
      pDT = new DisplayTransformationClass();pServerContex.CreateObject("esriDisplay.DisplayTransformation") as IDisplayTransformation;
    else

    /* Setting different DisplayTransformation properties to compute extent */
    pDT.Bounds = pMapServerInfo.FullExtent;
    IEnvelope pMDscExtent = pMapServerInfo.DefaultMapDescription.MapArea.Extent;
    pMDscExtent.CenterAt(pCenterAndScale.Center);
    pDT.VisibleBounds = pMDscExtent;
    pDT.SpatialReference = pMapServerInfo.DefaultMapDescription.SpatialReference;
    pDT.Units = pMapServerInfo.MapUnits;
    pDT.set_DeviceFrame(ref aRect);
    pDT.Resolution = pImageDisplay.DeviceResolution;
    pDT.ScaleRatio = pCenterAndScale.MapScale;

    /* printing map extent */
    Debug.Print("New Map Extent - After ScaleRatio: " + pDT.FittedBounds.XMin.ToString() + ", " + pDT.FittedBounds.YMin.ToString() + ", " + pDT.FittedBounds.XMax.ToString() + ", " + pDT.FittedBounds.YMax.ToString());

    //returning new map extent
    return pDT.FittedBounds;
  }
  catch (Exception exp)
  {
    MessageBox.Show(exp.Message, "Error in ComputeExtent", MessageBoxButtons.OK, MessageBoxIcon.Error);
    return null;
  }
}