Commit 61370ebd1d9807353feaed6475451561c86f6d51
1 parent
56af947d
update...
Showing
13 changed files
with
3048 additions
and
18 deletions
src/main/java/com/bsth/StartCommand.java
| ... | ... | @@ -66,20 +66,19 @@ public class StartCommand implements CommandLineRunner { |
| 66 | 66 | sexec.scheduleWithFixedDelay(fixedLoadCacheThread, 60 * 10, 60 * 10, TimeUnit.SECONDS); |
| 67 | 67 | |
| 68 | 68 | |
| 69 | - /**/ //定时刷新班次信息 | |
| 70 | - sexec.scheduleWithFixedDelay(refreshScheduleCacheThread, 60, 30, TimeUnit.SECONDS); | |
| 69 | + //定时刷新班次信息 | |
| 70 | + sexec.scheduleWithFixedDelay(refreshScheduleCacheThread, 60, 30, TimeUnit.SECONDS); | |
| 71 | 71 | |
| 72 | - //gps socket client | |
| 73 | - clientApp.init(); | |
| 74 | - //gps 数据处理 | |
| 75 | - dataMainProcessor.start(); | |
| 72 | + //gps socket client | |
| 73 | + clientApp.init(); | |
| 74 | + //gps 数据处理 | |
| 75 | + dataMainProcessor.start(); | |
| 76 | 76 | |
| 77 | - //历史站点耗时数据 | |
| 78 | - historyConsumeTimeDataHandler.start(); | |
| 79 | - | |
| 80 | - //预测准确性 | |
| 81 | - accuracyDataHandler.start(); | |
| 77 | + //历史站点耗时数据 | |
| 78 | + historyConsumeTimeDataHandler.start(); | |
| 82 | 79 | |
| 80 | + //预测准确性 | |
| 81 | + accuracyDataHandler.start(); | |
| 83 | 82 | |
| 84 | 83 | |
| 85 | 84 | //historyConsumeTimeDataHandler.start();//历史站点耗时数据 | ... | ... |
src/main/java/com/bsth/controller/XmlInfoPublishController.java
| ... | ... | @@ -180,7 +180,7 @@ public class XmlInfoPublishController { |
| 180 | 180 | || "out".equals(sch.getBcType())) |
| 181 | 181 | continue;//非营运班次 |
| 182 | 182 | |
| 183 | - if (serialNo > sch.getQdzNo() && serialNo < sch.getZdzNo()) | |
| 183 | + if (serialNo >= sch.getQdzNo() && serialNo <= sch.getZdzNo()) | |
| 184 | 184 | vs.add(gps); |
| 185 | 185 | } else { |
| 186 | 186 | vs.add(gps); | ... | ... |
src/main/java/com/bsth/data/charts_data/AccuracyDataHandler.java
| ... | ... | @@ -64,6 +64,8 @@ public class AccuracyDataHandler { |
| 64 | 64 | * @param request |
| 65 | 65 | */ |
| 66 | 66 | public void mark(List<CarMonitorEntity> list, String station, HttpServletRequest request) { |
| 67 | + if (null == list || list.size() == 0) | |
| 68 | + return; | |
| 67 | 69 | CarMonitorEntity near = null; |
| 68 | 70 | |
| 69 | 71 | for (CarMonitorEntity cme : list) { | ... | ... |
src/main/resources/static/assets/css/main.css
src/main/resources/static/assets/js/geolib/geolib.elevation.js
0 → 100644
| 1 | +/*! geolib.elevation 2.0.21 by Manuel Bieh | |
| 2 | +* | |
| 3 | +* Elevation Addon for Geolib.js | |
| 4 | +* | |
| 5 | +* @author Manuel Bieh | |
| 6 | +* @url http://www.manuelbieh.com/ | |
| 7 | +* @version 2.0.21 | |
| 8 | +* @license MIT | |
| 9 | +*/ | |
| 10 | +;(function(global, geolib, undefined) { | |
| 11 | + | |
| 12 | + var elevation = { | |
| 13 | + | |
| 14 | + /*global google:true geolib:true require:true module:true elevationResult:true */ | |
| 15 | + | |
| 16 | + /** | |
| 17 | + * @param Array Collection of coords [{latitude: 51.510, longitude: 7.1321}, {latitude: 49.1238, longitude: "8° 30' W"}, ...] | |
| 18 | + * @return Array [{lat:#lat, lng:#lng, elev:#elev},....]} | |
| 19 | + */ | |
| 20 | + getElevation: function() { | |
| 21 | + if (typeof global.navigator !== 'undefined') { | |
| 22 | + this.getElevationClient.apply(this, arguments); | |
| 23 | + } else { | |
| 24 | + this.getElevationServer.apply(this, arguments); | |
| 25 | + } | |
| 26 | + }, | |
| 27 | + | |
| 28 | + | |
| 29 | + /* Optional elevation addon requires Googlemaps API JS */ | |
| 30 | + getElevationClient: function(coords, cb) { | |
| 31 | + | |
| 32 | + if (!global.google) { | |
| 33 | + throw new Error("Google maps api not loaded"); | |
| 34 | + } | |
| 35 | + | |
| 36 | + if (coords.length === 0) { | |
| 37 | + return cb(null, null); | |
| 38 | + } | |
| 39 | + | |
| 40 | + if (coords.length === 1) { | |
| 41 | + return cb(new Error("getElevation requires at least 2 points.")); | |
| 42 | + } | |
| 43 | + | |
| 44 | + var path = []; | |
| 45 | + | |
| 46 | + for(var i = 0; i < coords.length; i++) { | |
| 47 | + path.push(new google.maps.LatLng( | |
| 48 | + this.latitude(coords[i]), | |
| 49 | + this.longitude(coords[i]) | |
| 50 | + )); | |
| 51 | + } | |
| 52 | + | |
| 53 | + var positionalRequest = { | |
| 54 | + 'path': path, | |
| 55 | + 'samples': path.length | |
| 56 | + }; | |
| 57 | + | |
| 58 | + var elevationService = new google.maps.ElevationService(); | |
| 59 | + var geolib = this; | |
| 60 | + | |
| 61 | + elevationService.getElevationAlongPath(positionalRequest, function (results, status) { | |
| 62 | + geolib.elevationHandler(results, status, coords, cb); | |
| 63 | + }); | |
| 64 | + | |
| 65 | + }, | |
| 66 | + | |
| 67 | + | |
| 68 | + getElevationServer: function(coords, cb) { | |
| 69 | + | |
| 70 | + if (coords.length === 0) { | |
| 71 | + return cb(null, null); | |
| 72 | + } | |
| 73 | + | |
| 74 | + if (coords.length === 1) { | |
| 75 | + return cb(new Error("getElevation requires at least 2 points.")); | |
| 76 | + } | |
| 77 | + | |
| 78 | + var gm = require('googlemaps'); | |
| 79 | + var path = []; | |
| 80 | + | |
| 81 | + for(var i = 0; i < coords.length; i++) { | |
| 82 | + path.push( | |
| 83 | + this.latitude(coords[i]) + ',' + this.longitude(coords[i]) | |
| 84 | + ); | |
| 85 | + } | |
| 86 | + | |
| 87 | + var geolib = this; | |
| 88 | + | |
| 89 | + gm.elevationFromPath(path.join('|'), path.length, function(err, results) { | |
| 90 | + geolib.elevationHandler(results.results, results.status, coords, cb); | |
| 91 | + }); | |
| 92 | + | |
| 93 | + }, | |
| 94 | + | |
| 95 | + | |
| 96 | + elevationHandler: function(results, status, coords, cb) { | |
| 97 | + | |
| 98 | + var latsLngsElevs = []; | |
| 99 | + | |
| 100 | + if (status == "OK" ) { | |
| 101 | + | |
| 102 | + for (var i = 0; i < results.length; i++) { | |
| 103 | + latsLngsElevs.push({ | |
| 104 | + "lat": this.latitude(coords[i]), | |
| 105 | + "lng": this.longitude(coords[i]), | |
| 106 | + "elev":results[i].elevation | |
| 107 | + }); | |
| 108 | + } | |
| 109 | + | |
| 110 | + cb(null, latsLngsElevs); | |
| 111 | + | |
| 112 | + } else { | |
| 113 | + | |
| 114 | + cb(new Error("Could not get elevation using Google's API"), elevationResult.status); | |
| 115 | + | |
| 116 | + } | |
| 117 | + | |
| 118 | + }, | |
| 119 | + | |
| 120 | + | |
| 121 | + /** | |
| 122 | + * @param Array [{lat:#lat, lng:#lng, elev:#elev},....]} | |
| 123 | + * @return Number % grade | |
| 124 | + */ | |
| 125 | + getGrade: function(coords) { | |
| 126 | + | |
| 127 | + var rise = Math.abs( | |
| 128 | + this.elevation(coords[coords.length-1]) - this.elevation(coords[0]) | |
| 129 | + ); | |
| 130 | + | |
| 131 | + var run = this.getPathLength(coords); | |
| 132 | + | |
| 133 | + return Math.floor((rise/run)*100); | |
| 134 | + | |
| 135 | + }, | |
| 136 | + | |
| 137 | + | |
| 138 | + /** | |
| 139 | + * @param Array [{lat:#lat, lng:#lng, elev:#elev},....]} | |
| 140 | + * @return Object {gain:#gain, loss:#loss} | |
| 141 | + */ | |
| 142 | + getTotalElevationGainAndLoss: function(coords) { | |
| 143 | + | |
| 144 | + var gain = 0; | |
| 145 | + var loss = 0; | |
| 146 | + | |
| 147 | + for(var i = 0; i < coords.length - 1; i++) { | |
| 148 | + | |
| 149 | + var deltaElev = this.elevation(coords[i]) - this.elevation(coords[i + 1]); | |
| 150 | + | |
| 151 | + if (deltaElev > 0) { | |
| 152 | + loss += deltaElev; | |
| 153 | + } else { | |
| 154 | + gain += Math.abs(deltaElev); | |
| 155 | + } | |
| 156 | + | |
| 157 | + } | |
| 158 | + | |
| 159 | + return { | |
| 160 | + "gain": gain, | |
| 161 | + "loss": loss | |
| 162 | + }; | |
| 163 | + | |
| 164 | + } | |
| 165 | + | |
| 166 | + }; | |
| 167 | + | |
| 168 | + // Node module | |
| 169 | + if (typeof module !== 'undefined' && | |
| 170 | + typeof module.exports !== 'undefined') { | |
| 171 | + | |
| 172 | + geolib = require('geolib'); | |
| 173 | + geolib.extend(elevation); | |
| 174 | + | |
| 175 | + // AMD module | |
| 176 | + } else if (typeof define === "function" && define.amd) { | |
| 177 | + | |
| 178 | + define(["geolib"], function (geolib) { | |
| 179 | + geolib.extend(elevation); | |
| 180 | + return geolib; | |
| 181 | + }); | |
| 182 | + | |
| 183 | + // we're in a browser | |
| 184 | + } else { | |
| 185 | + | |
| 186 | + geolib.extend(elevation); | |
| 187 | + | |
| 188 | + } | |
| 189 | + | |
| 190 | +}(this, this.geolib)); | |
| 0 | 191 | \ No newline at end of file | ... | ... |
src/main/resources/static/assets/js/geolib/geolib.elevation.min.js
0 → 100644
| 1 | +/*! geolib.elevation 2.0.21 by Manuel Bieh | |
| 2 | +* | |
| 3 | +* Elevation Addon for Geolib.js | |
| 4 | +* | |
| 5 | +* @author Manuel Bieh | |
| 6 | +* @url http://www.manuelbieh.com/ | |
| 7 | +* @version 2.0.21 | |
| 8 | +* @license MIT | |
| 9 | +*/ | |
| 10 | +!function(a,b,c){var d={getElevation:function(){"undefined"!=typeof a.navigator?this.getElevationClient.apply(this,arguments):this.getElevationServer.apply(this,arguments)},getElevationClient:function(b,c){if(!a.google)throw new Error("Google maps api not loaded");if(0===b.length)return c(null,null);if(1===b.length)return c(new Error("getElevation requires at least 2 points."));for(var d=[],e=0;e<b.length;e++)d.push(new google.maps.LatLng(this.latitude(b[e]),this.longitude(b[e])));var f={path:d,samples:d.length},g=new google.maps.ElevationService,h=this;g.getElevationAlongPath(f,function(a,d){h.elevationHandler(a,d,b,c)})},getElevationServer:function(a,b){if(0===a.length)return b(null,null);if(1===a.length)return b(new Error("getElevation requires at least 2 points."));for(var c=require("googlemaps"),d=[],e=0;e<a.length;e++)d.push(this.latitude(a[e])+","+this.longitude(a[e]));var f=this;c.elevationFromPath(d.join("|"),d.length,function(c,d){f.elevationHandler(d.results,d.status,a,b)})},elevationHandler:function(a,b,c,d){var e=[];if("OK"==b){for(var f=0;f<a.length;f++)e.push({lat:this.latitude(c[f]),lng:this.longitude(c[f]),elev:a[f].elevation});d(null,e)}else d(new Error("Could not get elevation using Google's API"),elevationResult.status)},getGrade:function(a){var b=Math.abs(this.elevation(a[a.length-1])-this.elevation(a[0])),c=this.getPathLength(a);return Math.floor(b/c*100)},getTotalElevationGainAndLoss:function(a){for(var b=0,c=0,d=0;d<a.length-1;d++){var e=this.elevation(a[d])-this.elevation(a[d+1]);e>0?c+=e:b+=Math.abs(e)}return{gain:b,loss:c}}};"undefined"!=typeof module&&"undefined"!=typeof module.exports?(b=require("geolib"),b.extend(d)):"function"==typeof define&&define.amd?define(["geolib"],function(a){return a.extend(d),a}):b.extend(d)}(this,this.geolib); | |
| 0 | 11 | \ No newline at end of file | ... | ... |
src/main/resources/static/assets/js/geolib/geolib.isPointInsideRobust.js
0 → 100644
| 1 | +/*! geolib.isPointInsideRobust 2.0.21 | |
| 2 | +* !!EXPERIMENTAL!! | |
| 3 | +* | |
| 4 | +* Robust version of isPointInside for Geolib.js | |
| 5 | +* | |
| 6 | +* Based on https://github.com/mikolalysenko/robust-point-in-polygon | |
| 7 | +* by Mikola Lysenko, licensed under MIT | |
| 8 | +* | |
| 9 | +* @author Manuel Bieh | |
| 10 | +* @url http://www.manuelbieh.com/ | |
| 11 | +* @version 2.0.21 | |
| 12 | +* @license MIT | |
| 13 | +* | |
| 14 | +*/ | |
| 15 | +;(function(global, geolib, undefined) { | |
| 16 | + | |
| 17 | + var addOn = function(geolib) { | |
| 18 | + | |
| 19 | + var SPLITTER = +(Math.pow(2, 27) + 1.0); | |
| 20 | + | |
| 21 | + var NUM_EXPAND = 5; | |
| 22 | + var EPSILON = 1.1102230246251565e-16; | |
| 23 | + var ERRBOUND3 = (3.0 + 16.0 * EPSILON) * EPSILON; | |
| 24 | + var ERRBOUND4 = (7.0 + 56.0 * EPSILON) * EPSILON; | |
| 25 | + | |
| 26 | + var twoProduct = function(a, b, result) { | |
| 27 | + var x = a * b; | |
| 28 | + var c = SPLITTER * a; | |
| 29 | + var abig = c - a; | |
| 30 | + var ahi = c - abig; | |
| 31 | + var alo = a - ahi; | |
| 32 | + var d = SPLITTER * b; | |
| 33 | + var bbig = d - b; | |
| 34 | + var bhi = d - bbig; | |
| 35 | + var blo = b - bhi; | |
| 36 | + var err1 = x - (ahi * bhi); | |
| 37 | + var err2 = err1 - (alo * bhi); | |
| 38 | + var err3 = err2 - (ahi * blo); | |
| 39 | + var y = alo * blo - err3; | |
| 40 | + if(result) { | |
| 41 | + result[0] = y; | |
| 42 | + result[1] = x; | |
| 43 | + return result; | |
| 44 | + } | |
| 45 | + return [ y, x ]; | |
| 46 | + }; | |
| 47 | + | |
| 48 | + var fastTwoSum = function(a, b, result) { | |
| 49 | + var x = a + b; | |
| 50 | + var bv = x - a; | |
| 51 | + var av = x - bv; | |
| 52 | + var br = b - bv; | |
| 53 | + var ar = a - av; | |
| 54 | + if(result) { | |
| 55 | + result[0] = ar + br; | |
| 56 | + result[1] = x; | |
| 57 | + return result; | |
| 58 | + } | |
| 59 | + return [ar+br, x]; | |
| 60 | + }; | |
| 61 | + | |
| 62 | + var twoSum = fastTwoSum; | |
| 63 | + | |
| 64 | + var linearExpansionSum = function(e, f) { | |
| 65 | + var ne = e.length|0; | |
| 66 | + var nf = f.length|0; | |
| 67 | + if(ne === 1 && nf === 1) { | |
| 68 | + return scalarScalar(e[0], f[0]); | |
| 69 | + } | |
| 70 | + var n = ne + nf; | |
| 71 | + var g = new Array(n); | |
| 72 | + var count = 0; | |
| 73 | + var eptr = 0; | |
| 74 | + var fptr = 0; | |
| 75 | + var abs = Math.abs; | |
| 76 | + var ei = e[eptr]; | |
| 77 | + var ea = abs(ei); | |
| 78 | + var fi = f[fptr]; | |
| 79 | + var fa = abs(fi); | |
| 80 | + var a, b; | |
| 81 | + if(ea < fa) { | |
| 82 | + b = ei; | |
| 83 | + eptr += 1; | |
| 84 | + if(eptr < ne) { | |
| 85 | + ei = e[eptr]; | |
| 86 | + ea = abs(ei); | |
| 87 | + } | |
| 88 | + } else { | |
| 89 | + b = fi; | |
| 90 | + fptr += 1; | |
| 91 | + if(fptr < nf) { | |
| 92 | + fi = f[fptr]; | |
| 93 | + fa = abs(fi); | |
| 94 | + } | |
| 95 | + } | |
| 96 | + if((eptr < ne && ea < fa) || (fptr >= nf)) { | |
| 97 | + a = ei; | |
| 98 | + eptr += 1; | |
| 99 | + if(eptr < ne) { | |
| 100 | + ei = e[eptr]; | |
| 101 | + ea = abs(ei); | |
| 102 | + } | |
| 103 | + } else { | |
| 104 | + a = fi; | |
| 105 | + fptr += 1; | |
| 106 | + if(fptr < nf) { | |
| 107 | + fi = f[fptr]; | |
| 108 | + fa = abs(fi); | |
| 109 | + } | |
| 110 | + } | |
| 111 | + var x = a + b; | |
| 112 | + var bv = x - a; | |
| 113 | + var y = b - bv; | |
| 114 | + var q0 = y; | |
| 115 | + var q1 = x; | |
| 116 | + var _x, _bv, _av, _br, _ar; | |
| 117 | + while(eptr < ne && fptr < nf) { | |
| 118 | + if(ea < fa) { | |
| 119 | + a = ei; | |
| 120 | + eptr += 1; | |
| 121 | + if(eptr < ne) { | |
| 122 | + ei = e[eptr]; | |
| 123 | + ea = abs(ei); | |
| 124 | + } | |
| 125 | + } else { | |
| 126 | + a = fi; | |
| 127 | + fptr += 1; | |
| 128 | + if(fptr < nf) { | |
| 129 | + fi = f[fptr]; | |
| 130 | + fa = abs(fi); | |
| 131 | + } | |
| 132 | + } | |
| 133 | + b = q0; | |
| 134 | + x = a + b; | |
| 135 | + bv = x - a; | |
| 136 | + y = b - bv; | |
| 137 | + if(y) { | |
| 138 | + g[count++] = y; | |
| 139 | + } | |
| 140 | + _x = q1 + x; | |
| 141 | + _bv = _x - q1; | |
| 142 | + _av = _x - _bv; | |
| 143 | + _br = x - _bv; | |
| 144 | + _ar = q1 - _av; | |
| 145 | + q0 = _ar + _br; | |
| 146 | + q1 = _x; | |
| 147 | + } | |
| 148 | + while(eptr < ne) { | |
| 149 | + a = ei; | |
| 150 | + b = q0; | |
| 151 | + x = a + b; | |
| 152 | + bv = x - a; | |
| 153 | + y = b - bv; | |
| 154 | + if(y) { | |
| 155 | + g[count++] = y; | |
| 156 | + } | |
| 157 | + _x = q1 + x; | |
| 158 | + _bv = _x - q1; | |
| 159 | + _av = _x - _bv; | |
| 160 | + _br = x - _bv; | |
| 161 | + _ar = q1 - _av; | |
| 162 | + q0 = _ar + _br; | |
| 163 | + q1 = _x; | |
| 164 | + eptr += 1; | |
| 165 | + if(eptr < ne) { | |
| 166 | + ei = e[eptr]; | |
| 167 | + } | |
| 168 | + } | |
| 169 | + while(fptr < nf) { | |
| 170 | + a = fi; | |
| 171 | + b = q0; | |
| 172 | + x = a + b; | |
| 173 | + bv = x - a; | |
| 174 | + y = b - bv; | |
| 175 | + if(y) { | |
| 176 | + g[count++] = y; | |
| 177 | + } | |
| 178 | + _x = q1 + x; | |
| 179 | + _bv = _x - q1; | |
| 180 | + _av = _x - _bv; | |
| 181 | + _br = x - _bv; | |
| 182 | + _ar = q1 - _av; | |
| 183 | + q0 = _ar + _br; | |
| 184 | + q1 = _x; | |
| 185 | + fptr += 1; | |
| 186 | + if(fptr < nf) { | |
| 187 | + fi = f[fptr]; | |
| 188 | + } | |
| 189 | + } | |
| 190 | + if(q0) { | |
| 191 | + g[count++] = q0; | |
| 192 | + } | |
| 193 | + if(q1) { | |
| 194 | + g[count++] = q1; | |
| 195 | + } | |
| 196 | + if(!count) { | |
| 197 | + g[count++] = 0.0; | |
| 198 | + } | |
| 199 | + g.length = count; | |
| 200 | + return g; | |
| 201 | + }; | |
| 202 | + | |
| 203 | + var robustSum = linearExpansionSum; | |
| 204 | + | |
| 205 | + var scaleLinearExpansion = function(e, scale) { | |
| 206 | + var n = e.length; | |
| 207 | + if(n === 1) { | |
| 208 | + var ts = twoProduct(e[0], scale); | |
| 209 | + if(ts[0]) { | |
| 210 | + return ts; | |
| 211 | + } | |
| 212 | + return [ ts[1] ]; | |
| 213 | + } | |
| 214 | + var g = new Array(2 * n); | |
| 215 | + var q = [0.1, 0.1]; | |
| 216 | + var t = [0.1, 0.1]; | |
| 217 | + var count = 0; | |
| 218 | + twoProduct(e[0], scale, q); | |
| 219 | + if(q[0]) { | |
| 220 | + g[count++] = q[0]; | |
| 221 | + } | |
| 222 | + for(var i=1; i<n; ++i) { | |
| 223 | + twoProduct(e[i], scale, t); | |
| 224 | + var pq = q[1]; | |
| 225 | + twoSum(pq, t[0], q); | |
| 226 | + if(q[0]) { | |
| 227 | + g[count++] = q[0]; | |
| 228 | + } | |
| 229 | + var a = t[1]; | |
| 230 | + var b = q[1]; | |
| 231 | + var x = a + b; | |
| 232 | + var bv = x - a; | |
| 233 | + var y = b - bv; | |
| 234 | + q[1] = x; | |
| 235 | + if(y) { | |
| 236 | + g[count++] = y; | |
| 237 | + } | |
| 238 | + } | |
| 239 | + if(q[1]) { | |
| 240 | + g[count++] = q[1]; | |
| 241 | + } | |
| 242 | + if(count === 0) { | |
| 243 | + g[count++] = 0.0; | |
| 244 | + } | |
| 245 | + g.length = count; | |
| 246 | + return g; | |
| 247 | + }; | |
| 248 | + | |
| 249 | + var robustScale = scaleLinearExpansion; | |
| 250 | + | |
| 251 | + var scalarScalar = function(a, b) { | |
| 252 | + var x = a + b; | |
| 253 | + var bv = x - a; | |
| 254 | + var av = x - bv; | |
| 255 | + var br = b - bv; | |
| 256 | + var ar = a - av; | |
| 257 | + var y = ar + br; | |
| 258 | + if(y) { | |
| 259 | + return [y, x]; | |
| 260 | + } | |
| 261 | + return [x]; | |
| 262 | + }; | |
| 263 | + | |
| 264 | + var robustSubtract = function(e, f) { | |
| 265 | + var ne = e.length|0; | |
| 266 | + var nf = f.length|0; | |
| 267 | + if(ne === 1 && nf === 1) { | |
| 268 | + return scalarScalar(e[0], -f[0]); | |
| 269 | + } | |
| 270 | + var n = ne + nf; | |
| 271 | + var g = new Array(n); | |
| 272 | + var count = 0; | |
| 273 | + var eptr = 0; | |
| 274 | + var fptr = 0; | |
| 275 | + var abs = Math.abs; | |
| 276 | + var ei = e[eptr]; | |
| 277 | + var ea = abs(ei); | |
| 278 | + var fi = -f[fptr]; | |
| 279 | + var fa = abs(fi); | |
| 280 | + var a, b; | |
| 281 | + if(ea < fa) { | |
| 282 | + b = ei; | |
| 283 | + eptr += 1; | |
| 284 | + if(eptr < ne) { | |
| 285 | + ei = e[eptr]; | |
| 286 | + ea = abs(ei); | |
| 287 | + } | |
| 288 | + } else { | |
| 289 | + b = fi; | |
| 290 | + fptr += 1; | |
| 291 | + if(fptr < nf) { | |
| 292 | + fi = -f[fptr]; | |
| 293 | + fa = abs(fi); | |
| 294 | + } | |
| 295 | + } | |
| 296 | + if((eptr < ne && ea < fa) || (fptr >= nf)) { | |
| 297 | + a = ei; | |
| 298 | + eptr += 1; | |
| 299 | + if(eptr < ne) { | |
| 300 | + ei = e[eptr]; | |
| 301 | + ea = abs(ei); | |
| 302 | + } | |
| 303 | + } else { | |
| 304 | + a = fi; | |
| 305 | + fptr += 1; | |
| 306 | + if(fptr < nf) { | |
| 307 | + fi = -f[fptr]; | |
| 308 | + fa = abs(fi); | |
| 309 | + } | |
| 310 | + } | |
| 311 | + var x = a + b; | |
| 312 | + var bv = x - a; | |
| 313 | + var y = b - bv; | |
| 314 | + var q0 = y; | |
| 315 | + var q1 = x; | |
| 316 | + var _x, _bv, _av, _br, _ar; | |
| 317 | + while(eptr < ne && fptr < nf) { | |
| 318 | + if(ea < fa) { | |
| 319 | + a = ei; | |
| 320 | + eptr += 1; | |
| 321 | + if(eptr < ne) { | |
| 322 | + ei = e[eptr]; | |
| 323 | + ea = abs(ei); | |
| 324 | + } | |
| 325 | + } else { | |
| 326 | + a = fi; | |
| 327 | + fptr += 1; | |
| 328 | + if(fptr < nf) { | |
| 329 | + fi = -f[fptr]; | |
| 330 | + fa = abs(fi); | |
| 331 | + } | |
| 332 | + } | |
| 333 | + b = q0; | |
| 334 | + x = a + b; | |
| 335 | + bv = x - a; | |
| 336 | + y = b - bv; | |
| 337 | + if(y) { | |
| 338 | + g[count++] = y; | |
| 339 | + } | |
| 340 | + _x = q1 + x; | |
| 341 | + _bv = _x - q1; | |
| 342 | + _av = _x - _bv; | |
| 343 | + _br = x - _bv; | |
| 344 | + _ar = q1 - _av; | |
| 345 | + q0 = _ar + _br; | |
| 346 | + q1 = _x; | |
| 347 | + } | |
| 348 | + while(eptr < ne) { | |
| 349 | + a = ei; | |
| 350 | + b = q0; | |
| 351 | + x = a + b; | |
| 352 | + bv = x - a; | |
| 353 | + y = b - bv; | |
| 354 | + if(y) { | |
| 355 | + g[count++] = y; | |
| 356 | + } | |
| 357 | + _x = q1 + x; | |
| 358 | + _bv = _x - q1; | |
| 359 | + _av = _x - _bv; | |
| 360 | + _br = x - _bv; | |
| 361 | + _ar = q1 - _av; | |
| 362 | + q0 = _ar + _br; | |
| 363 | + q1 = _x; | |
| 364 | + eptr += 1; | |
| 365 | + if(eptr < ne) { | |
| 366 | + ei = e[eptr]; | |
| 367 | + } | |
| 368 | + } | |
| 369 | + while(fptr < nf) { | |
| 370 | + a = fi; | |
| 371 | + b = q0; | |
| 372 | + x = a + b; | |
| 373 | + bv = x - a; | |
| 374 | + y = b - bv; | |
| 375 | + if(y) { | |
| 376 | + g[count++] = y; | |
| 377 | + } | |
| 378 | + _x = q1 + x; | |
| 379 | + _bv = _x - q1; | |
| 380 | + _av = _x - _bv; | |
| 381 | + _br = x - _bv; | |
| 382 | + _ar = q1 - _av; | |
| 383 | + q0 = _ar + _br; | |
| 384 | + q1 = _x; | |
| 385 | + fptr += 1; | |
| 386 | + if(fptr < nf) { | |
| 387 | + fi = -f[fptr]; | |
| 388 | + } | |
| 389 | + } | |
| 390 | + if(q0) { | |
| 391 | + g[count++] = q0; | |
| 392 | + } | |
| 393 | + if(q1) { | |
| 394 | + g[count++] = q1; | |
| 395 | + } | |
| 396 | + if(!count) { | |
| 397 | + g[count++] = 0.0; | |
| 398 | + } | |
| 399 | + g.length = count; | |
| 400 | + return g; | |
| 401 | + }; | |
| 402 | + | |
| 403 | + var cofactor = function(m, c) { | |
| 404 | + var result = new Array(m.length-1); | |
| 405 | + for(var i=1; i<m.length; ++i) { | |
| 406 | + var r = result[i-1] = new Array(m.length-1); | |
| 407 | + for(var j=0,k=0; j<m.length; ++j) { | |
| 408 | + if(j === c) { | |
| 409 | + continue; | |
| 410 | + } | |
| 411 | + r[k++] = m[i][j]; | |
| 412 | + } | |
| 413 | + } | |
| 414 | + return result; | |
| 415 | + }; | |
| 416 | + | |
| 417 | + var matrix = function(n) { | |
| 418 | + var result = new Array(n); | |
| 419 | + for(var i=0; i<n; ++i) { | |
| 420 | + result[i] = new Array(n); | |
| 421 | + for(var j=0; j<n; ++j) { | |
| 422 | + result[i][j] = ["m", j, "[", (n-i-1), "]"].join(""); | |
| 423 | + } | |
| 424 | + } | |
| 425 | + return result; | |
| 426 | + }; | |
| 427 | + | |
| 428 | + var sign = function(n) { | |
| 429 | + if(n & 1) { | |
| 430 | + return "-"; | |
| 431 | + } | |
| 432 | + return ""; | |
| 433 | + }; | |
| 434 | + | |
| 435 | + var generateSum = function(expr) { | |
| 436 | + if(expr.length === 1) { | |
| 437 | + return expr[0]; | |
| 438 | + } else if(expr.length === 2) { | |
| 439 | + return ["sum(", expr[0], ",", expr[1], ")"].join(""); | |
| 440 | + } else { | |
| 441 | + var m = expr.length>>1; | |
| 442 | + return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join(""); | |
| 443 | + } | |
| 444 | + }; | |
| 445 | + | |
| 446 | + var determinant = function(m) { | |
| 447 | + if(m.length === 2) { | |
| 448 | + return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")]; | |
| 449 | + } else { | |
| 450 | + var expr = []; | |
| 451 | + for(var i=0; i<m.length; ++i) { | |
| 452 | + expr.push(["scale(", generateSum(determinant(cofactor(m, i))), ",", sign(i), m[0][i], ")"].join("")); | |
| 453 | + } | |
| 454 | + return expr; | |
| 455 | + } | |
| 456 | + }; | |
| 457 | + | |
| 458 | + var orientation = function(n) { | |
| 459 | + var pos = []; | |
| 460 | + var neg = []; | |
| 461 | + var m = matrix(n); | |
| 462 | + var args = []; | |
| 463 | + for(var i=0; i<n; ++i) { | |
| 464 | + if((i&1)===0) { | |
| 465 | + pos.push.apply(pos, determinant(cofactor(m, i))); | |
| 466 | + } else { | |
| 467 | + neg.push.apply(neg, determinant(cofactor(m, i))); | |
| 468 | + } | |
| 469 | + args.push("m" + i); | |
| 470 | + } | |
| 471 | + var posExpr = generateSum(pos); | |
| 472 | + var negExpr = generateSum(neg); | |
| 473 | + var funcName = "orientation" + n + "Exact"; | |
| 474 | + var code = [ | |
| 475 | + "function ", | |
| 476 | + funcName, | |
| 477 | + "(", args.join(), "){var p=", | |
| 478 | + posExpr, | |
| 479 | + ",n=", | |
| 480 | + negExpr, | |
| 481 | + ",d=sub(p,n);return d[d.length-1];};return ", | |
| 482 | + funcName | |
| 483 | + ].join(""); | |
| 484 | + var proc = new Function("sum", "prod", "scale", "sub", code); | |
| 485 | + return proc(robustSum, twoProduct, robustScale, robustSubtract); | |
| 486 | + }; | |
| 487 | + | |
| 488 | + var orient; | |
| 489 | + var orientation3Exact = orientation(3); | |
| 490 | + var orientation4Exact = orientation(4); | |
| 491 | + | |
| 492 | + var CACHED = [ | |
| 493 | + function orientation0() { return 0; }, | |
| 494 | + function orientation1() { return 0; }, | |
| 495 | + function orientation2(a, b) { | |
| 496 | + return b[0] - a[0]; | |
| 497 | + }, | |
| 498 | + function orientation3(a, b, c) { | |
| 499 | + var l = (a[1] - c[1]) * (b[0] - c[0]); | |
| 500 | + var r = (a[0] - c[0]) * (b[1] - c[1]); | |
| 501 | + var det = l - r; | |
| 502 | + var s; | |
| 503 | + if(l > 0) { | |
| 504 | + if(r <= 0) { | |
| 505 | + return det; | |
| 506 | + } else { | |
| 507 | + s = l + r; | |
| 508 | + } | |
| 509 | + } else if(l < 0) { | |
| 510 | + if(r >= 0) { | |
| 511 | + return det; | |
| 512 | + } else { | |
| 513 | + s = -(l + r); | |
| 514 | + } | |
| 515 | + } else { | |
| 516 | + return det; | |
| 517 | + } | |
| 518 | + var tol = ERRBOUND3 * s; | |
| 519 | + if(det >= tol || det <= -tol) { | |
| 520 | + return det; | |
| 521 | + } | |
| 522 | + return orientation3Exact(a, b, c); | |
| 523 | + }, | |
| 524 | + function orientation4(a,b,c,d) { | |
| 525 | + var adx = a[0] - d[0]; | |
| 526 | + var bdx = b[0] - d[0]; | |
| 527 | + var cdx = c[0] - d[0]; | |
| 528 | + var ady = a[1] - d[1]; | |
| 529 | + var bdy = b[1] - d[1]; | |
| 530 | + var cdy = c[1] - d[1]; | |
| 531 | + var adz = a[2] - d[2]; | |
| 532 | + var bdz = b[2] - d[2]; | |
| 533 | + var cdz = c[2] - d[2]; | |
| 534 | + var bdxcdy = bdx * cdy; | |
| 535 | + var cdxbdy = cdx * bdy; | |
| 536 | + var cdxady = cdx * ady; | |
| 537 | + var adxcdy = adx * cdy; | |
| 538 | + var adxbdy = adx * bdy; | |
| 539 | + var bdxady = bdx * ady; | |
| 540 | + var det = adz * (bdxcdy - cdxbdy) + | |
| 541 | + bdz * (cdxady - adxcdy) + | |
| 542 | + cdz * (adxbdy - bdxady); | |
| 543 | + var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) + | |
| 544 | + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) + | |
| 545 | + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz); | |
| 546 | + var tol = ERRBOUND4 * permanent; | |
| 547 | + if ((det > tol) || (-det > tol)) { | |
| 548 | + return det; | |
| 549 | + } | |
| 550 | + return orientation4Exact(a,b,c,d); | |
| 551 | + } | |
| 552 | + ]; | |
| 553 | + | |
| 554 | + var slowOrient = function(args) { | |
| 555 | + var proc = CACHED[args.length]; | |
| 556 | + if(!proc) { | |
| 557 | + proc = CACHED[args.length] = orientation(args.length); | |
| 558 | + } | |
| 559 | + return proc.apply(undefined, args); | |
| 560 | + }; | |
| 561 | + | |
| 562 | + var generateOrientationProc = function() { | |
| 563 | + while(CACHED.length <= NUM_EXPAND) { | |
| 564 | + CACHED.push(orientation(CACHED.length)); | |
| 565 | + } | |
| 566 | + var args = []; | |
| 567 | + var procArgs = ["slow"]; | |
| 568 | + for(var i=0; i<=NUM_EXPAND; ++i) { | |
| 569 | + args.push("a" + i); | |
| 570 | + procArgs.push("o" + i); | |
| 571 | + } | |
| 572 | + var code = [ | |
| 573 | + "function getOrientation(", | |
| 574 | + args.join(), | |
| 575 | + "){switch(arguments.length){case 0:case 1:return 0;" | |
| 576 | + ]; | |
| 577 | + for(i=2; i<=NUM_EXPAND; ++i) { | |
| 578 | + code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");"); | |
| 579 | + } | |
| 580 | + code.push("}var s=new Array(arguments.length);for(var i=0;i<arguments.length;++i){s[i]=arguments[i]};return slow(s);}return getOrientation"); | |
| 581 | + procArgs.push(code.join("")); | |
| 582 | + | |
| 583 | + var proc = Function.apply(undefined, procArgs); | |
| 584 | + orient = proc.apply(undefined, [slowOrient].concat(CACHED)); | |
| 585 | + for(i=0; i<=NUM_EXPAND; ++i) { | |
| 586 | + orient[i] = CACHED[i]; | |
| 587 | + } | |
| 588 | + }; | |
| 589 | + | |
| 590 | + generateOrientationProc(); | |
| 591 | + | |
| 592 | + var robustPointInPolygon = function(vs, point) { | |
| 593 | + // transform from geolib format to array syntax | |
| 594 | + var x = geolib.longitude(point); | |
| 595 | + var y = geolib.latitude(point); | |
| 596 | + var coords = vs.map(function(coords) { | |
| 597 | + return [geolib.longitude(coords), geolib.latitude(coords)]; | |
| 598 | + }); | |
| 599 | + | |
| 600 | + vs = coords; | |
| 601 | + point = [x,y]; | |
| 602 | + | |
| 603 | + var n = vs.length; | |
| 604 | + var inside = 1; | |
| 605 | + var lim = n; | |
| 606 | + | |
| 607 | + var s, c, yk, px, p; | |
| 608 | + | |
| 609 | + for(var i = 0, j = n-1; i<lim; j=i++) { | |
| 610 | + var a = vs[i]; | |
| 611 | + var b = vs[j]; | |
| 612 | + var yi = a[1]; | |
| 613 | + var yj = b[1]; | |
| 614 | + if(yj < yi) { | |
| 615 | + if(yj < y && y < yi) { | |
| 616 | + s = orient(a, b, point); | |
| 617 | + if(s === 0) { | |
| 618 | + return 0; | |
| 619 | + } else { | |
| 620 | + inside ^= (0 < s)|0; | |
| 621 | + } | |
| 622 | + } else if(y === yi) { | |
| 623 | + c = vs[(i+1)%n]; | |
| 624 | + yk = c[1]; | |
| 625 | + if(yi < yk) { | |
| 626 | + s = orient(a, b, point); | |
| 627 | + if(s === 0) { | |
| 628 | + return 0; | |
| 629 | + } else { | |
| 630 | + inside ^= (0 < s)|0; | |
| 631 | + } | |
| 632 | + } | |
| 633 | + } | |
| 634 | + } else if(yi < yj) { | |
| 635 | + if(yi < y && y < yj) { | |
| 636 | + s = orient(a, b, point); | |
| 637 | + if(s === 0) { | |
| 638 | + return 0; | |
| 639 | + } else { | |
| 640 | + inside ^= (s < 0)|0; | |
| 641 | + } | |
| 642 | + } else if(y === yi) { | |
| 643 | + c = vs[(i+1)%n]; | |
| 644 | + yk = c[1]; | |
| 645 | + if(yk < yi) { | |
| 646 | + s = orient(a, b, point); | |
| 647 | + if(s === 0) { | |
| 648 | + return 0; | |
| 649 | + } else { | |
| 650 | + inside ^= (s < 0)|0; | |
| 651 | + } | |
| 652 | + } | |
| 653 | + } | |
| 654 | + } else if(y === yi) { | |
| 655 | + var x0 = Math.min(a[0], b[0]); | |
| 656 | + var x1 = Math.max(a[0], b[0]); | |
| 657 | + if(i === 0) { | |
| 658 | + while(j>0) { | |
| 659 | + var k = (j+n-1)%n; | |
| 660 | + p = vs[k]; | |
| 661 | + if(p[1] !== y) { | |
| 662 | + break; | |
| 663 | + } | |
| 664 | + px = p[0]; | |
| 665 | + x0 = Math.min(x0, px); | |
| 666 | + x1 = Math.max(x1, px); | |
| 667 | + j = k; | |
| 668 | + } | |
| 669 | + if(j === 0) { | |
| 670 | + if(x0 <= x && x <= x1) { | |
| 671 | + return 0; | |
| 672 | + } | |
| 673 | + return 1; | |
| 674 | + } | |
| 675 | + lim = j+1; | |
| 676 | + } | |
| 677 | + var y0 = vs[(j+n-1)%n][1]; | |
| 678 | + while(i+1<lim) { | |
| 679 | + p = vs[i+1]; | |
| 680 | + if(p[1] !== y) { | |
| 681 | + break; | |
| 682 | + } | |
| 683 | + px = p[0]; | |
| 684 | + x0 = Math.min(x0, px); | |
| 685 | + x1 = Math.max(x1, px); | |
| 686 | + i += 1; | |
| 687 | + } | |
| 688 | + if(x0 <= x && x <= x1) { | |
| 689 | + return 0; | |
| 690 | + } | |
| 691 | + var y1 = vs[(i+1)%n][1]; | |
| 692 | + if(x < x0 && (y0 < y !== y1 < y)) { | |
| 693 | + inside ^= 1; | |
| 694 | + } | |
| 695 | + } | |
| 696 | + } | |
| 697 | + return 2 * inside - 1; | |
| 698 | + }; | |
| 699 | + | |
| 700 | + return { | |
| 701 | + | |
| 702 | + /** | |
| 703 | + * @param object coordinate to check e.g. {latitude: 51.5023, longitude: 7.3815} | |
| 704 | + * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 705 | + * @return integer -1 if point is inside, 0 if point is on boundaries, 1 if point is outside | |
| 706 | + */ | |
| 707 | + isPointInsideRobust: function(latlng, coords) { | |
| 708 | + return robustPointInPolygon(coords, latlng); | |
| 709 | + }, | |
| 710 | + | |
| 711 | + isInside: function() { | |
| 712 | + return this.isPointInsideRobust.apply(this, arguments); | |
| 713 | + } | |
| 714 | + | |
| 715 | + }; | |
| 716 | + | |
| 717 | + }; | |
| 718 | + | |
| 719 | + | |
| 720 | + // Node module | |
| 721 | + if (typeof module !== 'undefined' && | |
| 722 | + typeof module.exports !== 'undefined') { | |
| 723 | + | |
| 724 | + module.exports = function(geolib) { | |
| 725 | + geolib.extend(addOn(geolib), true); | |
| 726 | + return geolib; | |
| 727 | + }; | |
| 728 | + | |
| 729 | + // AMD module | |
| 730 | + } else if (typeof define === "function" && define.amd) { | |
| 731 | + | |
| 732 | + define(["geolib"], function (geolib) { | |
| 733 | + geolib.extend(addOn(geolib), true); | |
| 734 | + return geolib; | |
| 735 | + }); | |
| 736 | + | |
| 737 | + // we're in a browser | |
| 738 | + } else { | |
| 739 | + | |
| 740 | + geolib.extend(addOn(geolib), true); | |
| 741 | + | |
| 742 | + } | |
| 743 | + | |
| 744 | +}(this, this.geolib)); | ... | ... |
src/main/resources/static/assets/js/geolib/geolib.isPointInsideRobust.min.js
0 → 100644
| 1 | +/*! geolib.isPointInsideRobust 2.0.21 | |
| 2 | +* !!EXPERIMENTAL!! | |
| 3 | +* | |
| 4 | +* Robust version of isPointInside for Geolib.js | |
| 5 | +* | |
| 6 | +* Based on https://github.com/mikolalysenko/robust-point-in-polygon | |
| 7 | +* by Mikola Lysenko, licensed under MIT | |
| 8 | +* | |
| 9 | +* @author Manuel Bieh | |
| 10 | +* @url http://www.manuelbieh.com/ | |
| 11 | +* @version 2.0.21 | |
| 12 | +* @license MIT | |
| 13 | +* | |
| 14 | +*/ | |
| 15 | +!function(a,b,c){var d=function(a){var b,d=+(Math.pow(2,27)+1),e=5,f=1.1102230246251565e-16,g=(3+16*f)*f,h=(7+56*f)*f,i=function(a,b,c){var e=a*b,f=d*a,g=f-a,h=f-g,i=a-h,j=d*b,k=j-b,l=j-k,m=b-l,n=e-h*l,o=n-i*l,p=o-h*m,q=i*m-p;return c?(c[0]=q,c[1]=e,c):[q,e]},j=function(a,b,c){var d=a+b,e=d-a,f=d-e,g=b-e,h=a-f;return c?(c[0]=h+g,c[1]=d,c):[h+g,d]},k=j,l=function(a,b){var c=0|a.length,d=0|b.length;if(1===c&&1===d)return p(a[0],b[0]);var e,f,g=c+d,h=new Array(g),i=0,j=0,k=0,l=Math.abs,m=a[j],n=l(m),o=b[k],q=l(o);q>n?(f=m,j+=1,c>j&&(m=a[j],n=l(m))):(f=o,k+=1,d>k&&(o=b[k],q=l(o))),c>j&&q>n||k>=d?(e=m,j+=1,c>j&&(m=a[j],n=l(m))):(e=o,k+=1,d>k&&(o=b[k],q=l(o)));for(var r,s,t,u,v,w=e+f,x=w-e,y=f-x,z=y,A=w;c>j&&d>k;)q>n?(e=m,j+=1,c>j&&(m=a[j],n=l(m))):(e=o,k+=1,d>k&&(o=b[k],q=l(o))),f=z,w=e+f,x=w-e,y=f-x,y&&(h[i++]=y),r=A+w,s=r-A,t=r-s,u=w-s,v=A-t,z=v+u,A=r;for(;c>j;)e=m,f=z,w=e+f,x=w-e,y=f-x,y&&(h[i++]=y),r=A+w,s=r-A,t=r-s,u=w-s,v=A-t,z=v+u,A=r,j+=1,c>j&&(m=a[j]);for(;d>k;)e=o,f=z,w=e+f,x=w-e,y=f-x,y&&(h[i++]=y),r=A+w,s=r-A,t=r-s,u=w-s,v=A-t,z=v+u,A=r,k+=1,d>k&&(o=b[k]);return z&&(h[i++]=z),A&&(h[i++]=A),i||(h[i++]=0),h.length=i,h},m=l,n=function(a,b){var c=a.length;if(1===c){var d=i(a[0],b);return d[0]?d:[d[1]]}var e=new Array(2*c),f=[.1,.1],g=[.1,.1],h=0;i(a[0],b,f),f[0]&&(e[h++]=f[0]);for(var j=1;c>j;++j){i(a[j],b,g);var l=f[1];k(l,g[0],f),f[0]&&(e[h++]=f[0]);var m=g[1],n=f[1],o=m+n,p=o-m,q=n-p;f[1]=o,q&&(e[h++]=q)}return f[1]&&(e[h++]=f[1]),0===h&&(e[h++]=0),e.length=h,e},o=n,p=function(a,b){var c=a+b,d=c-a,e=c-d,f=b-d,g=a-e,h=g+f;return h?[h,c]:[c]},q=function(a,b){var c=0|a.length,d=0|b.length;if(1===c&&1===d)return p(a[0],-b[0]);var e,f,g=c+d,h=new Array(g),i=0,j=0,k=0,l=Math.abs,m=a[j],n=l(m),o=-b[k],q=l(o);q>n?(f=m,j+=1,c>j&&(m=a[j],n=l(m))):(f=o,k+=1,d>k&&(o=-b[k],q=l(o))),c>j&&q>n||k>=d?(e=m,j+=1,c>j&&(m=a[j],n=l(m))):(e=o,k+=1,d>k&&(o=-b[k],q=l(o)));for(var r,s,t,u,v,w=e+f,x=w-e,y=f-x,z=y,A=w;c>j&&d>k;)q>n?(e=m,j+=1,c>j&&(m=a[j],n=l(m))):(e=o,k+=1,d>k&&(o=-b[k],q=l(o))),f=z,w=e+f,x=w-e,y=f-x,y&&(h[i++]=y),r=A+w,s=r-A,t=r-s,u=w-s,v=A-t,z=v+u,A=r;for(;c>j;)e=m,f=z,w=e+f,x=w-e,y=f-x,y&&(h[i++]=y),r=A+w,s=r-A,t=r-s,u=w-s,v=A-t,z=v+u,A=r,j+=1,c>j&&(m=a[j]);for(;d>k;)e=o,f=z,w=e+f,x=w-e,y=f-x,y&&(h[i++]=y),r=A+w,s=r-A,t=r-s,u=w-s,v=A-t,z=v+u,A=r,k+=1,d>k&&(o=-b[k]);return z&&(h[i++]=z),A&&(h[i++]=A),i||(h[i++]=0),h.length=i,h},r=function(a,b){for(var c=new Array(a.length-1),d=1;d<a.length;++d)for(var e=c[d-1]=new Array(a.length-1),f=0,g=0;f<a.length;++f)f!==b&&(e[g++]=a[d][f]);return c},s=function(a){for(var b=new Array(a),c=0;a>c;++c){b[c]=new Array(a);for(var d=0;a>d;++d)b[c][d]=["m",d,"[",a-c-1,"]"].join("")}return b},t=function(a){return 1&a?"-":""},u=function(a){if(1===a.length)return a[0];if(2===a.length)return["sum(",a[0],",",a[1],")"].join("");var b=a.length>>1;return["sum(",u(a.slice(0,b)),",",u(a.slice(b)),")"].join("")},v=function(a){if(2===a.length)return[["sum(prod(",a[0][0],",",a[1][1],"),prod(-",a[0][1],",",a[1][0],"))"].join("")];for(var b=[],c=0;c<a.length;++c)b.push(["scale(",u(v(r(a,c))),",",t(c),a[0][c],")"].join(""));return b},w=function(a){for(var b=[],c=[],d=s(a),e=[],f=0;a>f;++f)0===(1&f)?b.push.apply(b,v(r(d,f))):c.push.apply(c,v(r(d,f))),e.push("m"+f);var g=u(b),h=u(c),j="orientation"+a+"Exact",k=["function ",j,"(",e.join(),"){var p=",g,",n=",h,",d=sub(p,n);return d[d.length-1];};return ",j].join(""),l=new Function("sum","prod","scale","sub",k);return l(m,i,o,q)},x=w(3),y=w(4),z=[function(){return 0},function(){return 0},function(a,b){return b[0]-a[0]},function(a,b,c){var d,e=(a[1]-c[1])*(b[0]-c[0]),f=(a[0]-c[0])*(b[1]-c[1]),h=e-f;if(e>0){if(0>=f)return h;d=e+f}else{if(!(0>e))return h;if(f>=0)return h;d=-(e+f)}var i=g*d;return h>=i||-i>=h?h:x(a,b,c)},function(a,b,c,d){var e=a[0]-d[0],f=b[0]-d[0],g=c[0]-d[0],i=a[1]-d[1],j=b[1]-d[1],k=c[1]-d[1],l=a[2]-d[2],m=b[2]-d[2],n=c[2]-d[2],o=f*k,p=g*j,q=g*i,r=e*k,s=e*j,t=f*i,u=l*(o-p)+m*(q-r)+n*(s-t),v=(Math.abs(o)+Math.abs(p))*Math.abs(l)+(Math.abs(q)+Math.abs(r))*Math.abs(m)+(Math.abs(s)+Math.abs(t))*Math.abs(n),w=h*v;return u>w||-u>w?u:y(a,b,c,d)}],A=function(a){var b=z[a.length];return b||(b=z[a.length]=w(a.length)),b.apply(c,a)},B=function(){for(;z.length<=e;)z.push(w(z.length));for(var a=[],d=["slow"],f=0;e>=f;++f)a.push("a"+f),d.push("o"+f);var g=["function getOrientation(",a.join(),"){switch(arguments.length){case 0:case 1:return 0;"];for(f=2;e>=f;++f)g.push("case ",f,":return o",f,"(",a.slice(0,f).join(),");");g.push("}var s=new Array(arguments.length);for(var i=0;i<arguments.length;++i){s[i]=arguments[i]};return slow(s);}return getOrientation"),d.push(g.join(""));var h=Function.apply(c,d);for(b=h.apply(c,[A].concat(z)),f=0;e>=f;++f)b[f]=z[f]};B();var C=function(c,d){var e=a.longitude(d),f=a.latitude(d),g=c.map(function(b){return[a.longitude(b),a.latitude(b)]});c=g,d=[e,f];for(var h,i,j,k,l,m=c.length,n=1,o=m,p=0,q=m-1;o>p;q=p++){var r=c[p],s=c[q],t=r[1],u=s[1];if(t>u){if(f>u&&t>f){if(h=b(r,s,d),0===h)return 0;n^=h>0|0}else if(f===t&&(i=c[(p+1)%m],j=i[1],j>t)){if(h=b(r,s,d),0===h)return 0;n^=h>0|0}}else if(u>t){if(f>t&&u>f){if(h=b(r,s,d),0===h)return 0;n^=0>h|0}else if(f===t&&(i=c[(p+1)%m],j=i[1],t>j)){if(h=b(r,s,d),0===h)return 0;n^=0>h|0}}else if(f===t){var v=Math.min(r[0],s[0]),w=Math.max(r[0],s[0]);if(0===p){for(;q>0;){var x=(q+m-1)%m;if(l=c[x],l[1]!==f)break;k=l[0],v=Math.min(v,k),w=Math.max(w,k),q=x}if(0===q)return e>=v&&w>=e?0:1;o=q+1}for(var y=c[(q+m-1)%m][1];o>p+1&&(l=c[p+1],l[1]===f);)k=l[0],v=Math.min(v,k),w=Math.max(w,k),p+=1;if(e>=v&&w>=e)return 0;var z=c[(p+1)%m][1];v>e&&f>y!=f>z&&(n^=1)}}return 2*n-1};return{isPointInsideRobust:function(a,b){return C(b,a)},isInside:function(){return this.isPointInsideRobust.apply(this,arguments)}}};"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=function(a){return a.extend(d(a),!0),a}:"function"==typeof define&&define.amd?define(["geolib"],function(a){return a.extend(d(a),!0),a}):b.extend(d(b),!0)}(this,this.geolib); | |
| 0 | 16 | \ No newline at end of file | ... | ... |
src/main/resources/static/assets/js/geolib/geolib.js
0 → 100644
| 1 | +/*! geolib 2.0.21 by Manuel Bieh | |
| 2 | +* Library to provide geo functions like distance calculation, | |
| 3 | +* conversion of decimal coordinates to sexagesimal and vice versa, etc. | |
| 4 | +* WGS 84 (World Geodetic System 1984) | |
| 5 | +* | |
| 6 | +* @author Manuel Bieh | |
| 7 | +* @url http://www.manuelbieh.com/ | |
| 8 | +* @version 2.0.21 | |
| 9 | +* @license MIT | |
| 10 | +**/;(function(global, undefined) { | |
| 11 | + | |
| 12 | + "use strict"; | |
| 13 | + | |
| 14 | + function Geolib() {} | |
| 15 | + | |
| 16 | + // Constants | |
| 17 | + Geolib.TO_RAD = Math.PI / 180; | |
| 18 | + Geolib.TO_DEG = 180 / Math.PI; | |
| 19 | + Geolib.PI_X2 = Math.PI * 2; | |
| 20 | + Geolib.PI_DIV4 = Math.PI / 4; | |
| 21 | + | |
| 22 | + // Setting readonly defaults | |
| 23 | + var geolib = Object.create(Geolib.prototype, { | |
| 24 | + version: { | |
| 25 | + value: "2.0.21" | |
| 26 | + }, | |
| 27 | + radius: { | |
| 28 | + value: 6378137 | |
| 29 | + }, | |
| 30 | + minLat: { | |
| 31 | + value: -90 | |
| 32 | + }, | |
| 33 | + maxLat: { | |
| 34 | + value: 90 | |
| 35 | + }, | |
| 36 | + minLon: { | |
| 37 | + value: -180 | |
| 38 | + }, | |
| 39 | + maxLon: { | |
| 40 | + value: 180 | |
| 41 | + }, | |
| 42 | + sexagesimalPattern: { | |
| 43 | + value: /^([0-9]{1,3})°\s*([0-9]{1,3}(?:\.(?:[0-9]{1,2}))?)'\s*(([0-9]{1,3}(\.([0-9]{1,4}))?)"\s*)?([NEOSW]?)$/ | |
| 44 | + }, | |
| 45 | + measures: { | |
| 46 | + value: Object.create(Object.prototype, { | |
| 47 | + "m" : {value: 1}, | |
| 48 | + "km": {value: 0.001}, | |
| 49 | + "cm": {value: 100}, | |
| 50 | + "mm": {value: 1000}, | |
| 51 | + "mi": {value: (1 / 1609.344)}, | |
| 52 | + "sm": {value: (1 / 1852.216)}, | |
| 53 | + "ft": {value: (100 / 30.48)}, | |
| 54 | + "in": {value: (100 / 2.54)}, | |
| 55 | + "yd": {value: (1 / 0.9144)} | |
| 56 | + }) | |
| 57 | + }, | |
| 58 | + prototype: { | |
| 59 | + value: Geolib.prototype | |
| 60 | + }, | |
| 61 | + extend: { | |
| 62 | + value: function(methods, overwrite) { | |
| 63 | + for(var prop in methods) { | |
| 64 | + if(typeof geolib.prototype[prop] === 'undefined' || overwrite === true) { | |
| 65 | + if(typeof methods[prop] === 'function' && typeof methods[prop].bind === 'function') { | |
| 66 | + geolib.prototype[prop] = methods[prop].bind(geolib); | |
| 67 | + } else { | |
| 68 | + geolib.prototype[prop] = methods[prop]; | |
| 69 | + } | |
| 70 | + } | |
| 71 | + } | |
| 72 | + } | |
| 73 | + } | |
| 74 | + }); | |
| 75 | + | |
| 76 | + if (typeof(Number.prototype.toRad) === 'undefined') { | |
| 77 | + Number.prototype.toRad = function() { | |
| 78 | + return this * Geolib.TO_RAD; | |
| 79 | + }; | |
| 80 | + } | |
| 81 | + | |
| 82 | + if (typeof(Number.prototype.toDeg) === 'undefined') { | |
| 83 | + Number.prototype.toDeg = function() { | |
| 84 | + return this * Geolib.TO_DEG; | |
| 85 | + }; | |
| 86 | + } | |
| 87 | + | |
| 88 | + // Here comes the magic | |
| 89 | + geolib.extend({ | |
| 90 | + | |
| 91 | + decimal: {}, | |
| 92 | + | |
| 93 | + sexagesimal: {}, | |
| 94 | + | |
| 95 | + distance: null, | |
| 96 | + | |
| 97 | + getKeys: function(point) { | |
| 98 | + | |
| 99 | + // GeoJSON Array [longitude, latitude(, elevation)] | |
| 100 | + if(Object.prototype.toString.call(point) == '[object Array]') { | |
| 101 | + | |
| 102 | + return { | |
| 103 | + longitude: point.length >= 1 ? 0 : undefined, | |
| 104 | + latitude: point.length >= 2 ? 1 : undefined, | |
| 105 | + elevation: point.length >= 3 ? 2 : undefined | |
| 106 | + }; | |
| 107 | + | |
| 108 | + } | |
| 109 | + | |
| 110 | + var getKey = function(possibleValues) { | |
| 111 | + | |
| 112 | + var key; | |
| 113 | + | |
| 114 | + possibleValues.every(function(val) { | |
| 115 | + // TODO: check if point is an object | |
| 116 | + if(typeof point != 'object') { | |
| 117 | + return true; | |
| 118 | + } | |
| 119 | + return point.hasOwnProperty(val) ? (function() { key = val; return false; }()) : true; | |
| 120 | + }); | |
| 121 | + | |
| 122 | + return key; | |
| 123 | + | |
| 124 | + }; | |
| 125 | + | |
| 126 | + var longitude = getKey(['lng', 'lon', 'longitude']); | |
| 127 | + var latitude = getKey(['lat', 'latitude']); | |
| 128 | + var elevation = getKey(['alt', 'altitude', 'elevation', 'elev']); | |
| 129 | + | |
| 130 | + // return undefined if not at least one valid property was found | |
| 131 | + if(typeof latitude == 'undefined' && | |
| 132 | + typeof longitude == 'undefined' && | |
| 133 | + typeof elevation == 'undefined') { | |
| 134 | + return undefined; | |
| 135 | + } | |
| 136 | + | |
| 137 | + return { | |
| 138 | + latitude: latitude, | |
| 139 | + longitude: longitude, | |
| 140 | + elevation: elevation | |
| 141 | + }; | |
| 142 | + | |
| 143 | + }, | |
| 144 | + | |
| 145 | + // returns latitude of a given point, converted to decimal | |
| 146 | + // set raw to true to avoid conversion | |
| 147 | + getLat: function(point, raw) { | |
| 148 | + return raw === true ? point[this.getKeys(point).latitude] : this.useDecimal(point[this.getKeys(point).latitude]); | |
| 149 | + }, | |
| 150 | + | |
| 151 | + // Alias for getLat | |
| 152 | + latitude: function(point) { | |
| 153 | + return this.getLat.call(this, point); | |
| 154 | + }, | |
| 155 | + | |
| 156 | + // returns longitude of a given point, converted to decimal | |
| 157 | + // set raw to true to avoid conversion | |
| 158 | + getLon: function(point, raw) { | |
| 159 | + return raw === true ? point[this.getKeys(point).longitude] : this.useDecimal(point[this.getKeys(point).longitude]); | |
| 160 | + }, | |
| 161 | + | |
| 162 | + // Alias for getLon | |
| 163 | + longitude: function(point) { | |
| 164 | + return this.getLon.call(this, point); | |
| 165 | + }, | |
| 166 | + | |
| 167 | + getElev: function(point) { | |
| 168 | + return point[this.getKeys(point).elevation]; | |
| 169 | + }, | |
| 170 | + | |
| 171 | + // Alias for getElev | |
| 172 | + elevation: function(point) { | |
| 173 | + return this.getElev.call(this, point); | |
| 174 | + }, | |
| 175 | + | |
| 176 | + coords: function(point, raw) { | |
| 177 | + | |
| 178 | + var retval = { | |
| 179 | + latitude: raw === true ? point[this.getKeys(point).latitude] : this.useDecimal(point[this.getKeys(point).latitude]), | |
| 180 | + longitude: raw === true ? point[this.getKeys(point).longitude] : this.useDecimal(point[this.getKeys(point).longitude]) | |
| 181 | + }; | |
| 182 | + | |
| 183 | + var elev = point[this.getKeys(point).elevation]; | |
| 184 | + | |
| 185 | + if(typeof elev !== 'undefined') { | |
| 186 | + retval['elevation'] = elev; | |
| 187 | + } | |
| 188 | + | |
| 189 | + return retval; | |
| 190 | + | |
| 191 | + }, | |
| 192 | + | |
| 193 | + // Alias for coords | |
| 194 | + ll: function(point, raw) { | |
| 195 | + return this.coords.call(this, point, raw); | |
| 196 | + }, | |
| 197 | + | |
| 198 | + | |
| 199 | + // checks if a variable contains a valid latlong object | |
| 200 | + validate: function(point) { | |
| 201 | + | |
| 202 | + var keys = this.getKeys(point); | |
| 203 | + | |
| 204 | + if(typeof keys === 'undefined' || typeof keys.latitude === 'undefined' || keys.longitude === 'undefined') { | |
| 205 | + return false; | |
| 206 | + } | |
| 207 | + | |
| 208 | + var lat = point[keys.latitude]; | |
| 209 | + var lng = point[keys.longitude]; | |
| 210 | + | |
| 211 | + if(typeof lat === 'undefined' || !this.isDecimal(lat) && !this.isSexagesimal(lat)) { | |
| 212 | + return false; | |
| 213 | + } | |
| 214 | + | |
| 215 | + if(typeof lng === 'undefined' || !this.isDecimal(lng) && !this.isSexagesimal(lng)) { | |
| 216 | + return false; | |
| 217 | + } | |
| 218 | + | |
| 219 | + lat = this.useDecimal(lat); | |
| 220 | + lng = this.useDecimal(lng); | |
| 221 | + | |
| 222 | + if(lat < this.minLat || lat > this.maxLat || lng < this.minLon || lng > this.maxLon) { | |
| 223 | + return false; | |
| 224 | + } | |
| 225 | + | |
| 226 | + return true; | |
| 227 | + | |
| 228 | + }, | |
| 229 | + | |
| 230 | + /** | |
| 231 | + * Calculates geodetic distance between two points specified by latitude/longitude using | |
| 232 | + * Vincenty inverse formula for ellipsoids | |
| 233 | + * Vincenty Inverse Solution of Geodesics on the Ellipsoid (c) Chris Veness 2002-2010 | |
| 234 | + * (Licensed under CC BY 3.0) | |
| 235 | + * | |
| 236 | + * @param object Start position {latitude: 123, longitude: 123} | |
| 237 | + * @param object End position {latitude: 123, longitude: 123} | |
| 238 | + * @param integer Accuracy (in meters) | |
| 239 | + * @param integer Precision (in decimal cases) | |
| 240 | + * @return integer Distance (in meters) | |
| 241 | + */ | |
| 242 | + getDistance: function(start, end, accuracy, precision) { | |
| 243 | + | |
| 244 | + accuracy = Math.floor(accuracy) || 1; | |
| 245 | + precision = Math.floor(precision) || 0; | |
| 246 | + | |
| 247 | + var s = this.coords(start); | |
| 248 | + var e = this.coords(end); | |
| 249 | + | |
| 250 | + var a = 6378137, b = 6356752.314245, f = 1/298.257223563; // WGS-84 ellipsoid params | |
| 251 | + var L = (e['longitude']-s['longitude']).toRad(); | |
| 252 | + | |
| 253 | + var cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM, sinSigma; | |
| 254 | + | |
| 255 | + var U1 = Math.atan((1-f) * Math.tan(parseFloat(s['latitude']).toRad())); | |
| 256 | + var U2 = Math.atan((1-f) * Math.tan(parseFloat(e['latitude']).toRad())); | |
| 257 | + var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1); | |
| 258 | + var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2); | |
| 259 | + | |
| 260 | + var lambda = L, lambdaP, iterLimit = 100; | |
| 261 | + do { | |
| 262 | + var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda); | |
| 263 | + sinSigma = ( | |
| 264 | + Math.sqrt( | |
| 265 | + ( | |
| 266 | + cosU2 * sinLambda | |
| 267 | + ) * ( | |
| 268 | + cosU2 * sinLambda | |
| 269 | + ) + ( | |
| 270 | + cosU1 * sinU2 - sinU1 * cosU2 * cosLambda | |
| 271 | + ) * ( | |
| 272 | + cosU1 * sinU2 - sinU1 * cosU2 * cosLambda | |
| 273 | + ) | |
| 274 | + ) | |
| 275 | + ); | |
| 276 | + if (sinSigma === 0) { | |
| 277 | + return geolib.distance = 0; // co-incident points | |
| 278 | + } | |
| 279 | + | |
| 280 | + cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda; | |
| 281 | + sigma = Math.atan2(sinSigma, cosSigma); | |
| 282 | + sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma; | |
| 283 | + cosSqAlpha = 1 - sinAlpha * sinAlpha; | |
| 284 | + cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha; | |
| 285 | + | |
| 286 | + if (isNaN(cos2SigmaM)) { | |
| 287 | + cos2SigmaM = 0; // equatorial line: cosSqAlpha=0 (§6) | |
| 288 | + } | |
| 289 | + var C = ( | |
| 290 | + f / 16 * cosSqAlpha * ( | |
| 291 | + 4 + f * ( | |
| 292 | + 4 - 3 * cosSqAlpha | |
| 293 | + ) | |
| 294 | + ) | |
| 295 | + ); | |
| 296 | + lambdaP = lambda; | |
| 297 | + lambda = ( | |
| 298 | + L + ( | |
| 299 | + 1 - C | |
| 300 | + ) * f * sinAlpha * ( | |
| 301 | + sigma + C * sinSigma * ( | |
| 302 | + cos2SigmaM + C * cosSigma * ( | |
| 303 | + -1 + 2 * cos2SigmaM * cos2SigmaM | |
| 304 | + ) | |
| 305 | + ) | |
| 306 | + ) | |
| 307 | + ); | |
| 308 | + | |
| 309 | + } while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0); | |
| 310 | + | |
| 311 | + if (iterLimit === 0) { | |
| 312 | + return NaN; // formula failed to converge | |
| 313 | + } | |
| 314 | + | |
| 315 | + var uSq = ( | |
| 316 | + cosSqAlpha * ( | |
| 317 | + a * a - b * b | |
| 318 | + ) / ( | |
| 319 | + b*b | |
| 320 | + ) | |
| 321 | + ); | |
| 322 | + | |
| 323 | + var A = ( | |
| 324 | + 1 + uSq / 16384 * ( | |
| 325 | + 4096 + uSq * ( | |
| 326 | + -768 + uSq * ( | |
| 327 | + 320 - 175 * uSq | |
| 328 | + ) | |
| 329 | + ) | |
| 330 | + ) | |
| 331 | + ); | |
| 332 | + | |
| 333 | + var B = ( | |
| 334 | + uSq / 1024 * ( | |
| 335 | + 256 + uSq * ( | |
| 336 | + -128 + uSq * ( | |
| 337 | + 74-47 * uSq | |
| 338 | + ) | |
| 339 | + ) | |
| 340 | + ) | |
| 341 | + ); | |
| 342 | + | |
| 343 | + var deltaSigma = ( | |
| 344 | + B * sinSigma * ( | |
| 345 | + cos2SigmaM + B / 4 * ( | |
| 346 | + cosSigma * ( | |
| 347 | + -1 + 2 * cos2SigmaM * cos2SigmaM | |
| 348 | + ) -B / 6 * cos2SigmaM * ( | |
| 349 | + -3 + 4 * sinSigma * sinSigma | |
| 350 | + ) * ( | |
| 351 | + -3 + 4 * cos2SigmaM * cos2SigmaM | |
| 352 | + ) | |
| 353 | + ) | |
| 354 | + ) | |
| 355 | + ); | |
| 356 | + | |
| 357 | + var distance = b * A * (sigma - deltaSigma); | |
| 358 | + | |
| 359 | + distance = distance.toFixed(precision); // round to 1mm precision | |
| 360 | + | |
| 361 | + //if (start.hasOwnProperty(elevation) && end.hasOwnProperty(elevation)) { | |
| 362 | + if (typeof this.elevation(start) !== 'undefined' && typeof this.elevation(end) !== 'undefined') { | |
| 363 | + var climb = Math.abs(this.elevation(start) - this.elevation(end)); | |
| 364 | + distance = Math.sqrt(distance * distance + climb * climb); | |
| 365 | + } | |
| 366 | + | |
| 367 | + return this.distance = Math.round(distance * Math.pow(10, precision) / accuracy) * accuracy / Math.pow(10, precision); | |
| 368 | + | |
| 369 | + /* | |
| 370 | + // note: to return initial/final bearings in addition to distance, use something like: | |
| 371 | + var fwdAz = Math.atan2(cosU2*sinLambda, cosU1*sinU2-sinU1*cosU2*cosLambda); | |
| 372 | + var revAz = Math.atan2(cosU1*sinLambda, -sinU1*cosU2+cosU1*sinU2*cosLambda); | |
| 373 | + | |
| 374 | + return { distance: s, initialBearing: fwdAz.toDeg(), finalBearing: revAz.toDeg() }; | |
| 375 | + */ | |
| 376 | + | |
| 377 | + }, | |
| 378 | + | |
| 379 | + | |
| 380 | + /** | |
| 381 | + * Calculates the distance between two spots. | |
| 382 | + * This method is more simple but also far more inaccurate | |
| 383 | + * | |
| 384 | + * @param object Start position {latitude: 123, longitude: 123} | |
| 385 | + * @param object End position {latitude: 123, longitude: 123} | |
| 386 | + * @param integer Accuracy (in meters) | |
| 387 | + * @return integer Distance (in meters) | |
| 388 | + */ | |
| 389 | + getDistanceSimple: function(start, end, accuracy) { | |
| 390 | + | |
| 391 | + accuracy = Math.floor(accuracy) || 1; | |
| 392 | + | |
| 393 | + var distance = | |
| 394 | + Math.round( | |
| 395 | + Math.acos( | |
| 396 | + Math.sin( | |
| 397 | + this.latitude(end).toRad() | |
| 398 | + ) * | |
| 399 | + Math.sin( | |
| 400 | + this.latitude(start).toRad() | |
| 401 | + ) + | |
| 402 | + Math.cos( | |
| 403 | + this.latitude(end).toRad() | |
| 404 | + ) * | |
| 405 | + Math.cos( | |
| 406 | + this.latitude(start).toRad() | |
| 407 | + ) * | |
| 408 | + Math.cos( | |
| 409 | + this.longitude(start).toRad() - this.longitude(end).toRad() | |
| 410 | + ) | |
| 411 | + ) * this.radius | |
| 412 | + ); | |
| 413 | + | |
| 414 | + return geolib.distance = Math.floor(Math.round(distance/accuracy)*accuracy); | |
| 415 | + | |
| 416 | + }, | |
| 417 | + | |
| 418 | + | |
| 419 | + /** | |
| 420 | + * Calculates the center of a collection of geo coordinates | |
| 421 | + * | |
| 422 | + * @param array Collection of coords [{latitude: 51.510, longitude: 7.1321}, {latitude: 49.1238, longitude: "8° 30' W"}, ...] | |
| 423 | + * @return object {latitude: centerLat, longitude: centerLng} | |
| 424 | + */ | |
| 425 | + getCenter: function(coords) { | |
| 426 | + | |
| 427 | + var coordsArray = coords; | |
| 428 | + if(typeof coords === 'object' && !(coords instanceof Array)) { | |
| 429 | + | |
| 430 | + coordsArray = []; | |
| 431 | + | |
| 432 | + for(var key in coords) { | |
| 433 | + coordsArray.push( | |
| 434 | + this.coords(coords[key]) | |
| 435 | + ); | |
| 436 | + } | |
| 437 | + | |
| 438 | + } | |
| 439 | + | |
| 440 | + if(!coordsArray.length) { | |
| 441 | + return false; | |
| 442 | + } | |
| 443 | + | |
| 444 | + var X = 0.0; | |
| 445 | + var Y = 0.0; | |
| 446 | + var Z = 0.0; | |
| 447 | + var lat, lon, hyp; | |
| 448 | + | |
| 449 | + coordsArray.forEach(function(coord) { | |
| 450 | + | |
| 451 | + lat = this.latitude(coord).toRad(); | |
| 452 | + lon = this.longitude(coord).toRad(); | |
| 453 | + | |
| 454 | + X += Math.cos(lat) * Math.cos(lon); | |
| 455 | + Y += Math.cos(lat) * Math.sin(lon); | |
| 456 | + Z += Math.sin(lat); | |
| 457 | + | |
| 458 | + }, this); | |
| 459 | + | |
| 460 | + var nb_coords = coordsArray.length; | |
| 461 | + X = X / nb_coords; | |
| 462 | + Y = Y / nb_coords; | |
| 463 | + Z = Z / nb_coords; | |
| 464 | + | |
| 465 | + lon = Math.atan2(Y, X); | |
| 466 | + hyp = Math.sqrt(X * X + Y * Y); | |
| 467 | + lat = Math.atan2(Z, hyp); | |
| 468 | + | |
| 469 | + return { | |
| 470 | + latitude: (lat * Geolib.TO_DEG).toFixed(6), | |
| 471 | + longitude: (lon * Geolib.TO_DEG).toFixed(6) | |
| 472 | + }; | |
| 473 | + | |
| 474 | + }, | |
| 475 | + | |
| 476 | + | |
| 477 | + /** | |
| 478 | + * Gets the max and min, latitude, longitude, and elevation (if provided). | |
| 479 | + * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 480 | + * @return object {maxLat: maxLat, | |
| 481 | + * minLat: minLat | |
| 482 | + * maxLng: maxLng, | |
| 483 | + * minLng: minLng, | |
| 484 | + * maxElev: maxElev, | |
| 485 | + * minElev: minElev} | |
| 486 | + */ | |
| 487 | + getBounds: function(coords) { | |
| 488 | + | |
| 489 | + if (!coords.length) { | |
| 490 | + return false; | |
| 491 | + } | |
| 492 | + | |
| 493 | + var useElevation = this.elevation(coords[0]); | |
| 494 | + | |
| 495 | + var stats = { | |
| 496 | + maxLat: -Infinity, | |
| 497 | + minLat: Infinity, | |
| 498 | + maxLng: -Infinity, | |
| 499 | + minLng: Infinity | |
| 500 | + }; | |
| 501 | + | |
| 502 | + if (typeof useElevation != 'undefined') { | |
| 503 | + stats.maxElev = 0; | |
| 504 | + stats.minElev = Infinity; | |
| 505 | + } | |
| 506 | + | |
| 507 | + for (var i = 0, l = coords.length; i < l; ++i) { | |
| 508 | + | |
| 509 | + stats.maxLat = Math.max(this.latitude(coords[i]), stats.maxLat); | |
| 510 | + stats.minLat = Math.min(this.latitude(coords[i]), stats.minLat); | |
| 511 | + stats.maxLng = Math.max(this.longitude(coords[i]), stats.maxLng); | |
| 512 | + stats.minLng = Math.min(this.longitude(coords[i]), stats.minLng); | |
| 513 | + | |
| 514 | + if (useElevation) { | |
| 515 | + stats.maxElev = Math.max(this.elevation(coords[i]), stats.maxElev); | |
| 516 | + stats.minElev = Math.min(this.elevation(coords[i]), stats.minElev); | |
| 517 | + } | |
| 518 | + | |
| 519 | + } | |
| 520 | + | |
| 521 | + return stats; | |
| 522 | + | |
| 523 | + }, | |
| 524 | + | |
| 525 | + /** | |
| 526 | + * Calculates the center of the bounds of geo coordinates. | |
| 527 | + * | |
| 528 | + * On polygons like political borders (eg. states) | |
| 529 | + * this may gives a closer result to human expectation, than `getCenter`, | |
| 530 | + * because that function can be disturbed by uneven distribution of | |
| 531 | + * point in different sides. | |
| 532 | + * Imagine the US state Oklahoma: `getCenter` on that gives a southern | |
| 533 | + * point, because the southern border contains a lot more nodes, | |
| 534 | + * than the others. | |
| 535 | + * | |
| 536 | + * @param array Collection of coords [{latitude: 51.510, longitude: 7.1321}, {latitude: 49.1238, longitude: "8° 30' W"}, ...] | |
| 537 | + * @return object {latitude: centerLat, longitude: centerLng} | |
| 538 | + */ | |
| 539 | + getCenterOfBounds: function(coords) { | |
| 540 | + var b = this.getBounds(coords); | |
| 541 | + var latitude = b.minLat + ((b.maxLat - b.minLat) / 2); | |
| 542 | + var longitude = b.minLng + ((b.maxLng - b.minLng) / 2); | |
| 543 | + return { | |
| 544 | + latitude: parseFloat(latitude.toFixed(6)), | |
| 545 | + longitude: parseFloat(longitude.toFixed(6)) | |
| 546 | + }; | |
| 547 | + }, | |
| 548 | + | |
| 549 | + | |
| 550 | + /** | |
| 551 | + * Computes the bounding coordinates of all points on the surface | |
| 552 | + * of the earth less than or equal to the specified great circle | |
| 553 | + * distance. | |
| 554 | + * | |
| 555 | + * @param object Point position {latitude: 123, longitude: 123} | |
| 556 | + * @param number Distance (in meters). | |
| 557 | + * @return array Collection of two points defining the SW and NE corners. | |
| 558 | + */ | |
| 559 | + getBoundsOfDistance: function(point, distance) { | |
| 560 | + | |
| 561 | + var latitude = this.latitude(point); | |
| 562 | + var longitude = this.longitude(point); | |
| 563 | + | |
| 564 | + var radLat = latitude.toRad(); | |
| 565 | + var radLon = longitude.toRad(); | |
| 566 | + | |
| 567 | + var radDist = distance / this.radius; | |
| 568 | + var minLat = radLat - radDist; | |
| 569 | + var maxLat = radLat + radDist; | |
| 570 | + | |
| 571 | + var MAX_LAT_RAD = this.maxLat.toRad(); | |
| 572 | + var MIN_LAT_RAD = this.minLat.toRad(); | |
| 573 | + var MAX_LON_RAD = this.maxLon.toRad(); | |
| 574 | + var MIN_LON_RAD = this.minLon.toRad(); | |
| 575 | + | |
| 576 | + var minLon; | |
| 577 | + var maxLon; | |
| 578 | + | |
| 579 | + if (minLat > MIN_LAT_RAD && maxLat < MAX_LAT_RAD) { | |
| 580 | + | |
| 581 | + var deltaLon = Math.asin(Math.sin(radDist) / Math.cos(radLat)); | |
| 582 | + minLon = radLon - deltaLon; | |
| 583 | + | |
| 584 | + if (minLon < MIN_LON_RAD) { | |
| 585 | + minLon += Geolib.PI_X2; | |
| 586 | + } | |
| 587 | + | |
| 588 | + maxLon = radLon + deltaLon; | |
| 589 | + | |
| 590 | + if (maxLon > MAX_LON_RAD) { | |
| 591 | + maxLon -= Geolib.PI_X2; | |
| 592 | + } | |
| 593 | + | |
| 594 | + } else { | |
| 595 | + // A pole is within the distance. | |
| 596 | + minLat = Math.max(minLat, MIN_LAT_RAD); | |
| 597 | + maxLat = Math.min(maxLat, MAX_LAT_RAD); | |
| 598 | + minLon = MIN_LON_RAD; | |
| 599 | + maxLon = MAX_LON_RAD; | |
| 600 | + } | |
| 601 | + | |
| 602 | + return [ | |
| 603 | + // Southwest | |
| 604 | + { | |
| 605 | + latitude: minLat.toDeg(), | |
| 606 | + longitude: minLon.toDeg() | |
| 607 | + }, | |
| 608 | + // Northeast | |
| 609 | + { | |
| 610 | + latitude: maxLat.toDeg(), | |
| 611 | + longitude: maxLon.toDeg() | |
| 612 | + } | |
| 613 | + ]; | |
| 614 | + | |
| 615 | + }, | |
| 616 | + | |
| 617 | + | |
| 618 | + /** | |
| 619 | + * Checks whether a point is inside of a polygon or not. | |
| 620 | + * Note that the polygon coords must be in correct order! | |
| 621 | + * | |
| 622 | + * @param object coordinate to check e.g. {latitude: 51.5023, longitude: 7.3815} | |
| 623 | + * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 624 | + * @return bool true if the coordinate is inside the given polygon | |
| 625 | + */ | |
| 626 | + isPointInside: function(latlng, coords) { | |
| 627 | + | |
| 628 | + for(var c = false, i = -1, l = coords.length, j = l - 1; ++i < l; j = i) { | |
| 629 | + | |
| 630 | + if( | |
| 631 | + ( | |
| 632 | + (this.longitude(coords[i]) <= this.longitude(latlng) && this.longitude(latlng) < this.longitude(coords[j])) || | |
| 633 | + (this.longitude(coords[j]) <= this.longitude(latlng) && this.longitude(latlng) < this.longitude(coords[i])) | |
| 634 | + ) && | |
| 635 | + ( | |
| 636 | + this.latitude(latlng) < (this.latitude(coords[j]) - this.latitude(coords[i])) * | |
| 637 | + (this.longitude(latlng) - this.longitude(coords[i])) / | |
| 638 | + (this.longitude(coords[j]) - this.longitude(coords[i])) + | |
| 639 | + this.latitude(coords[i]) | |
| 640 | + ) | |
| 641 | + ) { | |
| 642 | + c = !c; | |
| 643 | + } | |
| 644 | + | |
| 645 | + } | |
| 646 | + | |
| 647 | + return c; | |
| 648 | + | |
| 649 | + }, | |
| 650 | + | |
| 651 | + | |
| 652 | + /** | |
| 653 | + * Pre calculate the polygon coords, to speed up the point inside check. | |
| 654 | + * Use this function before calling isPointInsideWithPreparedPolygon() | |
| 655 | + * @see Algorythm from http://alienryderflex.com/polygon/ | |
| 656 | + * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 657 | + */ | |
| 658 | + preparePolygonForIsPointInsideOptimized: function(coords) { | |
| 659 | + | |
| 660 | + for(var i = 0, j = coords.length-1; i < coords.length; i++) { | |
| 661 | + | |
| 662 | + if(this.longitude(coords[j]) === this.longitude(coords[i])) { | |
| 663 | + | |
| 664 | + coords[i].constant = this.latitude(coords[i]); | |
| 665 | + coords[i].multiple = 0; | |
| 666 | + | |
| 667 | + } else { | |
| 668 | + | |
| 669 | + coords[i].constant = this.latitude(coords[i]) - ( | |
| 670 | + this.longitude(coords[i]) * this.latitude(coords[j]) | |
| 671 | + ) / ( | |
| 672 | + this.longitude(coords[j]) - this.longitude(coords[i]) | |
| 673 | + ) + ( | |
| 674 | + this.longitude(coords[i])*this.latitude(coords[i]) | |
| 675 | + ) / ( | |
| 676 | + this.longitude(coords[j])-this.longitude(coords[i]) | |
| 677 | + ); | |
| 678 | + | |
| 679 | + coords[i].multiple = ( | |
| 680 | + this.latitude(coords[j])-this.latitude(coords[i]) | |
| 681 | + ) / ( | |
| 682 | + this.longitude(coords[j])-this.longitude(coords[i]) | |
| 683 | + ); | |
| 684 | + | |
| 685 | + } | |
| 686 | + | |
| 687 | + j=i; | |
| 688 | + | |
| 689 | + } | |
| 690 | + | |
| 691 | + }, | |
| 692 | + | |
| 693 | + /** | |
| 694 | + * Checks whether a point is inside of a polygon or not. | |
| 695 | + * "This is useful if you have many points that need to be tested against the same (static) polygon." | |
| 696 | + * Please call the function preparePolygonForIsPointInsideOptimized() with the same coords object before using this function. | |
| 697 | + * Note that the polygon coords must be in correct order! | |
| 698 | + * | |
| 699 | + * @see Algorythm from http://alienryderflex.com/polygon/ | |
| 700 | + * | |
| 701 | + * @param object coordinate to check e.g. {latitude: 51.5023, longitude: 7.3815} | |
| 702 | + * @param array array with coords e.g. [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 703 | + * @return bool true if the coordinate is inside the given polygon | |
| 704 | + */ | |
| 705 | + isPointInsideWithPreparedPolygon: function(point, coords) { | |
| 706 | + | |
| 707 | + var flgPointInside = false, | |
| 708 | + y = this.longitude(point), | |
| 709 | + x = this.latitude(point); | |
| 710 | + | |
| 711 | + for(var i = 0, j = coords.length-1; i < coords.length; i++) { | |
| 712 | + | |
| 713 | + if ((this.longitude(coords[i]) < y && this.longitude(coords[j]) >=y || | |
| 714 | + this.longitude(coords[j]) < y && this.longitude(coords[i]) >= y)) { | |
| 715 | + | |
| 716 | + flgPointInside^=(y*coords[i].multiple+coords[i].constant < x); | |
| 717 | + | |
| 718 | + } | |
| 719 | + | |
| 720 | + j=i; | |
| 721 | + | |
| 722 | + } | |
| 723 | + | |
| 724 | + return flgPointInside; | |
| 725 | + | |
| 726 | + }, | |
| 727 | + | |
| 728 | + | |
| 729 | + /** | |
| 730 | + * Shortcut for geolib.isPointInside() | |
| 731 | + */ | |
| 732 | + isInside: function() { | |
| 733 | + return this.isPointInside.apply(this, arguments); | |
| 734 | + }, | |
| 735 | + | |
| 736 | + | |
| 737 | + /** | |
| 738 | + * Checks whether a point is inside of a circle or not. | |
| 739 | + * | |
| 740 | + * @param object coordinate to check (e.g. {latitude: 51.5023, longitude: 7.3815}) | |
| 741 | + * @param object coordinate of the circle's center (e.g. {latitude: 51.4812, longitude: 7.4025}) | |
| 742 | + * @param integer maximum radius in meters | |
| 743 | + * @return bool true if the coordinate is within the given radius | |
| 744 | + */ | |
| 745 | + isPointInCircle: function(latlng, center, radius) { | |
| 746 | + return this.getDistance(latlng, center) < radius; | |
| 747 | + }, | |
| 748 | + | |
| 749 | + | |
| 750 | + /** | |
| 751 | + * Shortcut for geolib.isPointInCircle() | |
| 752 | + */ | |
| 753 | + withinRadius: function() { | |
| 754 | + return this.isPointInCircle.apply(this, arguments); | |
| 755 | + }, | |
| 756 | + | |
| 757 | + | |
| 758 | + /** | |
| 759 | + * Gets rhumb line bearing of two points. Find out about the difference between rhumb line and | |
| 760 | + * great circle bearing on Wikipedia. It's quite complicated. Rhumb line should be fine in most cases: | |
| 761 | + * | |
| 762 | + * http://en.wikipedia.org/wiki/Rhumb_line#General_and_mathematical_description | |
| 763 | + * | |
| 764 | + * Function heavily based on Doug Vanderweide's great PHP version (licensed under GPL 3.0) | |
| 765 | + * http://www.dougv.com/2009/07/13/calculating-the-bearing-and-compass-rose-direction-between-two-latitude-longitude-coordinates-in-php/ | |
| 766 | + * | |
| 767 | + * @param object origin coordinate (e.g. {latitude: 51.5023, longitude: 7.3815}) | |
| 768 | + * @param object destination coordinate | |
| 769 | + * @return integer calculated bearing | |
| 770 | + */ | |
| 771 | + getRhumbLineBearing: function(originLL, destLL) { | |
| 772 | + | |
| 773 | + // difference of longitude coords | |
| 774 | + var diffLon = this.longitude(destLL).toRad() - this.longitude(originLL).toRad(); | |
| 775 | + | |
| 776 | + // difference latitude coords phi | |
| 777 | + var diffPhi = Math.log( | |
| 778 | + Math.tan( | |
| 779 | + this.latitude(destLL).toRad() / 2 + Geolib.PI_DIV4 | |
| 780 | + ) / | |
| 781 | + Math.tan( | |
| 782 | + this.latitude(originLL).toRad() / 2 + Geolib.PI_DIV4 | |
| 783 | + ) | |
| 784 | + ); | |
| 785 | + | |
| 786 | + // recalculate diffLon if it is greater than pi | |
| 787 | + if(Math.abs(diffLon) > Math.PI) { | |
| 788 | + if(diffLon > 0) { | |
| 789 | + diffLon = (Geolib.PI_X2 - diffLon) * -1; | |
| 790 | + } | |
| 791 | + else { | |
| 792 | + diffLon = Geolib.PI_X2 + diffLon; | |
| 793 | + } | |
| 794 | + } | |
| 795 | + | |
| 796 | + //return the angle, normalized | |
| 797 | + return (Math.atan2(diffLon, diffPhi).toDeg() + 360) % 360; | |
| 798 | + | |
| 799 | + }, | |
| 800 | + | |
| 801 | + | |
| 802 | + /** | |
| 803 | + * Gets great circle bearing of two points. See description of getRhumbLineBearing for more information | |
| 804 | + * | |
| 805 | + * @param object origin coordinate (e.g. {latitude: 51.5023, longitude: 7.3815}) | |
| 806 | + * @param object destination coordinate | |
| 807 | + * @return integer calculated bearing | |
| 808 | + */ | |
| 809 | + getBearing: function(originLL, destLL) { | |
| 810 | + | |
| 811 | + destLL['latitude'] = this.latitude(destLL); | |
| 812 | + destLL['longitude'] = this.longitude(destLL); | |
| 813 | + originLL['latitude'] = this.latitude(originLL); | |
| 814 | + originLL['longitude'] = this.longitude(originLL); | |
| 815 | + | |
| 816 | + var bearing = ( | |
| 817 | + ( | |
| 818 | + Math.atan2( | |
| 819 | + Math.sin( | |
| 820 | + destLL['longitude'].toRad() - | |
| 821 | + originLL['longitude'].toRad() | |
| 822 | + ) * | |
| 823 | + Math.cos( | |
| 824 | + destLL['latitude'].toRad() | |
| 825 | + ), | |
| 826 | + Math.cos( | |
| 827 | + originLL['latitude'].toRad() | |
| 828 | + ) * | |
| 829 | + Math.sin( | |
| 830 | + destLL['latitude'].toRad() | |
| 831 | + ) - | |
| 832 | + Math.sin( | |
| 833 | + originLL['latitude'].toRad() | |
| 834 | + ) * | |
| 835 | + Math.cos( | |
| 836 | + destLL['latitude'].toRad() | |
| 837 | + ) * | |
| 838 | + Math.cos( | |
| 839 | + destLL['longitude'].toRad() - originLL['longitude'].toRad() | |
| 840 | + ) | |
| 841 | + ) | |
| 842 | + ).toDeg() + 360 | |
| 843 | + ) % 360; | |
| 844 | + | |
| 845 | + return bearing; | |
| 846 | + | |
| 847 | + }, | |
| 848 | + | |
| 849 | + | |
| 850 | + /** | |
| 851 | + * Gets the compass direction from an origin coordinate to a destination coordinate. | |
| 852 | + * | |
| 853 | + * @param object origin coordinate (e.g. {latitude: 51.5023, longitude: 7.3815}) | |
| 854 | + * @param object destination coordinate | |
| 855 | + * @param string Bearing mode. Can be either circle or rhumbline | |
| 856 | + * @return object Returns an object with a rough (NESW) and an exact direction (NNE, NE, ENE, E, ESE, etc). | |
| 857 | + */ | |
| 858 | + getCompassDirection: function(originLL, destLL, bearingMode) { | |
| 859 | + | |
| 860 | + var direction; | |
| 861 | + var bearing; | |
| 862 | + | |
| 863 | + if(bearingMode == 'circle') { | |
| 864 | + // use great circle bearing | |
| 865 | + bearing = this.getBearing(originLL, destLL); | |
| 866 | + } else { | |
| 867 | + // default is rhumb line bearing | |
| 868 | + bearing = this.getRhumbLineBearing(originLL, destLL); | |
| 869 | + } | |
| 870 | + | |
| 871 | + switch(Math.round(bearing/22.5)) { | |
| 872 | + case 1: | |
| 873 | + direction = {exact: "NNE", rough: "N"}; | |
| 874 | + break; | |
| 875 | + case 2: | |
| 876 | + direction = {exact: "NE", rough: "N"}; | |
| 877 | + break; | |
| 878 | + case 3: | |
| 879 | + direction = {exact: "ENE", rough: "E"}; | |
| 880 | + break; | |
| 881 | + case 4: | |
| 882 | + direction = {exact: "E", rough: "E"}; | |
| 883 | + break; | |
| 884 | + case 5: | |
| 885 | + direction = {exact: "ESE", rough: "E"}; | |
| 886 | + break; | |
| 887 | + case 6: | |
| 888 | + direction = {exact: "SE", rough: "E"}; | |
| 889 | + break; | |
| 890 | + case 7: | |
| 891 | + direction = {exact: "SSE", rough: "S"}; | |
| 892 | + break; | |
| 893 | + case 8: | |
| 894 | + direction = {exact: "S", rough: "S"}; | |
| 895 | + break; | |
| 896 | + case 9: | |
| 897 | + direction = {exact: "SSW", rough: "S"}; | |
| 898 | + break; | |
| 899 | + case 10: | |
| 900 | + direction = {exact: "SW", rough: "S"}; | |
| 901 | + break; | |
| 902 | + case 11: | |
| 903 | + direction = {exact: "WSW", rough: "W"}; | |
| 904 | + break; | |
| 905 | + case 12: | |
| 906 | + direction = {exact: "W", rough: "W"}; | |
| 907 | + break; | |
| 908 | + case 13: | |
| 909 | + direction = {exact: "WNW", rough: "W"}; | |
| 910 | + break; | |
| 911 | + case 14: | |
| 912 | + direction = {exact: "NW", rough: "W"}; | |
| 913 | + break; | |
| 914 | + case 15: | |
| 915 | + direction = {exact: "NNW", rough: "N"}; | |
| 916 | + break; | |
| 917 | + default: | |
| 918 | + direction = {exact: "N", rough: "N"}; | |
| 919 | + } | |
| 920 | + | |
| 921 | + direction['bearing'] = bearing; | |
| 922 | + return direction; | |
| 923 | + | |
| 924 | + }, | |
| 925 | + | |
| 926 | + | |
| 927 | + /** | |
| 928 | + * Shortcut for getCompassDirection | |
| 929 | + */ | |
| 930 | + getDirection: function(originLL, destLL, bearingMode) { | |
| 931 | + return this.getCompassDirection.apply(this, arguments); | |
| 932 | + }, | |
| 933 | + | |
| 934 | + | |
| 935 | + /** | |
| 936 | + * Sorts an array of coords by distance from a reference coordinate | |
| 937 | + * | |
| 938 | + * @param object reference coordinate e.g. {latitude: 51.5023, longitude: 7.3815} | |
| 939 | + * @param mixed array or object with coords [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 940 | + * @return array ordered array | |
| 941 | + */ | |
| 942 | + orderByDistance: function(latlng, coords) { | |
| 943 | + | |
| 944 | + var coordsArray = []; | |
| 945 | + | |
| 946 | + for(var coord in coords) { | |
| 947 | + | |
| 948 | + var distance = this.getDistance(latlng, coords[coord]); | |
| 949 | + var augmentedCoord = Object.create(coords[coord]); | |
| 950 | + augmentedCoord.distance = distance; | |
| 951 | + augmentedCoord.key = coord; | |
| 952 | + | |
| 953 | + coordsArray.push(augmentedCoord); | |
| 954 | + | |
| 955 | + } | |
| 956 | + | |
| 957 | + return coordsArray.sort(function(a, b) { | |
| 958 | + return a.distance - b.distance; | |
| 959 | + }); | |
| 960 | + | |
| 961 | + }, | |
| 962 | + | |
| 963 | + /** | |
| 964 | + * Check if a point lies in line created by two other points | |
| 965 | + * | |
| 966 | + * @param object Point to check: {latitude: 123, longitude: 123} | |
| 967 | + * @param object Start of line {latitude: 123, longitude: 123} | |
| 968 | + * @param object End of line {latitude: 123, longitude: 123} | |
| 969 | + * @return boolean | |
| 970 | + */ | |
| 971 | + isPointInLine: function(point, start, end) { | |
| 972 | + | |
| 973 | + return (this.getDistance(start, point, 1, 3)+this.getDistance(point, end, 1, 3)).toFixed(3)==this.getDistance(start, end, 1, 3); | |
| 974 | + }, | |
| 975 | + | |
| 976 | + /** | |
| 977 | + * Check if a point lies within a given distance from a line created by two other points | |
| 978 | + * | |
| 979 | + * @param object Point to check: {latitude: 123, longitude: 123} | |
| 980 | + * @param object Start of line {latitude: 123, longitude: 123} | |
| 981 | + * @param object End of line {latitude: 123, longitude: 123} | |
| 982 | + * @pararm float maximum distance from line | |
| 983 | + * @return boolean | |
| 984 | + */ | |
| 985 | + isPointNearLine: function(point, start, end, distance) { | |
| 986 | + return this.getDistanceFromLine(point, start, end) < distance; | |
| 987 | + }, | |
| 988 | + | |
| 989 | + /** | |
| 990 | + * return the minimum distance from a point to a line | |
| 991 | + * | |
| 992 | + * @param object Point away from line | |
| 993 | + * @param object Start of line {latitude: 123, longitude: 123} | |
| 994 | + * @param object End of line {latitude: 123, longitude: 123} | |
| 995 | + * @return float distance from point to line | |
| 996 | + */ | |
| 997 | + getDistanceFromLine: function(point, start, end) { | |
| 998 | + var d1 = this.getDistance(start, point, 1, 3); | |
| 999 | + var d2 = this.getDistance(point, end, 1, 3); | |
| 1000 | + var d3 = this.getDistance(start, end, 1, 3); | |
| 1001 | + var distance = 0; | |
| 1002 | + | |
| 1003 | + // alpha is the angle between the line from start to point, and from start to end // | |
| 1004 | + var alpha = Math.acos((d1*d1 + d3*d3 - d2*d2)/(2*d1*d3)); | |
| 1005 | + // beta is the angle between the line from end to point and from end to start // | |
| 1006 | + var beta = Math.acos((d2*d2 + d3*d3 - d1*d1)/(2*d2*d3)); | |
| 1007 | + | |
| 1008 | + // if the angle is greater than 90 degrees, then the minimum distance is the | |
| 1009 | + // line from the start to the point // | |
| 1010 | + if(alpha>Math.PI/2) { | |
| 1011 | + distance = d1; | |
| 1012 | + } | |
| 1013 | + // same for the beta // | |
| 1014 | + else if(beta > Math.PI/2) { | |
| 1015 | + distance = d2; | |
| 1016 | + } | |
| 1017 | + // otherwise the minimum distance is achieved through a line perpendular to the start-end line, | |
| 1018 | + // which goes from the start-end line to the point // | |
| 1019 | + else { | |
| 1020 | + distance = Math.sin(alpha) * d1; | |
| 1021 | + } | |
| 1022 | + | |
| 1023 | + return distance; | |
| 1024 | + }, | |
| 1025 | + | |
| 1026 | + /** | |
| 1027 | + * Finds the nearest coordinate to a reference coordinate | |
| 1028 | + * | |
| 1029 | + * @param object reference coordinate e.g. {latitude: 51.5023, longitude: 7.3815} | |
| 1030 | + * @param mixed array or object with coords [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 1031 | + * @return array ordered array | |
| 1032 | + */ | |
| 1033 | + findNearest: function(latlng, coords, offset, limit) { | |
| 1034 | + | |
| 1035 | + offset = offset || 0; | |
| 1036 | + limit = limit || 1; | |
| 1037 | + var ordered = this.orderByDistance(latlng, coords); | |
| 1038 | + | |
| 1039 | + if(limit === 1) { | |
| 1040 | + return ordered[offset]; | |
| 1041 | + } else { | |
| 1042 | + return ordered.splice(offset, limit); | |
| 1043 | + } | |
| 1044 | + | |
| 1045 | + }, | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + /** | |
| 1049 | + * Calculates the length of a given path | |
| 1050 | + * | |
| 1051 | + * @param mixed array or object with coords [{latitude: 51.5143, longitude: 7.4138}, {latitude: 123, longitude: 123}, ...] | |
| 1052 | + * @return integer length of the path (in meters) | |
| 1053 | + */ | |
| 1054 | + getPathLength: function(coords) { | |
| 1055 | + | |
| 1056 | + var dist = 0; | |
| 1057 | + var last; | |
| 1058 | + | |
| 1059 | + for (var i = 0, l = coords.length; i < l; ++i) { | |
| 1060 | + if(last) { | |
| 1061 | + //console.log(coords[i], last, this.getDistance(coords[i], last)); | |
| 1062 | + dist += this.getDistance(this.coords(coords[i]), last); | |
| 1063 | + } | |
| 1064 | + last = this.coords(coords[i]); | |
| 1065 | + } | |
| 1066 | + | |
| 1067 | + return dist; | |
| 1068 | + | |
| 1069 | + }, | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + /** | |
| 1073 | + * Calculates the speed between to points within a given time span. | |
| 1074 | + * | |
| 1075 | + * @param object coords with javascript timestamp {latitude: 51.5143, longitude: 7.4138, time: 1360231200880} | |
| 1076 | + * @param object coords with javascript timestamp {latitude: 51.5502, longitude: 7.4323, time: 1360245600460} | |
| 1077 | + * @param object options (currently "unit" is the only option. Default: km(h)); | |
| 1078 | + * @return float speed in unit per hour | |
| 1079 | + */ | |
| 1080 | + getSpeed: function(start, end, options) { | |
| 1081 | + | |
| 1082 | + var unit = options && options.unit || 'km'; | |
| 1083 | + | |
| 1084 | + if(unit == 'mph') { | |
| 1085 | + unit = 'mi'; | |
| 1086 | + } else if(unit == 'kmh') { | |
| 1087 | + unit = 'km'; | |
| 1088 | + } | |
| 1089 | + | |
| 1090 | + var distance = geolib.getDistance(start, end); | |
| 1091 | + var time = ((end.time*1)/1000) - ((start.time*1)/1000); | |
| 1092 | + var mPerHr = (distance/time)*3600; | |
| 1093 | + var speed = Math.round(mPerHr * this.measures[unit] * 10000)/10000; | |
| 1094 | + return speed; | |
| 1095 | + | |
| 1096 | + }, | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + /** | |
| 1100 | + * Computes the destination point given an initial point, a distance | |
| 1101 | + * and a bearing | |
| 1102 | + * | |
| 1103 | + * see http://www.movable-type.co.uk/scripts/latlong.html for the original code | |
| 1104 | + * | |
| 1105 | + * @param object start coordinate (e.g. {latitude: 51.5023, longitude: 7.3815}) | |
| 1106 | + * @param float longitude of the inital point in degree | |
| 1107 | + * @param float distance to go from the inital point in meter | |
| 1108 | + * @param float bearing in degree of the direction to go, e.g. 0 = north, 180 = south | |
| 1109 | + * @param float optional (in meter), defaults to mean radius of the earth | |
| 1110 | + * @return object {latitude: destLat (in degree), longitude: destLng (in degree)} | |
| 1111 | + */ | |
| 1112 | + computeDestinationPoint: function(start, distance, bearing, radius) { | |
| 1113 | + | |
| 1114 | + var lat = this.latitude(start); | |
| 1115 | + var lng = this.longitude(start); | |
| 1116 | + | |
| 1117 | + radius = (typeof radius === 'undefined') ? this.radius : Number(radius); | |
| 1118 | + | |
| 1119 | + var δ = Number(distance) / radius; // angular distance in radians | |
| 1120 | + var θ = Number(bearing).toRad(); | |
| 1121 | + | |
| 1122 | + var φ1 = Number(lat).toRad(); | |
| 1123 | + var λ1 = Number(lng).toRad(); | |
| 1124 | + | |
| 1125 | + var φ2 = Math.asin( Math.sin(φ1)*Math.cos(δ) + | |
| 1126 | + Math.cos(φ1)*Math.sin(δ)*Math.cos(θ) ); | |
| 1127 | + var λ2 = λ1 + Math.atan2(Math.sin(θ)*Math.sin(δ)*Math.cos(φ1), | |
| 1128 | + Math.cos(δ)-Math.sin(φ1)*Math.sin(φ2)); | |
| 1129 | + λ2 = (λ2+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180° | |
| 1130 | + | |
| 1131 | + return { | |
| 1132 | + latitude: φ2.toDeg(), | |
| 1133 | + longitude: λ2.toDeg() | |
| 1134 | + }; | |
| 1135 | + | |
| 1136 | + }, | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + /** | |
| 1140 | + * Converts a distance from meters to km, mm, cm, mi, ft, in or yd | |
| 1141 | + * | |
| 1142 | + * @param string Format to be converted in | |
| 1143 | + * @param float Distance in meters | |
| 1144 | + * @param float Decimal places for rounding (default: 4) | |
| 1145 | + * @return float Converted distance | |
| 1146 | + */ | |
| 1147 | + convertUnit: function(unit, distance, round) { | |
| 1148 | + | |
| 1149 | + if(distance === 0) { | |
| 1150 | + | |
| 1151 | + return 0; | |
| 1152 | + | |
| 1153 | + } else if(typeof distance === 'undefined') { | |
| 1154 | + | |
| 1155 | + if(this.distance === null) { | |
| 1156 | + throw new Error('No distance was given'); | |
| 1157 | + } else if(this.distance === 0) { | |
| 1158 | + return 0; | |
| 1159 | + } else { | |
| 1160 | + distance = this.distance; | |
| 1161 | + } | |
| 1162 | + | |
| 1163 | + } | |
| 1164 | + | |
| 1165 | + unit = unit || 'm'; | |
| 1166 | + round = (null == round ? 4 : round); | |
| 1167 | + | |
| 1168 | + if(typeof this.measures[unit] !== 'undefined') { | |
| 1169 | + return this.round(distance * this.measures[unit], round); | |
| 1170 | + } else { | |
| 1171 | + throw new Error('Unknown unit for conversion.'); | |
| 1172 | + } | |
| 1173 | + | |
| 1174 | + }, | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + /** | |
| 1178 | + * Checks if a value is in decimal format or, if neccessary, converts to decimal | |
| 1179 | + * | |
| 1180 | + * @param mixed Value(s) to be checked/converted (array of latlng objects, latlng object, sexagesimal string, float) | |
| 1181 | + * @return float Input data in decimal format | |
| 1182 | + */ | |
| 1183 | + useDecimal: function(value) { | |
| 1184 | + | |
| 1185 | + if(Object.prototype.toString.call(value) === '[object Array]') { | |
| 1186 | + | |
| 1187 | + var geolib = this; | |
| 1188 | + | |
| 1189 | + value = value.map(function(val) { | |
| 1190 | + | |
| 1191 | + //if(!isNaN(parseFloat(val))) { | |
| 1192 | + if(geolib.isDecimal(val)) { | |
| 1193 | + | |
| 1194 | + return geolib.useDecimal(val); | |
| 1195 | + | |
| 1196 | + } else if(typeof val == 'object') { | |
| 1197 | + | |
| 1198 | + if(geolib.validate(val)) { | |
| 1199 | + | |
| 1200 | + return geolib.coords(val); | |
| 1201 | + | |
| 1202 | + } else { | |
| 1203 | + | |
| 1204 | + for(var prop in val) { | |
| 1205 | + val[prop] = geolib.useDecimal(val[prop]); | |
| 1206 | + } | |
| 1207 | + | |
| 1208 | + return val; | |
| 1209 | + | |
| 1210 | + } | |
| 1211 | + | |
| 1212 | + } else if(geolib.isSexagesimal(val)) { | |
| 1213 | + | |
| 1214 | + return geolib.sexagesimal2decimal(val); | |
| 1215 | + | |
| 1216 | + } else { | |
| 1217 | + | |
| 1218 | + return val; | |
| 1219 | + | |
| 1220 | + } | |
| 1221 | + | |
| 1222 | + }); | |
| 1223 | + | |
| 1224 | + return value; | |
| 1225 | + | |
| 1226 | + } else if(typeof value === 'object' && this.validate(value)) { | |
| 1227 | + | |
| 1228 | + return this.coords(value); | |
| 1229 | + | |
| 1230 | + } else if(typeof value === 'object') { | |
| 1231 | + | |
| 1232 | + for(var prop in value) { | |
| 1233 | + value[prop] = this.useDecimal(value[prop]); | |
| 1234 | + } | |
| 1235 | + | |
| 1236 | + return value; | |
| 1237 | + | |
| 1238 | + } | |
| 1239 | + | |
| 1240 | + | |
| 1241 | + if (this.isDecimal(value)) { | |
| 1242 | + | |
| 1243 | + return parseFloat(value); | |
| 1244 | + | |
| 1245 | + } else if(this.isSexagesimal(value) === true) { | |
| 1246 | + | |
| 1247 | + return parseFloat(this.sexagesimal2decimal(value)); | |
| 1248 | + | |
| 1249 | + } | |
| 1250 | + | |
| 1251 | + throw new Error('Unknown format.'); | |
| 1252 | + | |
| 1253 | + }, | |
| 1254 | + | |
| 1255 | + /** | |
| 1256 | + * Converts a decimal coordinate value to sexagesimal format | |
| 1257 | + * | |
| 1258 | + * @param float decimal | |
| 1259 | + * @return string Sexagesimal value (XX° YY' ZZ") | |
| 1260 | + */ | |
| 1261 | + decimal2sexagesimal: function(dec) { | |
| 1262 | + | |
| 1263 | + if (dec in this.sexagesimal) { | |
| 1264 | + return this.sexagesimal[dec]; | |
| 1265 | + } | |
| 1266 | + | |
| 1267 | + var tmp = dec.toString().split('.'); | |
| 1268 | + | |
| 1269 | + var deg = Math.abs(tmp[0]); | |
| 1270 | + var min = ('0.' + (tmp[1] || 0))*60; | |
| 1271 | + var sec = min.toString().split('.'); | |
| 1272 | + | |
| 1273 | + min = Math.floor(min); | |
| 1274 | + sec = (('0.' + (sec[1] || 0)) * 60).toFixed(2); | |
| 1275 | + | |
| 1276 | + this.sexagesimal[dec] = (deg + '° ' + min + "' " + sec + '"'); | |
| 1277 | + | |
| 1278 | + return this.sexagesimal[dec]; | |
| 1279 | + | |
| 1280 | + }, | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + /** | |
| 1284 | + * Converts a sexagesimal coordinate to decimal format | |
| 1285 | + * | |
| 1286 | + * @param float Sexagesimal coordinate | |
| 1287 | + * @return string Decimal value (XX.XXXXXXXX) | |
| 1288 | + */ | |
| 1289 | + sexagesimal2decimal: function(sexagesimal) { | |
| 1290 | + | |
| 1291 | + if (sexagesimal in this.decimal) { | |
| 1292 | + return this.decimal[sexagesimal]; | |
| 1293 | + } | |
| 1294 | + | |
| 1295 | + var regEx = new RegExp(this.sexagesimalPattern); | |
| 1296 | + var data = regEx.exec(sexagesimal); | |
| 1297 | + var min = 0, sec = 0; | |
| 1298 | + | |
| 1299 | + if(data) { | |
| 1300 | + min = parseFloat(data[2]/60); | |
| 1301 | + sec = parseFloat(data[4]/3600) || 0; | |
| 1302 | + } | |
| 1303 | + | |
| 1304 | + var dec = ((parseFloat(data[1]) + min + sec)).toFixed(8); | |
| 1305 | + //var dec = ((parseFloat(data[1]) + min + sec)); | |
| 1306 | + | |
| 1307 | + // South and West are negative decimals | |
| 1308 | + dec = (data[7] == 'S' || data[7] == 'W') ? parseFloat(-dec) : parseFloat(dec); | |
| 1309 | + //dec = (data[7] == 'S' || data[7] == 'W') ? -dec : dec; | |
| 1310 | + | |
| 1311 | + this.decimal[sexagesimal] = dec; | |
| 1312 | + | |
| 1313 | + return dec; | |
| 1314 | + | |
| 1315 | + }, | |
| 1316 | + | |
| 1317 | + | |
| 1318 | + /** | |
| 1319 | + * Checks if a value is in decimal format | |
| 1320 | + * | |
| 1321 | + * @param string Value to be checked | |
| 1322 | + * @return bool True if in sexagesimal format | |
| 1323 | + */ | |
| 1324 | + isDecimal: function(value) { | |
| 1325 | + | |
| 1326 | + value = value.toString().replace(/\s*/, ''); | |
| 1327 | + | |
| 1328 | + // looks silly but works as expected | |
| 1329 | + // checks if value is in decimal format | |
| 1330 | + return (!isNaN(parseFloat(value)) && parseFloat(value) == value); | |
| 1331 | + | |
| 1332 | + }, | |
| 1333 | + | |
| 1334 | + | |
| 1335 | + /** | |
| 1336 | + * Checks if a value is in sexagesimal format | |
| 1337 | + * | |
| 1338 | + * @param string Value to be checked | |
| 1339 | + * @return bool True if in sexagesimal format | |
| 1340 | + */ | |
| 1341 | + isSexagesimal: function(value) { | |
| 1342 | + | |
| 1343 | + value = value.toString().replace(/\s*/, ''); | |
| 1344 | + | |
| 1345 | + return this.sexagesimalPattern.test(value); | |
| 1346 | + | |
| 1347 | + }, | |
| 1348 | + | |
| 1349 | + round: function(value, n) { | |
| 1350 | + var decPlace = Math.pow(10, n); | |
| 1351 | + return Math.round(value * decPlace)/decPlace; | |
| 1352 | + } | |
| 1353 | + | |
| 1354 | + }); | |
| 1355 | + | |
| 1356 | + // Node module | |
| 1357 | + if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') { | |
| 1358 | + | |
| 1359 | + module.exports = geolib; | |
| 1360 | + | |
| 1361 | + // react native | |
| 1362 | + if (typeof global === 'object') { | |
| 1363 | + global.geolib = geolib; | |
| 1364 | + } | |
| 1365 | + | |
| 1366 | + // AMD module | |
| 1367 | + } else if (typeof define === "function" && define.amd) { | |
| 1368 | + | |
| 1369 | + define("geolib", [], function () { | |
| 1370 | + return geolib; | |
| 1371 | + }); | |
| 1372 | + | |
| 1373 | + // we're in a browser | |
| 1374 | + } else { | |
| 1375 | + | |
| 1376 | + global.geolib = geolib; | |
| 1377 | + | |
| 1378 | + } | |
| 1379 | + | |
| 1380 | +}(this)); | ... | ... |
src/main/resources/static/assets/js/geolib/geolib.min.js
0 → 100644
| 1 | +/*! geolib 2.0.21 by Manuel Bieh | |
| 2 | +* Library to provide geo functions like distance calculation, | |
| 3 | +* conversion of decimal coordinates to sexagesimal and vice versa, etc. | |
| 4 | +* WGS 84 (World Geodetic System 1984) | |
| 5 | +* | |
| 6 | +* @author Manuel Bieh | |
| 7 | +* @url http://www.manuelbieh.com/ | |
| 8 | +* @version 2.0.21 | |
| 9 | +* @license MIT | |
| 10 | +**/ | |
| 11 | +!function(a,b){"use strict";function c(){}c.TO_RAD=Math.PI/180,c.TO_DEG=180/Math.PI,c.PI_X2=2*Math.PI,c.PI_DIV4=Math.PI/4;var d=Object.create(c.prototype,{version:{value:"2.0.21"},radius:{value:6378137},minLat:{value:-90},maxLat:{value:90},minLon:{value:-180},maxLon:{value:180},sexagesimalPattern:{value:/^([0-9]{1,3})°\s*([0-9]{1,3}(?:\.(?:[0-9]{1,2}))?)'\s*(([0-9]{1,3}(\.([0-9]{1,4}))?)"\s*)?([NEOSW]?)$/},measures:{value:Object.create(Object.prototype,{m:{value:1},km:{value:.001},cm:{value:100},mm:{value:1e3},mi:{value:1/1609.344},sm:{value:1/1852.216},ft:{value:100/30.48},"in":{value:100/2.54},yd:{value:1/.9144}})},prototype:{value:c.prototype},extend:{value:function(a,b){for(var c in a)("undefined"==typeof d.prototype[c]||b===!0)&&("function"==typeof a[c]&&"function"==typeof a[c].bind?d.prototype[c]=a[c].bind(d):d.prototype[c]=a[c])}}});"undefined"==typeof Number.prototype.toRad&&(Number.prototype.toRad=function(){return this*c.TO_RAD}),"undefined"==typeof Number.prototype.toDeg&&(Number.prototype.toDeg=function(){return this*c.TO_DEG}),d.extend({decimal:{},sexagesimal:{},distance:null,getKeys:function(a){if("[object Array]"==Object.prototype.toString.call(a))return{longitude:a.length>=1?0:b,latitude:a.length>=2?1:b,elevation:a.length>=3?2:b};var c=function(b){var c;return b.every(function(b){return"object"!=typeof a?!0:a.hasOwnProperty(b)?function(){return c=b,!1}():!0}),c},d=c(["lng","lon","longitude"]),e=c(["lat","latitude"]),f=c(["alt","altitude","elevation","elev"]);return"undefined"==typeof e&&"undefined"==typeof d&&"undefined"==typeof f?b:{latitude:e,longitude:d,elevation:f}},getLat:function(a,b){return b===!0?a[this.getKeys(a).latitude]:this.useDecimal(a[this.getKeys(a).latitude])},latitude:function(a){return this.getLat.call(this,a)},getLon:function(a,b){return b===!0?a[this.getKeys(a).longitude]:this.useDecimal(a[this.getKeys(a).longitude])},longitude:function(a){return this.getLon.call(this,a)},getElev:function(a){return a[this.getKeys(a).elevation]},elevation:function(a){return this.getElev.call(this,a)},coords:function(a,b){var c={latitude:b===!0?a[this.getKeys(a).latitude]:this.useDecimal(a[this.getKeys(a).latitude]),longitude:b===!0?a[this.getKeys(a).longitude]:this.useDecimal(a[this.getKeys(a).longitude])},d=a[this.getKeys(a).elevation];return"undefined"!=typeof d&&(c.elevation=d),c},ll:function(a,b){return this.coords.call(this,a,b)},validate:function(a){var b=this.getKeys(a);if("undefined"==typeof b||"undefined"==typeof b.latitude||"undefined"===b.longitude)return!1;var c=a[b.latitude],d=a[b.longitude];return"undefined"==typeof c||!this.isDecimal(c)&&!this.isSexagesimal(c)?!1:"undefined"==typeof d||!this.isDecimal(d)&&!this.isSexagesimal(d)?!1:(c=this.useDecimal(c),d=this.useDecimal(d),c<this.minLat||c>this.maxLat||d<this.minLon||d>this.maxLon?!1:!0)},getDistance:function(a,b,c,e){c=Math.floor(c)||1,e=Math.floor(e)||0;var f,g,h,i,j,k,l,m=this.coords(a),n=this.coords(b),o=6378137,p=6356752.314245,q=1/298.257223563,r=(n.longitude-m.longitude).toRad(),s=Math.atan((1-q)*Math.tan(parseFloat(m.latitude).toRad())),t=Math.atan((1-q)*Math.tan(parseFloat(n.latitude).toRad())),u=Math.sin(s),v=Math.cos(s),w=Math.sin(t),x=Math.cos(t),y=r,z=100;do{var A=Math.sin(y),B=Math.cos(y);if(k=Math.sqrt(x*A*(x*A)+(v*w-u*x*B)*(v*w-u*x*B)),0===k)return d.distance=0;f=u*w+v*x*B,g=Math.atan2(k,f),h=v*x*A/k,i=1-h*h,j=f-2*u*w/i,isNaN(j)&&(j=0);var C=q/16*i*(4+q*(4-3*i));l=y,y=r+(1-C)*q*h*(g+C*k*(j+C*f*(-1+2*j*j)))}while(Math.abs(y-l)>1e-12&&--z>0);if(0===z)return NaN;var D=i*(o*o-p*p)/(p*p),E=1+D/16384*(4096+D*(-768+D*(320-175*D))),F=D/1024*(256+D*(-128+D*(74-47*D))),G=F*k*(j+F/4*(f*(-1+2*j*j)-F/6*j*(-3+4*k*k)*(-3+4*j*j))),H=p*E*(g-G);if(H=H.toFixed(e),"undefined"!=typeof this.elevation(a)&&"undefined"!=typeof this.elevation(b)){var I=Math.abs(this.elevation(a)-this.elevation(b));H=Math.sqrt(H*H+I*I)}return this.distance=Math.round(H*Math.pow(10,e)/c)*c/Math.pow(10,e)},getDistanceSimple:function(a,b,c){c=Math.floor(c)||1;var e=Math.round(Math.acos(Math.sin(this.latitude(b).toRad())*Math.sin(this.latitude(a).toRad())+Math.cos(this.latitude(b).toRad())*Math.cos(this.latitude(a).toRad())*Math.cos(this.longitude(a).toRad()-this.longitude(b).toRad()))*this.radius);return d.distance=Math.floor(Math.round(e/c)*c)},getCenter:function(a){var b=a;if("object"==typeof a&&!(a instanceof Array)){b=[];for(var d in a)b.push(this.coords(a[d]))}if(!b.length)return!1;var e,f,g,h=0,i=0,j=0;b.forEach(function(a){e=this.latitude(a).toRad(),f=this.longitude(a).toRad(),h+=Math.cos(e)*Math.cos(f),i+=Math.cos(e)*Math.sin(f),j+=Math.sin(e)},this);var k=b.length;return h/=k,i/=k,j/=k,f=Math.atan2(i,h),g=Math.sqrt(h*h+i*i),e=Math.atan2(j,g),{latitude:(e*c.TO_DEG).toFixed(6),longitude:(f*c.TO_DEG).toFixed(6)}},getBounds:function(a){if(!a.length)return!1;var b=this.elevation(a[0]),c={maxLat:-(1/0),minLat:1/0,maxLng:-(1/0),minLng:1/0};"undefined"!=typeof b&&(c.maxElev=0,c.minElev=1/0);for(var d=0,e=a.length;e>d;++d)c.maxLat=Math.max(this.latitude(a[d]),c.maxLat),c.minLat=Math.min(this.latitude(a[d]),c.minLat),c.maxLng=Math.max(this.longitude(a[d]),c.maxLng),c.minLng=Math.min(this.longitude(a[d]),c.minLng),b&&(c.maxElev=Math.max(this.elevation(a[d]),c.maxElev),c.minElev=Math.min(this.elevation(a[d]),c.minElev));return c},getCenterOfBounds:function(a){var b=this.getBounds(a),c=b.minLat+(b.maxLat-b.minLat)/2,d=b.minLng+(b.maxLng-b.minLng)/2;return{latitude:parseFloat(c.toFixed(6)),longitude:parseFloat(d.toFixed(6))}},getBoundsOfDistance:function(a,b){var d,e,f=this.latitude(a),g=this.longitude(a),h=f.toRad(),i=g.toRad(),j=b/this.radius,k=h-j,l=h+j,m=this.maxLat.toRad(),n=this.minLat.toRad(),o=this.maxLon.toRad(),p=this.minLon.toRad();if(k>n&&m>l){var q=Math.asin(Math.sin(j)/Math.cos(h));d=i-q,p>d&&(d+=c.PI_X2),e=i+q,e>o&&(e-=c.PI_X2)}else k=Math.max(k,n),l=Math.min(l,m),d=p,e=o;return[{latitude:k.toDeg(),longitude:d.toDeg()},{latitude:l.toDeg(),longitude:e.toDeg()}]},isPointInside:function(a,b){for(var c=!1,d=-1,e=b.length,f=e-1;++d<e;f=d)(this.longitude(b[d])<=this.longitude(a)&&this.longitude(a)<this.longitude(b[f])||this.longitude(b[f])<=this.longitude(a)&&this.longitude(a)<this.longitude(b[d]))&&this.latitude(a)<(this.latitude(b[f])-this.latitude(b[d]))*(this.longitude(a)-this.longitude(b[d]))/(this.longitude(b[f])-this.longitude(b[d]))+this.latitude(b[d])&&(c=!c);return c},preparePolygonForIsPointInsideOptimized:function(a){for(var b=0,c=a.length-1;b<a.length;b++)this.longitude(a[c])===this.longitude(a[b])?(a[b].constant=this.latitude(a[b]),a[b].multiple=0):(a[b].constant=this.latitude(a[b])-this.longitude(a[b])*this.latitude(a[c])/(this.longitude(a[c])-this.longitude(a[b]))+this.longitude(a[b])*this.latitude(a[b])/(this.longitude(a[c])-this.longitude(a[b])),a[b].multiple=(this.latitude(a[c])-this.latitude(a[b]))/(this.longitude(a[c])-this.longitude(a[b]))),c=b},isPointInsideWithPreparedPolygon:function(a,b){for(var c=!1,d=this.longitude(a),e=this.latitude(a),f=0,g=b.length-1;f<b.length;f++)(this.longitude(b[f])<d&&this.longitude(b[g])>=d||this.longitude(b[g])<d&&this.longitude(b[f])>=d)&&(c^=d*b[f].multiple+b[f].constant<e),g=f;return c},isInside:function(){return this.isPointInside.apply(this,arguments)},isPointInCircle:function(a,b,c){return this.getDistance(a,b)<c},withinRadius:function(){return this.isPointInCircle.apply(this,arguments)},getRhumbLineBearing:function(a,b){var d=this.longitude(b).toRad()-this.longitude(a).toRad(),e=Math.log(Math.tan(this.latitude(b).toRad()/2+c.PI_DIV4)/Math.tan(this.latitude(a).toRad()/2+c.PI_DIV4));return Math.abs(d)>Math.PI&&(d=d>0?-1*(c.PI_X2-d):c.PI_X2+d),(Math.atan2(d,e).toDeg()+360)%360},getBearing:function(a,b){b.latitude=this.latitude(b),b.longitude=this.longitude(b),a.latitude=this.latitude(a),a.longitude=this.longitude(a);var c=(Math.atan2(Math.sin(b.longitude.toRad()-a.longitude.toRad())*Math.cos(b.latitude.toRad()),Math.cos(a.latitude.toRad())*Math.sin(b.latitude.toRad())-Math.sin(a.latitude.toRad())*Math.cos(b.latitude.toRad())*Math.cos(b.longitude.toRad()-a.longitude.toRad())).toDeg()+360)%360;return c},getCompassDirection:function(a,b,c){var d,e;switch(e="circle"==c?this.getBearing(a,b):this.getRhumbLineBearing(a,b),Math.round(e/22.5)){case 1:d={exact:"NNE",rough:"N"};break;case 2:d={exact:"NE",rough:"N"};break;case 3:d={exact:"ENE",rough:"E"};break;case 4:d={exact:"E",rough:"E"};break;case 5:d={exact:"ESE",rough:"E"};break;case 6:d={exact:"SE",rough:"E"};break;case 7:d={exact:"SSE",rough:"S"};break;case 8:d={exact:"S",rough:"S"};break;case 9:d={exact:"SSW",rough:"S"};break;case 10:d={exact:"SW",rough:"S"};break;case 11:d={exact:"WSW",rough:"W"};break;case 12:d={exact:"W",rough:"W"};break;case 13:d={exact:"WNW",rough:"W"};break;case 14:d={exact:"NW",rough:"W"};break;case 15:d={exact:"NNW",rough:"N"};break;default:d={exact:"N",rough:"N"}}return d.bearing=e,d},getDirection:function(a,b,c){return this.getCompassDirection.apply(this,arguments)},orderByDistance:function(a,b){var c=[];for(var d in b){var e=this.getDistance(a,b[d]),f=Object.create(b[d]);f.distance=e,f.key=d,c.push(f)}return c.sort(function(a,b){return a.distance-b.distance})},isPointInLine:function(a,b,c){return(this.getDistance(b,a,1,3)+this.getDistance(a,c,1,3)).toFixed(3)==this.getDistance(b,c,1,3)},isPointNearLine:function(a,b,c,d){return this.getDistanceFromLine(a,b,c)<d},getDistanceFromLine:function(a,b,c){var d=this.getDistance(b,a,1,3),e=this.getDistance(a,c,1,3),f=this.getDistance(b,c,1,3),g=0,h=Math.acos((d*d+f*f-e*e)/(2*d*f)),i=Math.acos((e*e+f*f-d*d)/(2*e*f));return g=h>Math.PI/2?d:i>Math.PI/2?e:Math.sin(h)*d},findNearest:function(a,b,c,d){c=c||0,d=d||1;var e=this.orderByDistance(a,b);return 1===d?e[c]:e.splice(c,d)},getPathLength:function(a){for(var b,c=0,d=0,e=a.length;e>d;++d)b&&(c+=this.getDistance(this.coords(a[d]),b)),b=this.coords(a[d]);return c},getSpeed:function(a,b,c){var e=c&&c.unit||"km";"mph"==e?e="mi":"kmh"==e&&(e="km");var f=d.getDistance(a,b),g=1*b.time/1e3-1*a.time/1e3,h=f/g*3600,i=Math.round(h*this.measures[e]*1e4)/1e4;return i},computeDestinationPoint:function(a,b,c,d){var e=this.latitude(a),f=this.longitude(a);d="undefined"==typeof d?this.radius:Number(d);var g=Number(b)/d,h=Number(c).toRad(),i=Number(e).toRad(),j=Number(f).toRad(),k=Math.asin(Math.sin(i)*Math.cos(g)+Math.cos(i)*Math.sin(g)*Math.cos(h)),l=j+Math.atan2(Math.sin(h)*Math.sin(g)*Math.cos(i),Math.cos(g)-Math.sin(i)*Math.sin(k));return l=(l+3*Math.PI)%(2*Math.PI)-Math.PI,{latitude:k.toDeg(),longitude:l.toDeg()}},convertUnit:function(a,b,c){if(0===b)return 0;if("undefined"==typeof b){if(null===this.distance)throw new Error("No distance was given");if(0===this.distance)return 0;b=this.distance}if(a=a||"m",c=null==c?4:c,"undefined"!=typeof this.measures[a])return this.round(b*this.measures[a],c);throw new Error("Unknown unit for conversion.")},useDecimal:function(a){if("[object Array]"===Object.prototype.toString.call(a)){var b=this;return a=a.map(function(a){if(b.isDecimal(a))return b.useDecimal(a);if("object"==typeof a){if(b.validate(a))return b.coords(a);for(var c in a)a[c]=b.useDecimal(a[c]);return a}return b.isSexagesimal(a)?b.sexagesimal2decimal(a):a})}if("object"==typeof a&&this.validate(a))return this.coords(a);if("object"==typeof a){for(var c in a)a[c]=this.useDecimal(a[c]);return a}if(this.isDecimal(a))return parseFloat(a);if(this.isSexagesimal(a)===!0)return parseFloat(this.sexagesimal2decimal(a));throw new Error("Unknown format.")},decimal2sexagesimal:function(a){if(a in this.sexagesimal)return this.sexagesimal[a];var b=a.toString().split("."),c=Math.abs(b[0]),d=60*("0."+(b[1]||0)),e=d.toString().split(".");return d=Math.floor(d),e=(60*("0."+(e[1]||0))).toFixed(2),this.sexagesimal[a]=c+"° "+d+"' "+e+'"',this.sexagesimal[a]},sexagesimal2decimal:function(a){if(a in this.decimal)return this.decimal[a];var b=new RegExp(this.sexagesimalPattern),c=b.exec(a),d=0,e=0;c&&(d=parseFloat(c[2]/60),e=parseFloat(c[4]/3600)||0);var f=(parseFloat(c[1])+d+e).toFixed(8);return f="S"==c[7]||"W"==c[7]?parseFloat(-f):parseFloat(f),this.decimal[a]=f,f},isDecimal:function(a){return a=a.toString().replace(/\s*/,""),!isNaN(parseFloat(a))&&parseFloat(a)==a},isSexagesimal:function(a){return a=a.toString().replace(/\s*/,""),this.sexagesimalPattern.test(a)},round:function(a,b){var c=Math.pow(10,b);return Math.round(a*c)/c}}),"undefined"!=typeof module&&"undefined"!=typeof module.exports?(module.exports=d,"object"==typeof a&&(a.geolib=d)):"function"==typeof define&&define.amd?define("geolib",[],function(){return d}):a.geolib=d}(this); | |
| 0 | 12 | \ No newline at end of file | ... | ... |
src/main/resources/static/assets/js/plugins/qrcode.min.js
0 → 100644
| 1 | +var QRCode;!function(){function a(a){this.mode=c.MODE_8BIT_BYTE,this.data=a,this.parsedData=[];for(var b=[],d=0,e=this.data.length;e>d;d++){var f=this.data.charCodeAt(d);f>65536?(b[0]=240|(1835008&f)>>>18,b[1]=128|(258048&f)>>>12,b[2]=128|(4032&f)>>>6,b[3]=128|63&f):f>2048?(b[0]=224|(61440&f)>>>12,b[1]=128|(4032&f)>>>6,b[2]=128|63&f):f>128?(b[0]=192|(1984&f)>>>6,b[1]=128|63&f):b[0]=f,this.parsedData=this.parsedData.concat(b)}this.parsedData.length!=this.data.length&&(this.parsedData.unshift(191),this.parsedData.unshift(187),this.parsedData.unshift(239))}function b(a,b){this.typeNumber=a,this.errorCorrectLevel=b,this.modules=null,this.moduleCount=0,this.dataCache=null,this.dataList=[]}function i(a,b){if(void 0==a.length)throw new Error(a.length+"/"+b);for(var c=0;c<a.length&&0==a[c];)c++;this.num=new Array(a.length-c+b);for(var d=0;d<a.length-c;d++)this.num[d]=a[d+c]}function j(a,b){this.totalCount=a,this.dataCount=b}function k(){this.buffer=[],this.length=0}function m(){return"undefined"!=typeof CanvasRenderingContext2D}function n(){var a=!1,b=navigator.userAgent;return/android/i.test(b)&&(a=!0,aMat=b.toString().match(/android ([0-9]\.[0-9])/i),aMat&&aMat[1]&&(a=parseFloat(aMat[1]))),a}function r(a,b){for(var c=1,e=s(a),f=0,g=l.length;g>=f;f++){var h=0;switch(b){case d.L:h=l[f][0];break;case d.M:h=l[f][1];break;case d.Q:h=l[f][2];break;case d.H:h=l[f][3]}if(h>=e)break;c++}if(c>l.length)throw new Error("Too long data");return c}function s(a){var b=encodeURI(a).toString().replace(/\%[0-9a-fA-F]{2}/g,"a");return b.length+(b.length!=a?3:0)}a.prototype={getLength:function(){return this.parsedData.length},write:function(a){for(var b=0,c=this.parsedData.length;c>b;b++)a.put(this.parsedData[b],8)}},b.prototype={addData:function(b){var c=new a(b);this.dataList.push(c),this.dataCache=null},isDark:function(a,b){if(0>a||this.moduleCount<=a||0>b||this.moduleCount<=b)throw new Error(a+","+b);return this.modules[a][b]},getModuleCount:function(){return this.moduleCount},make:function(){this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17,this.modules=new Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=new Array(this.moduleCount);for(var e=0;e<this.moduleCount;e++)this.modules[d][e]=null}this.setupPositionProbePattern(0,0),this.setupPositionProbePattern(this.moduleCount-7,0),this.setupPositionProbePattern(0,this.moduleCount-7),this.setupPositionAdjustPattern(),this.setupTimingPattern(),this.setupTypeInfo(a,c),this.typeNumber>=7&&this.setupTypeNumber(a),null==this.dataCache&&(this.dataCache=b.createData(this.typeNumber,this.errorCorrectLevel,this.dataList)),this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,b){for(var c=-1;7>=c;c++)if(!(-1>=a+c||this.moduleCount<=a+c))for(var d=-1;7>=d;d++)-1>=b+d||this.moduleCount<=b+d||(this.modules[a+c][b+d]=c>=0&&6>=c&&(0==d||6==d)||d>=0&&6>=d&&(0==c||6==c)||c>=2&&4>=c&&d>=2&&4>=d?!0:!1)},getBestMaskPattern:function(){for(var a=0,b=0,c=0;8>c;c++){this.makeImpl(!0,c);var d=f.getLostPoint(this);(0==c||a>d)&&(a=d,b=c)}return b},createMovieClip:function(a,b,c){var d=a.createEmptyMovieClip(b,c),e=1;this.make();for(var f=0;f<this.modules.length;f++)for(var g=f*e,h=0;h<this.modules[f].length;h++){var i=h*e,j=this.modules[f][h];j&&(d.beginFill(0,100),d.moveTo(i,g),d.lineTo(i+e,g),d.lineTo(i+e,g+e),d.lineTo(i,g+e),d.endFill())}return d},setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(var b=8;b<this.moduleCount-8;b++)null==this.modules[6][b]&&(this.modules[6][b]=0==b%2)},setupPositionAdjustPattern:function(){for(var a=f.getPatternPosition(this.typeNumber),b=0;b<a.length;b++)for(var c=0;c<a.length;c++){var d=a[b],e=a[c];if(null==this.modules[d][e])for(var g=-2;2>=g;g++)for(var h=-2;2>=h;h++)this.modules[d+g][e+h]=-2==g||2==g||-2==h||2==h||0==g&&0==h?!0:!1}},setupTypeNumber:function(a){for(var b=f.getBCHTypeNumber(this.typeNumber),c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[Math.floor(c/3)][c%3+this.moduleCount-8-3]=d}for(var c=0;18>c;c++){var d=!a&&1==(1&b>>c);this.modules[c%3+this.moduleCount-8-3][Math.floor(c/3)]=d}},setupTypeInfo:function(a,b){for(var c=this.errorCorrectLevel<<3|b,d=f.getBCHTypeInfo(c),e=0;15>e;e++){var g=!a&&1==(1&d>>e);6>e?this.modules[e][8]=g:8>e?this.modules[e+1][8]=g:this.modules[this.moduleCount-15+e][8]=g}for(var e=0;15>e;e++){var g=!a&&1==(1&d>>e);8>e?this.modules[8][this.moduleCount-e-1]=g:9>e?this.modules[8][15-e-1+1]=g:this.modules[8][15-e-1]=g}this.modules[this.moduleCount-8][8]=!a},mapData:function(a,b){for(var c=-1,d=this.moduleCount-1,e=7,g=0,h=this.moduleCount-1;h>0;h-=2)for(6==h&&h--;;){for(var i=0;2>i;i++)if(null==this.modules[d][h-i]){var j=!1;g<a.length&&(j=1==(1&a[g]>>>e));var k=f.getMask(b,d,h-i);k&&(j=!j),this.modules[d][h-i]=j,e--,-1==e&&(g++,e=7)}if(d+=c,0>d||this.moduleCount<=d){d-=c,c=-c;break}}}},b.PAD0=236,b.PAD1=17,b.createData=function(a,c,d){for(var e=j.getRSBlocks(a,c),g=new k,h=0;h<d.length;h++){var i=d[h];g.put(i.mode,4),g.put(i.getLength(),f.getLengthInBits(i.mode,a)),i.write(g)}for(var l=0,h=0;h<e.length;h++)l+=e[h].dataCount;if(g.getLengthInBits()>8*l)throw new Error("code length overflow. ("+g.getLengthInBits()+">"+8*l+")");for(g.getLengthInBits()+4<=8*l&&g.put(0,4);0!=g.getLengthInBits()%8;)g.putBit(!1);for(;;){if(g.getLengthInBits()>=8*l)break;if(g.put(b.PAD0,8),g.getLengthInBits()>=8*l)break;g.put(b.PAD1,8)}return b.createBytes(g,e)},b.createBytes=function(a,b){for(var c=0,d=0,e=0,g=new Array(b.length),h=new Array(b.length),j=0;j<b.length;j++){var k=b[j].dataCount,l=b[j].totalCount-k;d=Math.max(d,k),e=Math.max(e,l),g[j]=new Array(k);for(var m=0;m<g[j].length;m++)g[j][m]=255&a.buffer[m+c];c+=k;var n=f.getErrorCorrectPolynomial(l),o=new i(g[j],n.getLength()-1),p=o.mod(n);h[j]=new Array(n.getLength()-1);for(var m=0;m<h[j].length;m++){var q=m+p.getLength()-h[j].length;h[j][m]=q>=0?p.get(q):0}}for(var r=0,m=0;m<b.length;m++)r+=b[m].totalCount;for(var s=new Array(r),t=0,m=0;d>m;m++)for(var j=0;j<b.length;j++)m<g[j].length&&(s[t++]=g[j][m]);for(var m=0;e>m;m++)for(var j=0;j<b.length;j++)m<h[j].length&&(s[t++]=h[j][m]);return s};for(var c={MODE_NUMBER:1,MODE_ALPHA_NUM:2,MODE_8BIT_BYTE:4,MODE_KANJI:8},d={L:1,M:0,Q:3,H:2},e={PATTERN000:0,PATTERN001:1,PATTERN010:2,PATTERN011:3,PATTERN100:4,PATTERN101:5,PATTERN110:6,PATTERN111:7},f={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var b=a<<10;f.getBCHDigit(b)-f.getBCHDigit(f.G15)>=0;)b^=f.G15<<f.getBCHDigit(b)-f.getBCHDigit(f.G15);return(a<<10|b)^f.G15_MASK},getBCHTypeNumber:function(a){for(var b=a<<12;f.getBCHDigit(b)-f.getBCHDigit(f.G18)>=0;)b^=f.G18<<f.getBCHDigit(b)-f.getBCHDigit(f.G18);return a<<12|b},getBCHDigit:function(a){for(var b=0;0!=a;)b++,a>>>=1;return b},getPatternPosition:function(a){return f.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,b,c){switch(a){case e.PATTERN000:return 0==(b+c)%2;case e.PATTERN001:return 0==b%2;case e.PATTERN010:return 0==c%3;case e.PATTERN011:return 0==(b+c)%3;case e.PATTERN100:return 0==(Math.floor(b/2)+Math.floor(c/3))%2;case e.PATTERN101:return 0==b*c%2+b*c%3;case e.PATTERN110:return 0==(b*c%2+b*c%3)%2;case e.PATTERN111:return 0==(b*c%3+(b+c)%2)%2;default:throw new Error("bad maskPattern:"+a)}},getErrorCorrectPolynomial:function(a){for(var b=new i([1],0),c=0;a>c;c++)b=b.multiply(new i([1,g.gexp(c)],0));return b},getLengthInBits:function(a,b){if(b>=1&&10>b)switch(a){case c.MODE_NUMBER:return 10;case c.MODE_ALPHA_NUM:return 9;case c.MODE_8BIT_BYTE:return 8;case c.MODE_KANJI:return 8;default:throw new Error("mode:"+a)}else if(27>b)switch(a){case c.MODE_NUMBER:return 12;case c.MODE_ALPHA_NUM:return 11;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 10;default:throw new Error("mode:"+a)}else{if(!(41>b))throw new Error("type:"+b);switch(a){case c.MODE_NUMBER:return 14;case c.MODE_ALPHA_NUM:return 13;case c.MODE_8BIT_BYTE:return 16;case c.MODE_KANJI:return 12;default:throw new Error("mode:"+a)}}},getLostPoint:function(a){for(var b=a.getModuleCount(),c=0,d=0;b>d;d++)for(var e=0;b>e;e++){for(var f=0,g=a.isDark(d,e),h=-1;1>=h;h++)if(!(0>d+h||d+h>=b))for(var i=-1;1>=i;i++)0>e+i||e+i>=b||(0!=h||0!=i)&&g==a.isDark(d+h,e+i)&&f++;f>5&&(c+=3+f-5)}for(var d=0;b-1>d;d++)for(var e=0;b-1>e;e++){var j=0;a.isDark(d,e)&&j++,a.isDark(d+1,e)&&j++,a.isDark(d,e+1)&&j++,a.isDark(d+1,e+1)&&j++,(0==j||4==j)&&(c+=3)}for(var d=0;b>d;d++)for(var e=0;b-6>e;e++)a.isDark(d,e)&&!a.isDark(d,e+1)&&a.isDark(d,e+2)&&a.isDark(d,e+3)&&a.isDark(d,e+4)&&!a.isDark(d,e+5)&&a.isDark(d,e+6)&&(c+=40);for(var e=0;b>e;e++)for(var d=0;b-6>d;d++)a.isDark(d,e)&&!a.isDark(d+1,e)&&a.isDark(d+2,e)&&a.isDark(d+3,e)&&a.isDark(d+4,e)&&!a.isDark(d+5,e)&&a.isDark(d+6,e)&&(c+=40);for(var k=0,e=0;b>e;e++)for(var d=0;b>d;d++)a.isDark(d,e)&&k++;var l=Math.abs(100*k/b/b-50)/5;return c+=10*l}},g={glog:function(a){if(1>a)throw new Error("glog("+a+")");return g.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;a>=256;)a-=255;return g.EXP_TABLE[a]},EXP_TABLE:new Array(256),LOG_TABLE:new Array(256)},h=0;8>h;h++)g.EXP_TABLE[h]=1<<h;for(var h=8;256>h;h++)g.EXP_TABLE[h]=g.EXP_TABLE[h-4]^g.EXP_TABLE[h-5]^g.EXP_TABLE[h-6]^g.EXP_TABLE[h-8];for(var h=0;255>h;h++)g.LOG_TABLE[g.EXP_TABLE[h]]=h;i.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var b=new Array(this.getLength()+a.getLength()-1),c=0;c<this.getLength();c++)for(var d=0;d<a.getLength();d++)b[c+d]^=g.gexp(g.glog(this.get(c))+g.glog(a.get(d)));return new i(b,0)},mod:function(a){if(this.getLength()-a.getLength()<0)return this;for(var b=g.glog(this.get(0))-g.glog(a.get(0)),c=new Array(this.getLength()),d=0;d<this.getLength();d++)c[d]=this.get(d);for(var d=0;d<a.getLength();d++)c[d]^=g.gexp(g.glog(a.get(d))+b);return new i(c,0).mod(a)}},j.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]],j.getRSBlocks=function(a,b){var c=j.getRsBlockTable(a,b);if(void 0==c)throw new Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+b);for(var d=c.length/3,e=[],f=0;d>f;f++)for(var g=c[3*f+0],h=c[3*f+1],i=c[3*f+2],k=0;g>k;k++)e.push(new j(h,i));return e},j.getRsBlockTable=function(a,b){switch(b){case d.L:return j.RS_BLOCK_TABLE[4*(a-1)+0];case d.M:return j.RS_BLOCK_TABLE[4*(a-1)+1];case d.Q:return j.RS_BLOCK_TABLE[4*(a-1)+2];case d.H:return j.RS_BLOCK_TABLE[4*(a-1)+3];default:return void 0}},k.prototype={get:function(a){var b=Math.floor(a/8);return 1==(1&this.buffer[b]>>>7-a%8)},put:function(a,b){for(var c=0;b>c;c++)this.putBit(1==(1&a>>>b-c-1))},getLengthInBits:function(){return this.length},putBit:function(a){var b=Math.floor(this.length/8);this.buffer.length<=b&&this.buffer.push(0),a&&(this.buffer[b]|=128>>>this.length%8),this.length++}};var l=[[17,14,11,7],[32,26,20,14],[53,42,32,24],[78,62,46,34],[106,84,60,44],[134,106,74,58],[154,122,86,64],[192,152,108,84],[230,180,130,98],[271,213,151,119],[321,251,177,137],[367,287,203,155],[425,331,241,177],[458,362,258,194],[520,412,292,220],[586,450,322,250],[644,504,364,280],[718,560,394,310],[792,624,442,338],[858,666,482,382],[929,711,509,403],[1003,779,565,439],[1091,857,611,461],[1171,911,661,511],[1273,997,715,535],[1367,1059,751,593],[1465,1125,805,625],[1528,1190,868,658],[1628,1264,908,698],[1732,1370,982,742],[1840,1452,1030,790],[1952,1538,1112,842],[2068,1628,1168,898],[2188,1722,1228,958],[2303,1809,1283,983],[2431,1911,1351,1051],[2563,1989,1423,1093],[2699,2099,1499,1139],[2809,2213,1579,1219],[2953,2331,1663,1273]],o=function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){function g(a,b){var c=document.createElementNS("http://www.w3.org/2000/svg",a);for(var d in b)b.hasOwnProperty(d)&&c.setAttribute(d,b[d]);return c}var b=this._htOption,c=this._el,d=a.getModuleCount();Math.floor(b.width/d),Math.floor(b.height/d),this.clear();var h=g("svg",{viewBox:"0 0 "+String(d)+" "+String(d),width:"100%",height:"100%",fill:b.colorLight});h.setAttributeNS("http://www.w3.org/2000/xmlns/","xmlns:xlink","http://www.w3.org/1999/xlink"),c.appendChild(h),h.appendChild(g("rect",{fill:b.colorDark,width:"1",height:"1",id:"template"}));for(var i=0;d>i;i++)for(var j=0;d>j;j++)if(a.isDark(i,j)){var k=g("use",{x:String(i),y:String(j)});k.setAttributeNS("http://www.w3.org/1999/xlink","href","#template"),h.appendChild(k)}},a.prototype.clear=function(){for(;this._el.hasChildNodes();)this._el.removeChild(this._el.lastChild)},a}(),p="svg"===document.documentElement.tagName.toLowerCase(),q=p?o:m()?function(){function a(){this._elImage.src=this._elCanvas.toDataURL("image/png"),this._elImage.style.display="block",this._elCanvas.style.display="none"}function d(a,b){var c=this;if(c._fFail=b,c._fSuccess=a,null===c._bSupportDataURI){var d=document.createElement("img"),e=function(){c._bSupportDataURI=!1,c._fFail&&_fFail.call(c)},f=function(){c._bSupportDataURI=!0,c._fSuccess&&c._fSuccess.call(c)};return d.onabort=e,d.onerror=e,d.onload=f,d.src="data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==",void 0}c._bSupportDataURI===!0&&c._fSuccess?c._fSuccess.call(c):c._bSupportDataURI===!1&&c._fFail&&c._fFail.call(c)}if(this._android&&this._android<=2.1){var b=1/window.devicePixelRatio,c=CanvasRenderingContext2D.prototype.drawImage;CanvasRenderingContext2D.prototype.drawImage=function(a,d,e,f,g,h,i,j){if("nodeName"in a&&/img/i.test(a.nodeName))for(var l=arguments.length-1;l>=1;l--)arguments[l]=arguments[l]*b;else"undefined"==typeof j&&(arguments[1]*=b,arguments[2]*=b,arguments[3]*=b,arguments[4]*=b);c.apply(this,arguments)}}var e=function(a,b){this._bIsPainted=!1,this._android=n(),this._htOption=b,this._elCanvas=document.createElement("canvas"),this._elCanvas.width=b.width,this._elCanvas.height=b.height,a.appendChild(this._elCanvas),this._el=a,this._oContext=this._elCanvas.getContext("2d"),this._bIsPainted=!1,this._elImage=document.createElement("img"),this._elImage.style.display="none",this._el.appendChild(this._elImage),this._bSupportDataURI=null};return e.prototype.draw=function(a){var b=this._elImage,c=this._oContext,d=this._htOption,e=a.getModuleCount(),f=d.width/e,g=d.height/e,h=Math.round(f),i=Math.round(g);b.style.display="none",this.clear();for(var j=0;e>j;j++)for(var k=0;e>k;k++){var l=a.isDark(j,k),m=k*f,n=j*g;c.strokeStyle=l?d.colorDark:d.colorLight,c.lineWidth=1,c.fillStyle=l?d.colorDark:d.colorLight,c.fillRect(m,n,f,g),c.strokeRect(Math.floor(m)+.5,Math.floor(n)+.5,h,i),c.strokeRect(Math.ceil(m)-.5,Math.ceil(n)-.5,h,i)}this._bIsPainted=!0},e.prototype.makeImage=function(){this._bIsPainted&&d.call(this,a)},e.prototype.isPainted=function(){return this._bIsPainted},e.prototype.clear=function(){this._oContext.clearRect(0,0,this._elCanvas.width,this._elCanvas.height),this._bIsPainted=!1},e.prototype.round=function(a){return a?Math.floor(1e3*a)/1e3:a},e}():function(){var a=function(a,b){this._el=a,this._htOption=b};return a.prototype.draw=function(a){for(var b=this._htOption,c=this._el,d=a.getModuleCount(),e=Math.floor(b.width/d),f=Math.floor(b.height/d),g=['<table style="border:0;border-collapse:collapse;">'],h=0;d>h;h++){g.push("<tr>");for(var i=0;d>i;i++)g.push('<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:'+e+"px;height:"+f+"px;background-color:"+(a.isDark(h,i)?b.colorDark:b.colorLight)+';"></td>');g.push("</tr>")}g.push("</table>"),c.innerHTML=g.join("");var j=c.childNodes[0],k=(b.width-j.offsetWidth)/2,l=(b.height-j.offsetHeight)/2;k>0&&l>0&&(j.style.margin=l+"px "+k+"px")},a.prototype.clear=function(){this._el.innerHTML=""},a}();QRCode=function(a,b){if(this._htOption={width:256,height:256,typeNumber:4,colorDark:"#000000",colorLight:"#ffffff",correctLevel:d.H},"string"==typeof b&&(b={text:b}),b)for(var c in b)this._htOption[c]=b[c];"string"==typeof a&&(a=document.getElementById(a)),this._android=n(),this._el=a,this._oQRCode=null,this._oDrawing=new q(this._el,this._htOption),this._htOption.text&&this.makeCode(this._htOption.text)},QRCode.prototype.makeCode=function(a){this._oQRCode=new b(r(a,this._htOption.correctLevel),this._htOption.correctLevel),this._oQRCode.addData(a),this._oQRCode.make(),this._el.title=a,this._oDrawing.draw(this._oQRCode),this.makeImage()},QRCode.prototype.makeImage=function(){"function"==typeof this._oDrawing.makeImage&&(!this._android||this._android>=3)&&this._oDrawing.makeImage()},QRCode.prototype.clear=function(){this._oDrawing.clear()},QRCode.CorrectLevel=d}(); | |
| 0 | 2 | \ No newline at end of file | ... | ... |
src/main/resources/static/index.html
| ... | ... | @@ -60,20 +60,21 @@ |
| 60 | 60 | </a> |
| 61 | 61 | </li> |
| 62 | 62 | <li class="nav-item "> |
| 63 | - <a class="nav-link" title="所有通过 “carMonitor” 接口发布的预测,事后与实际GPS到站匹配" href="/pages/charts_data/accuracy.html"> | |
| 63 | + <a class="nav-link" title="所有通过 “carMonitor” 接口发布的预测,事后与实际GPS到站匹配" | |
| 64 | + href="/pages/charts_data/accuracy.html"> | |
| 64 | 65 | <i class="material-icons">spellcheck</i> |
| 65 | 66 | <p>信息发布准确性</p> |
| 66 | 67 | </a> |
| 67 | 68 | </li> |
| 68 | 69 | |
| 69 | 70 | <li class="nav-item disabled"> |
| 70 | - <a class="nav-link" > | |
| 71 | + <a class="nav-link"> | |
| 71 | 72 | <i class="material-icons">history</i> |
| 72 | 73 | <p>历史发布查询</p> |
| 73 | 74 | </a> |
| 74 | 75 | </li> |
| 75 | 76 | <li class="nav-item disabled"> |
| 76 | - <a class="nav-link" > | |
| 77 | + <a class="nav-link"> | |
| 77 | 78 | <i class="material-icons">bar_chart</i> |
| 78 | 79 | <p>统计分析</p> |
| 79 | 80 | </a> |
| ... | ... | @@ -102,6 +103,12 @@ |
| 102 | 103 | |
| 103 | 104 | <ul class="navbar-nav"> |
| 104 | 105 | <li class="nav-item"> |
| 106 | + <a class="nav-link phone_popover_qr_code"> | |
| 107 | + | |
| 108 | + </a> | |
| 109 | + </li> | |
| 110 | + | |
| 111 | + <li class="nav-item"> | |
| 105 | 112 | <a class="nav-link"> |
| 106 | 113 | panzhao <i class="material-icons">person</i> |
| 107 | 114 | </a> |
| ... | ... | @@ -134,7 +141,7 @@ |
| 134 | 141 | <script src="/assets/js/plugins/d3.min.js"></script> |
| 135 | 142 | <script src="/assets/js/plugins/moment/moment.min.js"></script> |
| 136 | 143 | <script src="/assets/js/plugins/moment/zh-cn.js"></script> |
| 137 | - | |
| 144 | +<script src="/assets/js/plugins/qrcode.min.js"></script> | |
| 138 | 145 | |
| 139 | 146 | <script type="text/javascript" src="//api.map.baidu.com/api?ak=IGGrr4UjwIYzatoCRFKEL8sT&v=3.0"></script> |
| 140 | 147 | <script src="/pages/geo_data/js/map_utils.js"></script> |
| ... | ... | @@ -144,6 +151,20 @@ |
| 144 | 151 | var loadShade = '.main-panel .content_shade.c_s_load' |
| 145 | 152 | var exitCallbackFun; |
| 146 | 153 | $(function () { |
| 154 | + var m_url = window.location.href + 'pages/m/m.html'; | |
| 155 | + var qrcode = new QRCode($('.phone_popover_qr_code')[0], { | |
| 156 | + text: m_url, | |
| 157 | + width: 64, | |
| 158 | + height: 64, | |
| 159 | + colorDark: "#000000", | |
| 160 | + colorLight: "#ffffff", | |
| 161 | + correctLevel: QRCode.CorrectLevel.H | |
| 162 | + }); | |
| 163 | + | |
| 164 | + $('.phone_popover_qr_code').on('click', function () { | |
| 165 | + window.open(m_url); | |
| 166 | + }); | |
| 167 | + | |
| 147 | 168 | $('.left_menus ul>li.nav-item>a').on('click', function () { |
| 148 | 169 | if (exitCallbackFun) { |
| 149 | 170 | exitCallbackFun(); |
| ... | ... | @@ -152,7 +173,7 @@ |
| 152 | 173 | |
| 153 | 174 | var h = $(this).attr('href') |
| 154 | 175 | , t = $(this).attr('title'); |
| 155 | - if(!h) | |
| 176 | + if (!h) | |
| 156 | 177 | return; |
| 157 | 178 | |
| 158 | 179 | t = t ? t : $('p', this).text(); |
| ... | ... | @@ -194,7 +215,7 @@ |
| 194 | 215 | } |
| 195 | 216 | } |
| 196 | 217 | })(document.createElement('div')); |
| 197 | - | |
| 218 | + | |
| 198 | 219 | $.fn.extend({ |
| 199 | 220 | animateCss: function (animationName, callback) { |
| 200 | 221 | ... | ... |
src/main/resources/static/pages/m/m.html
0 → 100644
| 1 | +<!DOCTYPE html> | |
| 2 | +<html lang="en"> | |
| 3 | + | |
| 4 | +<head> | |
| 5 | + <meta charset="utf-8"> | |
| 6 | + <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/> | |
| 7 | + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> | |
| 8 | + <!-- Favicons --> | |
| 9 | + <link rel="icon" href="/assets/img/favicon.png"> | |
| 10 | + <title>信息发布测试</title> | |
| 11 | + <!-- Fonts and icons --> | |
| 12 | + <link rel="stylesheet" type="text/css" href="/assets/css/font.css"/> | |
| 13 | + <link rel="stylesheet" href="/assets/css/bootstrap-material-design.min.css"> | |
| 14 | + | |
| 15 | + <style> | |
| 16 | + html, body { | |
| 17 | + background: #f4f4f4; | |
| 18 | + height: 100%; | |
| 19 | + } | |
| 20 | + | |
| 21 | + .top_wrap { | |
| 22 | + background: #fff; | |
| 23 | + height: 138px; | |
| 24 | + } | |
| 25 | + | |
| 26 | + .ct_auto_wrap { | |
| 27 | + position: relative; | |
| 28 | + display: inline-block; | |
| 29 | + width: 100%; | |
| 30 | + } | |
| 31 | + | |
| 32 | + .ct_autocompleter_rs { | |
| 33 | + position: absolute; | |
| 34 | + z-index: 2; | |
| 35 | + background: #fefefe; | |
| 36 | + width: 100%; | |
| 37 | + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12); | |
| 38 | + margin-top: 10px; | |
| 39 | + } | |
| 40 | + | |
| 41 | + .line_detail_info { | |
| 42 | + font-size: 14px; | |
| 43 | + padding-left: 15px; | |
| 44 | + position: relative; | |
| 45 | + padding-bottom: 5px; | |
| 46 | + } | |
| 47 | + | |
| 48 | + .line_detail_info > div { | |
| 49 | + margin-bottom: 7px; | |
| 50 | + } | |
| 51 | + | |
| 52 | + .line_detail_info .sub_info { | |
| 53 | + font-size: 12px; | |
| 54 | + } | |
| 55 | + | |
| 56 | + .line_detail_info .sub_info span.badge { | |
| 57 | + vertical-align: top; | |
| 58 | + } | |
| 59 | + | |
| 60 | + .line_detail_info i { | |
| 61 | + color: #999999; | |
| 62 | + vertical-align: middle; | |
| 63 | + margin-top: -3px; | |
| 64 | + } | |
| 65 | + | |
| 66 | + .line_detail_info .change_updown_icon i { | |
| 67 | + position: absolute; | |
| 68 | + right: 20px; | |
| 69 | + font-size: 20px; | |
| 70 | + top: 2px; | |
| 71 | + color: #6565ff; | |
| 72 | + } | |
| 73 | + | |
| 74 | + .top_form .form-group > label, | |
| 75 | + .top_form .form-group input { | |
| 76 | + text-indent: 15px | |
| 77 | + } | |
| 78 | + | |
| 79 | + .station_chart_wrap { | |
| 80 | + background: #fff; | |
| 81 | + height: calc(100% - 236px); | |
| 82 | + margin-top: 9px; | |
| 83 | + overflow: auto; | |
| 84 | + position: relative; | |
| 85 | + } | |
| 86 | + | |
| 87 | + .near_txt { | |
| 88 | + position: absolute; | |
| 89 | + color: blue; | |
| 90 | + font-size: 14px; | |
| 91 | + } | |
| 92 | + | |
| 93 | + .publish_infos { | |
| 94 | + background: #fff; | |
| 95 | + height: 80px; | |
| 96 | + margin-top: 9px; | |
| 97 | + } | |
| 98 | + | |
| 99 | + /** | |
| 100 | + svg | |
| 101 | + */ | |
| 102 | + text.station_text { | |
| 103 | + letter-spacing: -.5px; | |
| 104 | + font-size: 13px; | |
| 105 | + } | |
| 106 | + | |
| 107 | + text.station_text.active { | |
| 108 | + fill: red; | |
| 109 | + } | |
| 110 | + | |
| 111 | + path.station_link { | |
| 112 | + stroke-width: 1.5px; | |
| 113 | + stroke: #cfd1cf; | |
| 114 | + transform: translate(-15px, 0); | |
| 115 | + } | |
| 116 | + | |
| 117 | + path.cut_link { | |
| 118 | + stroke-width: .5px; | |
| 119 | + stroke: #dedede; | |
| 120 | + } | |
| 121 | + | |
| 122 | + text.circle_no { | |
| 123 | + transform: translate(-18px, 0); | |
| 124 | + font-size: 11px; | |
| 125 | + fill: #fff; | |
| 126 | + } | |
| 127 | + | |
| 128 | + circle.station_circle { | |
| 129 | + fill: #cfd1cf; | |
| 130 | + r: 9; | |
| 131 | + stroke: #ffffff; | |
| 132 | + stroke-width: 2; | |
| 133 | + transform: translate(-16px, -4px); | |
| 134 | + } | |
| 135 | + | |
| 136 | + svg g.gps-wrap > rect { | |
| 137 | + width: 64px; | |
| 138 | + height: 15px; | |
| 139 | + rx: 2px; | |
| 140 | + cursor: pointer; | |
| 141 | + stroke: #c94f21; | |
| 142 | + fill: #c94f21; | |
| 143 | + transform: translate(-10px, -11px); | |
| 144 | + } | |
| 145 | + | |
| 146 | + svg g.gps-wrap > text { | |
| 147 | + font-size: 12px; | |
| 148 | + fill: #fff; | |
| 149 | + transform: translate(-9px, 1px); | |
| 150 | + } | |
| 151 | + | |
| 152 | + .publish_infos { | |
| 153 | + display: -webkit-flex; | |
| 154 | + display: flex; | |
| 155 | + } | |
| 156 | + | |
| 157 | + .publish_infos > div { | |
| 158 | + -webkit-flex: 1; | |
| 159 | + flex: 1; | |
| 160 | + text-align: center; | |
| 161 | + height: 51px; | |
| 162 | + margin-top: 15px; | |
| 163 | + border-right: 1px solid #efefef; | |
| 164 | + color: #2196F3; | |
| 165 | + font-size: 12px; | |
| 166 | + } | |
| 167 | + | |
| 168 | + .publish_infos > div > h6 { | |
| 169 | + font-size: 12px; | |
| 170 | + color: grey; | |
| 171 | + } | |
| 172 | + | |
| 173 | + .publish_infos > div:last-child { | |
| 174 | + border-right: none; | |
| 175 | + } | |
| 176 | + | |
| 177 | + .publish_infos span.no { | |
| 178 | + font-size: 18px; | |
| 179 | + } | |
| 180 | + | |
| 181 | + .publish_infos span.no.red, | |
| 182 | + .publish_infos > div > h6.red { | |
| 183 | + color: #e22a2a; | |
| 184 | + font-size: 12px; | |
| 185 | + } | |
| 186 | + | |
| 187 | + .publish_infos span.no.red { | |
| 188 | + margin-top: 6px; | |
| 189 | + display: block; | |
| 190 | + margin-bottom: 2px; | |
| 191 | + } | |
| 192 | + </style> | |
| 193 | +</head> | |
| 194 | + | |
| 195 | +<body> | |
| 196 | +<div class="top_wrap"> | |
| 197 | + <div class="top_form"> | |
| 198 | + <form onsubmit="return false;"> | |
| 199 | + <div class="form-group"> | |
| 200 | + <label for="lineInput" class="bmd-label-floating">输入线路</label> | |
| 201 | + <div class="ct_auto_wrap line_autocompleter"> | |
| 202 | + <input type="text" class="form-control" id="lineInput"> | |
| 203 | + </div> | |
| 204 | + </div> | |
| 205 | + </form> | |
| 206 | + </div> | |
| 207 | + | |
| 208 | + <div class="line_detail_info"></div> | |
| 209 | +</div> | |
| 210 | + | |
| 211 | +<div class="station_chart_wrap"> | |
| 212 | + <svg></svg> | |
| 213 | +</div> | |
| 214 | +<div class="publish_infos"></div> | |
| 215 | + | |
| 216 | +<script id="line_detail_info-temp" type="text/html"> | |
| 217 | + <div class="change_updown_icon"> | |
| 218 | + <i class="material-icons">repeat</i> | |
| 219 | + </div> | |
| 220 | + <div> | |
| 221 | + {{qd}} | |
| 222 | + <i class="material-icons">arrow_right</i> | |
| 223 | + {{zd}} | |
| 224 | + </div> | |
| 225 | + <div class="sub_info"> | |
| 226 | + <span class="badge badge-primary">首</span> {{t1}} | |
| 227 | + <span class="badge badge-danger">末</span> {{t2}} | |
| 228 | + </div> | |
| 229 | +</script> | |
| 230 | +</body> | |
| 231 | + | |
| 232 | +<script src="/assets/js/core/jquery.min.js"></script> | |
| 233 | +<script src="/assets/js/plugins/template.js"></script> | |
| 234 | +<script src="/assets/js/plugins/popper.min.js"></script> | |
| 235 | +<script src="/assets/js/bootstrap-material-design.min.js"></script> | |
| 236 | +<script src="/assets/js/utils/ct_autocompleter.js"></script> | |
| 237 | +<script src="/assets/js/plugins/d3.min.js"></script> | |
| 238 | +<script src="/assets/js/plugins/moment/moment.min.js"></script> | |
| 239 | +<script src="/assets/js/geolib/geolib.min.js"></script> | |
| 240 | + | |
| 241 | +<script> | |
| 242 | + $('body').bootstrapMaterialDesign(); | |
| 243 | + var lineMaps = {}; | |
| 244 | + | |
| 245 | + var _curr; | |
| 246 | + //线路自动补全 | |
| 247 | + $.get('/basic/lines', function (rs) { | |
| 248 | + var data = [], item; | |
| 249 | + for (var i = 0, len = rs.length; i < len; i++) { | |
| 250 | + item = rs[i]; | |
| 251 | + data.push({ | |
| 252 | + code: item.lineCode, | |
| 253 | + text: item.name, | |
| 254 | + others: [item.fullChars, item.camelChars] | |
| 255 | + }); | |
| 256 | + | |
| 257 | + lineMaps[item.lineCode] = { | |
| 258 | + qd: item.startStationName, | |
| 259 | + zd: item.endStationName, | |
| 260 | + st_0: item.startStationFirstTime, | |
| 261 | + et_0: item.startStationEndTime, | |
| 262 | + st_1: item.endStationFirstTime, | |
| 263 | + et_1: item.endStationEndTime | |
| 264 | + } | |
| 265 | + } | |
| 266 | + gb_ct_autocompleter.build($('.line_autocompleter', '.top_form'), data); | |
| 267 | + }); | |
| 268 | + | |
| 269 | + //线路选择事件 | |
| 270 | + $('.line_autocompleter input', '.top_form').on('auto_change', function () { | |
| 271 | + var lineCode = $(this).data('val'); | |
| 272 | + | |
| 273 | + _curr = { | |
| 274 | + lineCode: lineCode, | |
| 275 | + upDown: 0 | |
| 276 | + } | |
| 277 | + | |
| 278 | + $.get('/geo_data/stations/' + lineCode, function (rs) { | |
| 279 | + _curr.data = rs.stations; | |
| 280 | + | |
| 281 | + clearTimeout(timer); | |
| 282 | + timer = null; | |
| 283 | + changeDetailInfo(); | |
| 284 | + }); | |
| 285 | + }); | |
| 286 | + | |
| 287 | + var changeDetailInfo = function () { | |
| 288 | + var info = lineMaps[_curr.lineCode] | |
| 289 | + , data; | |
| 290 | + | |
| 291 | + if (_curr.upDown == 0) { | |
| 292 | + data = { | |
| 293 | + qd: info.qd, | |
| 294 | + zd: info.zd, | |
| 295 | + t1: info.st_0, | |
| 296 | + t2: info.et_0 | |
| 297 | + } | |
| 298 | + } | |
| 299 | + else { | |
| 300 | + data = { | |
| 301 | + qd: info.zd, | |
| 302 | + zd: info.qd, | |
| 303 | + t1: info.st_1, | |
| 304 | + t2: info.et_1 | |
| 305 | + } | |
| 306 | + } | |
| 307 | + | |
| 308 | + var htmlStr = template('line_detail_info-temp', data); | |
| 309 | + $('.line_detail_info').html(htmlStr); | |
| 310 | + | |
| 311 | + //站点图 | |
| 312 | + showStationChart(); | |
| 313 | + }; | |
| 314 | + | |
| 315 | + var showStationChart = function () { | |
| 316 | + var srs = _curr.data[_curr.upDown]; | |
| 317 | + //当前有选中站点 | |
| 318 | + var $cs = $('text.station_text.active'); | |
| 319 | + _call_info = []; | |
| 320 | + if ($cs.length > 0) { | |
| 321 | + var name = $cs.text(); | |
| 322 | + var station; | |
| 323 | + var ci; | |
| 324 | + for (var i = 0, len = srs.length; i < len; i++) { | |
| 325 | + if (srs[i].name == name) { | |
| 326 | + station = srs[i] | |
| 327 | + ci = i; | |
| 328 | + break; | |
| 329 | + } | |
| 330 | + } | |
| 331 | + | |
| 332 | + if (station) { | |
| 333 | + _call_info.auto = 1; | |
| 334 | + _call_info.id = station.stationCode; | |
| 335 | + _call_info.ci = ci; | |
| 336 | + _call_info.srs = srs; | |
| 337 | + } | |
| 338 | + } | |
| 339 | + drawSvgCharts(srs); | |
| 340 | + | |
| 341 | + if (_call_info.auto) { | |
| 342 | + _call_info.auto = null; | |
| 343 | + var $text = $('text.station_text[_id=' + _call_info.id + ']').trigger('click'); | |
| 344 | + | |
| 345 | + $('.station_chart_wrap').animate({ | |
| 346 | + scrollTop: $text.attr('y') - 25 | |
| 347 | + }); | |
| 348 | + } | |
| 349 | + } | |
| 350 | + | |
| 351 | + var drawSvgCharts = function (data) { | |
| 352 | + var wrap = '.station_chart_wrap'; | |
| 353 | + var len = data.length; | |
| 354 | + var h = len * 65; | |
| 355 | + | |
| 356 | + var yScale = d3.scale.linear().range([30, h - 30]).domain([0, len - 1]); | |
| 357 | + var cx = 105; | |
| 358 | + var cy = function (d, i) { | |
| 359 | + return yScale(i); | |
| 360 | + }; | |
| 361 | + var tText = function (d, i) { | |
| 362 | + return d.name.replace('(', '(').replace(')', ')'); | |
| 363 | + }; | |
| 364 | + | |
| 365 | + var line = d3.svg.line().x(cx).y(yScale); | |
| 366 | + | |
| 367 | + $('svg', wrap).empty(); | |
| 368 | + var svg = d3.select('svg', wrap).style('height', h); | |
| 369 | + //add item g | |
| 370 | + var items = svg.selectAll('g.item').data(data) | |
| 371 | + .enter().append('g').classed({ | |
| 372 | + 'item': true | |
| 373 | + }); | |
| 374 | + | |
| 375 | + //text | |
| 376 | + items.append('text').classed({'station_text': true}) | |
| 377 | + .text(tText) | |
| 378 | + .attr('x', cx) | |
| 379 | + .attr('y', cy) | |
| 380 | + .attr('_id', function (d) { | |
| 381 | + return d.stationCode; | |
| 382 | + }); | |
| 383 | + | |
| 384 | + //path | |
| 385 | + items.append('path').classed({'station_link': true}) | |
| 386 | + .attr('d', function (d, i) { | |
| 387 | + return i < len - 1 ? line([i, i + 1]) : ''; | |
| 388 | + }); | |
| 389 | + | |
| 390 | + //circle | |
| 391 | + items.append('circle').classed({'station_circle': true}) | |
| 392 | + .attr('cx', cx) | |
| 393 | + .attr('cy', cy) | |
| 394 | + .attr('data-id', function (d) { | |
| 395 | + return d.stationCode; | |
| 396 | + }); | |
| 397 | + | |
| 398 | + //circle num | |
| 399 | + items.append('text').classed({'circle_no': true}) | |
| 400 | + .attr('x', function (d, i) { | |
| 401 | + return i >= 9 ? cx - 4.7 : cx - 1; | |
| 402 | + }) | |
| 403 | + .attr('y', cy) | |
| 404 | + .text(function (d, i) { | |
| 405 | + return i + 1; | |
| 406 | + }); | |
| 407 | + | |
| 408 | + //分割线 | |
| 409 | + var w = $(wrap).width(); | |
| 410 | + items.append('path').classed({'cut_link': true}) | |
| 411 | + .attr('d', function (d, i) { | |
| 412 | + var y = yScale(i) + 26; | |
| 413 | + return i == len - 1 ? 'M15,' + y + 'L' + w + ',' + y : 'M85,' + y + 'L' + w + ',' + y; | |
| 414 | + }); | |
| 415 | + | |
| 416 | + svg.append('g').classed({ | |
| 417 | + 'gps-wrap': true | |
| 418 | + }); | |
| 419 | + | |
| 420 | + //定位到最靠近的站点 | |
| 421 | + if(!_call_info.auto) | |
| 422 | + focusNearStation(data); | |
| 423 | + $('.publish_infos').empty(); | |
| 424 | + } | |
| 425 | + | |
| 426 | + var focusNearStation = function (arr) { | |
| 427 | + $('.near_txt', '.station_chart_wrap').remove(); | |
| 428 | + navigator.geolocation.getCurrentPosition(function (position) { | |
| 429 | + | |
| 430 | + var near; | |
| 431 | + var point = {latitude: position.coords.latitude, longitude: position.coords.longitude} | |
| 432 | + , sp; | |
| 433 | + var distance, min = -1; | |
| 434 | + for (var i = 0, len = arr.length; i < len; i++) { | |
| 435 | + sp = {latitude: arr[i].lat, longitude: arr[i].lon}; | |
| 436 | + | |
| 437 | + distance = geolib.getDistance(point, sp); | |
| 438 | + | |
| 439 | + if (min == -1 || distance < min) { | |
| 440 | + min = distance; | |
| 441 | + near = arr[i]; | |
| 442 | + } | |
| 443 | + } | |
| 444 | + | |
| 445 | + if (min < 2000 && near) { | |
| 446 | + var $text = $('text.station_text[_id=' + near.stationCode + ']', '.station_chart_wrap'); | |
| 447 | + var x = parseFloat($text.attr('x')) + $text[0].getBBox().width; | |
| 448 | + var y = $text.attr('y') - 15; | |
| 449 | + | |
| 450 | + var $nt = $('<span class="near_txt" style="top: ' + y + 'px;left: ' + x + 'px;">(离我最近)</span>'); | |
| 451 | + $('.station_chart_wrap').append($nt); | |
| 452 | + | |
| 453 | + //滚动条 | |
| 454 | + $('.station_chart_wrap').animate({ | |
| 455 | + scrollTop: y - 10 | |
| 456 | + }); | |
| 457 | + } | |
| 458 | + }, null, {enableHighAccuracy: true}); | |
| 459 | + }; | |
| 460 | + | |
| 461 | + $(document).on('click', 'svg text.station_text', function () { | |
| 462 | + $('text.station_text.active').attr('class', 'station_text'); | |
| 463 | + $(this).attr('class', 'station_text active'); | |
| 464 | + | |
| 465 | + var _id = $(this).attr('_id'); | |
| 466 | + var ci; | |
| 467 | + var srs = _curr.data[_curr.upDown]; | |
| 468 | + for (var i = 0, len = srs.length; i < len; i++) { | |
| 469 | + if (srs[i].stationCode == _id) { | |
| 470 | + ci = i; | |
| 471 | + break; | |
| 472 | + } | |
| 473 | + } | |
| 474 | + | |
| 475 | + _call_info.id = _id; | |
| 476 | + _call_info.ci = ci; | |
| 477 | + _call_info.srs = srs; | |
| 478 | + start_call_xxfb(); | |
| 479 | + }); | |
| 480 | + | |
| 481 | + var delay = 1000 * 7; | |
| 482 | + var timer; | |
| 483 | + var _call_info = {}; | |
| 484 | + var start_call_xxfb = function () { | |
| 485 | + //定时调用信息发布接口 | |
| 486 | + if (timer) { | |
| 487 | + clearTimeout(timer); | |
| 488 | + timer = null; | |
| 489 | + } | |
| 490 | + | |
| 491 | + (function () { | |
| 492 | + var f = arguments.callee; | |
| 493 | + _call_xxfb(function () { | |
| 494 | + timer = setTimeout(f, delay); | |
| 495 | + }); | |
| 496 | + })(); | |
| 497 | + } | |
| 498 | + | |
| 499 | + var _call_xxfb = function (cb) { | |
| 500 | + //调用信息发布接口 /xxfb/carMonitor | |
| 501 | + $.ajax({ | |
| 502 | + url: '/xxfb/carMonitor?lineid=' + _curr.lineCode + '&direction=' + _curr.upDown + '&stopid=' + _call_info.id, | |
| 503 | + dataType: 'xml', | |
| 504 | + success: function (data) { | |
| 505 | + var array = []; | |
| 506 | + $(data).find('car').each(function () { | |
| 507 | + var stopdis = parseInt($('stopdis', this).text()); | |
| 508 | + array.push({ | |
| 509 | + terminal: $('terminal', this).text(), | |
| 510 | + stopdis: stopdis, | |
| 511 | + distance: $('distance', this).text(), | |
| 512 | + time: $('time', this).text(), | |
| 513 | + sCode: _call_info.srs[_call_info.ci - stopdis].stationCode | |
| 514 | + }); | |
| 515 | + }); | |
| 516 | + | |
| 517 | + showXXFBResult(array); | |
| 518 | + | |
| 519 | + cb && cb(); | |
| 520 | + } | |
| 521 | + }); | |
| 522 | + } | |
| 523 | + | |
| 524 | + var gps_key = function (d) { | |
| 525 | + return d.terminal; | |
| 526 | + }; | |
| 527 | + | |
| 528 | + var tx_id = function (d) { | |
| 529 | + return 'tx_' + d.terminal; | |
| 530 | + }; | |
| 531 | + var g_text = function (d) { | |
| 532 | + return !d.terminal ? 'null' : d.terminal.replace('-', ''); | |
| 533 | + }; | |
| 534 | + var line_gps_index = {}; | |
| 535 | + var showXXFBResult = function (data) { | |
| 536 | + data.sort(function (a, b) { | |
| 537 | + return a.stopdis - b.stopdis; | |
| 538 | + }); | |
| 539 | + var array = data.slice(0, 3); | |
| 540 | + var htmlStr = ''; | |
| 541 | + var seconds; | |
| 542 | + for (var i = 0, len = array.length; i < len; i++) { | |
| 543 | + seconds = parseInt(array[i].time / 60); | |
| 544 | + if (seconds == 0) | |
| 545 | + htmlStr += '<div><span class="no red">即将到站</span><h6 class="red">' + array[i].stopdis + '站</h6></div>'; | |
| 546 | + else | |
| 547 | + htmlStr += '<div><span class="no">' + seconds + '</span>分<h6>' + array[i].stopdis + '站</h6></div>'; | |
| 548 | + } | |
| 549 | + $('.publish_infos').html(htmlStr); | |
| 550 | + | |
| 551 | + | |
| 552 | + var svg = d3.select('.station_chart_wrap svg'); | |
| 553 | + var gps_cont = svg.select('.gps-wrap'); | |
| 554 | + | |
| 555 | + line_gps_index = gps_index_mapp(data); | |
| 556 | + //rect | |
| 557 | + var rects = gps_cont.selectAll('rect').data(data, gps_key); | |
| 558 | + rects.enter().append('rect'); | |
| 559 | + rects.exit().remove(); | |
| 560 | + | |
| 561 | + gps_update_point(rects, svg); | |
| 562 | + | |
| 563 | + //text | |
| 564 | + var ts = gps_cont.selectAll('text').data(data, gps_key); | |
| 565 | + ts.enter().append('text'); | |
| 566 | + ts.exit().remove(); | |
| 567 | + ts.text(g_text) | |
| 568 | + gps_update_point(ts, svg); | |
| 569 | + }; | |
| 570 | + | |
| 571 | + var gps_index_mapp = function (data) { | |
| 572 | + var rs = {}; | |
| 573 | + var dataGroupStop = groupByStation(data); | |
| 574 | + for (var stopNo in dataGroupStop) { | |
| 575 | + rs[stopNo] = {}; | |
| 576 | + $.each(dataGroupStop[stopNo], function (i, gps) { | |
| 577 | + rs[stopNo][gps.terminal] = i; | |
| 578 | + }); | |
| 579 | + } | |
| 580 | + return rs; | |
| 581 | + }; | |
| 582 | + | |
| 583 | + var groupByStation = function (data) { | |
| 584 | + var rs = {}, | |
| 585 | + key; | |
| 586 | + $.each(data, function () { | |
| 587 | + key = this['sCode']; | |
| 588 | + if (!rs[key]) | |
| 589 | + rs[key] = []; | |
| 590 | + | |
| 591 | + rs[key].push(this); | |
| 592 | + }); | |
| 593 | + | |
| 594 | + return rs; | |
| 595 | + }; | |
| 596 | + | |
| 597 | + var get_circle = function (dataId, svg) { | |
| 598 | + try { | |
| 599 | + var circle = $('.station_circle[data-id=' + dataId + ']', svg[0]); | |
| 600 | + if (circle.length == 0) | |
| 601 | + circle = null; | |
| 602 | + } catch (e) { | |
| 603 | + console.log('get_circle error! station_circle data-id:' + dataId); | |
| 604 | + return null; | |
| 605 | + } | |
| 606 | + return circle; | |
| 607 | + }; | |
| 608 | + | |
| 609 | + var gx = function (gps, svg, wrapId) { | |
| 610 | + var circle = get_circle(gps.sCode, svg); | |
| 611 | + if (!circle) return -300; | |
| 612 | + | |
| 613 | + var x = circle.attr('cx') - 80; | |
| 614 | + return x; | |
| 615 | + }; | |
| 616 | + | |
| 617 | + var gy = function (gps, svg) { | |
| 618 | + var circle = get_circle(gps.sCode, svg); | |
| 619 | + if (!circle) return -300; | |
| 620 | + | |
| 621 | + var cy = parseInt(circle.attr('cy')), | |
| 622 | + index = line_gps_index[gps.sCode][gps.terminal]; | |
| 623 | + | |
| 624 | + if (index >= 3) | |
| 625 | + return -100; | |
| 626 | + return cy + (index * 19); | |
| 627 | + }; | |
| 628 | + | |
| 629 | + function gps_update_point(e, svg) { | |
| 630 | + var x; | |
| 631 | + | |
| 632 | + e.attr('x', function (d) { | |
| 633 | + x = gx(d, svg); | |
| 634 | + if (x == -100) | |
| 635 | + $(this).css('transition-duration', 0).hide(); | |
| 636 | + else | |
| 637 | + $(this).show();//找不到停靠点,直接隐藏 | |
| 638 | + return x; | |
| 639 | + }) | |
| 640 | + .attr('y', function (d) { | |
| 641 | + return gy(d, svg); | |
| 642 | + }); | |
| 643 | + } | |
| 644 | + | |
| 645 | + $(document).on('click', '.change_updown_icon', function () { | |
| 646 | + if (!_curr) | |
| 647 | + return; | |
| 648 | + | |
| 649 | + _curr.upDown = _curr.upDown ? 0 : 1; | |
| 650 | + changeDetailInfo(); | |
| 651 | + }); | |
| 652 | +</script> | |
| 653 | +</html> | ... | ... |