SetViewpoint to zoom to several layers

292
2
08-27-2018 04:28 AM
WaldemarNowak
New Contributor III

I have several layers:

  1. Base layer from mapbox.com "satellite-streets-v10" with SRID=3857
  2. Operational layer "A" with SRID=2230
  3. Operational layer "B" with SRID=2229

I can zoom to one layer (e.g. "A") using the code:

MyMapView.SetViewpoint(new Viewpoint(layerA.FullExtent));

How can I zoom to all operational layers (A and B in this example)?

According to documentaiton when I add layers to the map they should be automatically reprojected to the SRID of the first added layer. However, this does not seem to be true, as they still keep original SRID in layer.SpatialReference property. 

I tried to create envelope as union of all layers:

envelopeBuilder.UnionOf(layerB.FullExtent);

This generates exception: "The input spatial reference is not equivalent to the owning spatial reference." This proves that layers are not reprojected and they don't have the same coordinate system on the map. 

Any suggestions how to get full extent of union of a few layers?

Regards,

Waldek

Tags (3)
0 Kudos
2 Replies
JenniferNery
Esri Regular Contributor

I'm not able to reproduce the issue with the following services and code. What version of the API are you using? and what layer type? 

In sample below, I am using FeatureLayer with the same SpatialReferences as you have. The reported FullExtent for each layer matches the map.

Envelope envelope = null;
MyMapView.LayerViewStateChanged += (s, e) =>
  {
      var error = e.LayerViewState.Error ?? e.Layer.LoadError;
      if(error != null)
      {
          MessageBox.Show(error.Message, error.GetType().Name);
          return;
      }
      if (e.Layer is FeatureLayer && e.LayerViewState.Status != LayerViewStatus.Loading && e.Layer.FullExtent != null && !e.Layer.FullExtent.IsEmpty)
      {
          var extent = e.Layer.FullExtent;
          if (envelope == null)
              envelope = extent;
          else
          {
              envelope = GeometryEngine.Union(envelope, extent)?.Extent;
          }
          if (envelope != null)
          {
              System.Diagnostics.Debug.WriteLine(extent);
              MyMapView.SetViewpoint(new Viewpoint(envelope));
          }
      }
  };
var map = new Map(Basemap.CreateTopographic());
map.OperationalLayers.Add(new FeatureLayer(new Uri("http://zimas.lacity.org/arcgis/rest/services/B_ZONING/MapServer/0")) { Id = "2229" });
map.OperationalLayers.Add(new FeatureLayer(new Uri("https://gis-public.co.san-diego.ca.us/arcgis/rest/services/rov/sdvote_politicalbounds/MapServer/0")) { Id = "2230" });
MyMapView.Map = map;‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

You may be using service metadata, LayerInfo.Extent, which is not projected. Before you can perform a union of two extents, you must put them in the same projection. You can then use GeometryEngine.Project

var extent = (((FeatureLayer)e.Layer).FeatureTable as ArcGISFeatureTable)?.Extent;
if (envelope == null)
    envelope = extent;
else if(!envelope.SpatialReference.IsEqual(extent.SpatialReference))
{
    var projectedExtent = GeometryEngine.Project(extent, envelope.SpatialReference);
    envelope = GeometryEngine.Union(envelope, projectedExtent)?.Extent;
}
else
{
    envelope = GeometryEngine.Union(envelope, extent)?.Extent;
}
if (extent != null)
{
    System.Diagnostics.Debug.WriteLine(extent);
    MyMapView.SetViewpoint(new Viewpoint(envelope));
}
WaldemarNowak
New Contributor III

Hi Jennifer!

The last code snippet works like a charm! Thank you.

To answer all your questions:

1) I use API verison 100.3.

2) The basemap is WmtsLayer, and operational layers are: FeatureLayer.

3) In your example, when I loop through OperationalLayers, the property layer.SpatialReference contains original SRID (not projected) as well as in my code. It looks like this is correct, I thought that it should have contained projected SRID, but it didn't.

4) I think the crucial here was to use: 

GeometryEngine.Project
0 Kudos