Google Maps API, Part 1

When I returned to Binghamton University at the beginning of this semester, I was immediately confronted by large amounts of construction in the middle of campus. Binghamton has been doing construction for the past 2 years, so this wasn’t that much of a surprise. However, with the construction being directly in the area of what used to be highly traveled walking paths, students and faculty were being forced to walk through other buildings to get to certain parts of campus. I’ll be honest, it took me a few days to figure out how to get around, even after being here for 4 years.

On Tuesdays and Thursdays, I have class from 2:50-5:50, a quick 10 minute break, and then another class at 6. By the time I get out of the first classes, I’m usually pretty hungry and make a run for the dining hall. In the first 2 weeks of the semester, this quick run to the dining hall meant showing up 5-10 minutes late to my 6:00 class. While making the move to get food 2 weeks ago, I was discussing with a friend in my class the quickest way to get to our next class. After quickly thinking about our options, we ended up picking a route and hoping for the best. At the same time, we joked about how nice it would be to have a website that would provide you with the quickest way to get from Point A to Point B on campus.

The next day I decided to give it a shot – I mean, the worst thing that could have happened was I tried to implement something and it wouldn’t work. Best case scenario, I develop a great new tool for Binghamton University students. I looked up the Google Maps API and quickly plugged in the latitude/longitude coordinates for several buildings on campus. I put all of the necessary code in place, selected my start point and end point, and was immediately disappointed with the results. Google only indexed the roads around campus – there were no paths on their map to go through the walkways in the middle. This meant that every route the map returned required you to walk around the edge of campus, even if the buildings were located in the middle.

After explaining to my friend Alex what I was trying to do, he helped me put together a rough idea of what would need to be done to get the map working the way I wanted it to. In short, I would need to index the middle of campus myself, and then use an algorithm to create the shortest path. Ultimately, I would only be using the Google Maps API for the picture of the map.

To make the process of indexing the middle of campus easier, I had to put together another page using the API. This page would have to have drastically different options than my first page that was just going to show the map. The basic functionality is as follows:

  1. Click on the map to place a marker – either a building, entrance/exit, or walkway via point – and at the same time add this location into a javascript object with an array attached to it. For instance, A[point1] = new Array(). This was necessary for creating a mapping of connected points, which was to come later.
  2. Each marker also had to have a click event attached to it. If it was clicked while in mode 0, the marker would have to be removed, as well as any references to it in the data structures. If it was clicked while in mode 1, it would have to be stored in memory until a second marker was clicked, at which point a connection was made between them, and again the necessary data structures were updated.

With the basic modes in place, I began putting everything together. Below you’ll find the javascript necessary to perform the operations as outlined above. If you don’t really care about the code, check out the live demo here.

