A geographic information system (GIS) can provide an excellent source of useful data in the form of a web service to be displayed to users of a web site.  GIS data can make the user experience much more valuable and increase the amount of time they will spend on your site.

The County of Pueblo can provide unique value to its citizens through GIS data integration.  Specifically, the GIS features needed for Pueblo County needed were address standardization, Google Map, Parcel map, and additional Parcel details.  These features are implemented by making web service calls to Pueblo's implementation of ArcGIS.

Address Matching Service Example

The address standardization is the first and most critical step in the use of GIS on the Pueblo County web site.  When a user enters an address, a web service call is made to the GIS server to determine the standardized address and whether or not the address is within Pueblo County.  If the address is within the county, coordinates are stored for use with Google Maps and a subsequent web service call is made to return a map of the parcel.

The form returned from the web server on the user registration and edit pages calls a javascript function when the submit button is selected.  The address data is then run through some simple validation to make sure a value is present, then the javascript sends a request to the server to complete the web service request.

$.post('/gis/address', data, function(d) { 
  $('#pueblo-gis-processing').dialog('close'); 
  if (d.error) { 
    alert(d.error.message); 
  } 
  else { 
    if (d.candidates.length > 0) { 
      pueblo_gis.data = d; 
      pueblo_gis_build_address_choices(d.candidates); 
      pueblo_gis_display_address_choices(); 
    } 
    else { 
      pueblo_gis_submit_user_form(); 
    } 
  } 
}, 'json');

The javascript code above handles the posting of data to the web server and what to do with the returned data.

function pueblo_gis_user_address() { 
  $address = $_POST['address']; 
  $city = $_POST['city']; 
  $state = $_POST['state']; 
  $zipcode = $_POST['zipcode']; 
  $path = 'web service url'; 
  $url = url($path, array( 
    'query' => array( 
      'Street' => $address, 
      'City' => $city, 
      'State' => $state, 
      'ZIP' => $zipcode, 
      'outFields' => '', 
      'f' => 'pjson', 
    ), 
    'external' => TRUE, 
  )); 
  $req = drupal_http_request($url); 
  echo $req->data; 
}

This function makes a call to the Pueblo GIS address matching service and returns the json encoded data results to the browser for further process by javascript. If there were no errors in calling the web service, a dialog is shown with the available options to select.

var h = '<div id="pueblo-gis-address-choices">'; 
  h += '<p>Select your corrected address from the list below. The score column represents the best match for the address you entered.</p>'; 
  h += '<table width="100%" border="0">' 
  h += '<tr><th>&nbsp;</th><th>Address</th><th>Score</th></tr>'; 
    for (var i = 0, ii = d.length; i < ii; i++) { 
      h += '<tr>'; 
        h += '<td><a href="javascript:pueblo_gis_select_address(' + i + ');">Select</a></td>'; 
        h += '<td>' + d[i].address + '</td>'; 
        h += '<td>' + d[i].score + '</td>'; 
      h += '</tr>'; 
    } 
  h += '</table>'; 
h += '</div>'; 
$('body').append(h); 
 
$('#pueblo-gis-address-choices').dialog({ 
  'title' : 'Address Matches', 
  'width' : 600, 
  'modal' : true, 
  'autoOpen' : true, 
  close : function () { 
    $(this).remove(); 
    pueblo_gis_submit_user_form(); 
  } 
});

The above javascript code handles the building and display of the address choices returned from the web service. Once a corrected address has been selected, the form is submitted to the server and the data is saved to the database.

if ($form_state['values']['profile_address'] != '' && $form_state['values']['profile_city'] != '' 
    && $form_state['values']['profile_state'] != '' && $form_state['values']['profile_zipcode'] != '') { 
  $location = array( 
    'street' => $form_state['values']['profile_address'], 
    'city' => $form_state['values']['profile_city'], 
    'province' => $form_state['values']['profile_state'], 
    'postal_code' => $form_state['values']['profile_zipcode'], 
  ); 
  include_once drupal_get_path('module', 'location') . '/supported/location.us.inc'; 
  if (function_exists('_location_latlon_exact_us_geocoder')) { 
    $locdata = _location_latlon_exact_us_geocoder($location); 
  } 
  if (isset($locdata) && $locdata !== NULL) { 
    $form_state['values']['gmap_xloc'] = $locdata['lat']; 
    $form_state['values']['gmap_yloc'] = $locdata['lon']; 
    $form_state['clicked_button']['#post']['gmap_xloc'] = $locdata['lat']; 
    $form_state['clicked_button']['#post']['gmap_yloc'] = $locdata['lon']; 
  } 
}

