CO Flag
  comaps.org: Colorado Interactive Maps
  Powered by Google Maps

COUNTY MAPS

If you want the more technically oriented howto with Javascript/XML details, click here for that section.

Maps

Google Maps API allows for polylines to be made and overlayed onto their current system of maps through a script in your webbrowser.  They allow for more than district maps, since you can make things such as the Bolder Boulder 2006 course map.

For Google Maps, your browser will load the data.  The data is a list of latitude and longitude points that are connected together to produce an image that overlays onto the map. In the case of searchable click map, that click is translated into the latitude and longitude of that point, and the districts are returned to your browser in the same way that the district maps are loaded.  For the district maps, the marker is also distinct in that each marker is loaded from the server to display, and the color of that marker will match the district.  This data is also included in the files used to generate the districts.

Accuracy of the Maps

The maps themselves come from the data provided by the Reapportionment Committee of the State of Colorado.  I have also filtered the amount of data points to prevent slower computers from having issues with the large amount points needed to produce a district.

Demographics and Other Data

The demographic data again comes from the State of Colorado from their April 11, 2006 reports.  The Elections and About data are my own editorialized comments.  The representative and senator information were updated in April 2006, after Sen. Hanna's retirement.  There will be updates only for new websites until November 2006.

Obtaining the Data

The data will eventually be collected into three zipped files so people can download them, but I plan on getting other things completed before that begins.  This data is not compatible with Google Earth Data. Google Earth can load the data that can be download from the state, so this data is compatible with whomever would like to load it this way instead.

There are four parts to producing a map.  I should likely have some block diagram for explaining the steps, but I will just use a list.

1.  Districts XML Files
2.  Information XML Files
3.  Loading 1 and 2 with XMLhttpRequest or GXmlHttp.create
4.  Display everything

Completely Unrelated Part - Click to Find a District Map

If you have never heard of XML before, read the section below, or skip to the XML formats.


This sections just explains my XML format, so you can understand how things work.  This is a bit of a mess, considering I only partially modified it when I moved the page, leaving parts in less than optimal condition.

Quickie XML

As a quick XML tutorial, XML is formatted similar to HTML, except there are no specific rules in what can go between the < > brackets.  The example below is given with a programming relevance notation in (parenthesis).

<people>
   <dan>
        <age>39</age>
        <height>150</height>
        <IQ>108</IQ>
   </dan>
   <bob age="39" height="150" / >
</people>
Always needed, the character element (Need but ignored)
- This is child element (JS - Elements)
     39 is the content of element dan.age (JS - Attribute)


- The end of the dan element
- Attributes of bob (JS - Attribute)

From this XML is a hierarchial format makes it easy to read and parse, but fairly chunky in terms of file size.  If you choose to make it attributes instead of the nested elements, it is actually fairly compact.  CSV or something else could be used, but that is just boring, and Google Maps API provides a function to load XML files.

In either case, the data file is read the same in Javascript or in Perl, so it is a bit of a waster to the nested brackets, even though it is a bit easier to read.  It also takes up on the order of 2 time the space, and whe you are loading 40 kb files versus, 80 kb, you choose the 40.

I have decided to use demo XML structures to avoid terminology that may confuse people, since the terminology and the programming do not coincide.


District XML

District XML files are separated into single files for each district, all 107 distrcts.  Each file has only two parts to it, the markerx00 and x00 sections.  And example follows for Senate District 1.

<district>
<markers01 lng="-103" lat="39.5" number="01" color="#F00000" scale="9"/>
 <s01>
   <pt lng="-102.74761" lat="37.64364"/>
   <pt lng="-103.74761" lat="37.64364"/>
   <pt lng="-103.74761" lat="38.64364"/>
   <pt lng="-102.74761" lat="37.64364"/>
 </s01>
</district>

markersx00
contains the latitude/longitude for the marker point that appears on the screen, and is also used to center the map.  The scale is also used in the zoom of the map, while the color determines the overlayed polylines color.  x00 should be the same in both instances.

x00 is the three letter code for a district.  The 00 is the number of the district, while the x is a letter defining the district type.  The letters used are given below, along with the file name format. The file name is completely unrelated, which is a holdover from the old site.

District Type Letter Used Name of File
U.S. House h uscon01.xml
Colorado Senate s senated01.xml
Colorado House d housed01.xml
RTD Board (planned) r rtd00.xml
Regents/Board of Education Same as US House
Demo Files x demo00.xml

