Category Archives: Ruby

ArcGIS Server Legend Resource Application

Building on my last post, I wanted to create a RESTful app that serves up legends from ArcGIS Server.  Ideally, this app would not need any configuration.  I thought this was very doable, since I could just put the URL information for the map service into the URL for the legend resource service by my new RESTful app.  All in all, this was much easier than even I predicted.  Oh, and I have to thank Colin Casey (again) for refactoring my code to look more Ruby-way like.

At first, I thought of using a Rails app for this, which I did stand up and get running.  However, it seemed like way too much for just a simple app.  There is no database, no real views, and not much that required all the conventions that Rails uses.  I have been hearing tons about Sinatra (including a running joke that it’s where experienced Rails developers eventually land) and how lightweight it is.  And, it is VERY lightweight.  I am not going to post any examples of Sinatra here, but a rudimentary scan of the Sinatra home page is enough to show that it’s not a lot of weight.  So, I selected Sinatra and had the app working in a  few hours (most of which were me struggling with my RubyNoob issues)  The result is legend_resource and is posted on github for your criticism and mockery.

Using LegendResource

It’s very easy to get legend_resource up and running.

  1. Pull down the code (git clone git@github.com:ruprict/legend_resource.git)
  2. Install Bundler, if it isn’t already (gem install bundler –pre)
  3. You might have to install RMagick, if you have not already.  As I alluded to in my last post, you should go the the RMagick site and figure out the best way to install it for your operating system.  (#copout)
  4. type ‘bundle install’ from the git repo root.   This should install all the necessary gems.
  5. type ‘rackup’. This should fire up the application on port 9292.

Now that the app is up and running, you can generate a legend for any map service.  For example, if you want a legend for the USA_Percent_Male map service in the Demographics folder on server.arcgisonline.com, click on this link:

http://localhost:9292/legend/server.arcgisonline.com/Demographics/USA_Percent_Male

Or create an HTML page with an img tag and set that link to the src.  Like this,

Neat, eh?

That’s it.  Neat, huh?

The URL scheme is pretty simple:  http://<webserver>/legend/<mapserver>/<mapservicepath>, where

  • webserver is whereever the legend_resource app is currently hosted.
  • mapserver is your ArcGIS server
  • mapservicepath is the path to the service on mapserver.  This works for services in the root or in a folder.  The link above was in a folder, for example.

Config Options

The configuration options for legend_resource are few right now.  Out-of-the-github, I want it to just work, and it does.   It writes the files to the local file system if you don’t tell it otherwise.  Right now, the only other option is a Google Storage for Developers backend that exists because I received my invite to it this morning.  If you want to use that, you have to:

1) Change the gstore.yaml file to add your access_key and secret.

2) Comment out the line in config.ru that sets up the GStoreLegend as the file handler.

run LegendResource
# Uncomment this line to use Google Storage (don't forget to change the gstore.yml file)')
#LegendResource.set :filehandler, GStoreLegend

I did that for a Heroku app that I am hosting at http://agslegend.heroku.com (the image above is from said Heroku app) that you are free to use to crank out a few legends.  Just bear in mind that the map service will have to be exposed to the web for my Heroku app to see it.

I hope someone else finds this useful.  It was a ton of fun to make and I learned a lot about ruby in the process.  I realize that my code is pretty noobish from the Ruby standpoint, so feel free to fork the repo, refactor, and issue pull requests.  That’s how I learn.  Also, if you’d like to see other options for the legends, hit me on github or leave a comment.

Happy Legending!

UPDATE:  One thing I don’t think I made clear is that the REST interface for this service only handles GET and DELETE.  If you HTTP GET to the url, it will either create or return the legend.  If you HTTP DELETE to it, it deletes the legend, so, the next GET will create it anew.

Advertisements

Create Legend Images from ArcGIS Server with Ruby

Recently, I needed to create a legend for an ArcGIS Server map service, and was amazed that it was still a non-trivial activity. Googling it, I saw a few posts with (what I considered to be) WAY too complicated C# code for such a simple task. Also, there is no great way to get a legend out of ArcMap (for gawd’s sake) which left me thinking “Surely, there is an easy way to do this.” (expletives removed)

