|
|
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 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 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 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 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]+(clat-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
|