idfg-bthomas's blog

Resource to check your maps and webpages for the color-blind

Are you a red means "Stop" and green mean "Go" kind of person?  You might want to rethink this approach for cartography.

Here's an example of just how poorly your maps may translate for the color-blind.

So before pressing print, save an image and run it through some software to see how it translates to those with Deuteronopia, Protanopia and Tritanopia:

  • Vischeck lets you upload images to their server to view with various kinds of colorblindness.
  • Color Oracle installs on Windows, Mac and Linux for local processing on large files.

Don't forget the real world too... ask around and find coworkers who can evaluate your maps before publishing.

 

We feed so you can follow

Let us make this easy.

We're trying to make it easier for you to keep on top of what we are working on here at IFWIS.  Our work is not just to compile Natural Resources data, but to make it more open, accessible, and well, yours. 

We've just started this process with our new Roadkill App. Stripped of any personal details, save your username, all uploaded data are instantaneously available at http://fishandgame.idaho.gov/ifwis/core/view/roadkills where you are free to query, reuse and remix:

We are just getting started. Over the next year we'll be opening up

more data streams via the IFWIS Core API to allow you to remix, reuse and download IFWIS data and we needed a way to tell you about it.  Which brings us to this post.

RSS broadcasting RSS

We feed. You follow.

We've just started this little IFWIS Blog, but we realize that our projects, tastes and interest are pretty diverse. Though you are welcome to follow all our posts via RSS or email subscriptions, we expect the chatter - ranging from web server configs to PIT tagging - will get a little overwhelming.  To that end, we just added RSS Feeds for any tag (the keyword kind) and posted them in sidebar of the IFWIS Blog.  So if your passion *is* roadkill, you can follow those posts via RSS or HTML without all the extra noise.

And if you are passionate about RSS. You can follow the posts on RSS via RSS.

Enable Cross-Origin Resource Sharing to Allow Cross-Site JSON

We just discovered our open data wasn't nearly as open as we believed.  Turns out for true cross-site requests of JSON data you need to add a HTTP Reponse Header:

 Access-Control-Allow-Origin: "*"

The method one uses to do so vary widely by webserver and host.  In our case, for IIS7 the simplest method was to configure it in the web.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

For more information on the why and how as well as directions for other webservers visit enable-cors.org. The folks behind hacks.mozilla.org also offer a solid overview of Cross-site XmlHttpRequest with CORS.  Use the form at http://enable-cors.org/#check to see if your site is CORS enabled.

At this time only IFWIS Core is CORS-Enabled on IDFG's website.

About geographic transformations and how to choose the right one

I just stumbled on this most helpful post About geographic transformations and how to choose the right one by Aileen Buckley of ESRI's Mapping Center.  I even learned a few things from the comments...

I'd highly recommend the read, but if you only have a moment, read this:

So how do you choose the geographic transformation that should be used? Here are two Esri Knowledge Base articles that can help you:

HowTo: Select the correct geographic (datum) transformation when projecting between datums. This article contains links to downloadable zip files (for different versions of the software) that contain a list of all available datum transformations and their appropriate geographic areas of use.

HowTo: Determine which NAD_1983_To_WGS_1984 transformation to use.  The gist of this article is summarized below:

  1. NAD_1983_To_WGS_1984_1 - for the entire North American continent.
  2. NAD_1983_To_WGS_1984_2 - for the Aleutian islands.
  3. NAD_1983_To_WGS_1984_3 - for Hawai'i.
  4. NAD_1983_To_WGS_1984_4 - superseded by _5; this transformation method should no longer be used!
  5. NAD_1983_To_WGS_1984_5 - for the 48 contiguous United States.
  6. NAD_1983_To_WGS_1984_6 - for the Canadian province of Quebec.
  7. NAD_1983_To_WGS_1984_7 - for the Canadian province of Saskatchewan.
  8. NAD_1983_To_WGS_1984_8 - for the Canadian province of Alberta.

Note that geographic transformations work in either direction. For example, the transformation listed as NAD_1983_To_WGS_1984_5 transforms from NAD 1983 to WGS 1984, as well as from WGS 1984 to NAD 1983. When using the Project Tool, the geographic transformation is recorded in the metadata.

Using the Roadkill API to add a Google Map to your webpage

UPDATE: This demonstration is for Google Maps Javascript API Version 2. Directions are now available for using Google Maps Javascript API Version 3 with the Roadkills Controller in the IFWIS Core API.

Are you concerned about roadkill?  Would you like to display current roadkill information on your website or blog?  Now you can using the Roadkills Controller in the Core API.  Here's how in three easy steps.

 

STEP 1. Configure the URL to request