The x00 section contains a long list of pt elements, with lng and lat attributes, which correspong to longitude and latitude, respectively.  I use 5 places after the demical point, since any more is not noticeable in most cases. Each district in the raw file format consists of a massive amount of latitude/longitude data points, ranging from 300 to 5800 points, dependent on the amount of curvature in the boundary.

Each district was cut down through an angle/distance filter of varying degrees, dependent on the size of the district and its location. In mountain districts, where the district could exceed 5800 points, the mountain ranges used as boundaries were filtered with high angle/distance limits.  Small districts, such as metro districts, had restrivtive limits since most boundaries were streets or county lines.  The maximum points in a district is roughly 1500 points.

Information XML Files

The Information XML Files are setup differently, but have the same x00 codes.  There is just multiple files, dependent on what needs to be loaded.  A truncated example is given below.

<districts>
<s01>
  <Republican>35636</Republican >
  <Democrat>14615</Democrat >
  <Unaffiliated>18970</Unaffiliated >
  <Total_Registered>69340</Total_Registered >
</s01 >
</districts>

It is formatted in this fasion so I can read it and update it faster through Excel.  The underscores _ are removed during processing, since XML cannot have spaces within the bracketed element names.

Formatting for portions that have HTML elements are done with a web page builder, with the raw HTML translated into codes for < and > brackets.  These are converted with the Javascript program.


So, to the point people care about - making the map.

A demo map is provided of the Bolder Boulder 2006 race course. The XML file for this data is also available here.

A single Javascript is used for all district page loading.  omniload.js does all of the parsing and file formatting required.  Since I don't feel like including the demo.xml file determination within my script that is used for the rest of the site, there is omniload-demo.js.  The only thing that has changed is the xml file selection protocol.  It is clearly marked.

The beginning of the demo file is shown below:

<district>
<markerx02 lng="-104.98269" lat="39.76264" number ="5" color="#0000F0" scale="5"/>
<x02>
<pt lng="-105.2536583" lat="40.03372645"/>
<pt lng="-105.2536583" lat="40.02321082"/>
<pt lng="-105.2631855" lat="40.02137042"/>

Steps

1.  IN HTML: <body onload="makeMap(key)">
When the html file is loaded, this invokes the omniload script to generate a map.  The key in this case is x02.  Note: there is also the javacript indentifiers for the Google javascript.  See the demo page html for a description.

2.  Find the correct file
letter is used to determine the right XML file to load.  In this case, it finds demo02.xml is the correct file.  If you would have the key as s02, it will return senated02.xml.

3.  Load the XML file:
The critical step is loading the XML file.   function gets the correct XML file (senated01.xml), and loads it to memory.  In Javascript, the correct portion that is needed is the var xmlDoc = xmlhttp.XMLResponse

4.  Get the marker and create
Once loaded, the javascript finds the "marker+key" term, in this case markers01, and reads all of the variables contained there.  The lat and lng are the latitude and longitude of the marker point, the number refereces the marker icon to load.  These are used to mark the marker in the right point and put the correct HTML into the info box.  The color determines the polyline color, and the scale will set the zoom on the map, which doesn't work in IE, sometimes.

5.  Create and Overlay the Polylines
The point array that makes the district boundary is now parsed into lat/long points. These are loaded from pt indicies. After 300 points are read, the line is overlayed to the Google map. This prevents the warnings from your web browser that the Javascript file is taking too much processing time. The color line is determined from the color value in markers01.

6.  Load the data for the representative
ImportXML will load the contact information for the senator/representative of the chosen district. In a similar manner to loading the XML for a map, the data in placed into a table where the element name becomes the top line and the value within become the second line.

7.  Hiding/Showing the Rest of the Data
ImportXML also will remove data loaded if the paragraph element already contains text, allowing you to hide and show the data at will.  Thankfully, XML is cached, so this takes up no bandwith. One loads the data through ImportXML, except using different files in the case of the data that needs to be shown.  

And that is that - the Javascript file can be seen in omnidemo.js - with minor changes to prevent errors from occuring due to missing data in the demo files.  For districts, the pt elements must end and start with the same point, or else there is a gap in the line.  A simple district is shown in this demo and its XML file.

Crude Example

If we draw District 7 in the most simplistic fashion, you end up with a vaguely gun shaped district, seen below.  I will use this to explain the technique.

Image of District
Image 1.  Peter's crude drawing of District 7 for my demostration purpose.

