Navigation for closest facility not showing

684
8
10-18-2021 09:32 AM
JeffersonTotimeh
New Contributor

I'm working on a project and I want to add the closest facility function to my work. The code runs perfectly but the route to the closest facility doesn't seem to work. I tried using other people's code but same results. Please how do I fix this problem.

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>ArcGIS Developer Guide: Closest facility routing</title>
  <style>
    html, body, #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }
  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.21/esri/themes/light/main.css">
  <script src="https://js.arcgis.com/4.21/"></script>

  <script>
    require([
      "esri/config",
      "esri/Map",
      "esri/views/MapView",
      "esri/Graphic",
      "esri/layers/GraphicsLayer",
      "esri/rest/closestFacility",
      "esri/rest/support/ClosestFacilityParameters",
      "esri/rest/support/FeatureSet",
      "esri/geometry/Point",
      "esri/symbols/Symbol",
      "esri/rest/locator"
    ], (
      esriConfig,
      Map,
      MapView,
      Graphic,
      GraphicsLayer,
      closestFacility,
      ClosestFacilityParameters,
      FeatureSet,
      Point,
      Symbol,
      locator,
    )=> {

      esriConfig.apiKey = "YOUR_API_KEY";

      let placeCategory = "Gas station";

      let startSymbol = {
        type: "simple-marker",
        color: "white",
        size: "10px",
        outline: {
          color: "black",
          width: "1px",
        },
      };

      let facilitySymbol = {
        type: "simple-marker",
        color: "black",
        size: "11px",
        outline: {
          color: "white",
          width: "1px",
        },
      };

      let routeSymbol = {
        type: "simple-line",
        color: [50, 150, 255, 0.75],
        width: "5",
      };

      const locatorUrl = "http://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer";

      const closestFacilityUrl = "https://route-api.arcgis.com/arcgis/rest/services/World/ClosestFacility/NAServer/ClosestFacility_World/solveClosestFacility/";


      const routeLayer = new GraphicsLayer();
      const facilitiesLayer = new GraphicsLayer();
      const selectedFacilitiesLayer = new GraphicsLayer();
      const startLayer = new GraphicsLayer();

      let map = new Map({
        basemap: "arcgis-navigation",
        layers: [routeLayer, facilitiesLayer, selectedFacilitiesLayer, startLayer],
      });

      let view = new MapView({
        container: "viewDiv",
        map: map,
        center: [-123.18586,49.24824],
        zoom: 12,
        constraints: {
          snapToZoom: false
        }
      });

      view.popup.actions = [];

      const places = [
        ["Gas station", "gas-station"],
        ["College", "school"],
        ["Grocery", "grocery-store"],
        ["Hotel", "hotel"],
        ["Hospital", "hospital"]
      ];

      const select = document.createElement("select", "");
      select.setAttribute("class", "esri-widget esri-select");
      select.setAttribute(
        "style",
        "width: 175px; font-family: 'Avenir Next'; font-size: 1em"
      );

      places.forEach((p) => {
        const option = document.createElement("option");
        option.value = p[0];
        option.innerHTML = p[0];
        select.appendChild(option);
      });

      view.ui.add(select, "top-right");

      view.when(() => {
        addStart(view.center);
        findFacilities(view.center, true);
      });

      view.on("click", (event)=> {
        view.hitTest(event).then((response)=> {
          if (response.results.length === 1) {
            findFacilities(event.mapPoint, false);
          }
        });
      });

      select.addEventListener("change", (event) => {
        placeCategory = event.target.value;
        findFacilities(startLayer.graphics.getItemAt(0).geometry, true);
      });

      // Find places and add them to the map
      function findFacilities(pt, refresh) {
        view.popup.close();
        //startLayer.graphics.removeAll();
        addStart(pt);
        if (refresh) {
          // Add facilities
          locator
            .addressToLocations(locatorUrl,{
              location: pt,
              searchExtent: view.extent,
              categories: [placeCategory],
              maxLocations: 25,
              outFields: ["Place_addr", "PlaceName"],
              outSpatialReference: view.spatialReference
            })
            .then((results)=> {
              facilitiesLayer.removeAll();
              // Add graphics
              showFacilities(results);
              // Find closest place
              findClosestFacility(startLayer.graphics.getItemAt(0), facilitiesLayer.graphics);
            });
          } else {
            findClosestFacility(startLayer.graphics.getItemAt(0), facilitiesLayer.graphics);
          }
      }

      function addStart(pt) {
        startLayer.graphics.removeAll();
        startLayer.add(new Graphic({
          geometry: pt,
          symbol: startSymbol
        }));
      }

      function findClosestFacility(startGraphic, facilityGraphics) {
        routeLayer.removeAll();
        selectedFacilitiesLayer.removeAll();
        let params = new ClosestFacilityParameters({
          incidents: new FeatureSet({
            features: [startGraphic],
          }),
          facilities: new FeatureSet({
            features: facilityGraphics.toArray(),
          }),
          returnRoutes: true,
          returnFacilities: true,
          defaultTargetFacilityCount: 3,
        });

        closestFacility.solve(closestFacilityUrl, params).then(
          (results) => {
            results.routes.forEach((route, i)=> {
              // Add closest route
              route.symbol = routeSymbol;
              routeLayer.add(route);
              // Add closest facility
              const facility = results.facilities[route.attributes.FacilityID - 1];
              addSelectedFacility(i + 1, facility.latitude, facility.longitude, route.attributes);
            });
          },
          (error) => {
            console.log(error.details);
          }
        );
      }

      function showFacilities(results) {
        results.forEach((result,i)=> {
          facilitiesLayer.add(
            new Graphic({
              attributes: result.attributes,
              geometry: result.location,
              symbol: {
                type: "web-style",
                name: getIconName(placeCategory),
                styleName: "Esri2DPointSymbolsStyle",
              },
              popupTemplate: {
                title: "{PlaceName}",
                content: "{Place_addr}" +
                  "<br><br>" +
                  result.location.longitude.toFixed(5) +
                  "," +
                  result.location.latitude.toFixed(5),
              },
            })
          );
        });
      }

      function addSelectedFacility(number, latitude, longitude, attributes) {
        selectedFacilitiesLayer.add(new Graphic({
          symbol: {
            type: "simple-marker",
            color: [255, 255, 255,1.0],
            size: 18,
            outline: {
              color: [50,50,50],
              width: 1
            }
          },
          geometry: {
            type: "point",
            latitude: latitude,
            longitude: longitude
          },
          attributes: attributes
        }));
        selectedFacilitiesLayer.add(new Graphic({
          symbol: {
            type: "text",
            text: number,
            font: { size: 11, weight: "bold" },
            yoffset: -4,
            color: [50,50,50]
          },
        geometry: {
          type: "point",
          latitude: latitude,
          longitude: longitude
        },
        attributes: attributes
        }));
      }

      function getIconName(category) {
        let iconName;
        switch (category) {
          case "Grocery":
            iconName = "grocery-store";
            break;
          case "College":
            iconName = "school";
            break;
          case "Gas station":
            iconName = "gas-station";
            break;
          case "Hospital":
            iconName = "hospital";
            break;
          case "Hotel":
            iconName = "hotel";
            break;
        }
        return iconName;
      }
    });

