1 /** 2 * Unit conversion table used by measureTool to convert metric units to others, 3 * and to select appropriate units based on size of value. 4 */ 5 madrona.measureConvTable = [ 6 [ 'metric', 7 [ // distance measures 8 ['m', 1, 500 ], // switch to km at 1/2 km 9 ['km', 0.001, null ] 10 ], 11 [ // area measures 12 ['sq m', 1, 100000 ], // switch to sq km at 1/10 sq km 13 ['sq km', 0.000001, null ] 14 ] 15 ], 16 [ 'english', 17 [ // distance measures 18 ['ft', 3.2808399, 0.9144 ], // switch to yards at 1 yd 19 //['yd', 1.0936133, 804.672 ], // switch to miles at 1/2 mile 20 ['mi', 0.000621371192, null ] 21 ], 22 [ // area measures 23 ['sq ft', 10.7639104, 25899.8811 ], // switch to sq miles at 0.01 sq miles 24 //['sq yd', 1.19599005, 1294994.06 ], // switch to sq miles at 1/2 sq mile 25 ['sq mi', 0.000000386102159, null ] 26 ] 27 ], 28 [ 'nautical', 29 [ // distance measures 30 ['naut mi', 0.000539956803, null ] 31 ], 32 [ // area measures 33 ['sq naut mi', 0.00000029155335, null ] 34 ] 35 ] 36 ]; 37 38 /** 39 * Creates a new measurement tool. 40 * 41 * @constructor 42 */ 43 madrona.measureTool = function() { 44 this.placemark = null; 45 this.distTarget = null; 46 this.areaTarget = null; 47 this.gex = null; 48 this.area = 0.0; 49 this.distance = 0.0; 50 this.units = 'metric'; 51 this.area_unit = 'sq m'; 52 this.distance_unit = 'm'; 53 }; 54 55 madrona.measureTool.prototype.clear = function() 56 { 57 this.area = 0.0; 58 this.distance = 0.0; 59 60 if ( this.placemark ) 61 { 62 if ( this.distTarget ) 63 { 64 this.gex.edit.endEditLineString( this.placemark.getGeometry() ); 65 document.getElementById(this.distTarget).innerHTML = 'N/A'; 66 this.distTarget = null; 67 } 68 69 if ( this.areaTarget ) 70 { 71 this.gex.edit.endEditLineString( this.placemark.getGeometry().getOuterBoundary() ); 72 document.getElementById(this.areaTarget).innerHTML = 'N/A'; 73 this.areaTarget = null; 74 } 75 76 this.gex.dom.removeObject( this.placemark ); 77 this.placemark = null; 78 } 79 }; 80 81 /** 82 * Set the measure tool's system of measurement for reporting (still uses metric internally) 83 * @param {String} units The name of the system of measure, i.e. 'english', 'metric', 'nautical' 84 */ 85 madrona.measureTool.prototype.setUnits = function( units ) { 86 this.units = units; 87 this.updateDistance(); 88 }; 89 90 /** 91 * Start accepting user input for shape-draw. Sets callbacks to keep measures updated and to switch to edit mode on completion. 92 * @param {GEarthExtensions} gex The handle to the GEarthExtensions object 93 * @param {String} areaSpanId The id of an HTML tag whose innerHTML will be overwritten with measure results. 94 */ 95 madrona.measureTool.prototype.measureArea = function( gex, areaSpanId ) 96 { 97 var self = this; 98 this.gex = gex; 99 100 this.clear(); 101 102 this.areaTarget = areaSpanId; 103 104 this.placemark = gex.dom.addPlacemark({ 105 polygon: [], 106 style: { 107 line: { width: 2, color: '#ff0' }, 108 poly: { color: '8000ffff' } 109 } 110 }); 111 112 var drawLineStringOptions = { 113 bounce: false, 114 drawCallback: function() { 115 self.updateDistance(); 116 }, 117 finishCallback: function() { 118 var editLineStringOptions = { 119 editCallback: function() { 120 self.updateDistance(); 121 } 122 } 123 gex.edit.editLineString( self.placemark.getGeometry().getOuterBoundary(), editLineStringOptions ); 124 } 125 }; 126 127 gex.edit.drawLineString( this.placemark.getGeometry().getOuterBoundary(), drawLineStringOptions ); 128 }; 129 130 /** 131 * Start accepting user input for line-draw. Sets callbacks to keep measures updated and to switch to edit mode on completion. 132 * @param {GEarthExtensions} gex The handle to the GEarthExtensions object 133 * @param {String} distSpanId The id of an HTML tag whose innerHTML will be overwritten with measure results. 134 */ 135 madrona.measureTool.prototype.measureDistance = function( gex, distSpanId ) 136 { 137 var self = this; 138 this.gex = gex; 139 140 this.clear(); 141 142 this.distTarget = distSpanId; 143 144 this.placemark = gex.dom.addPlacemark({ 145 lineString: [], 146 style: { 147 line: { width: 2, color: '#ff0' } 148 } 149 }); 150 151 var drawLineStringOptions = { 152 bounce: false, 153 drawCallback: function() { 154 self.updateDistance(); 155 }, 156 finishCallback: function() { 157 var editLineStringOptions = { 158 editCallback: function() { 159 self.updateDistance(); 160 } 161 } 162 gex.edit.editLineString( self.placemark.getGeometry(), editLineStringOptions ); 163 } 164 }; 165 166 gex.edit.drawLineString( this.placemark.getGeometry(), drawLineStringOptions ); 167 }; 168 169 170 /** 171 * Start accepting user input for shape-draw. Sets callbacks to keep measures updated and to switch to edit mode on completion. 172 * @param {String} measure_type_str 'distance' or 'area' (assumes 'distance' if not 'area') 173 * @param {Number} value The metric value to convert to the measureTool's currently set units. 174 * @return [{Number}, {String}] The converted value and its units. 175 */ 176 madrona.measureTool.prototype.convertMetricValue = function( measure_type_str, value ) 177 { 178 var SYSTEM = 0; 179 var DISTANCE_MAPPINGS = 1; 180 var AREA_MAPPINGS = 2; 181 182 var UNIT = 0; 183 var CONVERSION_FACTOR = 1; 184 var RANGE_MAX = 2; 185 186 var measure_type = DISTANCE_MAPPINGS; 187 if ( measure_type_str == 'area' ) 188 measure_type = AREA_MAPPINGS; 189 190 for ( var system_iter = 0; system_iter < madrona.measureConvTable.length; system_iter++ ) 191 { 192 if ( madrona.measureConvTable[system_iter][SYSTEM] == this.units ) 193 { 194 for ( var unit_iter = 0; unit_iter < madrona.measureConvTable[system_iter][measure_type].length; unit_iter++ ) 195 { 196 if ( value < madrona.measureConvTable[system_iter][measure_type][unit_iter][RANGE_MAX] 197 || madrona.measureConvTable[system_iter][measure_type][unit_iter][RANGE_MAX] == null ) 198 return [ value * 199 madrona.measureConvTable[system_iter][measure_type][unit_iter][CONVERSION_FACTOR], 200 madrona.measureConvTable[system_iter][measure_type][unit_iter][UNIT] ]; 201 } 202 } 203 } 204 205 return[ 0, 'invalid units set' ]; 206 }; 207 208 /** 209 * Calculate the current measurement(s) based on the state of the measureTool's placemark object. 210 * Writes values to target HTML object and stores internally. 211 */ 212 madrona.measureTool.prototype.updateDistance = function() 213 { 214 if ( this.areaTarget ) 215 { 216 this.area = new geo.Polygon(this.placemark.getGeometry()).area(); 217 converted_val_n_unit = this.convertMetricValue( 'area', this.area ); 218 219 this.area = converted_val_n_unit[0]; 220 this.area_unit = converted_val_n_unit[1]; 221 222 document.getElementById(this.areaTarget).innerHTML = 223 this.area.toFixed(2) + ' ' + this.area_unit; 224 } 225 226 if ( this.distTarget ) 227 { 228 this.distance = new geo.Path(this.placemark.getGeometry()).distance(); 229 converted_val_n_unit = this.convertMetricValue( 'distance', this.distance ); 230 231 this.distance = converted_val_n_unit[0]; 232 this.distance_unit = converted_val_n_unit[1]; 233 234 document.getElementById(this.distTarget).innerHTML = 235 this.distance.toFixed(2) + ' ' + this.distance_unit; 236 } 237 }; 238