@2gis/general
Advanced tools
Comparing version 2.1.0 to 3.0.0
@@ -1,2 +0,2 @@ | ||
!function(r,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.General=n():r.General=n()}(window,function(){return function(r){var n={};function e(t){if(n[t])return n[t].exports;var o=n[t]={i:t,l:!1,exports:{}};return r[t].call(o.exports,o,o.exports,e),o.l=!0,o.exports}return e.m=r,e.c=n,e.d=function(r,n,t){e.o(r,n)||Object.defineProperty(r,n,{enumerable:!0,get:t})},e.r=function(r){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(r,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(r,"__esModule",{value:!0})},e.t=function(r,n){if(1&n&&(r=e(r)),8&n)return r;if(4&n&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(e.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&n&&"string"!=typeof r)for(var o in r)e.d(t,o,function(n){return r[n]}.bind(null,o));return t},e.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return e.d(n,"a",n),n},e.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},e.p="/dist/",e(e.s=4)}([function(r,n,e){"use strict";e.d(n,"a",function(){return o}),e.d(n,"c",function(){return i}),e.d(n,"b",function(){return a}),e.d(n,"d",function(){return u});var t=0,o={pixelPositionX:t++,pixelPositionY:t++,groupIndex:t++,iconIndex:t++,priority:t++},i=Object.keys(o).length;function a(r,n){for(var e=0,t=0;e<n.length;e++,t+=i){var a=n[e];r[t+o.pixelPositionX]=a.pixelPosition[0],r[t+o.pixelPositionY]=a.pixelPosition[1],r[t+o.groupIndex]=a.groupIndex,r[t+o.iconIndex]=a.iconIndex,r[t+o.priority]=Boolean(a.priority)?1:0}}function u(r,n){for(var e=0,t=0;e<r.length;e++,t+=i)r[e].iconIndex=n[t+o.iconIndex]}},function(r,n,e){"use strict";e.d(n,"a",function(){return o}),e.d(n,"c",function(){return i}),e.d(n,"b",function(){return a}),e.d(n,"d",function(){return u});var t=0,o={markerIndex:t++,offsetX:t++,offsetY:t++,width:t++,height:t++,display:t++,minZoom:t++},i=7;function a(r,n,e){for(var t=0,a=0;a<n.length;a++){var u=n[a].htmlLabel;void 0!==u&&(r[t+o.markerIndex]=a,r[t+o.offsetX]=u.offset[0]*e,r[t+o.offsetY]=u.offset[1]*e,r[t+o.width]=u.width*e,r[t+o.height]=u.height*e,r[t+o.display]=u.display?1:0,r[t+o.minZoom]=u.minZoom,t+=i)}}function u(r,n){for(var e=0,t=0,a=r;t<a.length;t++){var u=a[t].htmlLabel;void 0!==u&&(u.display=1===n[e+o.display],u.minZoom=n[e+o.minZoom],e+=i)}}},function(r,n,e){function t(r){var n={};function e(t){if(n[t])return n[t].exports;var o=n[t]={i:t,l:!1,exports:{}};return r[t].call(o.exports,o,o.exports,e),o.l=!0,o.exports}e.m=r,e.c=n,e.i=function(r){return r},e.d=function(r,n,t){e.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get:t})},e.r=function(r){Object.defineProperty(r,"__esModule",{value:!0})},e.n=function(r){var n=r&&r.__esModule?function(){return r.default}:function(){return r};return e.d(n,"a",n),n},e.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},e.p="/",e.oe=function(r){throw console.error(r),r};var t=e(e.s=ENTRY_MODULE);return t.default||t}var o="[\\.|\\-|\\+|\\w|/|@]+",i="\\(\\s*(/\\*.*?\\*/)?\\s*.*?("+o+").*?\\)";function a(r){return(r+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function u(r,n,t){var u={};u[t]=[];var f=n.toString(),c=f.match(/^function\s?\w*\(\w+,\s*\w+,\s*(\w+)\)/);if(!c)return u;for(var m,s=c[1],l=new RegExp("(\\\\n|\\W)"+a(s)+i,"g");m=l.exec(f);)"dll-reference"!==m[3]&&u[t].push(m[3]);for(l=new RegExp("\\("+a(s)+'\\("(dll-reference\\s('+o+'))"\\)\\)'+i,"g");m=l.exec(f);)r[m[2]]||(u[t].push(m[1]),r[m[2]]=e(m[1]).m),u[m[2]]=u[m[2]]||[],u[m[2]].push(m[4]);for(var d,p=Object.keys(u),x=0;x<p.length;x++)for(var v=0;v<u[p[x]].length;v++)d=u[p[x]][v],isNaN(1*d)||(u[p[x]][v]=1*u[p[x]][v]);return u}function f(r){return Object.keys(r).reduce(function(n,e){return n||r[e].length>0},!1)}r.exports=function(r,n){n=n||{};var o={main:e.m},i=n.all?{main:Object.keys(o.main)}:function(r,n){for(var e={main:[n]},t={main:[]},o={main:{}};f(e);)for(var i=Object.keys(e),a=0;a<i.length;a++){var c=i[a],m=e[c].pop();if(o[c]=o[c]||{},!o[c][m]&&r[c][m]){o[c][m]=!0,t[c]=t[c]||[],t[c].push(m);for(var s=u(r,r[c][m],c),l=Object.keys(s),d=0;d<l.length;d++)e[l[d]]=e[l[d]]||[],e[l[d]]=e[l[d]].concat(s[l[d]])}}return t}(o,r),a="";Object.keys(i).filter(function(r){return"main"!==r}).forEach(function(r){for(var n=0;i[r][n];)n++;i[r].push(n),o[r][n]="(function(module, exports, __webpack_require__) { module.exports = __webpack_require__; })",a=a+"var "+r+" = ("+t.toString().replace("ENTRY_MODULE",JSON.stringify(n))+")({"+i[r].map(function(n){return JSON.stringify(n)+": "+o[r][n].toString()}).join(",")+"});\n"}),a=a+"new (("+t.toString().replace("ENTRY_MODULE",JSON.stringify(r))+")({"+i.main.map(function(r){return JSON.stringify(r)+": "+o.main[r].toString()}).join(",")+"}))(self);";var c=new window.Blob([a],{type:"text/javascript"});if(n.bare)return c;var m=(window.URL||window.webkitURL||window.mozURL||window.msURL).createObjectURL(c),s=new window.Worker(m);return s.objectURL=m,s}},function(r,n,e){"use strict";e.r(n);var t={min:-1/0,max:1/0},o={min:-1/0,max:1/0},i={min:-1/0,max:1/0},a={min:0,max:1/0};function u(r,n,e){var u,c,m,s,l=n.anchorX-r.anchorX,d=n.anchorY-r.anchorY;return f(t,r.minX,r.maxX,n.minX,n.maxX,l),f(o,r.minY,r.maxY,n.minY,n.maxY,d),c=t,m=o,s=a,(u=i).min=Math.max(c.min,m.min,s.min),u.max=Math.min(c.max,m.max,s.max),i.min>=i.max?-1/0:e+Math.log(i.max)/Math.log(2)}function f(r,n,e,t,o,i){var a=i>0?n-o:t-e,u=i>0?e-t:o-n;r.min=a/Math.abs(i),r.max=u/Math.abs(i)}var c=e(0),m=e(1),s={minX:0,minY:0,maxX:0,maxY:0},l={minX:0,minY:0,maxX:0,maxY:0},d={minX:0,minY:0,maxX:0,maxY:0},p={minX:0,minY:0,maxX:0,maxY:0},x=[];function v(r){for(var n=r.bounds,e=r.priorityGroups,t=r.markers,o=r.markerCount,i=r.labels,a=r.labelCount,u=1+(n.maxX-n.minX>>3)<<3,f=n.maxY-n.minY,s=u*f+8>>3,l=new Uint8Array(s),d=new Uint8Array(s),p=[],v=0;v<e.length;v++)p[v]=new Uint8Array(s);var b=new Int8Array(o);for(v=0;v<o;v++){var g=v*c.c+c.a.iconIndex;b[v]=t[g],t[g]=-1}var w=new Uint8Array(a),k=new Float32Array(a);for(v=0;v<a;v++){var Y=v*m.c+m.a.display,X=v*m.c+m.a.minZoom;w[v]=i[Y],k[v]=i[X],i[Y]=0,i[X]=-1/0}x=[],h(r,l,p,u,f,b,!0,!0),h(r,l,p,u,f,b,!1,!0),y(r,d,u,f,w,k,!0,!0),y(r,d,u,f,w,k,!1,!0),h(r,l,p,u,f,b,!0,!1),h(r,l,p,u,f,b,!1,!1),y(r,d,u,f,w,k,!0,!1),y(r,d,u,f,w,k,!1,!1)}function h(r,n,e,t,o,i,a,u){for(var f=r.bounds,m=r.priorityGroups,s=r.sprites,l=r.markers,d=r.markerCount,p=0;p<m.length;p++){if(s[m[p].iconIndex])for(var x=0!==p?e[p-1]:void 0,v=p!==m.length-1?e[p]:void 0,h=0;h<d;h++){var y=-1!==i[h],g=1===l[c.c*h+c.a.priority];(a&&y||!a&&!y)&&(u&&g||!u&&!g)&&b(l,m,s,f,x,v,n,t,o,p,h)}}}function y(r,n,e,t,o,i,a,u){for(var f=r.bounds,s=r.markers,l=r.labels,d=r.labelCount,p=r.currentZoom,x=0;x<d;x++){var v=l[x*m.c+m.a.markerIndex],h=1===o[x]&&p>=i[x],y=1===s[v*c.c+c.a.priority];(a&&h||!a&&!h)&&(u&&y||!u&&!y)&&g(s,l,f,n,e,t,p,x)}}function b(r,n,e,t,o,i,a,u,f,m,p){var x=n[m],v=x.safeZone,h=x.iconIndex,y=x.margin,b=x.degradation,g=e[h],A=g.size,O=g.anchor,j=c.c,_=c.a,P=p*j,I=r[P+_.groupIndex],M=r[P+_.pixelPositionX]-t.minX,Z=r[P+_.pixelPositionY]-t.minY;I>m||(X(l,u,f,A,O,M,Z,y),Y(l)||I===m&&o&&w(o,u,l)||(X(s,u,f,A,O,M,Z,v),Y(s)||w(a,u,s)||(X(d,u,f,A,O,M,Z,b),k(a,u,l),i&&k(i,u,d),r[P+_.iconIndex]=h)))}function g(r,n,e,t,o,i,a,f){var s=m.c,l=m.a,d=f*s,v=n[d+l.markerIndex]*c.c;if(-1!==r[v+c.a.iconIndex]){var h=r[v+c.a.pixelPositionX]-e.minX,y=r[v+c.a.pixelPositionY]-e.minY,b=[n[d+l.width],n[d+l.height]],g=[-n[d+l.offsetX]/b[0],-n[d+l.offsetY]/b[1]];if(X(p,o,i,b,g,h,y,0),!Y(p)&&!w(t,o,p)){k(t,o,p),n[d+l.display]=1;for(var A={anchorX:h,anchorY:y,minX:-b[0]*g[0],minY:-b[1]*g[1],maxX:b[0]*(1-g[0]),maxY:b[1]*(1-g[1]),minZoom:-1/0},O=0,j=x;O<j.length;O++){var _=j[O],P=u(_,A,a);P>A.minZoom&&P>_.minZoom&&(A.minZoom=P)}n[d+l.minZoom]=A.minZoom,x.push(A)}}}function w(r,n,e){for(var t=e.minX,o=e.minY,i=e.maxX,a=e.maxY,u=o;u<a;u++){var f=u*n+t>>3,c=u*n+i>>3,m=0;if(f===c)m=r[f]&255>>(7&t)&255<<8-(7&i);else{m=r[f]&255>>(7&t);for(var s=f+1;s<c;s++)m=r[s]|m;m=r[c]&255<<8-(7&i)|m}if(0!==m)return!0}return!1}function k(r,n,e){for(var t=e.minX,o=e.minY,i=e.maxX,a=e.maxY,u=o;u<a;u++){var f=u*n+t>>3,c=u*n+i>>3;if(f===c)r[f]=r[f]|255>>(7&t)&255<<8-(7&i);else{r[f]=r[f]|255>>(7&t);for(var m=f+1;m<c;m++)r[m]=255;r[c]=r[c]|255<<8-(7&i)}}}function Y(r){return r.minX===r.maxX||r.minY===r.maxY}function X(r,n,e,t,o,i,a,u){var f=i-t[0]*o[0]-u|0,c=a-t[1]*o[1]-u|0,m=i+t[0]*(1-o[0])+u|0,s=a+t[1]*(1-o[1])+u|0;r.minX=f>0?f<n?f:n:0,r.minY=c>0?c<e?c:e:0,r.maxX=m>0?m<n?m:n:0,r.maxY=s>0?s<e?s:e:0}n.default=function(r){r.onmessage=function(n){v(n.data);var e=n.data,t=e.markers,o=e.labels;r.postMessage({markerArray:t,labelArray:o},[t.buffer,o.buffer])}}},function(r,n,e){"use strict";e.r(n);var t=e(0),o=e(1),i=e(2),a=e.n(i),u=function(){function r(){var r=this;this.worker=a()(3),this.queue=[],this.currentJob=void 0,this.markerArray=new Float32Array(1e3*t.c),this.labelArray=new Float32Array(1e3*o.c),this.worker.onmessage=function(n){if(void 0!==r.currentJob){var e=r.currentJob,i=e.markers,a=e.resolve,u=n.data;t.d(i,u.markerArray),o.d(i,u.labelArray),r.markerArray=u.markerArray,r.labelArray=u.labelArray,r.currentJob=void 0,r.dequeue(),a()}}}return r.prototype.generalize=function(r,n,e,t,o){var i=this,a={bounds:r,priorityGroups:n,sprites:e,currentZoom:o},u=t.length,f=t.filter(function(r){return void 0!==r.htmlLabel}).length;return new Promise(function(r){i.queue.push({message:a,markers:t,resolve:r,markerCount:u,labelCount:f}),i.dequeue()})},r.prototype.clear=function(){this.queue=[]},r.prototype.pack=function(r,n,e){n*t.c>this.markerArray.length&&(this.markerArray=new Float32Array(n*t.c)),e*o.c>this.labelArray.length&&(this.labelArray=new Float32Array(e*o.c)),t.b(this.markerArray,r),o.b(this.labelArray,r,window.devicePixelRatio)},r.prototype.dequeue=function(){if(void 0===this.currentJob){var r=this.queue.shift();if(void 0!==r){this.pack(r.markers,r.markerCount,r.labelCount);var n=r.message;n.markers=this.markerArray,n.markerCount=r.markerCount,n.labels=this.labelArray,n.labelCount=r.labelCount,this.worker.postMessage(n,[n.markers.buffer,n.labels.buffer]),this.currentJob=r}}},r}();e.d(n,"General",function(){return u})}])}); | ||
!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.General=r():e.General=r()}(window,function(){return function(e){var r={};function n(t){if(r[t])return r[t].exports;var o=r[t]={i:t,l:!1,exports:{}};return e[t].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=r,n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,r){if(1&r&&(e=n(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(n.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)n.d(t,o,function(r){return e[r]}.bind(null,o));return t},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},n.p="/dist/",n(n.s=2)}([function(e,r,n){"use strict";n.d(r,"a",function(){return t}),n.d(r,"c",function(){return o}),n.d(r,"b",function(){return i}),n.d(r,"d",function(){return a});var t={pixelPositionX:0,pixelPositionY:1,groupIndex:2,iconIndex:3},o=Object.keys(t).length;function i(e,r){for(var n=0,i=0;n<r.length;n++,i+=o){var a=r[n];e[i+t.pixelPositionX]=a.pixelPosition[0],e[i+t.pixelPositionY]=a.pixelPosition[1],e[i+t.groupIndex]=a.groupIndex,e[i+t.iconIndex]=a.iconIndex}}function a(e,r){for(var n=0,i=0;n<e.length;n++,i+=o)e[n].iconIndex=r[i+t.iconIndex]}},function(e,r,n){function t(e){var r={};function n(t){if(r[t])return r[t].exports;var o=r[t]={i:t,l:!1,exports:{}};return e[t].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=r,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},n.p="/",n.oe=function(e){throw console.error(e),e};var t=n(n.s=ENTRY_MODULE);return t.default||t}var o="[\\.|\\-|\\+|\\w|/|@]+",i="\\(\\s*(/\\*.*?\\*/)?\\s*.*?("+o+").*?\\)";function a(e){return(e+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function u(e,r,t){var u={};u[t]=[];var c=r.toString(),f=c.match(/^function\s?\w*\(\w+,\s*\w+,\s*(\w+)\)/);if(!f)return u;for(var s,l=f[1],p=new RegExp("(\\\\n|\\W)"+a(l)+i,"g");s=p.exec(c);)"dll-reference"!==s[3]&&u[t].push(s[3]);for(p=new RegExp("\\("+a(l)+'\\("(dll-reference\\s('+o+'))"\\)\\)'+i,"g");s=p.exec(c);)e[s[2]]||(u[t].push(s[1]),e[s[2]]=n(s[1]).m),u[s[2]]=u[s[2]]||[],u[s[2]].push(s[4]);for(var m,d=Object.keys(u),v=0;v<d.length;v++)for(var x=0;x<u[d[v]].length;x++)m=u[d[v]][x],isNaN(1*m)||(u[d[v]][x]=1*u[d[v]][x]);return u}function c(e){return Object.keys(e).reduce(function(r,n){return r||e[n].length>0},!1)}e.exports=function(e,r){r=r||{};var o={main:n.m},i=r.all?{main:Object.keys(o.main)}:function(e,r){for(var n={main:[r]},t={main:[]},o={main:{}};c(n);)for(var i=Object.keys(n),a=0;a<i.length;a++){var f=i[a],s=n[f].pop();if(o[f]=o[f]||{},!o[f][s]&&e[f][s]){o[f][s]=!0,t[f]=t[f]||[],t[f].push(s);for(var l=u(e,e[f][s],f),p=Object.keys(l),m=0;m<p.length;m++)n[p[m]]=n[p[m]]||[],n[p[m]]=n[p[m]].concat(l[p[m]])}}return t}(o,e),a="";Object.keys(i).filter(function(e){return"main"!==e}).forEach(function(e){for(var r=0;i[e][r];)r++;i[e].push(r),o[e][r]="(function(module, exports, __webpack_require__) { module.exports = __webpack_require__; })",a=a+"var "+e+" = ("+t.toString().replace("ENTRY_MODULE",JSON.stringify(r))+")({"+i[e].map(function(r){return JSON.stringify(r)+": "+o[e][r].toString()}).join(",")+"});\n"}),a=a+"new (("+t.toString().replace("ENTRY_MODULE",JSON.stringify(e))+")({"+i.main.map(function(e){return JSON.stringify(e)+": "+o.main[e].toString()}).join(",")+"}))(self);";var f=new window.Blob([a],{type:"text/javascript"});if(r.bare)return f;var s=(window.URL||window.webkitURL||window.mozURL||window.msURL).createObjectURL(f),l=new window.Worker(s);return l.objectURL=s,l}},function(e,r,n){"use strict";n.r(r);var t=n(0),o=n(1),i=n.n(o),a=function(){function e(){var e=this;this.worker=i()(3),this.queue=[],this.currentJob=void 0,this.markerArray=new Float32Array(1e3*t.c),this.worker.onmessage=function(r){if(void 0!==e.currentJob){var n=e.currentJob,o=n.markers,i=n.resolve;Object(t.d)(o,r.data),e.markerArray=r.data,e.currentJob=void 0,e.dequeue(),i()}}}return e.prototype.generalize=function(e,r,n,t){var o=this,i={bounds:e,priorityGroups:r,sprites:n};return new Promise(function(e){o.queue.push({message:i,markers:t,resolve:e}),o.dequeue()})},e.prototype.clear=function(){this.queue=[]},e.prototype.pack=function(e){e.length*t.c>this.markerArray.length&&(this.markerArray=new Float32Array(e.length*t.c)),Object(t.b)(this.markerArray,e)},e.prototype.dequeue=function(){if(void 0===this.currentJob){var e=this.queue.shift();if(void 0!==e){this.pack(e.markers);var r=e.message;r.markers=this.markerArray,r.markerCount=e.markers.length,this.worker.postMessage(r,[r.markers.buffer]),this.currentJob=e}}},e}();n.d(r,"General",function(){return a})},function(e,r,n){"use strict";n.r(r);var t=n(0),o={minX:0,minY:0,maxX:0,maxY:0},i={minX:0,minY:0,maxX:0,maxY:0},a={minX:0,minY:0,maxX:0,maxY:0};function u(e){for(var r=e.bounds,n=e.priorityGroups,o=e.sprites,i=e.markers,a=e.markerCount,u=1+(r.maxX-r.minX>>3)<<3,f=r.maxY-r.minY,s=u*f+8>>3,l=new Uint8Array(s),p=[],m=0;m<n.length;m++)p[m]=new Uint8Array(s);var d=new Int8Array(a);for(m=0;m<a;m++){var v=m*t.c+t.a.iconIndex;d[m]=i[v],i[v]=-1}for(m=0;m<n.length;m++){if(o[n[m].iconIndex])for(var x=0!==m?p[m-1]:void 0,g=m!==n.length-1?p[m]:void 0,y=0;y<a;y++)-1!==d[y]&&c(i,n,o,r,x,g,l,u,f,m,y)}for(m=0;m<n.length;m++){if(o[n[m].iconIndex])for(x=0!==m?p[m-1]:void 0,g=m!==n.length-1?p[m]:void 0,y=0;y<a;y++)-1===d[y]&&c(i,n,o,r,x,g,l,u,f,m,y)}}function c(e,r,n,u,c,m,d,v,x,g,y){var b=r[g],h=b.safeZone,w=b.iconIndex,k=b.margin,O=b.degradation,j=n[w],Y=j.size,_=j.anchor,X=y*t.c,P=e[X+t.a.groupIndex],I=e[X+t.a.pixelPositionX]-u.minX,S=e[X+t.a.pixelPositionY]-u.minY;P>g||(p(i,v,x,Y,_,I,S,k),l(i)||P===g&&c&&f(c,v,i)||(p(o,v,x,Y,_,I,S,h),l(o)||f(d,v,o)||(p(a,v,x,Y,_,I,S,O),s(d,v,i),m&&s(m,v,a),e[X+t.a.iconIndex]=w)))}function f(e,r,n){for(var t=n.minX,o=n.minY,i=n.maxX,a=n.maxY,u=o;u<a;u++){var c=u*r+t>>3,f=u*r+i>>3,s=0;if(c===f)s=e[c]&255>>(7&t)&255<<8-(7&i);else{s=e[c]&255>>(7&t);for(var l=c+1;l<f;l++)s=e[l]|s;s=e[f]&255<<8-(7&i)|s}if(0!==s)return!0}return!1}function s(e,r,n){for(var t=n.minX,o=n.minY,i=n.maxX,a=n.maxY,u=o;u<a;u++){var c=u*r+t>>3,f=u*r+i>>3;if(c===f)e[c]=e[c]|255>>(7&t)&255<<8-(7&i);else{e[c]=e[c]|255>>(7&t);for(var s=c+1;s<f;s++)e[s]=255;e[f]=e[f]|255<<8-(7&i)}}}function l(e){return e.minX===e.maxX||e.minY===e.maxY}function p(e,r,n,t,o,i,a,u){var c=i-t[0]*o[0]-u|0,f=a-t[1]*o[1]-u|0,s=i+t[0]*(1-o[0])+u|0,l=a+t[1]*(1-o[1])+u|0;e.minX=c>0?c<r?c:r:0,e.minY=f>0?f<n?f:n:0,e.maxX=s>0?s<r?s:r:0,e.maxY=l>0?l<n?l:n:0}r.default=function(e){e.onmessage=function(r){var n=r.data;u(n),e.postMessage(n.markers)}}}])}); | ||
//# sourceMappingURL=general.js.map |
@@ -7,5 +7,4 @@ import { BBox, PriorityGroup, Sprite, Marker } from './types'; | ||
private markerArray; | ||
private labelArray; | ||
constructor(); | ||
generalize(bounds: BBox, priorityGroups: PriorityGroup[], sprites: Sprite[], markers: Marker[], currentZoom: number): Promise<void>; | ||
generalize(bounds: BBox, priorityGroups: PriorityGroup[], sprites: Sprite[], markers: Marker[]): Promise<void>; | ||
clear(): void; | ||
@@ -12,0 +11,0 @@ private pack; |
@@ -7,3 +7,2 @@ import { Marker } from './types'; | ||
iconIndex: number; | ||
priority: number; | ||
}; | ||
@@ -10,0 +9,0 @@ export declare const stride: number; |
@@ -15,14 +15,3 @@ export declare type Vec2 = [number, number] | Float64Array | number[]; | ||
iconIndex: number; | ||
/** Опциональный флаг, указывающий приоритетность маркера */ | ||
priority?: boolean; | ||
/** Подпись маркера */ | ||
htmlLabel?: Label; | ||
} | ||
export interface Label { | ||
offset: Vec2; | ||
width: number; | ||
height: number; | ||
display: boolean; | ||
minZoom: number; | ||
} | ||
export interface PriorityGroup { | ||
@@ -44,7 +33,2 @@ /** Индекс иконки в атласе, которая будет установлена маркеру, попавшему в эту группу */ | ||
} | ||
export declare type LabelBBox = BBox & { | ||
anchorX: number; | ||
anchorY: number; | ||
minZoom: number; | ||
}; | ||
export interface JobMessage { | ||
@@ -54,3 +38,2 @@ bounds: BBox; | ||
sprites: Sprite[]; | ||
currentZoom: number; | ||
} | ||
@@ -63,5 +46,2 @@ export interface WorkerMessage { | ||
markers: Float32Array; | ||
labelCount: number; | ||
labels: Float32Array; | ||
currentZoom: number; | ||
} | ||
@@ -71,5 +51,3 @@ export interface Job { | ||
markers: Marker[]; | ||
markerCount: number; | ||
labelCount: number; | ||
resolve: () => void; | ||
} |
{ | ||
"name": "@2gis/general", | ||
"version": "2.1.0", | ||
"version": "3.0.0", | ||
"description": "Fast marker generalization algorithm", | ||
@@ -5,0 +5,0 @@ "contributors": [ |
@@ -109,12 +109,3 @@ # General [![Build Status](https://travis-ci.org/2gis/general.svg?branch=master)](https://travis-ci.org/2gis/general) | ||
- `groupIndex` – индекс в массиве групп, к которой маркер будет изначально принадлежать | ||
- `priority?: boolean` — опциональный флаг, позволяющий поднять приоритет маркера над другими. Приоритетные маркеры генерализуются раньше остальных, даже если расположены после них в исходном массиве. | ||
- `htmlLabel?: Label` — опциональная подпись маркера. Подписи генерализуются аналогично маркерам. У подписей при генерализации меньший приоритет, чем у маркеров. Другими словами, сначала генерализуются все маркеры, а затем все подписи. | ||
`Label` описывается следующим образом: | ||
- `offset: Vec2` - отступ в пикселях вправо и вниз от маркера | ||
- `width: number` - ширина в пикселях | ||
- `height: number` - высота в пикселях | ||
- `display: boolean` - флаг, означающий, нужно ли отображать подпись. Выставляется в процессе генерализации. | ||
- `minZoom: number` — минимальный зум, на котором можно отображать подпись без пересечения с другими подписями. Выставляется в процессе генерализации. | ||
Метод `generalize` **не возвращает** новый массив маркеров, он мутирует старый. | ||
@@ -121,0 +112,0 @@ |
@@ -1,3 +0,2 @@ | ||
import * as markerArray from './markerArray'; | ||
import * as labelArray from './labelArray'; | ||
import { stride, pack, unpack } from './markerArray'; | ||
import { | ||
@@ -19,3 +18,2 @@ BBox, | ||
private markerArray: Float32Array; | ||
private labelArray: Float32Array; | ||
@@ -26,4 +24,3 @@ constructor() { | ||
this.currentJob = undefined; | ||
this.markerArray = new Float32Array(1000 * markerArray.stride); | ||
this.labelArray = new Float32Array(1000 * labelArray.stride); | ||
this.markerArray = new Float32Array(1000 * stride); | ||
@@ -36,10 +33,4 @@ this.worker.onmessage = (event) => { | ||
const { markers, resolve } = this.currentJob; | ||
const { data } = event; | ||
markerArray.unpack(markers, data.markerArray); | ||
labelArray.unpack(markers, data.labelArray); | ||
this.markerArray = data.markerArray; | ||
this.labelArray = data.labelArray; | ||
unpack(markers, event.data); | ||
this.markerArray = event.data; | ||
this.currentJob = undefined; | ||
@@ -57,3 +48,2 @@ | ||
markers: Marker[], | ||
currentZoom: number, | ||
): Promise<void> { | ||
@@ -64,10 +54,6 @@ const message: JobMessage = { | ||
sprites, | ||
currentZoom, | ||
}; | ||
const markerCount = markers.length; | ||
const labelCount = markers.filter((marker) => marker.htmlLabel !== undefined).length; | ||
return new Promise((resolve) => { | ||
this.queue.push({ message, markers, resolve, markerCount, labelCount }); | ||
this.queue.push({ message, markers, resolve }); | ||
this.dequeue(); | ||
@@ -81,13 +67,8 @@ }); | ||
private pack(markers: Marker[], markerCount: number, labelCount: number): void { | ||
if (markerCount * markerArray.stride > this.markerArray.length) { | ||
this.markerArray = new Float32Array(markerCount * markerArray.stride); | ||
private pack(markers: Marker[]) { | ||
if (markers.length * stride > this.markerArray.length) { | ||
this.markerArray = new Float32Array(markers.length * stride); | ||
} | ||
if (labelCount * labelArray.stride > this.labelArray.length) { | ||
this.labelArray = new Float32Array(labelCount * labelArray.stride); | ||
} | ||
markerArray.pack(this.markerArray, markers); | ||
labelArray.pack(this.labelArray, markers, window.devicePixelRatio); | ||
pack(this.markerArray, markers); | ||
} | ||
@@ -106,11 +87,9 @@ | ||
this.pack(job.markers, job.markerCount, job.labelCount); | ||
this.pack(job.markers); | ||
const message = job.message as WorkerMessage; | ||
message.markers = this.markerArray; | ||
message.markerCount = job.markerCount; | ||
message.labels = this.labelArray; | ||
message.labelCount = job.labelCount; | ||
message.markerCount = job.markers.length; | ||
this.worker.postMessage(message, [message.markers.buffer, message.labels.buffer]); | ||
this.worker.postMessage(message, [message.markers.buffer]); | ||
@@ -117,0 +96,0 @@ this.currentJob = job; |
import { Marker } from './types'; | ||
// Оффсеты должны быть пронумерованы по порядку | ||
let i = 0; | ||
export const offsets = { | ||
pixelPositionX: i++, | ||
pixelPositionY: i++, | ||
groupIndex: i++, | ||
iconIndex: i++, | ||
priority: i++, | ||
pixelPositionX: 0, | ||
pixelPositionY: 1, | ||
groupIndex: 2, | ||
iconIndex: 3, | ||
}; | ||
@@ -26,3 +24,2 @@ | ||
markerArray[markerOffset + offsets.iconIndex] = marker.iconIndex; | ||
markerArray[markerOffset + offsets.priority] = Boolean(marker.priority) ? 1 : 0; | ||
} | ||
@@ -29,0 +26,0 @@ } |
@@ -17,16 +17,4 @@ export type Vec2 = [number, number] | Float64Array | number[]; | ||
iconIndex: number; | ||
/** Опциональный флаг, указывающий приоритетность маркера */ | ||
priority?: boolean; | ||
/** Подпись маркера */ | ||
htmlLabel?: Label; | ||
} | ||
export interface Label { | ||
offset: Vec2; | ||
width: number; | ||
height: number; | ||
display: boolean; | ||
minZoom: number; | ||
} | ||
export interface PriorityGroup { | ||
@@ -50,8 +38,2 @@ /** Индекс иконки в атласе, которая будет установлена маркеру, попавшему в эту группу */ | ||
export type LabelBBox = BBox & { | ||
anchorX: number; | ||
anchorY: number; | ||
minZoom: number; | ||
}; | ||
export interface JobMessage { | ||
@@ -61,3 +43,2 @@ bounds: BBox; | ||
sprites: Sprite[]; | ||
currentZoom: number; | ||
} | ||
@@ -71,5 +52,2 @@ | ||
markers: Float32Array; | ||
labelCount: number; | ||
labels: Float32Array; | ||
currentZoom: number; | ||
} | ||
@@ -80,5 +58,3 @@ | ||
markers: Marker[]; | ||
markerCount: number; | ||
labelCount: number; | ||
resolve: () => void; | ||
} |
@@ -1,5 +0,3 @@ | ||
import { BBox, Vec2, WorkerMessage, PriorityGroup, Sprite, LabelBBox } from '../types'; | ||
import { getIntersectionZoom } from './minZoom'; | ||
import * as markerArray from '../markerArray'; | ||
import * as labelArray from '../labelArray'; | ||
import { BBox, Vec2, WorkerMessage, PriorityGroup, Sprite } from '../types'; | ||
import { stride, offsets } from '../markerArray'; | ||
@@ -9,8 +7,5 @@ const collideBBox: BBox = { minX: 0, minY: 0, maxX: 0, maxY: 0 }; | ||
const degradationBBox: BBox = { minX: 0, minY: 0, maxX: 0, maxY: 0 }; | ||
const noMarginBBox: BBox = { minX: 0, minY: 0, maxX: 0, maxY: 0 }; | ||
let survivedLabelBoxes: LabelBBox[] = []; | ||
export function generalize(data: WorkerMessage) { | ||
const { bounds, priorityGroups, markers, markerCount, labels, labelCount } = data; | ||
const { bounds, priorityGroups, sprites, markers, markerCount } = data; | ||
@@ -29,8 +24,5 @@ const planeWidth = (bounds.maxX - bounds.minX >> 3) + 1 << 3; // Ширина должна быть кратна 8 | ||
// С помощью этой плоскости проверяется попадание маркеров с safeZone, и вставляются они с margin | ||
// Это первая, с помощью нее мы просто проверяем попадание маркеров с safeZone и вставляем их с margin | ||
const plane = new Uint8Array(planeLength); | ||
// Эта плоскость используется для подписей | ||
const labelPlane = new Uint8Array(planeLength); | ||
/** | ||
@@ -53,3 +45,3 @@ * Следующие плоскости используются для проверки на деградацию маркеров. | ||
for (let i = 0; i < markerCount; i++) { | ||
const index = i * markerArray.stride + markerArray.offsets.iconIndex; | ||
const index = i * stride + offsets.iconIndex; | ||
@@ -63,78 +55,5 @@ // Сохраняем предыдущие индексы иконок для работы гистерезиса | ||
const prevLabelState = new Uint8Array(labelCount); | ||
const prevLabelMinZoom = new Float32Array(labelCount); | ||
for (let i = 0; i < labelCount; i++) { | ||
const displayIndex = i * labelArray.stride + labelArray.offsets.display; | ||
const minZoomIndex = i * labelArray.stride + labelArray.offsets.minZoom; | ||
// Сохраняем предыдущее состояние лейблов | ||
prevLabelState[i] = labels[displayIndex]; | ||
prevLabelMinZoom[i] = labels[minZoomIndex]; | ||
// Сбрасываем состояние лейблов | ||
labels[displayIndex] = 0; | ||
labels[minZoomIndex] = -Infinity; | ||
} | ||
survivedLabelBoxes = []; | ||
// Здесь начинает работу основной алгоритм генерализации | ||
// Генерализуем в таком порядке: | ||
// 1. Приоритетные маркеры, видимые на экране | ||
// 2. Приоритетные маркеры, не видимые на экране | ||
// 3. Приоритетные подписи, видимые на экране | ||
// 4. Приоритетные подписи, не видимые на экране | ||
// 5. Неприоритетные маркеры, видимые на экране | ||
// 6. Неприоритетные маркеры, не видимые на экране | ||
// 7. Неприоритетные подписи, видимые на экране | ||
// 8. Неприоритетные подписи, не видимые на экране | ||
generalizeMarkers( | ||
data, plane, degradationPlanes, planeWidth, planeHeight, | ||
prevIconIndices, true, true, | ||
); | ||
generalizeMarkers( | ||
data, plane, degradationPlanes, planeWidth, planeHeight, | ||
prevIconIndices, false, true, | ||
); | ||
generalizeLabels( | ||
data, labelPlane, planeWidth, planeHeight, prevLabelState, | ||
prevLabelMinZoom, true, true, | ||
); | ||
generalizeLabels( | ||
data, labelPlane, planeWidth, planeHeight, prevLabelState, | ||
prevLabelMinZoom, false, true, | ||
); | ||
generalizeMarkers( | ||
data, plane, degradationPlanes, planeWidth, planeHeight, | ||
prevIconIndices, true, false, | ||
); | ||
generalizeMarkers( | ||
data, plane, degradationPlanes, planeWidth, planeHeight, | ||
prevIconIndices, false, false, | ||
); | ||
generalizeLabels( | ||
data, labelPlane, planeWidth, planeHeight, prevLabelState, | ||
prevLabelMinZoom, true, false, | ||
); | ||
generalizeLabels( | ||
data, labelPlane, planeWidth, planeHeight, prevLabelState, | ||
prevLabelMinZoom, false, false, | ||
); | ||
} | ||
function generalizeMarkers( | ||
data: WorkerMessage, | ||
plane: Uint8Array, | ||
degradationPlanes: Uint8Array[], | ||
planeWidth: number, | ||
planeHeight: number, | ||
prevIconIndices: Int8Array, | ||
processVisible: boolean, | ||
processPriority: boolean, | ||
): void { | ||
const { bounds, priorityGroups, sprites, markers, markerCount } = data; | ||
// Здесь начинает работу основной алгоритм генерализации. | ||
// У нас два вложенных цикла: по группам -> по маркерам. | ||
// Циклы запускаются два раза: первый прогон — для маркеров, которые были видны на экране | ||
for (let i = 0; i < priorityGroups.length; i++) { | ||
@@ -151,9 +70,3 @@ const sprite = sprites[priorityGroups[i].iconIndex]; | ||
for (let j = 0; j < markerCount; j++) { | ||
const isVisible = prevIconIndices[j] !== -1; | ||
const isPriority = markers[markerArray.stride * j + markerArray.offsets.priority] === 1; | ||
const visibilityOk = processVisible && isVisible || !processVisible && !isVisible; | ||
const priorityOk = processPriority && isPriority || !processPriority && !isPriority; | ||
if (visibilityOk && priorityOk) { | ||
if (prevIconIndices[j] !== -1) { | ||
generalizeMarker( | ||
@@ -174,27 +87,29 @@ markers, | ||
} | ||
} | ||
function generalizeLabels( | ||
data: WorkerMessage, | ||
labelPlane: Uint8Array, | ||
planeWidth: number, | ||
planeHeight: number, | ||
prevLabelState: Uint8Array, | ||
prevLabelMinZoom: Float32Array, | ||
processVisible: boolean, | ||
processPriority: boolean, | ||
): void { | ||
const { bounds, markers, labels, labelCount, currentZoom } = data; | ||
// Второй прогон циклов — для маркеров, которые в данный момент не видны на экране. | ||
for (let i = 0; i < priorityGroups.length; i++) { | ||
const sprite = sprites[priorityGroups[i].iconIndex]; | ||
if (!sprite) { | ||
// Защищаемся от ситуации, когда в конфиге передан некорректный индекс спрайта | ||
continue; | ||
} | ||
for (let i = 0; i < labelCount; i++) { | ||
const markerIndex = labels[i * labelArray.stride + labelArray.offsets.markerIndex]; | ||
const prevDegradationPlane = i !== 0 ? degradationPlanes[i - 1] : undefined; | ||
const degradationPlane = i !== priorityGroups.length - 1 ? degradationPlanes[i] : undefined; | ||
const isVisible = prevLabelState[i] === 1 && currentZoom >= prevLabelMinZoom[i]; | ||
const isPriority = markers[markerIndex * markerArray.stride + markerArray.offsets.priority] === 1; | ||
const visibilityOk = processVisible && isVisible || !processVisible && !isVisible; | ||
const priorityOk = processPriority && isPriority || !processPriority && !isPriority; | ||
if (visibilityOk && priorityOk) { | ||
generalizeLabel(markers, labels, bounds, labelPlane, planeWidth, planeHeight, currentZoom, i); | ||
for (let j = 0; j < markerCount; j++) { | ||
if (prevIconIndices[j] === -1) { | ||
generalizeMarker( | ||
markers, | ||
priorityGroups, | ||
sprites, | ||
bounds, | ||
prevDegradationPlane, | ||
degradationPlane, | ||
plane, | ||
planeWidth, | ||
planeHeight, | ||
i, j, | ||
); | ||
} | ||
} | ||
@@ -219,3 +134,2 @@ } | ||
const { size, anchor } = sprites[iconIndex]; | ||
const { stride, offsets } = markerArray; | ||
@@ -251,3 +165,3 @@ const markerOffset = markerIndex * stride; | ||
// Если все хорошо и маркер выжил, закрашиваем его в плоскости | ||
// Если все хорошо и маркер выжил, закрашиваем его в двух плоскостях | ||
putToArray(plane, planeWidth, marginBBox); | ||
@@ -263,69 +177,2 @@ | ||
function generalizeLabel( | ||
markers: Float32Array, | ||
labels: Float32Array, | ||
bounds: BBox, | ||
labelPlane: Uint8Array, | ||
planeWidth: number, | ||
planeHeight: number, | ||
currentZoom: number, | ||
labelIndex: number, | ||
): void { | ||
const { stride, offsets } = labelArray; | ||
const labelOffset = labelIndex * stride; | ||
const markerIndex = labels[labelOffset + offsets.markerIndex]; | ||
const markerOffset = markerIndex * markerArray.stride; | ||
const markerIsDisplayed = markers[markerOffset + markerArray.offsets.iconIndex] !== -1; | ||
if (!markerIsDisplayed) { | ||
return; | ||
} | ||
const pixelPositionX = markers[markerOffset + markerArray.offsets.pixelPositionX] - bounds.minX; | ||
const pixelPositionY = markers[markerOffset + markerArray.offsets.pixelPositionY] - bounds.minY; | ||
const size = [ | ||
labels[labelOffset + offsets.width], | ||
labels[labelOffset + offsets.height], | ||
]; | ||
const anchor = [ | ||
-labels[labelOffset + offsets.offsetX] / size[0], | ||
-labels[labelOffset + offsets.offsetY] / size[1], | ||
]; | ||
createBBox(noMarginBBox, planeWidth, planeHeight, size, anchor, pixelPositionX, pixelPositionY, 0); | ||
if (bboxIsEmpty(noMarginBBox)) { | ||
return; | ||
} | ||
if (!collide(labelPlane, planeWidth, noMarginBBox)) { | ||
putToArray(labelPlane, planeWidth, noMarginBBox); | ||
labels[labelOffset + offsets.display] = 1; | ||
const labelBox: LabelBBox = { | ||
anchorX: pixelPositionX, | ||
anchorY: pixelPositionY, | ||
minX: -size[0] * anchor[0], | ||
minY: -size[1] * anchor[1], | ||
maxX: size[0] * (1 - anchor[0]), | ||
maxY: size[1] * (1 - anchor[1]), | ||
minZoom: -Infinity, | ||
}; | ||
for (const existingBox of survivedLabelBoxes) { | ||
const minZoom = getIntersectionZoom(existingBox, labelBox, currentZoom); | ||
if (minZoom > labelBox.minZoom && minZoom > existingBox.minZoom) { | ||
labelBox.minZoom = minZoom; | ||
} | ||
} | ||
labels[labelOffset + offsets.minZoom] = labelBox.minZoom; | ||
survivedLabelBoxes.push(labelBox); | ||
} | ||
} | ||
/** | ||
@@ -332,0 +179,0 @@ * Проверяет, пересекает ли область что-либо в плоскости |
@@ -12,14 +12,6 @@ import { WorkerMessage } from '../types'; | ||
self.onmessage = (event) => { | ||
generalize(event.data); | ||
const { markers, labels } = event.data; | ||
self.postMessage({ | ||
markerArray: markers, | ||
labelArray: labels, | ||
}, [ | ||
markers.buffer, | ||
labels.buffer, | ||
]); | ||
const data = event.data; | ||
generalize(data); | ||
self.postMessage(data.markers); | ||
}; | ||
}; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
86154
22
692
119