</script>
</head>
<body>
  <div id="viewDiv"></div>
</body>
</html>
Tags (1)
0 Kudos
8 Replies
woriginal1
New Contributor II

Could you clarify what part of it doesn't work?

I used my own API key for your sample code and it looks like it functions as it should. If you aren't getting any routes at all then you may need to configure the Location Services for your API key. This can be done on through:

Developer's site>Dashboard>API Keys>Your App's API Key>Location Services

0 Kudos
JeffersonTotimeh
New Contributor

I'm not seeing what you talking about. Can you be more specific?

 

0 Kudos
JeffersonTotimeh
New Contributor

@ woriginal I've have configured it but it still doesn't work is it because I'm using the default API KEY?

 

0 Kudos
woriginal1
New Contributor II

You should create your own API key for your app then insert the API key into the YOUR_API_KEY part of your code below (keep the quotations):

esriConfig.apiKey = "YOUR_API_KEY";

 The above code can be found on Line 45 of your sample code.

I was able to get your sample code to work with my own API key by enabling 3 of the Location Services provided:

  • Geocoding (not stored)
  • Routing
  • Closest Facility

woriginal1_0-1634663545112.png

 

0 Kudos
JeffersonTotimeh
New Contributor

I tried enabling it but it didn't work 

0 Kudos
woriginal1
New Contributor II

@JeffersonTotimeh 

Are you getting any errors in the console?

I used the exact code you provided except with the API key I created myself that has the 3 following services enabled: Geocoding (not stored), Routing, and Closest Facility.

Make sure you have those enabled and the API key in the code replaced with your own because it works for me.

woriginal1_0-1635190781897.png

 

0 Kudos
JeffersonTotimeh
New Contributor

I did but it still didn't show 

 

0 Kudos