@2gis/general
Advanced tools
Comparing version 0.3.1 to 1.0.0
@@ -1,2 +0,2 @@ | ||
!function(r,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.General=e():r.General=e()}(this,function(){return function(r){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}var n={};return e.m=r,e.c=n,e.d=function(r,n,t){e.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get: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,e){return Object.prototype.hasOwnProperty.call(r,e)},e.p="/dist/",e(e.s=1)}([function(r,e,n){"use strict";function t(r,e){for(var n=0,t=0;n<e.length;n++,t+=a){var o=e[n],u=o.iconIndex,c=o.prevGroupIndex;r[t+i.pixelPositionX]=o.pixelPosition[0],r[t+i.pixelPositionY]=o.pixelPosition[1],r[t+i.groupIndex]=o.groupIndex,r[t+i.iconIndex]=void 0!==u?u:NaN,r[t+i.prevGroupIndex]=void 0!==c?c:NaN}}function o(r,e){for(var n=0,t=0;n<r.length;n++,t+=a){var o=e[t+i.iconIndex],u=e[t+i.prevGroupIndex];r[n].iconIndex=o!==o?void 0:o,r[n].prevGroupIndex=u!==u?void 0:u}}n.d(e,"a",function(){return i}),n.d(e,"c",function(){return a}),e.b=t,e.d=o;var i={pixelPositionX:0,pixelPositionY:1,groupIndex:2,iconIndex:3,prevGroupIndex:4},a=Object.keys(i).length},function(r,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=n(2);n.d(e,"General",function(){return t.a})},function(r,e,n){"use strict";n.d(e,"a",function(){return a});var t=n(0),o=n(3),i=n.n(o),a=function(){function r(){var r=this;this.worker=i()(4),this.queue=[],this.currentJob=void 0,this.markerArray=new Float32Array(1e3*t.c),this.worker.onmessage=function(e){if(void 0!==r.currentJob){var n=r.currentJob,o=n.markers,i=n.resolve;Object(t.d)(o,e.data),r.markerArray=e.data,r.currentJob=void 0,r.dequeue(),i()}}}return r.prototype.generalize=function(r,e,n,t){var o=this,i={bounds:r,priorityGroups:e,sprites:n};return new Promise(function(r){o.queue.push({message:i,markers:t,resolve:r}),o.dequeue()})},r.prototype.clear=function(){this.queue=[]},r.prototype.pack=function(r){r.length*t.c>this.markerArray.length&&(this.markerArray=new Float32Array(r.length*t.c)),Object(t.b)(this.markerArray,r)},r.prototype.dequeue=function(){if(void 0===this.currentJob){var r=this.queue.shift();if(void 0!==r){this.pack(r.markers);var e=r.message;e.markers=this.markerArray,e.markerCount=r.markers.length,this.worker.postMessage(e,[e.markers.buffer]),this.currentJob=r}}},r}()},function(r,e,n){function t(r){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}var n={};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.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,e){return Object.prototype.hasOwnProperty.call(r,e)},e.p="/",e.oe=function(r){throw console.error(r),r};var t=e(e.s=ENTRY_MODULE);return t.default||t}function o(r){return(r+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function i(r){var e=[],n=r.toString(),t=n.match(/^function\s?\(\w+,\s*\w+,\s*(\w+)\)/);if(!t)return e;for(var i,a=t[1],u=new RegExp("(\\\\n|\\W)"+o(a)+"\\((/\\*.*?\\*/)?s?.*?([\\.|\\-|\\w|/|@]+).*?\\)","g");i=u.exec(n);)e.push(i[3]);return e}function a(r,e){for(var n=[e],t=[],o={};n.length;){var a=n.pop();if(!o[a]&&r[a]){o[a]=!0,t.push(a);var u=i(r[a]);n=n.concat(u)}}return t}r.exports=function(r,e){e=e||{};var o=n.m,i=e.all?Object.keys(o):a(o,r),u="("+t.toString().replace("ENTRY_MODULE",JSON.stringify(r))+")({"+i.map(function(r){return JSON.stringify(r)+": "+o[r].toString()}).join(",")+"})(self);",c=new window.Blob([u],{type:"text/javascript"});if(e.bare)return c;var s=window.URL||window.webkitURL||window.mozURL||window.msURL,f=s.createObjectURL(c),p=new window.Worker(f);return p.objectURL=f,p}},function(r,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=n(5);e.default=function(r){r.onmessage=function(e){var n=e.data;Object(t.a)(n),r.postMessage(n.markers)}}},function(r,e,n){"use strict";function t(r){for(var e=r.bounds,n=r.priorityGroups,t=r.sprites,m=r.markers,v=r.markerCount,l=1+(e.maxX-e.minX>>3)<<3,x=e.maxY-e.minY,h=l*x+8>>3,g=new Uint8Array(h),b=[],y=0;y<n.length;y++)b[y]=new Uint8Array(h);for(var y=0;y<v;y++){var w=y*s.c,k=m[w+s.a.prevGroupIndex];if(!a(k)){var Y=m[w+s.a.pixelPositionX]-e.minX,I=m[w+s.a.pixelPositionY]-e.minY,X=n[k],j=X.iconIndex,O=X.margin,P=X.degradation,G=t[j];if(!G)continue;var A=G.size,U=G.anchor;c(f,l,x,A,U,Y,I,0),u(f)?m[w+s.a.iconIndex]=-1:m[w+s.a.iconIndex]=j,c(p,l,x,A,U,Y,I,O),u(p)||i(g,l,p),c(d,l,x,A,U,Y,I,P),u(d)||i(b[k],l,d)}}for(var y=0;y<n.length;y++){var _=n[y],R=_.safeZone,j=_.iconIndex,O=_.margin,P=_.degradation,G=t[j];if(G)for(var A=G.size,U=G.anchor,J=0!==y?b[y-1]:void 0,L=y!==n.length-1?b[y]:void 0,M=0;M<v;M++){var w=M*s.c,N=m[w+s.a.groupIndex],k=m[w+s.a.prevGroupIndex],Y=m[w+s.a.pixelPositionX]-e.minX,I=m[w+s.a.pixelPositionY]-e.minY;N>y||!a(k)||(c(p,l,x,A,U,Y,I,O),u(p)||N===y&&J&&o(J,l,p)||(c(f,l,x,A,U,Y,I,R),u(f)||o(g,l,f)||(c(d,l,x,A,U,Y,I,P),i(g,l,p),L&&i(L,l,d),m[w+s.a.iconIndex]=j,m[w+s.a.prevGroupIndex]=y)))}}}function o(r,e,n){for(var t=n.minX,o=n.minY,i=n.maxX,a=n.maxY,u=o;u<a;u++){var c=u*e+t>>3,s=u*e+i>>3,f=0;if(c===s)f=r[c]&255>>(7&t)&255<<8-(7&i);else{f=r[c]&255>>(7&t);for(var p=c+1;p<s;p++)f=r[p]|f;f=r[s]&255<<8-(7&i)|f}if(0!==f)return!0}return!1}function i(r,e,n){for(var t=n.minX,o=n.minY,i=n.maxX,a=n.maxY,u=o;u<a;u++){var c=u*e+t>>3,s=u*e+i>>3;if(c===s)r[c]=r[c]|255>>(7&t)&255<<8-(7&i);else{r[c]=r[c]|255>>(7&t);for(var f=c+1;f<s;f++)r[f]=255;r[s]=r[s]|255<<8-(7&i)}}}function a(r){return r!==r}function u(r){return r.minX===r.maxX||r.minY===r.maxY}function c(r,e,n,t,o,i,a,u){var c=i-t[0]*o[0]-u|0,s=a-t[1]*o[1]-u|0,f=i+t[0]*(1-o[0])+u|0,p=a+t[1]*(1-o[1])+u|0;r.minX=c>0?c<e?c:e:0,r.minY=s>0?s<n?s:n:0,r.maxX=f>0?f<e?f:e:0,r.maxY=p>0?p<n?p:n:0}e.a=t;var s=n(0),f={minX:0,minY:0,maxX:0,maxY:0},p={minX:0,minY:0,maxX:0,maxY:0},d={minX:0,minY:0,maxX:0,maxY:0}}])}); | ||
!function(r,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.General=e():r.General=e()}(this,function(){return function(r){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}var n={};return e.m=r,e.c=n,e.d=function(r,n,t){e.o(r,n)||Object.defineProperty(r,n,{configurable:!1,enumerable:!0,get: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,e){return Object.prototype.hasOwnProperty.call(r,e)},e.p="/dist/",e(e.s=1)}([function(r,e,n){"use strict";function t(r,e){for(var n=0,t=0;n<e.length;n++,t+=a){var o=e[n];r[t+i.pixelPositionX]=o.pixelPosition[0],r[t+i.pixelPositionY]=o.pixelPosition[1],r[t+i.groupIndex]=o.groupIndex,r[t+i.iconIndex]=o.iconIndex}}function o(r,e){for(var n=0,t=0;n<r.length;n++,t+=a)r[n].iconIndex=e[t+i.iconIndex]}n.d(e,"a",function(){return i}),n.d(e,"c",function(){return a}),e.b=t,e.d=o;var i={pixelPositionX:0,pixelPositionY:1,groupIndex:2,iconIndex:3},a=Object.keys(i).length},function(r,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=n(2);n.d(e,"General",function(){return t.a})},function(r,e,n){"use strict";n.d(e,"a",function(){return a});var t=n(0),o=n(3),i=n.n(o),a=function(){function r(){var r=this;this.worker=i()(4),this.queue=[],this.currentJob=void 0,this.markerArray=new Float32Array(1e3*t.c),this.worker.onmessage=function(e){if(void 0!==r.currentJob){var n=r.currentJob,o=n.markers,i=n.resolve;Object(t.d)(o,e.data),r.markerArray=e.data,r.currentJob=void 0,r.dequeue(),i()}}}return r.prototype.generalize=function(r,e,n,t){var o=this,i={bounds:r,priorityGroups:e,sprites:n};return new Promise(function(r){o.queue.push({message:i,markers:t,resolve:r}),o.dequeue()})},r.prototype.clear=function(){this.queue=[]},r.prototype.pack=function(r){r.length*t.c>this.markerArray.length&&(this.markerArray=new Float32Array(r.length*t.c)),Object(t.b)(this.markerArray,r)},r.prototype.dequeue=function(){if(void 0===this.currentJob){var r=this.queue.shift();if(void 0!==r){this.pack(r.markers);var e=r.message;e.markers=this.markerArray,e.markerCount=r.markers.length,this.worker.postMessage(e,[e.markers.buffer]),this.currentJob=r}}},r}()},function(r,e,n){function t(r){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}var n={};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.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,e){return Object.prototype.hasOwnProperty.call(r,e)},e.p="/",e.oe=function(r){throw console.error(r),r};var t=e(e.s=ENTRY_MODULE);return t.default||t}function o(r){return(r+"").replace(/[.?*+^$[\]\\(){}|-]/g,"\\$&")}function i(r){var e=[],n=r.toString(),t=n.match(/^function\s?\(\w+,\s*\w+,\s*(\w+)\)/);if(!t)return e;for(var i,a=t[1],u=new RegExp("(\\\\n|\\W)"+o(a)+"\\((/\\*.*?\\*/)?s?.*?([\\.|\\-|\\w|/|@]+).*?\\)","g");i=u.exec(n);)e.push(i[3]);return e}function a(r,e){for(var n=[e],t=[],o={};n.length;){var a=n.pop();if(!o[a]&&r[a]){o[a]=!0,t.push(a);var u=i(r[a]);n=n.concat(u)}}return t}r.exports=function(r,e){e=e||{};var o=n.m,i=e.all?Object.keys(o):a(o,r),u="("+t.toString().replace("ENTRY_MODULE",JSON.stringify(r))+")({"+i.map(function(r){return JSON.stringify(r)+": "+o[r].toString()}).join(",")+"})(self);",c=new window.Blob([u],{type:"text/javascript"});if(e.bare)return c;var s=window.URL||window.webkitURL||window.mozURL||window.msURL,f=s.createObjectURL(c),p=new window.Worker(f);return p.objectURL=f,p}},function(r,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=n(5);e.default=function(r){r.onmessage=function(e){var n=e.data;Object(t.a)(n),r.postMessage(n.markers)}}},function(r,e,n){"use strict";function t(r){for(var e=r.bounds,n=r.priorityGroups,t=r.sprites,i=r.markers,a=r.markerCount,u=1+(e.maxX-e.minX>>3)<<3,c=e.maxY-e.minY,f=u*c+8>>3,p=new Uint8Array(f),d=[],m=0;m<n.length;m++)d[m]=new Uint8Array(f);for(var l=new Int8Array(a),m=0;m<a;m++){var v=m*s.c+s.a.iconIndex;l[m]=i[v],i[v]=-1}for(var m=0;m<n.length;m++){var x=t[n[m].iconIndex];if(x)for(var h=0!==m?d[m-1]:void 0,g=m!==n.length-1?d[m]:void 0,b=0;b<a;b++)-1!==l[b]&&o(i,n,t,e,h,g,p,u,c,m,b)}for(var m=0;m<n.length;m++){var x=t[n[m].iconIndex];if(x)for(var h=0!==m?d[m-1]:void 0,g=m!==n.length-1?d[m]:void 0,b=0;b<a;b++)-1===l[b]&&o(i,n,t,e,h,g,p,u,c,m,b)}}function o(r,e,n,t,o,m,l,v,x,h,g){var b=e[h],y=b.safeZone,w=b.iconIndex,k=b.margin,Y=b.degradation,X=n[w],j=X.size,O=X.anchor,I=g*s.c,P=r[I+s.a.groupIndex],A=r[I+s.a.pixelPositionX]-t.minX,U=r[I+s.a.pixelPositionY]-t.minY;P>h||(c(p,v,x,j,O,A,U,k),u(p)||P===h&&o&&i(o,v,p)||(c(f,v,x,j,O,A,U,y),u(f)||i(l,v,f)||(c(d,v,x,j,O,A,U,Y),a(l,v,p),m&&a(m,v,d),r[I+s.a.iconIndex]=w)))}function i(r,e,n){for(var t=n.minX,o=n.minY,i=n.maxX,a=n.maxY,u=o;u<a;u++){var c=u*e+t>>3,s=u*e+i>>3,f=0;if(c===s)f=r[c]&255>>(7&t)&255<<8-(7&i);else{f=r[c]&255>>(7&t);for(var p=c+1;p<s;p++)f=r[p]|f;f=r[s]&255<<8-(7&i)|f}if(0!==f)return!0}return!1}function a(r,e,n){for(var t=n.minX,o=n.minY,i=n.maxX,a=n.maxY,u=o;u<a;u++){var c=u*e+t>>3,s=u*e+i>>3;if(c===s)r[c]=r[c]|255>>(7&t)&255<<8-(7&i);else{r[c]=r[c]|255>>(7&t);for(var f=c+1;f<s;f++)r[f]=255;r[s]=r[s]|255<<8-(7&i)}}}function u(r){return r.minX===r.maxX||r.minY===r.maxY}function c(r,e,n,t,o,i,a,u){var c=i-t[0]*o[0]-u|0,s=a-t[1]*o[1]-u|0,f=i+t[0]*(1-o[0])+u|0,p=a+t[1]*(1-o[1])+u|0;r.minX=c>0?c<e?c:e:0,r.minY=s>0?s<n?s:n:0,r.maxX=f>0?f<e?f:e:0,r.maxY=p>0?p<n?p:n:0}e.a=t;var s=n(0),f={minX:0,minY:0,maxX:0,maxY:0},p={minX:0,minY:0,maxX:0,maxY:0},d={minX:0,minY:0,maxX:0,maxY:0}}])}); | ||
//# sourceMappingURL=general.js.map |
@@ -7,3 +7,2 @@ import { Marker } from './types'; | ||
iconIndex: number; | ||
prevGroupIndex: number; | ||
}; | ||
@@ -10,0 +9,0 @@ export declare const stride: number; |
@@ -9,4 +9,3 @@ export declare type Vec2 = [number, number] | Float64Array | number[]; | ||
groupIndex: number; | ||
iconIndex?: number; | ||
prevGroupIndex?: number; | ||
iconIndex: number; | ||
} | ||
@@ -13,0 +12,0 @@ export interface PriorityGroup { |
@@ -6,3 +6,2 @@ import { BBox, Vec2, WorkerMessage } from '../types'; | ||
putToArray: (arr: Uint8Array, width: number, bbox: BBox) => void; | ||
isNaN: (a: any) => boolean; | ||
bboxIsEmpty: (a: BBox) => boolean; | ||
@@ -9,0 +8,0 @@ createBBox: (dst: BBox, planeWidth: number, planeHeight: number, size: Vec2, anchor: Vec2, positionX: number, positionY: number, offset: number) => void; |
{ | ||
"name": "@2gis/general", | ||
"version": "0.3.1", | ||
"version": "1.0.0", | ||
"description": "Fast marker generalization algorithm", | ||
@@ -5,0 +5,0 @@ "contributors": [ |
@@ -114,6 +114,2 @@ # General [![Build Status](https://travis-ci.org/2gis/general.svg?branch=master)](https://travis-ci.org/2gis/general) | ||
Также, генерализация выставляет маркерам дополнительный параметр `prevGroupIndex`, чтобы при повторной генерализации, обрабатывать только новые маркера. Это помогает избежать моментов, когда при добавление новых маркеров, старые маркеры генерализуются в новых условиях по-новому. | ||
Таким образом, если результаты предыдущей генерализации сохранять не надо, например, при изменении масштаба карты, то перед вызовом метода `generalize` нужно выставить параметр `prevGroupIndex` в `undefined` у каждого маркера. | ||
## Релиз ## | ||
@@ -120,0 +116,0 @@ 1. `npm version patch` – обновить версию в `package.json` |
@@ -9,3 +9,2 @@ import { Marker } from './types'; | ||
iconIndex: 3, | ||
prevGroupIndex: 4, | ||
}; | ||
@@ -22,12 +21,6 @@ | ||
const iconIndex = marker.iconIndex; | ||
const prevGroupIndex = marker.prevGroupIndex; | ||
markerArray[markerOffset + offsets.pixelPositionX] = marker.pixelPosition[0]; | ||
markerArray[markerOffset + offsets.pixelPositionY] = marker.pixelPosition[1]; | ||
markerArray[markerOffset + offsets.groupIndex] = marker.groupIndex; | ||
markerArray[markerOffset + offsets.iconIndex] = | ||
iconIndex !== undefined ? iconIndex : NaN; | ||
markerArray[markerOffset + offsets.prevGroupIndex] = | ||
prevGroupIndex !== undefined ? prevGroupIndex : NaN; | ||
markerArray[markerOffset + offsets.iconIndex] = marker.iconIndex; | ||
} | ||
@@ -41,10 +34,4 @@ } | ||
for (let i = 0, markerOffset = 0; i < markers.length; i++, markerOffset += stride) { | ||
const iconIndex = markerArray[markerOffset + offsets.iconIndex]; | ||
const prevGroupIndex = markerArray[markerOffset + offsets.prevGroupIndex]; | ||
markers[i].iconIndex = | ||
iconIndex !== iconIndex ? undefined : iconIndex; | ||
markers[i].prevGroupIndex = | ||
prevGroupIndex !== prevGroupIndex ? undefined : prevGroupIndex; | ||
markers[i].iconIndex = markerArray[markerOffset + offsets.iconIndex]; | ||
} | ||
} |
@@ -11,5 +11,3 @@ export type Vec2 = [number, number] | Float64Array | number[]; | ||
groupIndex: number; // Индекс в массиве групп, к которой маркер будет изначально принадлежать | ||
iconIndex?: number; // Индекс спрайта в атласе, добавляется в ходе генерализации | ||
prevGroupIndex?: number; // Параметр выставляемый после генерализации, нужен, чтобы не считать старые маркера | ||
iconIndex: number; // Индекс спрайта в атласе, добавляется в ходе генерализации | ||
} | ||
@@ -16,0 +14,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { BBox, Vec2, WorkerMessage } from '../types'; | ||
import { BBox, Vec2, WorkerMessage, PriorityGroup, Sprite } from '../types'; | ||
import { stride, offsets } from '../markerArray'; | ||
@@ -41,70 +41,52 @@ | ||
/** | ||
* Одни и те же маркера могут участвовать в генерализации несколько раз, | ||
* такие маркера имеют поле prevGroupIndex. | ||
* | ||
* Чтобы не делать лишнюю работу, и чтобы результат генерализации был устойчив, | ||
* мы используем результаты предыдущей генерализации. | ||
*/ | ||
// Поэтому вначале закрашиваем плоскость повторно генерализуемыми маркерами | ||
const prevIconIndices = new Int8Array(markerCount); | ||
for (let i = 0; i < markerCount; i++) { | ||
const markerOffset = i * stride; | ||
const index = i * stride + offsets.iconIndex; | ||
const prevGroupIndex = markers[markerOffset + offsets.prevGroupIndex]; | ||
// Сохраняем предыдущие индексы иконок для работы гистерезиса | ||
prevIconIndices[i] = markers[index]; | ||
// prevGroupIndex не равен NaN, если маркер уже проходил генерализацию | ||
if (!isNaN(prevGroupIndex)) { | ||
const pixelPositionX = markers[markerOffset + offsets.pixelPositionX] - bounds.minX; | ||
const pixelPositionY = markers[markerOffset + offsets.pixelPositionY] - bounds.minY; | ||
const { iconIndex, margin, degradation } = priorityGroups[prevGroupIndex]; | ||
const sprite = sprites[iconIndex]; | ||
// Сбрасываем значение iconIndex у маркера | ||
markers[index] = -1; | ||
} | ||
if (!sprite) { | ||
// smth shit | ||
continue; | ||
} | ||
// Здесь начинает работу основной алгоритм генерализации. | ||
// У нас два вложенных цикла: по группам -> по маркерам. | ||
// Циклы запускаются два раза: первый прогон — для маркеров, которые были видны на экране | ||
for (let i = 0; i < priorityGroups.length; i++) { | ||
const sprite = sprites[priorityGroups[i].iconIndex]; | ||
if (!sprite) { | ||
// Защищаемся от ситуации, когда в конфиге передан некорректный индекс спрайта | ||
continue; | ||
} | ||
const { size, anchor } = sprite; | ||
const prevDegradationPlane = i !== 0 ? degradationPlanes[i - 1] : undefined; | ||
const degradationPlane = i !== priorityGroups.length - 1 ? degradationPlanes[i] : undefined; | ||
// Проверяем, попадает ли иконка маркера в новые границы | ||
createBBox(collideBBox, planeWidth, planeHeight, size, anchor, | ||
pixelPositionX, pixelPositionY, 0); | ||
if (bboxIsEmpty(collideBBox)) { | ||
markers[markerOffset + offsets.iconIndex] = -1; | ||
} else { | ||
markers[markerOffset + offsets.iconIndex] = iconIndex; | ||
for (let j = 0; j < markerCount; j++) { | ||
if (prevIconIndices[j] !== -1) { | ||
generalizeMarker( | ||
markers, | ||
priorityGroups, | ||
sprites, | ||
bounds, | ||
prevDegradationPlane, | ||
degradationPlane, | ||
plane, | ||
planeWidth, | ||
planeHeight, | ||
i, j, | ||
); | ||
} | ||
// Вставляем маркеры на основную плоскость и плоскость деградации без всяких проверок | ||
createBBox(marginBBox, planeWidth, planeHeight, size, anchor, | ||
pixelPositionX, pixelPositionY, margin); | ||
if (!bboxIsEmpty(marginBBox)) { | ||
putToArray(plane, planeWidth, marginBBox); | ||
} | ||
createBBox(degradationBBox, planeWidth, planeHeight, size, anchor, | ||
pixelPositionX, pixelPositionY, degradation); | ||
if (!bboxIsEmpty(degradationBBox)) { | ||
putToArray(degradationPlanes[prevGroupIndex], planeWidth, degradationBBox); | ||
} | ||
} | ||
} | ||
// Здесь начинает работу основной алгоритм генерализации. | ||
// У нас два вложенных цикла: по группам -> по маркерам. | ||
// Второй прогон циклов — для маркеров, которые в данный момент не видны на экране. | ||
for (let i = 0; i < priorityGroups.length; i++) { | ||
const group = priorityGroups[i]; | ||
const { safeZone, iconIndex, margin, degradation } = group; | ||
const sprite = sprites[iconIndex]; | ||
const sprite = sprites[priorityGroups[i].iconIndex]; | ||
if (!sprite) { | ||
// smth shit | ||
// Защищаемся от ситуации, когда в конфиге передан некорректный индекс спрайта | ||
continue; | ||
} | ||
const { size, anchor } = sprite; | ||
const prevDegradationPlane = i !== 0 ? degradationPlanes[i - 1] : undefined; | ||
@@ -114,45 +96,73 @@ const degradationPlane = i !== priorityGroups.length - 1 ? degradationPlanes[i] : undefined; | ||
for (let j = 0; j < markerCount; j++) { | ||
const markerOffset = j * stride; | ||
if (prevIconIndices[j] === -1) { | ||
generalizeMarker( | ||
markers, | ||
priorityGroups, | ||
sprites, | ||
bounds, | ||
prevDegradationPlane, | ||
degradationPlane, | ||
plane, | ||
planeWidth, | ||
planeHeight, | ||
i, j, | ||
); | ||
} | ||
} | ||
} | ||
} | ||
const groupIndex = markers[markerOffset + offsets.groupIndex]; | ||
const prevGroupIndex = markers[markerOffset + offsets.prevGroupIndex]; | ||
const pixelPositionX = markers[markerOffset + offsets.pixelPositionX] - bounds.minX; | ||
const pixelPositionY = markers[markerOffset + offsets.pixelPositionY] - bounds.minY; | ||
function generalizeMarker( | ||
markers: Float32Array, | ||
priorityGroups: PriorityGroup[], | ||
sprites: Sprite[], | ||
bounds: BBox, | ||
prevDegradationPlane: Uint8Array | undefined, | ||
degradationPlane: Uint8Array | undefined, | ||
plane: Uint8Array, | ||
planeWidth: number, | ||
planeHeight: number, | ||
groupIndex: number, | ||
markerIndex: number, | ||
): void { | ||
const { safeZone, iconIndex, margin, degradation } = priorityGroups[groupIndex]; | ||
const { size, anchor } = sprites[iconIndex]; | ||
// Пропускаем маркера, чей изначальный groupIndex больше индекса текущей перебираемой группы. | ||
// Такие маркера будут проверены в следующах группах. | ||
// Также пропускаем повторно генерализуемые маркера. | ||
if (groupIndex > i || !isNaN(prevGroupIndex)) { | ||
continue; | ||
} | ||
const markerOffset = markerIndex * stride; | ||
const markerGroupIndex = markers[markerOffset + offsets.groupIndex]; | ||
const pixelPositionX = markers[markerOffset + offsets.pixelPositionX] - bounds.minX; | ||
const pixelPositionY = markers[markerOffset + offsets.pixelPositionY] - bounds.minY; | ||
// Маркер первый раз попал в область деградации – пропускаем | ||
createBBox(marginBBox, planeWidth, planeHeight, size, anchor, pixelPositionX, pixelPositionY, margin); | ||
if (bboxIsEmpty(marginBBox) || (groupIndex === i && | ||
prevDegradationPlane && collide(prevDegradationPlane, planeWidth, marginBBox)) | ||
) { | ||
continue; | ||
} | ||
// Пропускаем маркера, чей изначальный groupIndex больше индекса текущей перебираемой группы. | ||
// Такие маркера будут проверены в следующах группах. | ||
if (markerGroupIndex > groupIndex) { | ||
return; | ||
} | ||
// Область маркера пересекает область уже вставшего маркера – пропускаем | ||
createBBox(collideBBox, planeWidth, planeHeight, size, anchor, pixelPositionX, pixelPositionY, safeZone); | ||
if (bboxIsEmpty(collideBBox)) { | ||
continue; | ||
} | ||
// Маркер первый раз попал в область деградации – пропускаем | ||
createBBox(marginBBox, planeWidth, planeHeight, size, anchor, pixelPositionX, pixelPositionY, margin); | ||
if (bboxIsEmpty(marginBBox) || (markerGroupIndex === groupIndex && | ||
prevDegradationPlane && collide(prevDegradationPlane, planeWidth, marginBBox)) | ||
) { | ||
return; | ||
} | ||
if (!collide(plane, planeWidth, collideBBox)) { | ||
createBBox(degradationBBox, planeWidth, planeHeight, size, anchor, | ||
pixelPositionX, pixelPositionY, degradation); | ||
// Область маркера пересекает область уже вставшего маркера – пропускаем | ||
createBBox(collideBBox, planeWidth, planeHeight, size, anchor, pixelPositionX, pixelPositionY, safeZone); | ||
if (bboxIsEmpty(collideBBox)) { | ||
return; | ||
} | ||
// Если все хорошо и маркер выжил, закрашиваем его в двух плоскостях | ||
putToArray(plane, planeWidth, marginBBox); | ||
if (!collide(plane, planeWidth, collideBBox)) { | ||
createBBox(degradationBBox, planeWidth, planeHeight, size, anchor, | ||
pixelPositionX, pixelPositionY, degradation); | ||
if (degradationPlane) { | ||
putToArray(degradationPlane, planeWidth, degradationBBox); | ||
} | ||
// Если все хорошо и маркер выжил, закрашиваем его в двух плоскостях | ||
putToArray(plane, planeWidth, marginBBox); | ||
markers[markerOffset + offsets.iconIndex] = iconIndex; | ||
markers[markerOffset + offsets.prevGroupIndex] = i; | ||
} | ||
if (degradationPlane) { | ||
putToArray(degradationPlane, planeWidth, degradationBBox); | ||
} | ||
markers[markerOffset + offsets.iconIndex] = iconIndex; | ||
} | ||
@@ -235,6 +245,2 @@ } | ||
function isNaN(a) { | ||
return a !== a; | ||
} | ||
function bboxIsEmpty(a: BBox): boolean { | ||
@@ -270,3 +276,2 @@ return a.minX === a.maxX || a.minY === a.maxY; | ||
putToArray, | ||
isNaN, | ||
bboxIsEmpty, | ||
@@ -273,0 +278,0 @@ createBBox, |
@@ -22,3 +22,4 @@ { | ||
"noUnusedParameters": true, | ||
"declaration": true | ||
"declaration": true, | ||
"skipLibCheck": true | ||
}, | ||
@@ -25,0 +26,0 @@ "exclude": [ |
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
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
1
207159
671
119