The first thing that is done is to ensure that you are not dragging the map, which is done by checking the overlay tag in the Google Map javascript file.  If it is a clicked point, you find the location of that clicked point and do some basic error checks (making sure it is within the Colorado Border, etc.)

This is the red dot seen in the next image, Image 2.

From your clicked point, which marker (and therefore district) is closest to the point in question.  This is done from the marker points already in the XML files, except a separate file is used to prevent needless loading of data.  There are multiple marker points per district, only rural district boundaries with urban districts along the front range make for long waiting times.

Image of District
Image 2.  A sampled clicked point, shown in red, on the map.

Next comes the fun math part.  Image 3 shows a blue line, with purple marks where the blue line intersects the district boundary (black).  In a complex polygon, such as this, the number of TOTAL intersections will always equal an even number (or zero).

Image of District
Image 3.  The purple marks show the intersection points with the blue line.

However, you can determine whether a point is within that polygon by checking how many intersections are on greater than that point.  If that number is odd, then the point lies within the polygon, if even or zero, it does not.

In this case, we have three intersection on the right hand side, showing what we can visually see.  Now since a computer cannot do that, we have to use some formula to determine what we can see visually.

The Formula

The formula uses the same technique as above, except in a mathematical fashion.  This polygon is made of ten points, labeled below in Image 4.

Image of District
Image 4.  Numbered polgon vertices

The perl script knows the location of everypoint that makes up the polygons shape from the XML file.  It then takes each pair and compares them to the clicked point.

We have 6 variables here:

Red clicked point:  clat, clng
Point i: lat(i), lng(i)
Point k: lat(k), lng(k)

k is always the next point in the line, or mod(i+1, number of points).  With that notation, when i is 10, k will be 1, and complete the polygon.

The formula in psuedo code goes as follows:

polysides = number of vertices
cross = 0

for (i=0; i<polysides; i++)
 {
 k++;
 k = modulus(k, polySides)
 if (lat[i]<clat && 
lat[k]>clat || lat[k]<clat && lat[i]>clat)
  {
  if (lng[i]+(c
lat-lat[i])/(lat[k]-lat[i])*(lng[k]-lng[i]) < clng)
   {
   cross++;
   }
  }
 }
success = modulus(cross,2)


What you are doing is two conditional statements.

The first if clause will return true if the clicked latitude is inbetween the two vertices' latitudes.  If that is true, an linear interpolation is done to find the latitude at the clicked latitude.  This is compared to the clicked longitude, and if it is less than that value, cross is incremented.

After all points have been tested, the modulus of cross is found, with a 1 being a sucess and zero for failure.

There is a additional error checking needed, since if the latitudes of both vertices are the same, you get division by zero, and other fun prospects.

What is returned is a simple text string.  It contains the clicked latitude and longitude, and all three district types and the district for each.  It will return an error if it fails.

Once the Perl script is completed, Javascript again takes over.  Each district xml file is loaded sequentially, and displayed on the map.  Some additional formatting is done to pretty up the results window.  And that is about it.


Contact:  webmaster@comaps.org or peterco@gmail.com

If you have any of these data sets, I would be happy to take them and credit you for your awesome work in finding them.

Requested GIS Data
RTD Routes (All or partial)
Open Space Trails (Wherever)
Zip+4 as Lat/Long Coordinates
Other multicounty boundary districts such as RTD Board

Requested Information (Any delmited format or Excel)
Voting Places - especially voting centers (I have Denver, Weld, Douglas, and Larimer) Dem/Gov Party County Offices, or respective office locations
By State House/Senate District results for statewide races (I have county)
Any Contact Information I currently do not have for current elected officals

The geospatial data is available on the Colorado Reapportionment website, and the current district have been created from that data or replicated in the case of districts with excessive data points. This means that the map is not exact. Due to the truncation of the datapoints or from slight changes in how GIS data and Google maps data is laid out, there may be differences that are not logical. For example, in the Denver metro area, most district follow streets, wher the street itself is the boundary line. If the data from the geospatial system is slightly different that the Google map location, it will appear that the boundary is slightly off from the street. This is likely not the case. Please use Project Vote Smart for a definitive answer to your representatives.


If there are any large errors in the maps or data, please let me know and I will correct them. Certain maps follow streets in a wavy pattern, which is what was done in the geospatial data I downloaded. There is no logical reason for this. I will clean up the district lines when I complete everything, but not before.

If you have any questions, let me know I will reply to them on this site. webmaster@comaps.org