Visit http://fishandgame.idaho.gov/ifwis/core/view/roadkills and design your query using the editor.  For example, you may just be interested in one Highway section such as the first 22 miles of Highway 21.

Stripped of the empty parameters your url should now resemble: http://fishandgame.idaho.gov/ifwis/core/view/roadkills?highway=94817&mpTo=22

Now, we can add some special parameters to grab the most recent observations.  Add to your url the following &start=-730&end=now to limit your results to the last two years of observations.  The -730 is the number of days before the current date and time to include.  You may tailor this to your needs.  You can of course also use full dates, but this allows your query to be dynamic and useful in the future.

Possible parameters for date fields Observed Date (start, end) and Reported or iNsert Date (nstart, nend) include:

  • Valid dates in the format 1/10/2008
  • Now - current system datetime in Mountain Standard Time
  • Today - current day in Mountain Standard Time
  • Yesterday - previous day in Mountain Standard Time
  • Integer - positive or negative offset in days

Finally, add the kml extension, by copying the path from the kml icon or copying the following:

http://fishandgame.idaho.gov/ifwis/core/view/roadkills/list.kml?highway=94817&mpTo=22&start=-730&end=now

 

STEP 2: Add the Code

<html>
<head>
<script type="text/javascript" src="http://www.google.com/jsapi?key={YOUR GOOGLE MAPS API KEY}">
   <script src="https://www.google.com/jsapi" type="text/javascript"></script>
   <script type="text/javascript">

       google.load("jquery", "1.4.2");
       google.load("maps", "2", {
           other_params: "sensor=false"
       });

       google.setOnLoadCallback(function () {
           initializemaps();
       });

       var map;
       var geoXml;

       function initializemaps() {
           if (GBrowserIsCompatible()) {
               geoXml = new GGeoXml("http://fishandgame.idaho.gov/ifwis/core/view/roadkills/list.kml?&start=-720&end=now&highway=94817&mpFrom=0&mpTo=22&cachebuster=" + parseInt(Math.random() * 99999999, 10));
               map = new GMap2(document.getElementById("map_canvas"));
               map.setMapType(G_PHYSICAL_MAP);
               map.addMapType(G_PHYSICAL_MAP);
               map.setCenter(new GLatLng(43.58, -116.06), 12);
               map.setUIToDefault();
               map.addOverlay(geoXml);
           }
       }

   </script>
</head>
<body>
    <div id="map_canvas" style="width: 550px; height: 600px; float:left; border: 1px solid black;">Loading...</div>
</body>
</html>

Couple small configuration notes:

  • If you are putting this online you'll need to replace {YOUR GOOGLE MAPS API KEY} with your own where indicated above.  If you don't already have one, visit http://code.google.com/apis/loader/signup.html (don't worry they're free!).
  • The URL you built in Step 1 may be different, edit the following with your url.  Keep the final cachebuster part as it'll keep your data current.
    geoXml = new GGeoXml("http://fishandgame.idaho.gov/ifwis/core/view/roadkills/list.kml?&start=-720&end=now&highway=94817&mpFrom=0&mpTo=22&cachebuster=" + parseInt(Math.random() * 99999999, 10));
  • Change the zoom center and zoom level by modifying this line appropriately:
    map.setCenter(new GLatLng(43.58, -116.06), 12);
  • You may not have full access to HTML behind your pages (for example in a blog).  Simply add the <div> section and then past the <script> sections afterwards.  If you already have jquery or google maps loaded you may skip these sections.

 

Result:  View a Live Demo
Below is a static image because GMaps Ver. 2 does not support HTTPS. Click here to see and download a live demo. An HTTPS GMaps Ver. 3 demo is also available.

Example Output


STEP 3: Enjoy

That's it!  This page you have created will update itself as new observations are added to the Roadkill page.

Displaying Recent Roadkill on your Webpage

You can use the Roadkills API to display the most recently reported roadkill on your webpage.

Passionate about Mule Deer perchance?  In a couple quick steps you can add a real-time list of the Recent Mule Deer Roadkills using the magic of JQuery and the Roadkills API.  First, a demo, then the code.

Demonstration

Recent Mule Deer Roadkill

    Loading Roadkill...

The Code

