Problems when trying to retrieve information from ArcGis Map Image Layer instance by query

1232
6
Jump to solution
05-19-2020 01:29 AM
FrancoisPicard
New Contributor II

Hi all

Having a hard time getting access by query to the information included in a Map Image Layer object.

I am trying to work with the following map image layer instance:
http://banedanmark.maps.arcgis.com/home/item.html?id=298233b172c347248080e7e58f06310d
linked to the following URL: http://agis1.cloudapp.net/arcgis/rest/services/BaneGISX_OpenData/Info/MapServer

This instance is displaying several information about the railways in Denmark and includes the following sublayers:

  • "Stationer", index 0
  • "Kilometermærker", index 1
  • "10km", index 2
  • "5km", index 3
  • "1km", index 4
  • "Alle", index 5
  • "Strkafs", index 6

These information can be visualized here, among other things: http://banedanmark.maps.arcgis.com/apps/webappviewer/index.html?id=6541fbc0cbba499b861e4d7fe23b10b6

What I want is to display the "Kilometermærker" information (= kilometer marks) and get access to the attributes of the closest ones to, let's say, my current position, which is the center position of my view.

But I am having a hard time retrieving by query the information of the closest kilometer marks. The query does not return any FeatureSet instances and I am not sure why:

  • I have no problem handling other Feature Layer instances (like the ones displayed in the previously mentioned link) and getting access to the closest elements with the same method.
  • Displaying all the visual information from the map image layer instance by adding it to the map does not present any problems.
  • I tried several sublayers from the map image layer object with the same result (no feature set returned).
  • I tried to wait for the loading of the view before querying with the same result.
  • I tried to create a feature layer from the sublayer with the same result.
  • I tried to specify the sublayers to be displayed with the "sublayers" property of the map image layer instance. Still no feature set returned but what I don't understand is that modifying the renderer of the specified sublayer is visible:

var infoMapLayer = new MapImageLayer({
  url: "http://agis1.cloudapp.net/arcgis/rest/services/BaneGISX_OpenData/Info/MapServer",
  sublayers: [
  {
    id: 5,
    title: "Alle",
    renderer: {
      type: "simple", // autocasts as new SimpleRenderer()
     symbol: {
       type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
       color: "yellow",
       size: 10
     }
   }
  }
  ]
});

There's surely something I did not understand about these map image layers but I can't find out what. Can anybody help me with the issue?

I am attaching to this post the final code.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

