From 60f3d858c9243aa38a8940b6645f0b615bf6cdfc Mon Sep 17 00:00:00 2001 From: Russ Garrett Date: Thu, 23 May 2024 21:04:51 +0100 Subject: [PATCH] Add vehicle tracking layer --- web/public/sdf/cherrypicker.png | Bin 0 -> 1455 bytes web/public/sdf/golf-buggy.png | Bin 0 -> 3155 bytes web/public/sdf/parking.png | Bin 0 -> 1518 bytes web/public/sdf/telehandler.png | Bin 0 -> 3623 bytes web/src/index.ts | 41 ++++++++++++++++++++++--- web/src/style/map_style.ts | 52 ++++++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 web/public/sdf/cherrypicker.png create mode 100644 web/public/sdf/golf-buggy.png create mode 100644 web/public/sdf/parking.png create mode 100644 web/public/sdf/telehandler.png diff --git a/web/public/sdf/cherrypicker.png b/web/public/sdf/cherrypicker.png new file mode 100644 index 0000000000000000000000000000000000000000..1a33ed43588bcb93eb6b54981aabd1fa6d1b0f90 GIT binary patch literal 1455 zcma)6do&XY7$0&8yW}16=v=P3i`il{Ll}0jl1J92yso-=L{Ymo*K2a+)v=;jp>Bm~ zM#zxIn2oFD(NIk>uiP?k^4#4$oztJ4`T&uKFJmKai=go004r5j@%MI2I{LgNAkWDn=wBOgc-V4@*6C*`xg8rW?HavD$c82 zXl+G`pCU|7R?QIcx!4s81DY>~^}oUt008^K(Jse*3Do(wxI)S?b-+0JW(x1M=EtLt zR?k+d9jd>$_Az!xO4HK(U~|}@ETOz-#jgt57jFuq|qBkK>SpgYE05*@J=t)a{;W|(}5(u z8_t9&k~y{vwpmz1sR(M)qM;%Zyc=2mWT_FT=W9O}&;@BwSNfZ4W8B#m>DH1Mu-0LO zAi@uL4YxDM)btu|2)w1Hd;P*DP0gtqMR^hiylz}l$r#l&BJ$3`TEaKf4Ei<*=~aSjL&dCTQFb;WO#eQZex)(p(9oixGR zuTjp^fNcJ`;*CDd+L$B|5`@D$J0NgDftN*sA+B?Did9oL^8+VtZWQ!Vc-PIIfp=36 zsv?GToec|(lo2S{!tFNKD?n20`jU94SUO*4Ivy$$$<)4|3dX1^l(9aK5(_-&=QgJr zbD9IrV{4UYgxmXR42rq6eoypmTU=sh5!|%O7}nlBzTzViB%3Fg#A^DmvU;H0tx26e zW_Zoa^4Kh^r!4q%AE4>e{Pl8!5jLvb#F@po^aS`r8yONR4M9u68`zi~h(mG~CZ8mr&ZW|6xy9-7oywuJPE%=J`Qk_;S z>SJExrgN_0F-v5to#%?ZGAU^(iN1RyG|tw7bY|ws{&VpgelD*clz^85TLrVb#@D>I zpz`-Jy{B;cC1JaWWk_B2vzFpTlZa+Ub@A_cE)MK@u@T80poDz|akI)kaN&~|Qjhx- zqA%Urn>QHuYmgLX z?}YbsE(_S&0k=`>k5y8lSlyJ(Epa4Zo4FtcMB~Rxym^`ev&Ts~nvT7io1da9D%}y7 z%8tZeD+FOx{n=*8IDXL(azeCC+6^kj`IRe!2L#L3{^tX%AJsluI7pPscyj|8Rynr^ zdi(hC)9<)z&p*)$X3%KpI7&mKeTUr30Z{i zt|zkcoq(28a0V&^CjA4o@aD zLhMa5yph!H7*ND>=F6Cg;tCh`Q^>^>#9(RqB}G9_^czO&p5eoKYkY$kFg%yYJ;LmS QNq!dqjl#Iloq|&T1#~_uXaE2J literal 0 HcmV?d00001 diff --git a/web/public/sdf/golf-buggy.png b/web/public/sdf/golf-buggy.png new file mode 100644 index 0000000000000000000000000000000000000000..e57f304794d67930c7ca60c48dd8bd6b5eaf2dfe GIT binary patch literal 3155 zcmZ{mc{CJk8^#r~ODNewvhOolq6|XD*vVL@u|?U}2FXrYBD@UIWEY0Wz6>VDAT*W+ zLrjJiTMKHMn9n(#)9JkD{ho84>;660eVzM{`>*GLmBlqKb|H2K1_my$iJ{F=MI2o} zR>mXEKS=RED*IMuc1CnM{qXScNPoj0{!iy$-QStN^-th$_``oEkNE%jf5-ln`PcLJ zkl*GX{Tq(>KM$RiB!093n=l&-TLuOeL3tfB*MRJ7SJO-KtfkE_XGm-N^h%_e$c5f7 z&%I6MnBH4*^=?@H7<2Sq1rCX=ufSn_ z(_dx!jpZv*6E`t;zQKft^LM8+u9XX3DzdlbF;#(}@)xgb)Jmh+jj7#%t7l}dpUgO9 z?`XLpnz=lx6f5p&ZycI>;k%{siB$x&ik@5eI;dcCw4A8S`22 zmF)aD-_mL0@cz@fnXlPC@by>bPsG;|azh`$%ztP;7NNZaYrLkva;<%1&VG65XX-w~nqo=jliP^O(U)f; z=;REaN4whlNSBymmv7HZ$0Xh()L*l@wuet+f^wkv*ThQ$9xH=B1n=)tWV=BufG5B^g&_9 zYsV5Oz&21GhdzF?-+EsGt>=*^5lb=K=F8Th zrD@z-&$oE88y!ekd4l5#w~hH+pN3`jxw$HaZIco4WY5r>BkxRu649053aZl0>7WRO zr@N`QKoz2_laX@}_!D(sRQz270Jv$;u5}aS9manm3wS22YUQE^PQO6AY~!iMa*X%6 zDNfakTaV4&Zcz+j|2&}721x%jr#LOB->dWhF)bPxM5ZSjvxr3Rrf0QO502~M`#fFk zz*ZQfNJ}Ba$lhOfYBD_xe`jZU!WgCVCeTTeXY`@-S2@(sGvDc!2sZ)S8i-C9KaC)6 z+9#fV&Y6Sz;R5Z{7~8$sdmJ$Lnq+HuE!;# zS+dT@pu}z8EjC}&Lx+Xz(VpmV{t8JYS|j?qOXJF#B*u@>jHQq#I@t9DB3OB?wwVqmm zAn^-G(^<9? z;+-2f%UEriDzWm`Kl#>05`P&~F=>4XmQYinjLemA6vk^^lf^Wh#((7nsS` z&%9vzm78jsG3ASMJ)_Ce1=h`k4ef{iB>VH9)3>z7w(mF6o8)Z-@UadN@hBUXhixZ{ z{7#EIYiOp!9ZX5-94}QTCdnu_Km8(dFhC963oQGlmuv;;AI0jF!u4Wt&Jtk1-e$Pw zIhX49H{JGMl2YmZ7$F_jl|A1O#ymj~N2hq&Ny&cb!ULSfmc}KSlNL;FK^Z~=3ib#K z(JLj9vQd;diyVli#LhyR=xn5E&tl5&QM zlTzlY{;t+Pvl@@T3+uWh4yqKkPj}B){JL(n-@$di^a=Ud! zvve?!FjIVYuG8Q=-m7u6lRr|O^5|mwkX98aqo7&z8gTbmzd%nkg~M{dA+m)ta>Q0D zDw$S`DZzYSRWD{F0vgpIWDd(IQNWDnDg2!-NB#uw4&jNoM%Q4`RCwZ|K(O46Cq_Pv zJdjSR$5{gbhW#ly$<^rF>ka<;Yk)SL#t}63g_y>md@OsT7Q(XSqT&MI3?i!F!v<1+ zEY4|s?$gKNvgWHYVNxRBl)cG2ckxJ+xi^Y}UgX?~kp&m*>F7<&z1Pg+6I@E;sn}WP8 z*wr`?ff?>D*YF31vjuRUd<`{x5m-oL4G7{?r3&8LHlDP~+AqYb}WwcdIY(QsY&I^;kBMRMZBWmK^+?1U&?4;Jhx7&WPjbGKwTb!Re(&405!GL*?^5eP}J{9@cgYgHW_3WKiGpy|wrjy=>KQ<0A z6U`I}Tf=NrC0RjiTf4nH(8v+?*spOs)<14Qdx7ADyrBn$mJd(Em2_D~z$Yca%~yxY zK=!xq@*-ee`m9rS6!W}`X#?1vrgya9>Z)h0ZBlp6k$<&Evx%gAQlA&|O~_)84xY?| z8lCC6Ue5~sCs1xEcd4r*^h`Z+x4EJ6ly=Uq<>($tpCW&JYgmC`k6P*{TbnV(@H?mH2L-12Q*S~Bi9rq<#`5yKcpe5w} zZ04LJpIZrtyahFx&-ZF3&SvI`TG9@oZ1z1Pd>Nmi{k%1*lZV{{dnvz!J8J#5=}Zl3 zwPiyef!6to)!#33y@hnVouj2lB>MZ8w(6hyIr!E6|NO82ujT*pnX$Uq)_FQX1bZR? zpk{uV=7j+x9`#O%1f5P`{O}iZsmApRwAzAvYl%3Dqp8@8L0>jn)%0?r;ib?wa|{6h z@qU~I*70V}v|E2hwjt0`F}}8?tFPF#(bJ$MJ`9=lLsYR>j03`tj3IbqCNKSAlQt!U z&)Rjy-HX(VQf7;WeG*K4Z14TRdjV$ipvGZp^!LP zx9S+Jn~_J84Ab@*>YnRtIQP;4|G=rXkvKs#4Vie1s-{Txyi27wRFE)Ekt>(j8h^FT zha%~gy9&$Hk6ndRUNQIP=@fZG1LRu(R84PH8?yTaNY+_qnQhYS<3lW!h-;-aY)on; z#d1~k4K_86Jf*lzp(DA{72MHO0KI4u(N?)4j7imMNVuQQUjpkhsM8q=yg8r`+@mYG zn(A$&@Vrvllr0y;j*6})eTon?y9wrL*@ef%G-Bk|%1QPcgN8xQHAaO%zL{iP>u0U# z@DE)n>+T~KBV6=}rEof(pyc!0u<@Yv(V4^H}1g0Ad~M9p5RV>UX{Xu;u1!TyYkU~w^S)_8*^YWg1r*)(1HTYj?tdNA@(PlAY$u zYMI&m!)GliD_KCD1HZHRQY?2`3XPAZYVmx*WGDy%bJp}OM>$du$icON+Jo^6>M5t= z25`RN6Q-%XfxZK|Z}fNvvi}IEH7QHCp1<=EJ{gH2uA%N2YiP>tg8mi?UL=NipyRJF zYzAtdr%yc)hoyKfk@{Ipt=5@brwgGDxJJuPYUMS!TzAPHC(@T_vuYF~)vQ2i-0oJQ zTS6THXQ4@iArY>gSj~22i!hsblPP0ST$$e=BU)A;sv9gpxJA66uxePm02%W(7B3Y#C&9T-Ab``6);&Zri;) z#lEx2BcHgH{WElE+70z|6+Rs+?iJMpKvbM?0r#GEKa%@WLN{TK%q;Ii_voWo82a+= z2C%Kwl(4NGf1J4~KYhL;Pae#>4K5P0&aDcp$lK#XIIm6N&FZ*ud$I(TZ{Wus#_r~q z1p1^g+}huX>dE*^%h2^^ZnlR?@7R0Ch5R{DU~`@AJnhutzR|P8?g1iu8Ii**(%yDIr|F;j`{vy-lKq>Ob4(H&l4++3o+FLNqJn#Jj D+v+3i literal 0 HcmV?d00001 diff --git a/web/public/sdf/telehandler.png b/web/public/sdf/telehandler.png new file mode 100644 index 0000000000000000000000000000000000000000..a5ae65d474fcaa4a3d9d85d3c779cbc72729b156 GIT binary patch literal 3623 zcmbtWXHb(}8jVPA(j{~xbV49VQG_7UyYv)#0BO>tOGm1RbR%F;6akf{p-GWmq!*O{ z0r{vRT|nAqhgs$ucXnrI_L=)W?|IHW=iK|_{qZIk8EDc`b5H{S06J|gHDlsCkodS! zUL^LU{SRXR0147a&s6>N^z`K9gxLR|`Xhljp4ETKJU%}DPg`d^(S9yC!{?T>Wa4t_tnc&;IW^PF@3j5*&r2Y>Ly@t>#Ap&|1Lf}Jp99WbaX^?{h>V55c~hg z6J`G; z@?DROxk?!uo&?xwNPLNRHjn{MEEc)T1CzQ}+8+6uQPI;Mo8^oiw!=!CWfaW@-`|C> z((W4o$w8~wd_8S|i1xx?@>i^KuNhO4qo(9O_==cT)UT6(R0)C%AjQ`4JvteQs<9s< zdXy}@-uuc@&(Q~aiNBr$jg z08m$ItKBpWd^+}I(}sBw*bGtq6gy9HQ$_1p3@U<>LYu9a4DWYON)yCXBJ@r7!!r_Z zG@(svG^%h|A3?&JH~2bd)J{L|&63w!`>`odi=W!QzaBKb z7)D$W%1Wy%>DtrHSswE`)q){zw#&jHoP^WM(YO?Gs{Z_X0Z0MU!9%cj+K)9emS-6v ztVohYg0uQftWJ>_3x%_zmlKM*tm7)Jr6t7M{6#xzE|G@KJl!3V9k>vQbM@*#Ne1?k zJNG*_tG6TKTcD!RX{Z_u;c;Hk9eAz%{EdIlLw67F^GRn% zHr&$6dM`2tiouM4B7vrvFDCYSZT#<52bkGfz6*c$d>e%DCyXxB)(-abjH-ez@Nn>z zwRsWx-j(hZ2G^4**tWqKuAY*EIazPXi0nV3POi089q82Yl=dtO;hM*KyL#nK zm|owFc>^9bhK!;U#pSXfdNEkzNv%jooGX(_>+&8%bn0S$hg!24`<YKK?bRTj&B}Y~6*(63Pd4TN1qf}BTfWK*V8N^}9eQJy zazQ?-C8DlvBFM-~Rhh(!m&^(_bfXicJ8k9;m9rDfWRnZDp{2|3G$my}eQq-PN=@K&%kV5~wFH*c)p8nAAkyYO^D&yaQ3)wP;-DDIr_QJx%6Aoud#S*aGx{ z*K(650+OM&X^PyqZG4ArexMn;3*sGSn8N64`0EKc+g*Z|kc?`_#ZGFCjR^7L+@rt7K|0 z7wJe3v_PAXu_jv-6SLfx7$o+T80lTJr%D% z9bo3r<8`EoO9N_(=hv>W$4f+RO<5*@+0!+Fkz^t1AOAg45-??C zh2}4QKL&A=on&FG!kZT2#&Q(n-oqx9c__X;-a-d^^k9>rzz56zTNIK!#-h9|0s<4o zbwP(MIh{*jw(rUiO*dbjN_*%FUs_yz8P9X;VZNa@@04ezTE%c4v0EE0c$=6N5W+~& znN)oO{MN!gpt{8(S)7^s5R@M(7Ehz|MF6XSL~Iy}D3mntkF^Q}WGG({{o;^jR94&$ z`Bam7r5LWtt*D$jqqklfF6wMvbk&gIpqx=Q$1vX90F#;NaNv7#FWLQ~f0VfQ5=u4G zb#r5BkD>hDRredA`%=~BC@qwr2IQ5?!gFb_ZaQ71so)jY4a-Yt^NKbStkjVc0T^DW=Jd6;RuMylCRhK1+diCUUOK4^-L zPR&sC(~M=!#;1e(!i-7I9aLIFpP@VN47fXuR9C2Grliml2Q zM}L)vDbup4oaA`=OZ9DM?bxLuoxF;5JayGF8Te7ixX0b9$V`fkJn5s%uEZ3@Mzof# z2c$$E0_S*8j!o^%F6Q+O^G9?XOeJhMmCEhV%6>QmuMCtYj%|{0FK_hB{@RL@_1~G9 zyC_#3T_!t#q4?$ZY%(3*ofgQtDQw19R>BUI!& zhLK9)Q`ux%?bu2Y;9PjT@9^V$h(4i~Ud($$Y05SKKteQzd^6C;pNHwABsN J-m2P0{R2sI2)F f()) ) - /* - const sdfs = ['parking'] + + const sdfs = ['telehandler', 'golf-buggy', 'cherrypicker'] for (const sdf of sdfs) { const img = await map.loadImage(`/sdf/${sdf}.png`) map.addImage(sdf, img.data, { sdf: true }) } - */ +} + +let lastSuccessfulFetch = 0 + +function updateVehicles(map: maplibregl.Map) { + if (map.getLayer('vehicles')?.visibility == 'none') return + + fetchWithTimeout('https://geojson.thinkl33t.co.uk/') + .then((response) => response.json()) + .then((data) => { + const source = map.getSource('vehicles') as maplibregl.GeoJSONSource + if (!source) return + source.setData(data) + lastSuccessfulFetch = Date.now() + }) + .catch((error) => { + console.error(error) + if (Date.now() - lastSuccessfulFetch < 60000) return + const source = map.getSource('vehicles') as maplibregl.GeoJSONSource + if (!source) return + source.setData({ type: 'FeatureCollection', features: [] }) + }) +} + +function initVehicles(map: maplibregl.Map) { + window.setTimeout(() => updateVehicles(map), 0) + window.setInterval(() => updateVehicles(map), 20000) } class EventMap { @@ -58,6 +84,7 @@ class EventMap { Power: 'power_', Lighting: 'lighting_', Villages: 'villages_', + 'Vehicle tracking': 'vehicles', } map?: maplibregl.Map layer_switcher?: LayerSwitcher @@ -142,6 +169,12 @@ class EventMap { const [lng, lat] = roundPosition([coords.lng, coords.lat], this.map!.getZoom()) navigator.clipboard.writeText(lat + ', ' + lng) }) + + initVehicles(this.map) + + this.map.on('styledata', () => { + updateVehicles(this.map!) + }) } } diff --git a/web/src/style/map_style.ts b/web/src/style/map_style.ts index 9d128da..e11f347 100644 --- a/web/src/style/map_style.ts +++ b/web/src/style/map_style.ts @@ -975,6 +975,54 @@ const layers: LayerSpecificationWithZIndex[] = [ }, paint: {}, }, + { + id: 'vehicles', + type: 'symbol', + source: 'vehicles', + minzoom: 14, + filter: ['match', ['get', 'icon'], ['telehandler', 'cherrypicker', 'golf-buggy'], true, false], + layout: { + 'icon-image': [ + 'match', + ['get', 'icon'], + 'telehandler', + 'telehandler', + 'cherrypicker', + 'cherrypicker', + 'golf-buggy', + ], + 'icon-size': ['interpolate', ['linear'], ['zoom'], 14, 0.1, 24, 1], + 'icon-allow-overlap': true, + 'text-field': '{name}', + 'text-font': ['Open Sans Regular'], + 'text-size': ['step', ['zoom'], 0, 17, 12], + 'text-optional': true, + 'text-offset': [ + 'interpolate', + ['linear'], + ['zoom'], + 17, + ['literal', [0, 2]], + 24, + ['literal', [0, 6]], + ], + }, + paint: { + 'icon-color': [ + 'match', + ['get', 'icon'], + 'cherrypicker', + 'rgba(100, 100, 255, 1)', + 'golf-buggy', + 'rgba(100, 100, 100, 1)', + 'rgba(255, 50, 50, 1)', + ], + 'icon-halo-color': 'rgba(30, 30, 30, 1)', + 'icon-halo-width': ['step', ['zoom'], 0, 17.4, 2], + 'text-halo-color': 'rgba(255, 255, 255, 1)', + 'text-halo-width': 2, + }, + }, { id: 'villages_text', type: 'symbol', @@ -1160,6 +1208,10 @@ const style: StyleSpecification = { type: 'raster', tiles: ['https://map.emfcamp.org/data/ortho/{z}/{x}/{y}'], }, + vehicles: { + type: 'geojson', + data: { type: 'FeatureCollection', features: [] }, + }, }, sprite: 'https://openmaptiles.github.io/positron-gl-style/sprite', glyphs: 'https://map.emfcamp.org/fonts/{fontstack}/{range}.pbf',