Commit 61370ebd1d9807353feaed6475451561c86f6d51

Authored by panzh
1 parent 56af947d

update...

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
... ... @@ -370,3 +370,7 @@ li.nav-item.disabled i.material-icons {
370 370 color: #cacaca;
371 371 cursor: no-drop;
372 372 }
  373 +
  374 +.phone_popover_qr_code{
  375 + cursor: pointer;
  376 +}
... ...
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}} &nbsp; &nbsp;
  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>
... ...