<ul id="roadkillfeed">Loading Roadkill...</ul><script type="text/javascript" src="http://www.google.com/jsapi?key={YOUR GOOGLE API KEY}">
    <script type="text/javascript" src="https://www.google.com/jsapi"></script><script type="text/javascript">
        google.load("feeds", "1");

        google.setOnLoadCallback(function () {
            initializefeeds()
        });

        function initializefeeds() {
            var feed = new google.feeds.Feed("http://fishandgame.idaho.gov/ifwis/core/view/roadkills/list.rss?species=16300&start=-365&end=now&pageSize=25&cachebuster=" + parseInt(Math.random() * 99999999, 10));
            feed.setNumEntries(25);
            feed.load(function (result) {
                if (!result.error) {

                    var content = document.getElementById('roadkillfeed');
                    var html = '';

                    for (var i = 0; i < result.feed.entries.length; i++) {
                        var entry = result.feed.entries[i];

                        html += '<li><a href="' + entry.link + '">' + entry.title + '</a></li>';

                    }
                    content.innerHTML = html;
                }
            });
        }
    </script>

Substitute your Google API Key and your customized URL and you're live!  Well, not the roadkill, but the page is displaying live data as it arrives!

GIS Q&A for Professionals

The best programming question and answer site on the web now has a dedicated GIS section.

http://gis.stackexchange.com

This is a great resource to try next time you have a question that you know others have faced.  You can limit your results to just gis.stackexchange.com performing a google search by adding the parameters "site:gis.stackexchange.com" to your query.

Here's a demonstration

 

Simple HTTP Redirect with Querystring in IIS7

 

HTTP Redirect seems simple enough. Always was in IIS6 and in IIS7 there's even a button labeled HTTP Redirect that promises relative redirects.  It looks like it'll be as easy Apache finally.  That is until you try to redirect a querystring.  Then everything bombs.

Turns out it still is relatively easy, except you have to know that Microsoft changed $S$Q to $V$Q. Why? $Ss and $Gs I suspect.

And How.
In our example we'll redirect all pages under http://olddomain.com/content to http://mydomain.com/content.



  1. Pick the virtual directory you want to redirect. e.g. http://olddomain.com/content
  2. Click HTTP Redirect under IIS in the IIS management console.
  3. In the HTTP Redirect Dialog:
    • Check Redirect requests to this destination
    • Enter your new path ending with $V$Q.  e.g. http://mydomain.com$V$Q
    • Counter-intuitively check Redirect all request to exact destination (instead of relative destination)
    • Choose the appropriate Status Code (Permanent or Temporary)
  4. Apply Changes and Test

Using Drupal Feeds Module to Import Content from MS Access

Drupal Feeds Module works brilliantly, but there is a couple weird gotchas when working from MS Access to Drupal that are worth documenting:

  1. Seems self-explanatory, but since you are importing as .txt or .csv make sure you remove all carriage returns.  In MS Access this involves writing an update query and doing a replace on all Chr(10) and Chr(13).  e.g. Replace(Replace([myfield],Chr(10),"<br />"),Chr(13),"<br />")
     
  2. Although CCK Date fields import perfectly as MS Access dates, published dates do not.  This is because the published field in Drupal is a Unix Timestamp which is a quite different than Access dates. 

    To fix you need to first account for the difference between the start dates of the two time systems and then account for the fact that is decimal days and unix is seconds (or something like that.

    Formulas:

    Access -> Unix
    DateDiff("s", #1/1/1970#,[myAccessDate]) AS myUnixDate

    Unix -> Access
    DateAdd("s", [myUnixDate],
    #1/1/1970#) As myAccessDate
     

  3. Exporting from MS Access can also cause you problems with Memo fields.  Strangely, if you use Text Qualifiers your exported Memo fields will be truncated to 512 characters.  Don't do that.  There is a better way - export tables not queries and this won't happen.
     
  4. If Importing Taxonomy fields to Drupal, you'll need to edit your Taxonomies at least for now to Free Text.  You can set them back later, but at least for me, even if the Term existed it wouldn't insert unless I set it to Free Text.  Your mileage may vary.
     
  5. Apostrophes will cause you nightmares. They terminate strings early. Replace them with right apostrophes or quotes.
     
  6. Real HTML required. If you're like me and you've stored all your <HTML> as &lt;HTML&gt; in your ASP and .Net applications to get around Microsoft injection filters you'll have to undo all that silliness.

And I think that's it. If I remember any more from this evening I'll edit this post. Good times.

Finding and Replacing Special Characters in MS Access

Most special characters like Tabs and Line Break and Carriage Returns can be found and replaced in MS Access by using the character codes.  But you can't use the find and replace dialog.

Instead, author an update query and enter the following to remove tabs:
Replace([myfield],Chr(9),"")

If removing line breaks you need to replace both the line break and carriage return character:
Replace(Replace([myfield],Chr(10),""),Chr(13),"")

If editing for HTML you'd edit this to the following for HTML line breaks:
Replace(Replace([myfield],Chr(10),"<br />"),Chr(13),"<br />")

For other characters, look up the ascii character code. (use the numbers in the "Dec" column in the tables)