That layer did not support querying by distance. Here is your code fixed.

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="X - UA - Compatible" content="IE =edge">
  <meta charset=" utf-8">
  <meta name=" viewport " content=" initial-scale=1, maximum-scale=1, user-scalable=no ">
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>
  <link rel=" stylesheet " href="https://js.arcgis.com/4.14/esri/themes/light/main.css">
  <script src="https://js.arcgis.com/4.14/"></script>

  <script>
    var view;

    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/GraphicsLayer",
      "esri/layers/MapImageLayer",
      "esri/Graphic",
      "esri/geometry/geometryEngine"
    ], function (Map, MapView, GraphicsLayer, MapImageLayer, Graphic, geometryEngine) {

      // ***************************************************************************
      // initialization

      var map = new Map({
        basemap: "topo-vector"
      });

      view = new MapView({
        container: "viewDiv",
        // display the standard maps
        map: map,
        center: [11.961214, 55.329578],
        zoom: 19
      });

      // current center position
      var currentPoseGraphicsLayer = new GraphicsLayer();

      var posPoint = {
        type: "point",
        longitude: view.center.x,
        latitude: view.center.y
      };

      var posMarkerSymbol = {
        type: "simple-marker",
        color: "green",
        outline: {
          color: "#efefef",
          width: "1.5px"
        }
      };

      var posPointGraphic = new Graphic({
        geometry: posPoint,
        symbol: posMarkerSymbol
      });

      // displaying the kilometer marks
      var allKmMarkGraphicsLayer = new GraphicsLayer();

      // ***************************************************************************
      // layers

      // info
      var infoMapLayer = new MapImageLayer({
        url: "http://agis1.cloudapp.net/arcgis/rest/services/BaneGISX_OpenData/Info/MapServer",
        //sublayers: [
        //    {
        //        id: 5,
        //        title: "Alle",
        //        renderer: {
        //            type: "simple",  // autocasts as new SimpleRenderer()
        //            symbol: {
        //                type: "simple-marker",  // autocasts as new SimpleMarkerSymbol()
        //                color: "yellow",
        //                size: 10
        //            }
        //        }
        //    }
        //]
      });

      var allKmMarkSublayer;

      // ***************************************************************************
      // functions

      function displayClosestKmMarks(result) {
        allKmMarkGraphicsLayer.removeAll();
        result.features.forEach(function (feature) {
          var g = new Graphic({
            geometry: feature.geometry,
            attributes: feature.attributes,
            symbol: {
              type: "simple-marker",
              color: [0, 255, 255],
              size: "20px"
            }
          });
          allKmMarkGraphicsLayer.add(g);
        });
      }

      function queryFeatureLayer(point, distance, spatialRelationship, sqlExpression) {
        var ptBuff = geometryEngine.buffer(point, distance, "feet");
        var query = {
          geometry: ptBuff,
          distance: distance,
          spatialRelationship: spatialRelationship,
          outFields: ["*"],
          returnGeometry: true,
          where: sqlExpression,
          outSpatialReference: view.spatialReference
        };

        allKmMarkSublayer.queryFeatures(query).then(function (result) {
          displayClosestKmMarks(result);
        });
      }

      // ***************************************************************************
      // event handling

      // update display elements with respect to the view center
      view.watch("center", function (newValue) {

        map.remove(currentPoseGraphicsLayer);
        currentPoseGraphicsLayer = new GraphicsLayer();
        map.add(currentPoseGraphicsLayer);

        posPoint.longitude = newValue.longitude;
        posPoint.latitude = newValue.latitude;

        posPointGraphic = new Graphic({
          geometry: posPoint,
          symbol: posMarkerSymbol
        });

        currentPoseGraphicsLayer.add(posPointGraphic);

        var subLayerId = 5;
        allKmMarkSublayer = infoMapLayer.allSublayers.find(function (sublayer) {
          //alert(sublayer.title + " with id " + sublayer.id);
          return sublayer.id === subLayerId;
        });

        queryFeatureLayer(view.center, 500, "intersects")
      });

      // ***************************************************************************
      // adding to map

      // displaying the view center
      map.addMany([currentPoseGraphicsLayer, allKmMarkGraphicsLayer]);

      // info
      map.add(infoMapLayer);

    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>

View solution in original post

6 Replies
RobertScheitlin__GISP
MVP Emeritus

That layer did not support querying by distance. Here is your code fixed.

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="X - UA - Compatible" content="IE =edge">
  <meta charset=" utf-8">
  <meta name=" viewport " content=" initial-scale=1, maximum-scale=1, user-scalable=no ">
  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>
  <link rel=" stylesheet " href="https://js.arcgis.com/4.14/esri/themes/light/main.css">
  <script src="https://js.arcgis.com/4.14/"></script>

  <script>
    var view;

    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/GraphicsLayer",
      "esri/layers/MapImageLayer",
      "esri/Graphic",
      "esri/geometry/geometryEngine"
    ], function (Map, MapView, GraphicsLayer, MapImageLayer, Graphic, geometryEngine) {

      // ***************************************************************************
      // initialization

      var map = new Map({
        basemap: "topo-vector"
      });

      view = new MapView({
        container: "viewDiv",
        // display the standard maps
        map: map,
        center: [11.961214, 55.329578],
        zoom: 19
      });

      // current center position
      var currentPoseGraphicsLayer = new GraphicsLayer();

      var posPoint = {
        type: "point",
        longitude: view.center.x,
        latitude: view.center.y
      };

      var posMarkerSymbol = {
        type: "simple-marker",
        color: "green",
        outline: {
          color: "#efefef",
          width: "1.5px"
        }
      };

      var posPointGraphic = new Graphic({
        geometry: posPoint,
        symbol: posMarkerSymbol
      });

      // displaying the kilometer marks
      var allKmMarkGraphicsLayer = new GraphicsLayer();

      // ***************************************************************************
      // layers

      // info
      var infoMapLayer = new MapImageLayer({
        url: "http://agis1.cloudapp.net/arcgis/rest/services/BaneGISX_OpenData/Info/MapServer",
        //sublayers: [
        //    {
        //        id: 5,
        //        title: "Alle",
        //        renderer: {
        //            type: "simple",  // autocasts as new SimpleRenderer()
        //            symbol: {
        //                type: "simple-marker",  // autocasts as new SimpleMarkerSymbol()
        //                color: "yellow",
        //                size: 10
        //            }
        //        }
        //    }
        //]
      });

      var allKmMarkSublayer;

      // ***************************************************************************
      // functions

      function displayClosestKmMarks(result) {
        allKmMarkGraphicsLayer.removeAll();
        result.features.forEach(function (feature) {
          var g = new Graphic({
            geometry: feature.geometry,
            attributes: feature.attributes,
            symbol: {
              type: "simple-marker",
              color: [0, 255, 255],
              size: "20px"
            }
          });
          allKmMarkGraphicsLayer.add(g);
        });
      }

      function queryFeatureLayer(point, distance, spatialRelationship, sqlExpression) {
        var ptBuff = geometryEngine.buffer(point, distance, "feet");
        var query = {
          geometry: ptBuff,
          distance: distance,
          spatialRelationship: spatialRelationship,
          outFields: ["*"],
          returnGeometry: true,
          where: sqlExpression,
          outSpatialReference: view.spatialReference
        };

        allKmMarkSublayer.queryFeatures(query).then(function (result) {
          displayClosestKmMarks(result);
        });
      }

      // ***************************************************************************
      // event handling

      // update display elements with respect to the view center
      view.watch("center", function (newValue) {

        map.remove(currentPoseGraphicsLayer);
        currentPoseGraphicsLayer = new GraphicsLayer();
        map.add(currentPoseGraphicsLayer);

        posPoint.longitude = newValue.longitude;
        posPoint.latitude = newValue.latitude;

        posPointGraphic = new Graphic({
          geometry: posPoint,
          symbol: posMarkerSymbol
        });

        currentPoseGraphicsLayer.add(posPointGraphic);

        var subLayerId = 5;
        allKmMarkSublayer = infoMapLayer.allSublayers.find(function (sublayer) {
          //alert(sublayer.title + " with id " + sublayer.id);
          return sublayer.id === subLayerId;
        });

        queryFeatureLayer(view.center, 500, "intersects")
      });

      // ***************************************************************************
      // adding to map

      // displaying the view center
      map.addMany([currentPoseGraphicsLayer, allKmMarkGraphicsLayer]);

      // info
      map.add(infoMapLayer);

    });
  </script>
</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>
FrancoisPicard
New Contributor II

Thanks a lot Robert. That's perfect.

So basically, I just needed to specify the right geometry in my query. Just for me to understand, how did you figure out that the layer was not supporting querying by distance?

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

I had a feeling that a sublayer class was not capable of distance queries and I looked at the capabilities property of the returned layer, by logging the layer object.

FrancoisPicard
New Contributor II

Thank you for your help!

0 Kudos
TanuHoque
Esri Regular Contributor

Francois Picard

It looks like your map service is running on an older version (10.3) of ArcGIS Enterprise. We didn't have support for query by distance back then. The support came later and I can't remember off the top of my head when.

Here is map service REST API help on query by distance: Query (Map Service/Layer)—ArcGIS REST API: Services Directory | ArcGIS for Developers 

Here is a REST query request to a map service running on sample server to returns points within 200 miles from a location.

https://sampleserver6.arcgisonline.com/arcgis/rest/services/SampleWorldCities/MapServer/0/query?&geo...

FrancoisPicard
New Contributor II

Thank you Tanu.

0 Kudos