?View Code JAVASCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01//EN' 'http://www.w3.org/TR/html4/strict.dtd'>
<html>
  <head>
    <!-- Information -->
    <meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1' />
    <!-- Stylesheets -->
    <link href="http://code.google.com/apis/maps/documentation/javascript/examples/default.css" rel="stylesheet" type="text/css" />
    <style>
      .left { float: right; width: 120px; }
      .clear { clear: both; }
    </style>
    <!-- Javascript -->
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript" src="jquery.iphone-switch.js"></script>
    <script type="text/javascript" src="json2.js"></script>
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript">
      var map;
      var markers = [];
      var A = {};
      var cnt = 0;
      var mode = 0; // 0 for Entering Points, 1 for Creating Graph
      var startPt = -1;
      var endPt = -1;
      var first = true;
      var polyCoordinates = [];
      var polyLine;
      var buildings = new Array();
 
      function initialize() {
        var binghamtonU = new google.maps.LatLng(42.088889,-75.966929);
        var myOptions = {
          zoom:17,
          mapTypeId: google.maps.MapTypeId.HYBRID,
          center: binghamtonU
        }
 
        map = new google.maps.Map(document.getElementById('map_canvas'), myOptions);
 
        google.maps.event.addListener(map,'click',function(event) {
          var title = event.latLng.toString();
          var pos = new google.maps.LatLng(event.latLng.lat(), event.latLng.lng());
          markers.push(new google.maps.Marker({
            position: pos, 
            map: map,
            draggable: false,
            title: title
          }));
          A[title] = new Array();
          google.maps.event.addListener(markers[cnt],'click', (function(cnt) { 
            return function() { 
              if (mode == 0) {
                var foo = markers[cnt].getTitle();
                // Remove Marker
                markers[cnt].setMap(null);
                // Delete array in A
                delete A[markers[cnt].getTitle()];
                // Delete entries in A and polyCoordinates, if any
                for (var baz = 0; baz < polyCoordinates.length; baz++) {
                  if (polyCoordinates[baz] == foo) {
                    polyCoordinates.splice(baz, 1);
                    baz = 0;
                  }
                }
                for (var qux in A) {
                  for (var baz = 0; baz < A[qux].length; baz++) {
                    if (A[qux][baz] == foo) {
                      A[qux].splice(baz, 1);
                      baz = 0;
                    }
                  }
                }
                // Update Polyline
                if (polyLine != undefined) polyLine.setMap(null);
                polyLine = new google.maps.Polyline({
                  path: polyCoordinates,
                  strokeColor: "#FF0000",
                  strokeOpacity: 1.0,
                  strokeWeight: 2
                });
                polyLine.setMap(map);
              } else {
                // If Marker already selected, remove selection
                if (markers[cnt].getIcon() == "blue-dot.png") {
                  markers[cnt].setIcon(null);
                  first ? endPt = -1 : startPt = -1;
                  first = first ? false : true;
                } else {
                  // Select Marker
                  markers[cnt].setIcon("blue-dot.png");
                  first ? startPt = cnt : endPt = cnt;
                  first = first ? false : true;
                }
                // If 2 Markers selected, add to A and update Polyline
                if (startPt != -1 && endPt != -1) {
                  // Check if relation has already been entered
                  if ($.inArray(markers[endPt].getTitle(), A[markers[startPt].getTitle()]) == -1) {
                    // Add to A in appropriate locations
                    A[markers[startPt].getTitle()].push(markers[endPt].getTitle());
                    A[markers[endPt].getTitle()].push(markers[startPt].getTitle());
                    // Create Polyline
                    var foo = new google.maps.LatLng(markers[startPt].getPosition().lat(), markers[startPt].getPosition().lng());
                    if ($.inArray(markers[startPt].getTitle(), polyCoordinates) == -1)
                      polyCoordinates.push(foo);
                    var bar = new google.maps.LatLng(markers[endPt].getPosition().lat(), markers[endPt].getPosition().lng());
                    if ($.inArray(markers[endPt].getTitle(), polyCoordinates) == -1)
                      polyCoordinates.push(bar);
                    if (polyLine != undefined) polyLine.setMap(null);
                    polyLine = new google.maps.Polyline({
                      path: polyCoordinates,
                      strokeColor: "#FF0000",
                      strokeOpacity: 1.0,
                      strokeWeight: 2
                    });
                    polyLine.setMap(map);
                  }
                  // Reset Markers to Default
                  markers[startPt].setIcon(null);
                  markers[endPt].setIcon(null);
                  // Reset Variables
                  startPt = -1; endPt = -1;
                }
              }
            };
          })(cnt));
          cnt++;
        });
      }
    </script>
  </head>
  <body onload="initialize()">
     <span style='font-size: 28px; font-family: Verdana,sans-serif; margin-left: 20px;'><a href='#' id='showA' style='color: #000;'>Done?</a></span>
     <div id='containerA' style='display: none; position: absolute; left: 50%; top: 100px; width: 800px; margin-left: -400px; z-index: 10000; background: #FFF; border: 3px solid #000; -moz-border-radius: 8px; -webkit-border-radius: 8px;'>
       <div id='returnA' style='margin-left: 20px;'></div>
     </div>
     <div class="left" id="opMode"></div>
     <div class="clear"></div>
 
     <script type="text/javascript">
       $('#opMode').iphoneSwitch("off", function() {
         mode = 1;
       },
       function() {
         mode = 0;
       },
       {
         switch_on_container_path: 'iphone_switch_container_off.png'
       });
 
       $('#showA').click(function() {
         $('#containerA').hide();
         var retA = JSON.stringify(A);
         retA += "<br><br><center><a href='#' onClick=\"$('#containerA').hide();\" style='color: #000;'>Close</a></center>";
         $('#returnA').html(retA);
         $('#containerA').show();
       });
     </script>
 
     <div id="map_canvas" style='top: 30px;'></div>
  </body>
</html>

After mapping out Binghamton using this page, I quickly realized that I had left out some crucial options necessary to use the data I was generating. Most importantly, I had no ability to save/load my data which meant that I would never be able to leave the page if I was still in the middle of finishing the map. This lead to version 2 of the code, which I’ll save for the next post. Any questions/comments, leave a message below.

This entry was written by Marc Budofsky , posted on Monday September 26 2011at 10:09 am , filed under Binghamton University, Javascript, PHP, Programming, Tutorial, Web Design . Bookmark the permalink . Post a comment below or leave a trackback: Trackback URL.

One Response to “Google Maps API, Part 1”