I have been mucking about (again) with ruby and Rails, which is great and depressing all at the same time. I don’t use much ruby in my 9-to-5, as it’s neck-deep in Microsoft, so I try to shoehorn ruby into my work however I can. In this case, I remembered the venerable Dave Bouwman’s Ruby-Fu presentation at DevSummit (That guy is always doing the stuff I want to be doing. I don’t like him.) and that he had found a ruby library that spoke both REST and SOAP to ArcGIS Server. Being an experienced AGS dev-monkey, I also know that you can get legend and symbology information from the SOAP API. Thusly, a not-terribly-original-or-visionary idea was born: Use ruby to create a legend.

My main requirement is that it easy, something on the order of:

  1. Tell the thing the URL of my map service.
  2. Tell the thing I want a legend for the map service.
  3. Save the legend given to me by the thing to a file.

So, I got my shoehorn out and when in search of ArcGIS-flavored ruby bits.

arcserver.rb

I hunted down the slides for Dave’s preso to find the name of the ruby library he mentioned. It is arcserver.rb (github) written by Colin Casey, an extremely patient and approachable developer. I sent him a message with my Grand Legend Plan, and he say “Do it, man.” arcserver.rb already did #1 and #2 from my list above. All I had to do was #3.  Once you’ve installed the arcserver.rb gem (so, type ‘gem install arcserver.rb’ at your command prompt and watch it install all kinds of stuff….WEEE!)  (run this in irb):

require 'rubygems'
require 'arcserver'
server = ArcServer::MapServer.new("http://server.arcgisonline.com/ArcGIS/services/Demographics/ESRI_Diversity_US_2D/MapServer")
server.get_legend_info

That gives you a text representation of all the legend information for the service. So, all I had to do was loop through all the symbology and write out the symbols. Easy, right? Well, in ruby evertyhing is easy (no fanboy bias there at all). I needed an image processor, and the Old Man of Ruby Image Processors is RMagick. Now, bear in mind that I did all of this on a Windows box, but I used Cygwin. You can install RMagick 2 on Windows natively, so I hear/read, but I didn’t do it that way. However you do it, you’re gonna need RMagick, and therefore, ImageMagick. (um, everything in ruby is easy *cough*)

Got RMagick installed?? Awesome! Wasn’t that easy? Are you giving me the finger? Let’s continue. One of my goals in contributing to Colin’s project was to not pollute it too much. Being pretty much a ruby novice, I figured the best thing to do was to keep as much of my code in its own class/file, so Colin could easily remove/rewrite/laugh-and-point-at it how he saw fit. The final (cleaned and reorganized by Colin) version consists of a LegendImage class that you can see here on Github (I don’t want to post a ton of code here, it’s just unwieldy) I am not going to walk through the code, but I’d like to point out that it’s <70 lines and very readable. For a first run, I was very happy. If people use it or I find the need, the next step would be to handle options (dpi, width, height, layers to exclude, etc.) but, for now, this works. Also, I’ve heard that 10.1 is going to fix this legend issue and make it easy to create them, so putting a ton of work into this prove to be fruitless.

Now, to create a legend image, do the same thing we did above, but add (if you’ve installed RMagick since you started irb, you need to restart it):

require 'RMagick'
server.get_legend_image.write("legend.png")

which will write a PNG file called “legend.png” in the from which directory you fired up ‘irb’. Kick ass. Three lines of code (less if you chain) to get a (very basic, but usable) legend from ArcGIS Server. Here is the legend it creates using the Diversity service from ArcGISOnline.

Legend for Diversity Map Service

I thought that was pretty cool and useful. There may be other, more elegant ways out there to get a legend from an ArcGIS Server map service, and I am sure someone will mention them in the comments. Even so, I enjoyed doing this little exercise and I appreciate Colin letting me contribute to his project. Here are all the irb commands needed once you have the prerequisites and the gem installed:

require 'rubygems'
require 'RMagick'
require 'arcserver'
server = ArcServer::MapServer.new("http://server.arcgisonline.com/ArcGIS/services/Demographics/ESRI_Diversity_US_2D/MapServer")
server.get_legend_image.write("legend.png")

My next task is to use this library in a Rails-based web mapping application. Hopefully, I’ll get to that in the next week or so.

Enhanced by Zemanta