The above php code is run on submit of the registration or edit form. A function in the location module is called to geocode the address data for display on a Google Map. The coordinates to work with the Pueblo GIS system are returned by the address matching web service call and stored alongside these coordinates within the user data column in the database.

Google Maps Example

The Google Map is created by using the latitude and longitude coordinates returned by the location module when submitting the user registration or edit form. The map is displayed by utilizing the GMap module for Drupal.

if (!empty($user->gmap_xloc) && !empty($user->gmap_yloc)) { 
  $map = array( 
      'id' => 'my-address', 
      'width' => '250px', 
      'height' => '250px', 
      'latitude' => $user->gmap_xloc, 
      'longitude' => $user->gmap_yloc, 
      'zoom' => 14, 
      'maptype' => 'Map', 
      'mtc' => 'none', 
      'behavior' => array( 
        'overview' => FALSE, 
      ), 
      'markers' => array( 
        array( 
          'text' => $user->profile_address . '<br />' . $user->profile_city . ', ' . $user->profile_state . ' ' . $user->profile_zipcode, 
          'latitude' => $user->gmap_xloc, 
          'longitude' => $user->gmap_yloc, 
          'markername' => 'letters', 
          'offset' => 0, 
        ), 
      ), 
    ); 
    $gmap = theme('gmap', array('#settings' => $map)); 
}

A block is used to display the address and map data. The above code is within the display function for that block. An array is created and then passed to the gmap theme function to output the html code for the Google Map. The details of the array structure can be found in the GMap module api documentation.

Pueblo Parcel Map Example

The parcel map is displayed by making a web service call to the Pueblo County GIS server.

function pueblo_gis_get_parcel() { 
  static $req; 
  global $user; 
  if (!isset($req->data)) { 
    $path = 'GIS parcel details'; 
    $url = url($path, array( 
      'query' => array( 
        'text' => '', 
        'geometry' => $user->gis_xloc . ',' . $user->gis_yloc, 
        'geometryType' => 'esriGeometryPoint', 
        'inSR' => '', 
        'spatialRel' => 'esriSpatialRelIntersects', 
        'where' => '', 
        'returnGeometry' => 'true', 
        'outSR' => '', 
        'outFields' => 'PAR_NUM,Owner,TaxDistrict,Subdivision,Zoning,LegalDescription,LandAssessedValue,LandActualValue,PropertyTax,ZoningURL,LevyURL,AssessorURL', 
        'f' => 'pjson', 
      ), 
      'external' => TRUE, 
    )); 
    $req = drupal_http_request($url); 
    $req->data = json_decode($req->data); 
  } 
  return $req; 
} 
 
if (!$req->data->error) { 
  $x_vals = array(); 
  $y_vals = array(); 
  $vals = $req->data->features[0]->geometry->rings[0]; 
  foreach($vals as $k) { 
    $x_vals[] = $k[0]; 
    $y_vals[] = $k[1]; 
  } 
  $xmin = min($x_vals); 
  $xmax = max($x_vals); 
  $ymin = min($y_vals); 
  $ymax = max($y_vals); 
  $path = 'GIS parcel map url'; 
  $parcel_url = url($path, array( 
    'query' => array( 
      'bbox' => $xmin . ',' . $ymin . ',' . $xmax . ',' . $ymax, 
      'bboxSR' => '', 
      'layers' => '', 
      'layerdefs' => '', 
      'size' => '250,250', 
      'imageSR' => '', 
      'format' => 'png', 
      'transparent' => 'false', 
      'dpi' => '', 
      'f' => 'image', 
    ), 
    'external' => TRUE, 
  )); 
}

The pueblo_gis_get_parcel function makes a call to the Pueblo GIS web service and returns the parcel details based on the intersection of coordinates returned by the address matching service. Among the data returned are coordinates for the bounds of the parcel. These coordinates are used to determine the min and max values and then to make an additional web service call to return the parcel map.

Parcel Details

The parcel details are returned in the same web service call used to determine the bounding coordinates for the map display. The parcel details displayed include parcel number, tax disctrict, subdivision, zoning, legal description, land value, property tax, and links to additional details on levy, zoning, and parcel.