Permalink
Browse files

adding Kalin's fusion map

  • Loading branch information...
1 parent 7d26326 commit 970765cc81652d99a2365196ac51dae2b04adf4e @cowgp cowgp committed Aug 5, 2011
Showing with 602 additions and 2 deletions.
  1. +2 −2 README.markdown
  2. +47 −0 fusionMap.php
  3. +421 −0 script/LatLonGraticule.js
  4. +124 −0 script/fusionMap.js
  5. +8 −0 style/base.css
View
4 README.markdown
@@ -7,7 +7,7 @@ How to Start?
* Ask Safecast for a copy of the database for you to run on your mysql server
* Add the following files to your build
-##/inc/fourishDB.php
+##/inc/flourishDB.php
<?php
$db = new fDatabase('mysql', 'DATABASE_NAME', 'DATABASE_USER', 'DATABASE_PASSWORD', 'localhost');
@@ -34,4 +34,4 @@ The following directories need to be write-able by your webserver for a fully fu
After CHMODing, for any of the drive maps that you want to display you need to generate them
by going to /drive/manage and clicking on the "Generate Static Files" link for every drive.
This will populate the /feeds/driveCache directory with the static JSON (and KML and CSV) files
-for each drive.
+for each drive.
View
47 fusionMap.php
@@ -0,0 +1,47 @@
+<?php
+include './inc/init.php';
+$tmpl->add('js', 'http://maps.google.com/maps/api/js?sensor=false');
+$tmpl->add('js', 'script/fusionMap.js');
+$tmpl->add('js', 'script/LatLonGraticule.js');
+$tmpl->add('css', 'http://code.google.com/apis/maps/documentation/javascript/examples/default.css');
+$tmpl->set('title', 'Safecast');
+$tmpl->set('siteName', $translations->siteName);
+$tmpl->set('siteTagline', $translations->siteTagline);
+$tmpl->set('formallyKnownAs', $translations->formallyKnownAs);
+$tmpl->set('aboutCaps', $translations->about);
+$tmpl->set('maps', $translations->maps);
+$tmpl->set('blog', $translations->blog);
+$tmpl->set('japan', $translations->japan);
+$tmpl->set('forums', $translations->forums);
+$tmpl->set('submitAReading', $translations->submitAReading);
+$tmpl->set('languageSelect', $translations->languageSelect);
+$tmpl->set('contact', $translations->contact);
+$tmpl->set('follow', $translations->follow);
+$tmpl->set('termsPolicy', $translations->termsPolicy);
+$tmpl->set('conceivedPart1', $translations->conceivedPart1);
+$tmpl->set('conceivedPart2', $translations->conceivedPart2);
+$tmpl->set('pageName', 'index');
+$tmpl->set('lang', $lang);
+
+$tmpl->place('header');
+?>
+ <div class="content">
+ <div class="relativeWrap">
+ <div class="fullScreenWidth">
+ <div id="fusion_canvas"></div>
+ <div id="info_under" style="position:absolute; top: 45px; right: 5px; height:6em; width:200em; background-color:gray; opacity:0.85;">
+ <span id="info_size" style="position:absolute; z-index:-1; visibility: hidden">__2011-07-09T18:35:29.000+0900__</span>
+ </div>
+ <div id="info" style="position:absolute; top: 45px; right: 5px; height:6em; width:200em;" onclick="go_back();"></div>
+
+ </div>
+ </div>
+ <script type="text/javascript">
+ <!--
+ document.getElementById('info_under').style.width = document.getElementById('info_size').clientWidth + 'px';
+ document.getElementById('info_under').style.height = document.getElementById('info_size').clientHeight * 4.5 + 'px';
+ document.getElementById('info').style.width = document.getElementById('info_size').clientWidth + 'px';
+ document.getElementById('info').style.height = document.getElementById('info_size').clientHeight * 4.5 + 'px';
+ //-->
+ </script>
+<?php $tmpl->place('footer') ?>
View
421 script/LatLonGraticule.js
@@ -0,0 +1,421 @@
+// This shows a lat/lon graticule on the map. Interval is automatic
+// As first seen at www.bdcc.co.uk
+// Bill Chadwick 2006
+//
+// Free for any use
+// Updated 2011-07 by Kalin KOZHUHAROV <kalin@thinrope.net> to use v3 API
+
+function LatLonGraticule(sexagesimal) {
+ this.sex_ = sexagesimal || false; // default is decimal intervals
+}
+LatLonGraticule.prototype = new google.maps.OverlayView();
+
+LatLonGraticule.prototype.onAdd = function() {
+
+ //save for later
+ this.map_ = this.getMap();
+ //array for divs used for lines and labels
+ this.divs_ = new Array();
+
+ // in v3 API, draw() is not called by default on drag or window resize, make sure it is called
+ var me = this;
+ this.listeners_ = [ google.maps.event.addListener(this.getMap(), 'center_changed',function() { me.draw(); }) ];
+}
+
+LatLonGraticule.prototype.onRemove = function() {
+
+ try{
+ var i = 0;
+ var div = this.getPanes().mapPane;
+ for(i=0; i< this.divs_.length; i++)
+ div.removeChild(this.divs_[i]);
+ }
+ catch(e){
+ }
+
+}
+
+LatLonGraticule.prototype.copy = function() {
+ return new LatLonGraticule(this.sex_);
+}
+
+// Redraw the graticule based on the current projection and zoom level
+LatLonGraticule.prototype.draw = function(force) {
+
+ //clear old
+ this.onRemove();
+
+ //best color for writing on the map
+ this.color_lat_ = "#aa00aa"; //this.map_.getCurrentMapType().getTextColor();
+ this.color_lon_ = "#aa0000"; //this.map_.getCurrentMapType().getTextColor();
+
+ //determine graticule interval
+ var bnds = this.map_.getBounds();
+
+ var l = bnds.getSouthWest().lng();
+ var b = bnds.getSouthWest().lat();
+ var t = bnds.getNorthEast().lat();
+ var r = bnds.getNorthEast().lng();
+
+ //sanity
+ if (b < -90.0)
+ b = -90.0;
+ if(t > 90.0)
+ t = 90.0;
+ if(l < -180.0)
+ l = -180.0;
+ if(r > 180.0)
+ r = 180.0;
+
+ if(l == r){
+ l = -180.0;
+ r = 180.0;
+ }
+
+ if(t == b){
+ b = -90.0;
+ t = 90.0;
+ }
+
+ //grid interval in minutes
+ var dLat = this.gridIntervalMins(t-b);
+ var dLng;
+ if(r>l)
+ dLng = this.gridIntervalMins(r-l);
+ else
+ dLng = this.gridIntervalMins((180-l)+(r+180));
+
+ //round iteration limits to the computed grid interval
+ l = Math.floor(l*60/dLng)*dLng/60;
+ b = Math.floor(b*60/dLat)*dLat/60;
+ t = Math.ceil(t*60/dLat)*dLat/60;
+ r = Math.ceil(r*60/dLng)*dLng/60;
+
+ //Sanity
+ if (b <= -90.0)
+ b = -90;
+ if(t >= 90.0)
+ t = 90;
+ if(l < -180.0)
+ l = -180.0;
+ if(r > 180.0)
+ r = 180.0;
+
+ //to whole degrees
+ dLat /= 60;
+ dLng /= 60;
+
+ //# digits after DP for decimal labels
+ var latDecs = this.gridPrecision(dLat);
+ var lonDecs = this.gridPrecision(dLng);
+
+ this.divs_ = new Array();
+ var i=0; //count inserted divs
+
+ //min and max x and y pixel values for graticule lines
+ var pbl = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(b,l));
+ var ptr = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(t,r));
+
+ this.maxX = ptr.x;
+ this.maxY = pbl.y;
+ this.minX = pbl.x;
+ this.minY = ptr.y;
+
+ var x; //coord for label
+ //labels on second column to avoid peripheral controls
+ var y = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(b+dLat+dLat,l)).y + 2; //coord for label
+
+ //pane/layer to write on
+ var mapDiv = this.getPanes().mapPane;
+
+ var lo = l; //copy to save original
+
+ if(r<lo)
+ r += 360.0;
+
+ //vertical lines
+ while(lo<=r){
+
+ var p = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(b,lo));
+
+ //line
+ this.divs_[i] = this.createVLine(p.x);
+ mapDiv.insertBefore(this.divs_[i],null);
+ i++;
+
+ //label
+ var d = document.createElement("DIV");
+ x = p.x + 3;
+ d.style.position = "absolute";
+ d.style.left = x.toString() + "px";
+ d.style.top = y.toString() + "px";
+ d.style.color = this.color_lon_;
+ d.style.fontFamily='Arial';
+ d.style.fontSize='small';
+ d.style.backgroundColor='yellow';
+ d.style.opacity=0.8;
+ if(this.sex_){
+ var degs = Math.floor(Math.abs(lo));
+ var mins = ((Math.abs(lo)-degs)*60.0).toFixed(2);
+ if(mins == "60.00"){
+ degs += 1.0;
+ mins = "0.00";
+ }
+ d.innerHTML= degs + ":" + mins;
+ }
+ else{
+ d.innerHTML = lo.toFixed(lonDecs); // only significant digits
+ }
+ if(lo<0)
+ d.title = "West (WGS84)";
+ else
+ d.title = "East (WGS84)";
+ mapDiv.insertBefore(d,null);
+
+ this.divs_[i] = d; //save for remove
+
+ i++; // next
+ lo += dLng;
+ if (lo > 180.0){
+ r -= 360.0;
+ lo -= 360.0;
+ }
+
+ }
+
+ var j = 0; // count lines
+
+ //labels on second row to avoid controls
+ x = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(b,l+dLng+dLng)).x + 3;
+
+ //horizontal lines
+ while(b<=t){
+
+ var p = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(b,l));
+
+ //line
+ if(r < l){ //draw lines across the dateline
+ this.divs_[i] = this.createHLine3(b);
+ mapDiv.insertBefore(this.divs_[i],null);
+ i++;
+ }
+ else if (r == l){ //draw lines for world scale zooms
+ this.divs_[i] = this.createHLine3(b);
+ mapDiv.insertBefore(this.divs_[i],null);
+ i++;
+ }
+ else{
+ this.divs_[i] = this.createHLine(p.y);
+ mapDiv.insertBefore(this.divs_[i],null);
+ i++;
+ }
+
+ //label
+ var d = document.createElement("DIV");
+ y = p.y + 2;
+
+ d.style.position = "absolute";
+ d.style.left = x.toString() + "px";
+ d.style.top = y.toString() + "px";
+ d.style.color = this.color_lat_;
+ d.style.fontFamily='Arial';
+ d.style.fontSize='small';
+ d.style.backgroundColor='yellow';
+ d.style.opacity=0.8;
+ if(this.sex_){
+ var degs = Math.floor(Math.abs(b));
+ var mins = ((Math.abs(b)-degs)*60.0).toFixed(2);
+ if(mins == "60.00"){
+ degs += 1.0;
+ mins = "0.00";
+ }
+ d.innerHTML= degs + ":" + mins;
+ }
+ else{
+ d.innerHTML = b.toFixed(latDecs); // only significant digits
+ }
+ if(b<0)
+ d.title = "South (WGS84)";
+ else
+ d.title = "North (WGS84)";
+
+ if(j != 2)//dont put two labels in the same place
+ {
+ mapDiv.insertBefore(d,null);
+ this.divs_[i] = d; // save for remove
+ i++;
+ }
+
+ j++; //next
+ b += dLat;
+ }
+
+}
+
+LatLonGraticule.prototype.gridIntervalMins = function(dDeg) {
+ if(this.sex_)
+ return this.gridIntervalSexMins(dDeg)
+ else
+ return this.gridIntervalDecMins(dDeg)
+}
+
+// calculate rounded graticule interval in decimals of degrees for supplied lat/lon span
+// return is in minutes
+LatLonGraticule.prototype.gridIntervalDecMins = function(dDeg) {
+
+ var dDeg = dDeg/10; // want around 10 lines in the graticule
+ dDeg *= 6000; // to minutes*100
+ dDeg = Math.ceil(dDeg)/100; // minutes and hundredths of mins
+
+ if(dDeg <= 0.06)
+ dDeg = 0.06; // 0.001 degrees
+ else if(dDeg <= 0.12)
+ dDeg = 0.12; // 0.002 degrees
+ else if(dDeg <= 0.3)
+ dDeg = 0.3; // 0.005 degrees
+ else if(dDeg <= 0.6)
+ dDeg = 0.6; // 0.01 degrees
+ else if (dDeg <= 1.2)
+ dDeg = 1.2; // 0.02 degrees
+ else if(dDeg <= 3)
+ dDeg = 3; // 0.05 degrees
+ else if(dDeg <= 6)
+ dDeg = 6; // 0.1 degrees
+ else if (dDeg <= 12)
+ dDeg = 12; // 0.2 degrees
+ else if (dDeg <= 30)
+ dDeg = 30; // 0.5
+ else if (dDeg <= 60)
+ dDeg = 60; // 1
+ else if (dDeg <= (60*2))
+ dDeg = 60*2;
+ else if (dDeg <= (60*5))
+ dDeg = 60*5;
+ else if (dDeg <= (60*10))
+ dDeg = 60*10;
+ else if (dDeg <= (60*20))
+ dDeg = 60*20;
+ else if (dDeg <= (60*30))
+ dDeg = 60*30;
+ else
+ dDeg = 60*45;
+
+ return dDeg;
+}
+
+//calculate rounded graticule interval in Minutes for supplied lat/lon span
+//return is in minutes
+LatLonGraticule.prototype.gridIntervalSexMins = function(dDeg) {
+
+ var dDeg = dDeg/10; //want around 10 lines in the graticule
+ dDeg *= 6000; //to minutes*100
+ dDeg = Math.ceil(dDeg)/100; //minutes and hundredths of mins
+
+ if(dDeg <= 0.01)
+ dDeg = 0.01; //0.01 minutes
+ else if(dDeg <= 0.02)
+ dDeg = 0.02; //0.02 minutes
+ else if(dDeg <= 0.05)
+ dDeg = 0.05; //0.05 minutes
+ else if(dDeg <= 0.1)
+ dDeg = 0.1; //0.1 minutes
+ else if(dDeg <= 0.2)
+ dDeg = 0.2; //0.2 minutes
+ else if(dDeg <= 0.5)
+ dDeg = 0.5; //0.5 minutes
+ else if(dDeg <= 1.0)
+ dDeg = 1.0; //1.0 minute
+ else if(dDeg <= 3)
+ dDeg = 3; //0.05 degrees
+ else if(dDeg <= 6)
+ dDeg = 6; //0.1 degrees
+ else if (dDeg <= 12)
+ dDeg = 12; //0.2 degrees
+ else if (dDeg <= 30)
+ dDeg = 30; //0.5
+ else if (dDeg <= 60)
+ dDeg = 60; //1
+ else if (dDeg <= (60*2))
+ dDeg = 60*2;
+ else if (dDeg <= (60*5))
+ dDeg = 60*5;
+ else if (dDeg <= (60*10))
+ dDeg = 60*10;
+ else if (dDeg <= (60*20))
+ dDeg = 60*20;
+ else if (dDeg <= (60*30))
+ dDeg = 60*30;
+ else
+ dDeg = 60*45;
+
+ return dDeg;
+
+}
+
+//calculate grid label precision from decimal grid interval in degrees
+LatLonGraticule.prototype.gridPrecision = function(dDeg) {
+
+if(dDeg < 0.01)
+ return 3;
+else if(dDeg < 0.1)
+ return 2;
+else if(dDeg < 1)
+ return 1;
+else return 0;
+
+}
+
+//returns a div that is a vertical single pixel line
+LatLonGraticule.prototype.createVLine = function(x) {
+
+ var div = document.createElement("DIV");
+ div.style.position = "absolute";
+ div.style.overflow = "hidden";
+ div.style.backgroundColor = this.color_lat_;
+ div.style.left = x + "px";
+ div.style.top = this.minY + "px";
+ div.style.width = "1px";
+ div.style.height = (this.maxY-this.minY) + "px";
+ return div;
+
+}
+
+//returns a div that is a horizontal single pixel line
+LatLonGraticule.prototype.createHLine = function(y) {
+
+ var div = document.createElement("DIV");
+ div.style.position = "absolute";
+ div.style.overflow = "hidden";
+ div.style.backgroundColor = this.color_lon_;
+ div.style.left = this.minX + "px";
+ div.style.top = y + "px";
+ div.style.width = (this.maxX-this.minX) + "px";
+ div.style.height = "1px";
+ return div;
+
+}
+
+//returns a div that is a horizontal single pixel line, across the dateline
+//we find the start and width of a 180 degree line and draw the same amount
+//to its left and right
+LatLonGraticule.prototype.createHLine3 = function(lat) {
+
+ var f = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(lat,0));
+ var t = this.getProjection().fromLatLngToDivPixel(new google.maps.LatLng(lat,180));
+ var div = document.createElement("DIV");
+ div.style.position = "absolute";
+ div.style.overflow = "hidden";
+ div.style.backgroundColor = this.color_lat_;
+ var x1 = f.x;
+ var x2 = t.x;
+ if(x2 < x1){
+ x2 = f.x;
+ x1 = t.x;
+ }
+ div.style.left = (x1-(x2-x1)) + "px";
+ div.style.top = f.y + "px";
+ div.style.width = ((x2-x1)*3) + "px";
+ div.style.height = "1px";
+ return div;
+
+}
View
124 script/fusionMap.js
@@ -0,0 +1,124 @@
+var map;
+var zoom_level = 7;
+var layer_count = 1;
+var fusion_layers = new Array(null, null, null, null);
+var fusion_listeners = new Array(null, null, null, null);
+var tables = new Array("1219714", "1122112", "1122112", "1122112"); //1122112 is empty table FIXME: how do I select a map from the dropdown?
+var grid_layer = null;
+
+
+$(document).ready(function()
+{
+ initialize_map();
+});
+
+
+function initialize_map()
+{
+ map = new google.maps.Map(document.getElementById('fusion_canvas'),
+ { center: new google.maps.LatLng(36.94111143010772, 140.60302734375),
+ zoom: zoom_level,
+ zoomControl: true,
+ panControl: false,
+ scaleControl: true,
+ mapTypeControl: false,
+ scaleControlOptions: { position: google.maps.ControlPosition.TOP_CENTER },
+ mapTypeId: google.maps.MapTypeId.ROADMAP });
+
+ var style = [{ featureType: 'all', elementType: 'all', stylers: [ { saturation: -69 } ]}];
+
+ var styledMapType = new google.maps.StyledMapType(style, { map: map, name: 'Styled Map' });
+ map.mapTypes.set('map-style', styledMapType);
+ map.setMapTypeId('map-style');
+ changeMap();
+}
+
+function changeMap()
+{
+ update_info(null); // grey-out the div initially
+ zoom = map.getZoom(); // update current zoom
+ document.getElementById('info').innerHTML = "<b>zoom: " + zoom + "</b>";
+ // create/destroy the grid
+
+ // grid_layer = new LatLonGraticule();
+ //grid_layer.setMap(map);
+
+ for (L = 0; L < layer_count; L++)
+ {
+ if (fusion_layers[L])
+ {
+ fusion_layers[L].setMap(null);
+ fusion_layers[L] = null;
+ }
+ var condition = "";
+ /*
+ if (document.getElementById('min_' + L).value > 0)
+ {
+ condition += "'DRE' >= " + document.getElementById('min_' + L).value.replace("'", "\\'");
+ if (document.getElementById('date_' + L).value !== "")
+ {
+ condition += " AND 'timestamp_JST' STARTS WITH '" + document.getElementById('date_' + L).value.replace("'", "\\'") + "'";
+ }
+ }
+ else
+ {
+ if (document.getElementById('date_' + L).value !== "")
+ {
+ condition += "'timestamp_JST' STARTS WITH '" + document.getElementById('date_' + L).value.replace("'", "\\'") + "'";
+ }
+ }
+*/
+ if ((tables[L] != "1122112") && (L == 0)) //automagcally swap tables based on zoom
+ {
+ tables[L] = (zoom > 12) ? "1219825" : "1219714" ;
+ }
+
+ fusion_layers[L] = new google.maps.FusionTablesLayer(
+ {
+ query: { select: 'lat_lon', from: tables[L], where: condition}
+ });
+
+ fusion_layers[L].setOptions({ suppressInfoWindows : true});
+ fusion_listeners[L] = google.maps.event.addListener(fusion_layers[L], 'click', function(e) { update_info(e);});
+ google.maps.event.addListener(map, 'zoom_changed', function() { if (zoom != map.getZoom()) { changeMap(); }; });
+
+ fusion_layers[L].setMap(map);
+ }
+}
+
+function update_info(e)
+{
+ var info_div = document.getElementById('info');
+ if (e)
+ {
+ info_div.innerHTML = e.infoWindowHtml;
+ //var DRE = e.infoWindowHtml.match(/([.0-9]+) μSv\/h/)[1];
+ var DRE = parseFloat(e.row.DRE.value);
+ if (DRE <= 0.2)
+ {document.getElementById("info_under").style.backgroundColor='#99ff99';}
+ else if (DRE >0.2 && DRE <= 0.5)
+ {document.getElementById("info_under").style.backgroundColor='#ffff99';}
+ else if (DRE >0.5 && DRE <= 1.0)
+ {document.getElementById("info_under").style.backgroundColor='#ff99ff';}
+ else if (DRE >1.0 && DRE <= 5.0)
+ {document.getElementById("info_under").style.backgroundColor='#9999ff';}
+ else if (DRE >5.0 && DRE <= 10.0)
+ {document.getElementById("info_under").style.backgroundColor='#ff6666';}
+ else
+ {document.getElementById("info_under").style.backgroundColor='red';}
+ }
+ else
+ {
+ document.getElementById("info_under").style.backgroundColor='gray';
+ info_div.innerHTML = '';
+ }
+}
+
+function go_back()
+{
+ var info_div = document.getElementById('info');
+ var ll = info_div.innerHTML.toString().match(/\(([\+\-\.0-9]+ [\+\-\.0-9]+)\)/)[1].split(/ /);
+ var coord = new google.maps.LatLng(ll[0], ll[1]);
+ map.setCenter(coord);
+ return true;
+}
View
8 style/base.css
@@ -1393,6 +1393,11 @@ legend {
min-height: 530px;
width:705px;
}
+#fusion_canvas{
+ height:530px;
+ min-height: 530px;
+ width:946px;
+}
#small_map_canvas{
height:320px;
min-height: 320px;
@@ -1495,6 +1500,9 @@ legend {
.halfScreenWidth{
width:465px;
}
+.fullScreenWidth{
+ width:946px;
+}
.posColumn1{
position: relative;

0 comments on commit 970765c

Please sign in to comment.