5

I want to know if I'm approaching this incorrectly. We are attempting to create an esri-based map where we add graphics to a map thru the javascript API. The points that we're adding are lat/lng coords(wkid:4326). Part of our requirements are to be able to show these items regardless of the spatialreference of the map. So we tried to use the geometry service that esri provides to project the 4326 coords to the map spatialreference.

That all works fine, unless we have a lot of points to project. If the geometry service is fed too many points at a time it returns Error:"timeout exceeded". We've split out the amount we give the service and called it iteratively, but it also errors out if we call it too many times too quickly. So we've tried to spread the interval between calls to limit that. The more I do this, the more I feel like I'm digging myself into a deep hole.

  1. Should we be approaching this problem in another way? If so, any suggestions?
  2. Should we homebrew our own geometry projection service to bypass the limitations we notice with the esri implementation?
    1. If so, any resources that would help with the required algorithms?
6
  • 1
    Where are the points coming from? If you're fetching via the REST query, you can request them to be returned in the map's spatial reference. All the SDK's should expose this, including the javascript SDK. Dec 5, 2011 at 16:59
  • The points are coming from our database, we need them converted, but as I mentioned the geometry service has limitations that I'm trying to work with
    – Jose
    Dec 5, 2011 at 17:04
  • How many points cause the service to time out? Dec 5, 2011 at 17:06
  • @Derek: 15+ points and if a request is < 30ms between each other it also errors out
    – Jose
    Dec 5, 2011 at 17:07
  • Assuming the points are coming from a web service, would a server-side solution be acceptable? If so, what is the DBMS you're running? Dec 5, 2011 at 17:08

2 Answers 2

4

You can do the reprojection on the client side (in javascript) rather than relying on a Geometry server.

The PROJ4JS library will let you do that. If you know ahead of time which projections your maps will be in, so much the better- you can prune down PROJ4JS to only include what you need. Otherwise, you can just use the whole thing.

2
  • how do I create a projection from wkid:4326 to wkid:102100? I don't know what spatialreference.org considers it?
    – Jose
    Dec 5, 2011 at 23:16
  • 1
    I think they use the "GOOGLE" code, EPSG:900913. They may also use the new EPSG code, EPSG:3857. See gis.stackexchange.com/questions/253/…
    – mwalker
    Dec 6, 2011 at 16:55
3

It shouldn't be a problem to send 15 or so points to a geometry service to be projected in a single call.

Below is an example that generates 50 "random" lat, lon points (if you run this locally, provide a URL for a proxy page) and sends them to a geometry service hosted by Esri to be projected to web mercator:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title></title>

    <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/2.5/js/dojo/dijit/themes/tundra/tundra.css">
    <script src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.5" type="text/javascript"></script>

    <script type="text/javascript">
      dojo.require("esri.map");
      dojo.require("esri.tasks.geometry");

      esri.config.defaults.io.proxyUrl = "URL TO YOUR PROXY PAGE";

      var map, gsvc, pt;

      function init() {
        var ext, layer;

        ext = esri.geometry.geographicToWebMercator(new esri.geometry.Extent(-144.13, 7.98, -52.76, 68.89, new esri.SpatialReference({wkid: 4326})));
        map = new esri.Map("map", { "extent": ext });

        layer = new esri.layers.ArcGISTiledMapServiceLayer("http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer");
        map.addLayer(layer);

        gsvc = new esri.tasks.GeometryService("http://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
        dojo.connect(map, "onClick", projectPoints);
      }

      function projectPoints(evt) {
        var pts, symbol, graphic, outSR, coordsTable;

        map.graphics.clear();
        pts = createPoints(evt.mapPoint);

        symbol = new esri.symbol.SimpleMarkerSymbol().setStyle(esri.symbol.SimpleMarkerSymbol.STYLE_DIAMOND);
        graphic = new esri.Graphic(evt.mapPoint, symbol);
        outSR = new esri.SpatialReference({ wkid: 102100 });

        map.graphics.add(graphic);

        gsvc.project(pts, outSR, function(projected) {
          console.log("gsvc returned: ", projected);
          coordsTable = "<table><thead><th>x</th><th>y</th></thead><tbody>";
          dojo.forEach(projected, function(p) {
            coordsTable += "<tr><td>" + p.x.toFixed() + "</td><td>" + p.y.toFixed() + "</td></tr>";
          });
          coordsTable += "</tbody></table>";
          dojo.byId("outCoords").innerHTML = coordsTable;
        });
      }

      function createPoints(mp) {
        var ext, width, height, numGraphics, latLonPts, i, randx, randy, pt;

        ext = map.extent;
        width = ext.xmax - ext.xmin;
        height = ext.ymax - ext.ymin;
        numGraphics = 50;
        latLonPts = [];
        for ( i=0; i<numGraphics; i++ ) {
          randx = (Math.random() * width) + ext.xmin;
          randy = (Math.random() * height) + ext.ymin,
          pt = esri.geometry.webMercatorToGeographic(new esri.geometry.Point(randx, randy, map.spatialReference));
          latLonPts.push(pt);
        }
        return latLonPts;
      }
      dojo.ready(init);
    </script>
  </head>
  <body class="tundra">
    <b>Click a location on the map to Project from LatLng -> Web Mercator:</b>
    <div id="map" style="width:600px; height:400px; border:1px solid #000;"></div>
    <div id="outCoords"></div>
  </body>
</html>

Can you post the code showing how you're talking to the geometry service?

Additionally, there are built-in client side methods to do geographic --> web mercator and web mercator --> geographic conversions. No geometry service necessary.

2
  • 1
    All i can say is I tried to send more than 15 and it would error out. The esri.geometry.geographicToWebMercator function is what got me where I needed to be. Thanks!
    – Jose
    Dec 6, 2011 at 16:07
  • Glad you got it sorted. If you're interested in pursuing this further, please email me: dswingley at esri dot com. Dec 6, 2011 at 16:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.