From 6c8c8a64770ba1e7b1789116465055ead83f594f Mon Sep 17 00:00:00 2001 From: ahocevar Date: Sun, 5 May 2019 14:34:17 +0200 Subject: [PATCH] Fix decluttering on VectorImage layers --- changelog/upgrade-notes.md | 2 +- .../expected.png | Bin 6192 -> 6841 bytes .../layer-vectorimage-decluttering/main.js | 6 +++--- src/ol/layer/BaseVector.js | 7 ++++--- src/ol/layer/VectorImage.js | 6 +++--- src/ol/layer/VectorTile.js | 7 ++++--- src/ol/render.js | 15 +++++++++++++++ src/ol/renderer/Map.js | 13 ++----------- src/ol/renderer/canvas/VectorImageLayer.js | 3 +++ 9 files changed, 35 insertions(+), 24 deletions(-) diff --git a/changelog/upgrade-notes.md b/changelog/upgrade-notes.md index 7740f1e13d..25ed045ef9 100644 --- a/changelog/upgrade-notes.md +++ b/changelog/upgrade-notes.md @@ -100,7 +100,7 @@ If you were previously using `Vector` layers with `renderMode: 'image'`, you hav ##### New declutter behavior -If a map has more than one layer with `declutter` set to true, decluttering now considers all layers instead of decluttering each layer separately. The higher the z-index of the layer, the higher the priority of decluttered items. +If a map has more than one layer with `declutter` set to true, decluttering now considers all `Vector` and `VectorTile` instead of decluttering each layer separately. Only `VectorImage` layers continue to be decluttered separately. The higher the z-index of the layer, the higher the priority of decluttered items. Within a layer, the declutter order has changed. Previously, styles with a lower `zIndex` were prioritized over those with a higher `zIndex`. Now the opposite order is used. diff --git a/rendering/cases/layer-vectorimage-decluttering/expected.png b/rendering/cases/layer-vectorimage-decluttering/expected.png index 7b907f8ba89832a669c27a16d7830126036e7af1..5ccebf610e8df3494230a7860df838968de8ea54 100644 GIT binary patch literal 6841 zcmdsc`9D-|{Pr1JQBr8JD_Ue}v9BWvm8FR6OSWW>F_w&}?2=Z>mL!U?$JmER$}-lm zj-fCZTNr~eJokK_=ZEL@{0HCXr*q~$_c`Z%-{<|luIqhG+%02$ZZ1JC2!gn;8(cMo zAQ(7>LHjwt!S>-7H|DPZQ+*w%s7rVbf&>GuU%hfCIDL^A;m1Ec`STyrKu1ShGKG|? zz2u*@oNS_6fxY{A*4&g8usBHx^_%b*v|Q7MDv z$Ypy-G<^MbZ*Q;K9l~SQedo@do0w>NddJ*+(obb`_ES>LR5@49VXVi?v&5x76ZrH? zebJA(xw)NXwDGVc7%Rt03!h0z$l8ojd&K%DvC?}#xFDa}MWx^E?W3}PhuuH8evjmY z#sd3{7LzNSe;%^7ww9~GXohX1=jAq;XhL(QiHV6C>)pC4!iS);va)viN3K|Wh*yNp%ij>ln+-;C)=Epk(uiLs0(=w zmql^%ow;Ra=dFlJ>ujwUv_GJI;|ABumoG)m7Zep08Ce+_8QIZ3vcF)_uIZ-~<9rl% z;X3+(n~tK*|0G;?d~2S)U0_C^upSW`HSxG$Iks@F>tWZz8M;1Sh0 zu_6Yo7a^rwGXzd)W`L!3y#Lz?Hub8$KD|>tWHm=o)AcuhG`Eo6!-tm#Z3DRD;^GMO zI`THyUP2Fw)DTVxtLLUBTxfta$V>nJ{Y$Y;MxuN_(xII8$mr--nVCNI_GK=dY0AF2 zSy^bKG$q)Jory@K>CYxDW8lX_S*WN0+b-e4MUwjf73iW=T>B?yD{d^NPREsP|810UD7Q2po z^XN!bOaS{MgkBuQmWR`WDD~177;#zI&gJx-`GR7Oi8VYNI}>6e`~Ca(w%@Z2MZ z&a?)2;C*7K6wPHT-1u7P4=()bnpO2`FRdcRlsU<5raI}*rAwJYkGm9KfGw!5&Qxc| zn|HmGIF9?E`7RXVO;_uUawwbH`LwC3N?yJ`w3xYiFb8@u5!mn;_w3noo(WmoS*tzM z-;~e%U~(PLMtWzIJq}LVo`=P*i)V;H{~eEqwrG*IqsRZd^-WsX(zF(7VDKdQ0Ho{7 zX#pAdsgaHh`z&u#>2Ia+5!af!MbS&FFD4KTbVzMg+eBYf@^_mGEhT>a9&^{!NFLhW zg?avPx);6uZqdS!StNEm)So_hfVnjkolN$&4llZlwtmt)2mC-5h*rt{P~GZ{iOL8X zQ7=L@mPK3cUHkOCzpaTwi$U}A^On6YV}j%?ybH-+#(U1v<*w>Q=jBbvLqnet2UxZ( z9IG8&U0r2tDi5LoJaJT(3|Zp)!pUJ-WSt)^!IfdHvk@r-+5PtqcRPyA?Nng90B~dG zdOqnR=d~)N&;FFp8hoiArhe)S$LgvdwtU&n9_y1Us?D?7v`?(W|F0f2)0yVZxH#ik zT(9TkbP{BIU0ud>%3ANQ*Xzh?xzMo0xHuUh^<cdEVvG6x{?L(rDNa&TgbqZ#p zwmop(%nKtU*2iQlp~g(jFpTTlw{P!QSOndZ#oe{H@5;WGpz3j(6Kq1+nZ1T7@3G9v5TKS9}h?* zGd`Y6GoWmeOUn}j0|Wj2{g5Ld zu8k2-_1aVm#v`GWhO6E5RTJZ85EUFOPs|#7H zB4>uF`2S&Jh6PRDwdYLIY~9n-Gi`8U?U9w;xi@8iQh31M)qP78#XzKg{1}-i&|Gk# zt`V!Kc*P9sn0=*DR8mW8Jau=ec6q48iSP%G*S#`0MJI*8|h4b;ny?p}MP(>LloypCA3yIH}V@w)iGbcWYW69bV zmyl4ND}DYvrb%i!7-~%OZSX)ilkp$$jgMIYXwycG?d?U?kxOhEcEmx4h>XZcHURX& zOV#8ZJsc^VX17#Nv!}diM!x7!-#0@9&?Jmlr@CxXY}^#yqB-#YqH|OuMfG0G{!^z;ZIa=89>la4Z{E1blBxsFQU;63oyw$~ zl9KLJxML$a3shH6VWVcp_oxHIrOx}HK|5pyLhxe1j3MRKK*xLekez=&8RN8-W*&MX zYcRmXe=}*mWgdNJM8g(JgW83)9;t+cgsji?#i%b;JuNG{jGMlG{d&gut?^Kb?CuU3 zj;&n)RPQp;_!!z*O~Fl-X6gv*> z2M^BkXs+K%qiJpoITJdy8tUpJf$VcGA0CnUpyVxx*H}9kz8$=KCo}j@oDyZrK662) z+#O%(W50Uz=+Pfv&GImV5j%gy3Y#>SACf{v;V6yS`D2FttQQS+byIXOR8Rwjd|fh2uW>C>bQ0}>;HCH90N^Moln_@PrAeHmyX zrfO*In(~hynZCIAMCzlxYleo)TZLSF^FwA*P)!q|Fmt)u7PmV_vJ?@bY_-nUE^F;6 zyX+GJ6Qrv?xAXH?5v!|xlx;U7zyW#tHga%c$MB1@Z#EsOY5V*x3l*kNtyyBtgU z-m9x>yML=5yXc67$!D;zwSkC8pAUY^&R(j0;|2!RsSry}0qS2AA*%2 zq`gK72-k`=O))!DAK&6noM5zj0IoDD0{8LM5i!cTgoa`h7sp7Y3kD(XkJN)x-VBdY z?z2!KwfD3JTG1UFiWIis-7S5ybCB9_H2_)J>D2%I%L>VDftc>;iBwC~fpy<}=NG8( z@wuH5IBjVSqKUF)f*>Anp^XW4_;1MRjE86Xd-(tRssFV|W{`Oo4aTN@*FhpFZf<+c znQxx?R+b5ZO&BtSc-sxx-^0d*hTh5NAyWoLT!ZvMu+V<=nC&}-ub#hC6~2aXOdEdr z#Hqk>Sp1BJwD14f14-rM7MT5B0tFTb-{y-SpVw!ELa<}8%k8Xq+U&k|iLx{OrC3uQ z@y69vjfl1ksUg8=5N9FyBH|Z{*J^$jSg^bQci&5vtOOa`S%Hq4p_gmdUu!J$%(Oc( zZ|*svtvpmS5D;kt@&VZgWQPy>y?h?ojzb>2?lDVNT1dntT8Bdyb$3(MwPSOEtJFb`@cOT0&w;u8{J?^OIxF&j?^K>8zq@gT~Fe_A-B4~hI<7%uB~4VbaM>PTJOyZlYwdsLiy+-5aW8! zg|FM%3X6rWAMvfHCX>|6&CL}Q6fTBsctHhCtm!KLPx#InLx=hJ0tn%ZZAx)rrtZy~ z2^AUNzw1ET8;hQ@VS5akzltz47DCPd3)b44U?mjVkg=W2m+h?K%e{s#11<~(WDJ&2 znyjp-=!6};Zfsn+(S+S?pv0$}++s(MF3z;X@nLMRT@QBV=H{LWDL)4)XTncq2p0hd zz@OLm%VBr*IHexwf|Kg%Y1~3emTQ;gxH&d;$U zAd=ahPhO*y+-M9&=GX;$!<#n`T)TD+I6FYkI5|1(P#pHk#+4ECcicKtqnam6Sj6S! zU&qGo7e2HPNLWJ6`}gl%TwE@C^h$bW5`D0_Ka<3Ksa%lO&Wf(q_N)Ysu|UGX6OLbS zYed5cb%2n~KpzggEXEAXBD{`1GB)N#H8>?9VO0|-#h}yNL4QJ+a5gkN=nzhQOKku- z^C~052-F-X-g-rnGPG1fk#p-x4|#54+2YX64)otX%;1qDM={{-`1Yq z-h0%;*`GeWzvRqu^5jWWqSI{mN2sN>^;LShAp)TYV&9oFi6|2c2@F)2AjL9O87>_7 zAKCf&zkTgN;ZH<_`faa!02GyD*Frv3k4rA%_tZ!QN8y`IJY5?-@!zDs_^`z%CQbv*9EP-!L@mXLjAGc3GSZe@% zn^m6=HVw25y?uR*-8ByMvZKrO>v03!XH7B>26LQSTU#qc)M+OC{h4I5mS0dXTo+P4 zun7XUEOCTEz#7t6X=EMpQu1UV$3tTNYkdk%gFXuaHpuJbEB z@M}@g8AZi`2UmM~dQke*7cUNj^m;^KP`%$V+m(%wme?cw{QRI?Hm6>jKqh$Cm5C+@ zg%DP_fB2JL;;A!dqB}Y|loEr%o@i`My>vHRhT3cvdzG3B#PK=CHnqH!4R}!iMhTvvd;tWXQ1KI|QmM8`B7!_N2-Ka@8q+JK z?6NzQyLCRGg#%@ulam9w!!H<2%Us}Puc3=z^}q0V_pvH}kQRJLkGj^M)zA=b^!57N zegOw2v!%3O1Lz2>1$A;mg7#sKMgRxD!j|jzH8LxMV_*rlhkEtumBEc0r{v}NYKg{X zW_-o<8`f!ypx;#njl^wWF)n>B?dUKB2o6v>$>D%+?Ck6Szhi*C`%MZ7j9)YvwXZle zRgls@NwD!XhYVua22McQK|xCGDHmw!e?qpDFscDFmV@7$eQ4Am_8y~oSn^*(jL|6wx-^> zKgYLWD;g|uo3?BM^tZ!G#kX&M3qzNTGc}mR0<6`@sHh{nygE1(1M>pB0a%SsK-&ef zeMinDKK*7l2RfF`z8eU3gTdSXv*i-A;V9W-tu@kPTzY<+`6m^0{hIOBA|1yk{|h>` B9+dz9 literal 6192 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 0; --z) { + const zIndexItems = items[z]; + for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) { + declutterTree = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], declutterTree); + } + } + items.length = 0; + return declutterTree; +} diff --git a/src/ol/renderer/Map.js b/src/ol/renderer/Map.js index 488698d081..9955be7a51 100644 --- a/src/ol/renderer/Map.js +++ b/src/ol/renderer/Map.js @@ -10,6 +10,7 @@ import {TRUE} from '../functions.js'; import {visibleAtResolution} from '../layer/Layer.js'; import {shared as iconImageCache} from '../style/IconImageCache.js'; import {compose as composeTransform, makeInverse} from '../transform.js'; +import {renderDeclutterItems} from '../render.js'; /** * @abstract @@ -266,17 +267,7 @@ class MapRenderer extends Disposable { * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. */ renderFrame(frameState) { - if (this.declutterTree_) { - this.declutterTree_.clear(); - } - const items = frameState.declutterItems; - for (let z = items.length - 1; z >= 0; --z) { - const zIndexItems = items[z]; - for (let i = 0, ii = zIndexItems.length; i < ii; i += 3) { - this.declutterTree_ = zIndexItems[i].renderDeclutter(zIndexItems[i + 1], zIndexItems[i + 2], this.declutterTree_); - } - } - items.length = 0; + this.declutterTree_ = renderDeclutterItems(frameState, this.declutterTree_); } /** diff --git a/src/ol/renderer/canvas/VectorImageLayer.js b/src/ol/renderer/canvas/VectorImageLayer.js index c92c36885e..8d7e7b20b3 100644 --- a/src/ol/renderer/canvas/VectorImageLayer.js +++ b/src/ol/renderer/canvas/VectorImageLayer.js @@ -11,6 +11,7 @@ import CanvasVectorLayerRenderer from './VectorLayer.js'; import {listen} from '../../events.js'; import EventType from '../../events/EventType.js'; import ImageState from '../../ImageState.js'; +import {renderDeclutterItems} from '../../render.js'; /** * @classdesc @@ -72,6 +73,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { let skippedFeatures = this.skippedFeatures_; const context = vectorRenderer.context; const imageFrameState = /** @type {import("../../PluggableMap.js").FrameState} */ (assign({}, frameState, { + declutterItems: [], size: [ getWidth(renderedExtent) / viewResolution, getHeight(renderedExtent) / viewResolution @@ -86,6 +88,7 @@ class CanvasVectorImageLayerRenderer extends CanvasImageLayerRenderer { (vectorRenderer.replayGroupChanged || !equals(skippedFeatures, newSkippedFeatures))) { vectorRenderer.renderFrame(imageFrameState, layerState); + renderDeclutterItems(imageFrameState, null); skippedFeatures = newSkippedFeatures; callback(); }