retrieving map extent across 180

1233
5
Jump to solution
10-05-2018 09:03 AM
WayneGuidry
New Contributor III

I'm performing IDL (international date line) testing on an application and am having an issue getting the map extent if the map view crosses over 180 degrees. If I zoom in around the 180 longitude and then use the code below to get the current display extent:

Esri::ArcGIS::Runtime::ViewPoint mapViewPoint = m_mapView->currentViewPoint(Esri::ArcGISRuntime::ViewPointType::BoundingGeometry);

Esri::ArcGIS::Runtime::Envelope *m_pZoomBox = new ESRI::ArcGISRuntime::Envelope(Esri::ArcGISRuntime::GeometryEngine::project(mapViewPoint.targetGeometry().extent(), Esri::ArcGISRuntime::SpatialReference::wgs84()));

Checking the return envelope, results in the xMin being -180 and the xMax being 180 which doesn't help determine the boundary of the extent in view. It seems like there should be a way to convert it to a 0 to 360 reference so you can get the actual extent of the map.

Is there a different call I should make to get the bounds across 180? I'm using ArcGIS Runtime 100.1.

Thanks for any assistance!

0 Kudos
1 Solution

Accepted Solutions
LucasDanzinger
Esri Frequent Contributor

I think the issue might be related to the Project call. In your example, what spatial reference is the Map in? My assumption is web mercator. If you use a wgs84 basemap instead and don't call project, it seems to properly give you xMin/Max beyond 180/-180. For example, here is some QML that gives me expected behavior

// add a mapView component
MapView {
    id: mapView
    anchors.fill: parent

    // add a map to the mapview
    Map {           
        Basemap {
            ArcGISTiledLayer {
                url: "http://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer"
            }
        }
    }
}

Button {
    text: "Get WGS84 Extent"
    onClicked: {
        text.text = JSON.stringify(mapView.currentViewpointExtent.extent.json)
    }
}

Text {
    id: text
    anchors.centerIn: parent
    width: parent.width / 2
    wrapMode: Text.WrapAnywhere
    color: "white"
}

I think it might be expected that the xMin/Max defaults to -180/180 when you call project because the coordinates you are passing in from the original geometry are outside the bounds of the spatial reference, and so once that gets processed in the project function, it just defaults.

With all of that said, if your end goal is the use web mercator and do a spatial query across the dateline, I think this is the general workflow you could follow:

- get the viewpoint extent Envelope

- don't project

- normalize the geometry to get folded geometry use normalizeCentralMeridian. 

- This will give you back a multipart polygon where 1 part is on the western side and one is on the eastern side of the dateline

- Pass that into your query parameters, as this should work with multipart geometries

For example, your query will perform against:

instead of

View solution in original post

5 Replies
LucasDanzinger
Esri Frequent Contributor

Wayne-

Maybe you can use the GeometryEngine::normalizeCentralMeridian function to get a folded geometry, and then store that geometry - GeometryEngine Class | ArcGIS for Developers 

If you want to later zoom to that folded geometry, you can call MapView::setViewpointGeometry - MapView Class | ArcGIS for Developers 

0 Kudos
WayneGuidry
New Contributor III

Hi Lucas,

To elaborate,

As a simple test, I'm listening to the MapGraphicsView::viewpointChanged signal and when I pan/zoom on the map and the signal fires, my slot attached to it hits and then I get the extent of the map across the 180 degree longitude using the code I posted above with some qDebug statements to see the values. This is where it returned -180 to 180 instead of 178 to 183 (let's use that as an example value I zoomed to). It seems that either setViewpointGeometry or currentViewpoint.targetGeometry is normalizing the value internally, is that correct?

I was wondering if there would be some way to get the value back without normalization since any time the map crosses the 180 mark in the display targetGeometry appears to return -180 to 180 (regardless if I'm zoomed in or out) which doesn't allow me to query for items within the mapview extent. In ArcGIS Engine, you could convert the -180/180 to 0 to 360 using a IGeographicCoordinateSystem2.LeftLongitude property which helped get around this particular scenario (I could then see a returned extent of 178 to 183 instead).

I'm not sure I understand your suggestion. I was under the impression calling normalizeCentralMeridian is used to return a value that is outside the boundary of the spatial reference to a value inside the spatial reference (for WGS 84 this would be returning a value between -180/180) or am I mistaken?

LucasDanzinger
Esri Frequent Contributor

I see what you're saying now. It seems like something is not working right, because as soon as I pan from 179 to 180, the xMin drops from what my actual xMin is to -180. I'll investigate a little more, but this seems like a bug of some sort

LucasDanzinger
Esri Frequent Contributor

I think the issue might be related to the Project call. In your example, what spatial reference is the Map in? My assumption is web mercator. If you use a wgs84 basemap instead and don't call project, it seems to properly give you xMin/Max beyond 180/-180. For example, here is some QML that gives me expected behavior

// add a mapView component
MapView {
    id: mapView
    anchors.fill: parent

    // add a map to the mapview
    Map {           
        Basemap {
            ArcGISTiledLayer {
                url: "http://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer"
            }
        }
    }
}

Button {
    text: "Get WGS84 Extent"
    onClicked: {
        text.text = JSON.stringify(mapView.currentViewpointExtent.extent.json)
    }
}

Text {
    id: text
    anchors.centerIn: parent
    width: parent.width / 2
    wrapMode: Text.WrapAnywhere
    color: "white"
}

I think it might be expected that the xMin/Max defaults to -180/180 when you call project because the coordinates you are passing in from the original geometry are outside the bounds of the spatial reference, and so once that gets processed in the project function, it just defaults.

With all of that said, if your end goal is the use web mercator and do a spatial query across the dateline, I think this is the general workflow you could follow:

- get the viewpoint extent Envelope

- don't project

- normalize the geometry to get folded geometry use normalizeCentralMeridian. 

- This will give you back a multipart polygon where 1 part is on the western side and one is on the eastern side of the dateline

- Pass that into your query parameters, as this should work with multipart geometries

For example, your query will perform against:

instead of

WayneGuidry
New Contributor III

Thanks Lucas, you are correct it is in web Mercator. I believe this will get me what I need.

Also wanted to mention attempting to programmatically zoom to an area that crosses 180 degrees using setViewpointGeometry using a projected map is proving to be a challenge as well. I think it is related to the project issue as well. I've decided just to use setViewpointCenter for now with a custom scale value. I really can't find a good way to pass in values to setViewpointGeometry as an Envelope that it likes (even normalized).

0 Kudos