From dc0cc32046dd3c168b86f9e4ca5c1e5f4f57f4fa Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 9 Aug 2016 10:51:33 +1000 Subject: [PATCH] Further tweaks to line labeling, add tests Sponsored by Andreas Neumann --- src/core/pal/feature.cpp | 12 +- .../python/test_qgspallabeling_placement.py | 46 +++ .../sp_label_line_avoid_jaggy.png | Bin 0 -> 5018 bytes .../sp_label_line_over_small_angles.png | Bin 0 -> 3239 bytes .../sp_label_line_toward_center.png | Bin 0 -> 2485 bytes .../sp_polygon_placement_perimeter.png | Bin 1310 -> 1321 bytes ...sp_prefer_line_above_instead_of_online.png | Bin 0 -> 6902 bytes ...sp_prefer_line_below_instead_of_online.png | Bin 0 -> 7092 bytes .../sp_prefer_longer_lines_over_shorter.png | Bin 0 -> 2719 bytes .../sp_prefer_more_horizontal_lines.png | Bin 0 -> 4171 bytes tests/testdata/labeling/line_placement_1.qml | 272 +++++++++++++++++ tests/testdata/labeling/line_placement_2.qml | 273 ++++++++++++++++++ tests/testdata/labeling/line_placement_3.qml | 273 ++++++++++++++++++ tests/testdata/labeling/line_placement_4.qml | 273 ++++++++++++++++++ tests/testdata/labeling/line_placement_5.qml | 249 ++++++++++++++++ .../testdata/labeling/pal_features_v3.sqlite | Bin 161792 -> 198656 bytes 16 files changed, 1397 insertions(+), 1 deletion(-) create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy.png create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_label_line_over_small_angles/sp_label_line_over_small_angles.png create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_label_line_toward_center/sp_label_line_toward_center.png create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online.png create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_prefer_line_below_instead_of_online/sp_prefer_line_below_instead_of_online.png create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter.png create mode 100644 tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines.png create mode 100644 tests/testdata/labeling/line_placement_1.qml create mode 100644 tests/testdata/labeling/line_placement_2.qml create mode 100644 tests/testdata/labeling/line_placement_3.qml create mode 100644 tests/testdata/labeling/line_placement_4.qml create mode 100644 tests/testdata/labeling/line_placement_5.qml diff --git a/src/core/pal/feature.cpp b/src/core/pal/feature.cpp index 67029482d8a..864ceb191e9 100644 --- a/src/core/pal/feature.cpp +++ b/src/core/pal/feature.cpp @@ -683,6 +683,7 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList 0.98 ) cost = 0.0001; @@ -738,10 +743,15 @@ int FeaturePart::createCandidatesAlongLineNearStraightSegments( QList 1 cost += costCenter * 0.0005; // < 0, 0.0005 > + + // penalize positions which are further from absolute center of whole linestring + double costLineCenter = 2 * qAbs( labelCenter - middleOfLine ) / totalLineLength; // 0 -> 1 + cost += costLineCenter * 0.0005; // < 0, 0.0005 > + cost += segmentCost * 0.0005; // prefer labels on longer straight segments cost += segmentAngleCost * 0.0001; // prefer more horizontal segments, but this is less important than length considerations diff --git a/tests/src/python/test_qgspallabeling_placement.py b/tests/src/python/test_qgspallabeling_placement.py index aeb1ac98c7a..4105d7a386d 100644 --- a/tests/src/python/test_qgspallabeling_placement.py +++ b/tests/src/python/test_qgspallabeling_placement.py @@ -276,6 +276,7 @@ class TestPointPlacement(TestPlacementBase): self.layer = TestQgsPalLabeling.loadFeatureLayer('polygon_perimeter') self._TestMapSettings = self.cloneMapSettings(self._MapSettings) self.lyr.placement = QgsPalLayerSettings.Line + self.lyr.placementFlags = QgsPalLayerSettings.AboveLine self.checkTest() self.removeMapLayer(self.layer) self.layer = None @@ -385,6 +386,51 @@ class TestPointPlacement(TestPlacementBase): self.removeMapLayer(self.layer) self.layer = None + def test_prefer_longer_lines_over_shorter(self): + # Test that labeling a line using parallel labels will tend to place the labels over the longer straight parts of + # the line + self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_1') + self._TestMapSettings = self.cloneMapSettings(self._MapSettings) + self.lyr.placement = QgsPalLayerSettings.Line + self.checkTest() + self.removeMapLayer(self.layer) + self.layer = None + + def test_prefer_more_horizontal_lines(self): + # Test that labeling a line using parallel labels will tend to place the labels over more horizontal sections + self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_2') + self._TestMapSettings = self.cloneMapSettings(self._MapSettings) + self.lyr.placement = QgsPalLayerSettings.Line + self.checkTest() + self.removeMapLayer(self.layer) + self.layer = None + + def test_label_line_over_small_angles(self): + # Test that labeling a line using parallel labels will place labels near center of straightish line + self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_3') + self._TestMapSettings = self.cloneMapSettings(self._MapSettings) + self.lyr.placement = QgsPalLayerSettings.Line + self.checkTest() + self.removeMapLayer(self.layer) + self.layer = None + + def test_label_line_toward_center(self): + # Test that labeling a line using parallel labels will try to place labels as close to center of line as possible + self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_4') + self._TestMapSettings = self.cloneMapSettings(self._MapSettings) + self.lyr.placement = QgsPalLayerSettings.Line + self.checkTest() + self.removeMapLayer(self.layer) + self.layer = None + + def test_label_line_avoid_jaggy(self): + # Test that labeling a line using parallel labels won't place labels over jaggy bits of line + self.layer = TestQgsPalLabeling.loadFeatureLayer('line_placement_5') + self._TestMapSettings = self.cloneMapSettings(self._MapSettings) + self.lyr.placement = QgsPalLayerSettings.Line + self.checkTest() + self.removeMapLayer(self.layer) + self.layer = None if __name__ == '__main__': # NOTE: unless PAL_SUITE env var is set all test class methods will be run diff --git a/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy.png b/tests/testdata/control_images/expected_pal_placement/sp_label_line_avoid_jaggy/sp_label_line_avoid_jaggy.png new file mode 100644 index 0000000000000000000000000000000000000000..66de17c8520df1ebc6e52b693a6e6f23d883bb79 GIT binary patch literal 5018 zcmeHLi9b~P`=3fT%OzXf$d;|4kR^LEkwK;!qA-*t`@Y3k;##hRLBeIY8cajTHg;o4 zWJy9}9mz0u8OAzeey4u-ulRny=XE}>^E%J#`JC7Dyr1R$oKNCim=Pzt5IYD2;xvXD zz(JrBMZo%l^*2DmXAq+eJXiuC#ulu=70&AP7x2#J3w;;>0&(#ETqnNFMA89O9b*H1 zi>G<(Gd7+@6hzO~Y|Ca|>uME|<3>CCx?(pdgPVQ&-OrB@clr;82xCdV~H&rS@ARySWCcuFK`5^P&k=Bsoa zhdL6X78#L6a`_|MZSG@{NBQ}(JFRgovLFywPQW-|^D_e!2y}~E3iOPPg$?xRr2a`z z_6un@(xNP&NqfR`=Qh4$BZe^G8WcJb&!S<_ag zqR4pgd{Te9PNw7VsVSL9C-gg`Z~bsFve$a&MU%s)kFC7VjwiJS{xcwuu12{_1~KNk=0D;WaU z`O@0)NY7xq{vn-@JiI3p#7|s#Z>ijOw)iFb@4GA14i-13Cot23r`Fw0kU87q8+f({ z`Y5h;(;j=Bm$~OY=RS}rqgOq49^o@VXl08hfBNLHHG#bklOp@a#y*pP-r(3;c;Vj# zc9!kQYzkbsf!7T4gP9KL6gwzauo6++N-S)y7hBpY{8e9@NL@6xHY+e+p`JNv8jQ}Z zzi%S*QuzELD_gVy>Y0p#{KJKWgq6ygjCrA!Y65osmdj%8ej;|IvVTj1n8tmHg)KrB z-%!*$X?@4>eHKG|&AobgD}s=ss;q)7-o8V$&*Eik%){SpjzQgDa2|BK17GkeD zOuY5aO+m@*(!Or`DpX>KK5{DP3W60(hX3Kv`qZ@(9<02Fu*e^8((5;ORBr*$(tmv5 zfk!@tvKv<|WZH#P;?gD#%&@Ccxa_|IVqAsrDM+9*L$0*9TO^3*X5;o*#oB3PsWNDZZ+!U|M0$E>3>xGv~*|&CCMN7p;{5AfAK&S!!_cxuU{e zZGoDkN`SSy|II(8GWq=Ch{Qc7?e?A%z^+6xRZjYQdJ+996TiL>cd3!zuTlNIp01;< zSy8B~;iay;m!f><=}ROnRtG#cj5r)>!;Ed! zjD<3E;&i+QwybcM$e~n=h@owMs?Ns@NIp}98386A%x2MtAo=t&vAUJl@j@Re7@uZK z>bEAh|9-K4zi0A~dcVA|Z|>2P)FuHNJ=a1R{pkxc$$nCC*X$?>ztO&m9orF^k(iKQ zrcx}P`{Y&IXa|^VAx+sS)Lhc6vDY#c?KDDpY2ENTvmkfHUC+pcQoHZD-Ms3q({oRn zH_hhKn+wSs`!i2IF{YxHzA8rASw%8d5$hPRjpM_pb+E-288;WCmM<}6ex>txHQujQ zx08l}UJ#0jJ+)nfQCvRjee7#rKexzH`u^rx;00)=WVhSe7Xxp|*z`Hgwsfw(pBnIkmj%40rWw zwIN4)uo_j>73bIYu@=~GfgC!Yl z&BDSxg*w_%`M-(vC`(_cu^|GNXle3sL*{`9@*t)nYF%E0$px?u5MZ!p8%}@4^F#d4 z4R9Uhf4ZmYk8F)QBuD7ijU1utEFmgKUXj)YHc7z{WeH|M`|Z?QYScB zr)L--6S$X-Hd&9q8Hp;I+=imXq?0$45T7l(SJaANFIo>J5mCowBAbE$XZ2w zG~Iunaa&@{%=36u|9=(0InW{!0Cl+G23L*XLFc!*Qcxf47-#Snt|K>%C7op~| zHrlc@c@?@&a+Wm)xUxJtb)y$7FhwGy-MY% zI)87T4u3oq09DJuv2h}rUek=k+zt<5KO>n#wL&2xsaptwww88fw}7cxEgU98#`|%8 z9Hh{eq8ODV#`^41L;nmUO~bN-!1zXml|Mz z=5{=CH2g+x_)XvNJGnF{%}38E)72o;tZ;kwPUMy(;=(aDKC~_`nc$J}K&x;i&-%M- zsnIdHbP&th2g9oEkfdi0J6&=kNgtP+4zrj2&<8`rsl$!lfxL~#!-;_bBA7&eIe`U%=l)4!RqTe1-Ef)@(;ik;bhq)X9%FI#V*nzG7uu6X@jk%L zdmh=QU_3DD>OBf%C@iQcb0s!?@cL>!sHxGmU);Imi_lRAp`O0}3sCe0qB(P)fp60W zhKf!4C!ZkINbm$H02-lY#(h#=Nq;4tqH!FXx0O9f@SN%YO*f)ZNER#9ad>Yk>?Wuz zn&bYdC9&mm3j*%LZ@a4+4mKTznGs$C5dA1>IU$qMVD_4_zp2jlSoc|-WOMw(OySf+ zcT>U9Hp-pK7J^Wg(yTkuhN;M|O$FB= zhqv>%aFfKDI}-;ZED^8VVt!N^p)Rw`u=1 zx^Vg{#L8V`=HZc9l_(4=G(PF0v$wa3y(WAIX?byOWwvh518XdqJ6pymISiZkVQK>t zp!TN~bk1&;8i7b2od7V}bW)3e;rgvYeura2h+{7^nrBCqcB!XZY2||2qQdXu#ZTKx zU$6vjaH!H$K;J_0$SY2sz_REvqssB8?xRtP)p$$Y&MA#AQ~V#o?LrEU$SFxp&e##5 zrto4zRIpuB%R=^8qNNQYH@#>$CzLU(9$7zMm6W)jQXe4}wf%ad0Qtf#=CdFxFPBAk zP_Y4I!QlH{d_j(h$6*1pc-f^Y^Mz=h?#Nd5#78#W-7YbJdHsBhVO4MH%*#{%v7T6G zbz2+buzotHt|cn??ysZ2c`gB^sTH;!4_WBL4+a0EvNKq*`<`wO=WN@SDUvnY)}8^% zW94!c@`_}|hgF$+W~eSz{Uu=*w&;u;n1}1*qqm&RR}gI(V6GR1X>G4^%PA9Z+Fhr9bTH6hg&Kl# z0q3k(c~8n}H%3Gh1p{oM`6R4mnJRz*29A~Q8%?*0ox-PhzD!stynD}b$fXbY=2Rk! zH>;f-yv&(wT`vB!6(B`mg0=TGMXieFKEwkfD4$-0xjJFzApgVZw-Qj+JpaojG``fO zUYam%ZxR7`4A&{4_g)ogJQyz7GgA1p7s!B?DtsaO#s=<=aWoy%757wS9`Wcy#GOS8 zrd3Ttntx`(YEV(MaJ_{PbSIE3eLw5!keBUEA!N?O*5Lxc0WiRN7G24l=*tL_|G*V} zt?Me-ZZ3g&kK*hX#H_1&j7i}pTK7;;L^;R17vd5qWpln@}7Q4(Xd8q)XO@a1c;8s^2rzb=NBz- zms;>&hrcXnr!@K+_P8tt`keK4MbX(T6J{d|fKcuMNO-IdfV;C^srep#%FnCFpqmFv zs`#vS;4+ZcFrh&3gZ=aV)x4sD{@Ob*oqrm~o7fuwu|}?q=D&~yxWk2}H+wv)LoFHHmbHcbm&Pa9d;hSD{yd{ z^Q9tm&lk&-4V&JG52W}`K(b@JH|1jOwyXciHF8fmmq1Lgd(@N^IH(Cn2I`PpUw!)g zQS?AYzWw%ATiDdU4lfF;YXZkw>!#8+07Rwsvj%|MTb(u-sVUj?lb<#CKQ)jzUlRu) zIObzzqYV;@w{#+0>ZPDou@}U&q5XtHRW;G%O=Ihr5XDU5aQt6u{o&HeJ_^OwVRN*R z>zq2r^|EoE)lsW)c-EjW)y<-_ z_p3DXw6z}m+R^w~>6n=z=|lYG;R3b_36`Mh{f@rQ_BeG{Ek{ig@Qd&PNwtXKz~8yP_n$;PebS6f*|O2Wq;<556hJbi}Xj23SJGTyRr4oev8-Y>!$3< zM3}pAW~#qzN$KeE4}(%-P7%!|Js2!BQn@OT2qj(~5e|ND_8`sPk0Dhqx_h5+^&gQ& zgp)tBKS%1OJ>{KBc6)Bn#}7sgF^Xbyk%L$l78hg{=U2WsJOVA`-)p~vXbQzITe?la zOZBN@Nuauf`51GI{M9CL>~MQhM!A)DgQOLblc&jeG{j)-o6>EKOT~NKIYjKI@?#J(Q1~E$Wb8GcYJ+s9U z^ENp-RvG^V-K*EnABl~CF{%w%A}`d5PBV?9UC8A6@c_`FOBn@)VZ!{0up`-)9{m|% zOE)3fgb6{H5$DO3V$eEkX_CokjVB4kd-L;ZPdHFJf>E*lRB;&S<-{!vw2&LWyvV9> zjAw?Oz%ueK%`(bbi)!Zd4NqAW*n^ydDtEI)u_)U2>=`D#f}Fdi0Y1gBxU1G+j^fIn z@==cf9|r7ek>NI=VN-+rjv0iPQfNgnP@2%MMHG=dX(CbA;!s8-i=?p}V+Ol6Gb($|`R>o9nEU0tQ7O9)w(j6Ub zew~3Myy#>Uv1mwpFcjJp^@l!xX)lhjzzJ2z4Pnf3Jx)v7q!orTMTUqQYeIHFyi5W< zFza~I$~FWH8Z@u9E7749$;ZNCLc%~TqV<*e?#ibX)@byaw9Z-C|A{1Emn?7W^nT*= zgqW&YJ$@RkCoJ4K?kb2GA#~O-@6#dmk2Y(^%Sr^3gEXAp?u;$vFWC-`xT}@B`(mwM zuuZAnEPm<~+I-ImkNny<+%t((aS1y%R+EMZ)_cb6wu|3sxLCXNK~Z}c1ejk+44Zwd-hFzpKl1&vH1Q3^Q2TUzp7~L&xHw0$c%7_QI8#5(DH#;5Ycp(tj7VV`*Oxr04M^UUl}pnVsH{6@O(9XNx6w%UR-dYt5hsa?M#7>z z$%FUouu|bnt-k(!KEvNax;+^;A!UjIN|UIoKT!cRHcl^L*_ZVTtL!+XtuN7r7)(ib z8LbRBHQR(^fgAmnda=TedOZ0CA5TLTFXra`B5J~bWP0$o*YN4yz-43ZK!#uq%^R%SyNf$F?aZ)sEMS~q^U^6YIT{L0 zRd1$32rMFRifoep$U9)JYdmK}`ph(^lLFqOTz%u`uzRksCkaAu$O#1$HiW z@SO!ammjMIjl{lkmnvP+%UHF2G@!iKDum>DP&#O*Acxx$mrwwa3q zaHP#ctW2exGwN2FfxcZ!nurV%z94A z!zV|B8Y3PmLmQ0Cq$4siNxIICCjNz?8>w8p5CX)3p^70l4fN;&c95W_76ngpo6xne xY`%=UCScFIt-J*M_tpH<{_&~uzt=+sd6U(gd2~CfQ~A>Xz+nhz+3Cv(e*8 z{eCW|97*t99lRO<0Nbby#LTk* z;1jfLUcVcdZWv2XijPe#t+N@Vypy!e3WuG(frhQ^67~nQ4sH1cm8L_SKyg11 z8%FX$+bFBn{G{=n?FAeei=L7{>D4W{QBi~yx&z+@3)gj zni{qd4FTbPSC&0hBWk{-h48OT#7KFhfx0g|y8*}%?z)Z9q@zJu(^al_Y z;{szhZGbaVb4S}ip%o)qgkH6~Hu@yMRkLmk#wD^535|GZ*1^3O`n`gdNq)`uWgc9) zDsh=1kLEc+@cRyyza_iZ`(e0WGTat`lg2uuUGkZ{@bNY9Y7S;1WdfImUIQONTq=5v z+Cgs4JKCGL>9O{WhlGbS18HV8L6B)081k zQ8%`x_P+vHW5!T_ew^LQRiqAkyB9- z!pyzV5w$b#PC2v3i|-QYjs!Nsy|lRSYo0~JduZ*9VA-X~g*Cx?(Lg~sU-ziC%6OC##IS&cT)?s&fm1p?8iIv zu}(tKF@nBA+hgy@7cKB+bh_7hg}MUWWREh3qE`wF%;M59ky4khQs+=aswY!ArNbr$ z;XJJr0ac&5*GBhjXf)dvDS}Y_dO@TD!2hTO!sR*%Oi(kw6wy=c^Nl3OCz<&8P)~8 z*8}uAtmEc|l}U)niki{Y8HDaAqu&egaTw7`u8_5sL_an6N@boGam-=Axn-I%!x@Pj zEP&=-x#lNK43b%0Bpgu>?&8svb93wJO@kq?6ppP1x@9eAx~%76M-hb%UA`2$@Rf7L z4}qa~vjm=dA>|&bo=hjlsA7lTgB!&#es0|Cs!eGvx#-BPG}0JrZ+@9F$h!!BFK0!S zWLIUA;Ehl@P*nwmhdLWiPzdC+%S1_ zhdpG|IJ8S`^WQZ(i}^_66UQjTQ=5R$-AWY^e}(yu5q^Aho#k*yIVRxqdY^gYwmAgV uH?R%O60toSI1RcRz5o9S|GN{w(#kbZV)LC~1RtKefTaCL;`#eNXa5b#C*xQE literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter.png b/tests/testdata/control_images/expected_pal_placement/sp_polygon_placement_perimeter/sp_polygon_placement_perimeter.png index 00ceee38824d9cc328c8d169274c27fb8502a541..ffe587fecfba4f767b4f660c53a0c83b2ef7fa81 100644 GIT binary patch delta 302 zcmbQowUTRsr{8H$7srr_Id5-n%nbz1+STzvR` z{?p9w#Z_zt&-Cu^jkl}&X=VF3h2>?v%(v73UVi`5<@@8~+uvVU+V0%B@8^GG-*o=V z+%nnVK zo&1nReR2Q`_hbPUZyeY~V-3iiF9oAZY~CzaXLz0$JH52ly8Q6fFAZy>^!0#3bEa;e h9LI18==y50miqmx6zmvv4FO#ofKh5i5l delta 328 zcmZ3i3VL2!@0kN53#IM2I;uDL74LWRji4B!`R)6OC;j zDBt@3f4fcof1mRVes`WOKYx09{{7|YGQA3WkJoK~Gw;9OdIrC{udjY-TKs7f^W=w& zw#X(B$CgrUIs1j--0i#l_b&@eeER(F`WKcYmd?WX`RkUe7o^;t-Tso3rSj%vLFQJY zLupkEIr(zS)EO9GzkPf$&L3w?()3Y>7};w-KTNCoO`YN^h-_#^`|wLxE*Fq eW@N4w`@pvRp8QlFp94=AfWXt$&t;ucLK6V!O^kK` diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_line_above_instead_of_online/sp_prefer_line_above_instead_of_online.png new file mode 100644 index 0000000000000000000000000000000000000000..c10e33edd10779690e44988d9af31ef047544e5b GIT binary patch literal 6902 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 HCF=hGy5cOp literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_longer_lines_over_shorter/sp_prefer_longer_lines_over_shorter.png new file mode 100644 index 0000000000000000000000000000000000000000..763edda1d789948893629a3074cd835293c0bfb9 GIT binary patch literal 2719 zcmeH}`&ZLw8po?dr6|&-USd%UrG*NMV-y@$2Qd(88cQ*VIO3=n!7V5{UeFQ73vrPI zsul@?j@PtRDxlzPyo~Fzr=rddo~2ONVf5g-qTrno@Pg>3;h&fvHs?Gi?>Eo$e4gjc z`<^#p=Nf1G`Y3%Q5{a)K#}Xxy0XD%P@4>J$3)MQ;&sc)uu^a zqkKjs?*Jlq-}ze_HzN6s@8Bu=6U*Uhdw!ZvBXjgG;GiP;smjsTnNN|s#e*imn0FHWJhjvIMhKfRX%cGZT9yTp~ zZ+L$H(&8K+iNc}6-$wV`diUVcXzFu)HaXDLY{4 z$0M~wmmFtNVbY`7ZeT(TCrL@3FUtAuL844b7iFY-uqYF=MLE(vM3n!+M7gm+%+0)$ zB+BFlF*mb0O_Wm`#N15R22qY`@Z@fv`c+@gqE2V@%Ns|Qe9GyVP|~i#88!9h~bKW*~=&jF!MQ2ANbhY>C%J_OMe-@5oz`125NXl0|Uw7zBIwpz{ z$4)?T8qi<$#Kn*x)Tmq6p>wkZraX$UgiXt^Co{GD^QN1&ItYX{7eS*M2)?KSAu8)lFi|rTX)(iDj^o;De`}t$ z?y1wXo{pfGlQ}Q0)V}@amqfz!^d=8xpThdW+l3FeZfKk1cO;S5W{L6dou*tmf;W@O zFi-6!r)ex5amGL@XLw`~6%l|Qn6*ZO zGEI(J*CeyC4P)$=mV2a1*Ce-%`9*F|^mH91vt~$LhU4bM4xt%#AKTakWa#E$6Xuu) z^H`D76hKFuMXX%7P?gtE5#!O&RI@gHSK}ty?KHOnM=qb1Zu=YKilnj?;p5ZHq&rwg<&>Dpk*# zZ}u>Z|I)r}1)>~A=Jc;-EXD08;C{JvqU%4=pKH5pjhl%ym2R_lV$2?0$K%r08-3TV zF3fSYW9%@eb~H*5Txtr%?SVDH#3WzjXT4>wLIagSZ5n)}Oam1_ZNYe{OmlZP)E0t| zlxyyqAvbCX4I*j+kdp=Qe4I;-q>@IXCpm51b!Wv)Itd}^vn+WCaIE8j8!UMha17u9 zKbE`?IOII`%2~0MZkCb!0;+j1nrYTH`XiYIa3s#P=R@b?EJ_V=&S-84!hIE*6pbzm zwAFWm_C;loE3}d=Da)B4X=;2*1NBLuId`L0@h_IY{qj+4f3=AI-g*f?n>dD z72~PqA?Q;>7ztXpGGsL1h>hhuC&EExe#E7HjETQ)&`)I!(kOeCaUnNw3A{LCLLf)clA?heNZZVd7R$- zAy8LESib)4f;buZGnsnonT&qoWq{pP?Jp8*r6?6vsT0Fj5th3xXZnd*-k^2b7vjXI zMP-EF(Q%%=vwF#;ajoy%KdkM(H6wokG6bQ91%TG+@423>oo`$v<>e4E%8zY~`oQ&U z`~51zOndjSY>tsqQO)I zcY?Y60F3yPC(9sY2udaMN#hY}BJF&RIRYr>L4Z|Z6QU7nHH{%WR|b(ZOmf<`ARVW| zM}!cY8M#IZPGAx@Q&*Zc`IYil8%cwQKqq z`=RTqPrv7v4LzN?11c_ti(8g)8#g}uZ*<>Q?62A^z4<0#!PnGY@!xc4oy4{JEJ3KZ?e(v5agAiwD?H*0qkpvH&)db-i~oN+~#B zVQ+FWDN@j_um@3C1Hc9|dm%C!<;O(L)|*Xva3dEWtns-Ri^-Tkf^%T`D%~t3g`s@zeqrZz87%NROh`Ti*L^M(Jb7>(q7fXgEpVN5 zy|7IlFmTDYfe=Gc9O7w9?>{LuD{XgSQ{UrbZ literal 0 HcmV?d00001 diff --git a/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines.png b/tests/testdata/control_images/expected_pal_placement/sp_prefer_more_horizontal_lines/sp_prefer_more_horizontal_lines.png new file mode 100644 index 0000000000000000000000000000000000000000..fc10a15b80ccb5321642b3eae64005895bc078e5 GIT binary patch literal 4171 zcmcgwi96JL+aE%f)XAD%qR?R|TZ<&gQX0%?|>{> zRAZ}W;WE0r*To^bd>CqlNmF!+jG39Sfrc0-&Z}@IeP2%)VxNJxS7;O`ADL*e!IwLiK8-0Aog7 zQ)b83S)Foe;!=KOgPnAXvgVN;S}o~mcZZ4=xqjY`lHIr?IL~Y?B9@jCz(@ks+Mt@P zw-)a<@G9d{*HT;$M8w$EnGtBZ@vBml(Juu-GaC&%lzZ!CiiTV3Qk?lggu(xL(F9|| zj4-97DRTv!!kG-$=U2E~8@MsI_y?|cc z%}~T0O&X(rQri#gPkNUhv??l`sZeD9;{pg6R@HV};4lB>DyFO{lYr>g;d{%qAip;t zml_;sQ5veHilT-@J)5O^ZZfq;dj&}{o#nr)Z57{q*hpMLO;hGIA`>hUWxvo9)2dK; z2@|0Jj-2XH(ab7ztug&6ZQVV?0yxALnlEI^nqH5Q{O1``HM&>4ix6$+W0()fdV=45 z&Gk{-om!a3j3|hyRLgxg$ys_F$Am~jDD$fQQ+$7k(Xlt8C7Ei~PQ-(=c(?I~BN~*k zMsZ+r{_4L$v7kf>kFA-QL2P;sqnFHFzGUT)cTuvXp&o;r7nrSie;qM%AOQ0HfZR#P z@#k}|?b{dc4Ypsx80-Pd-v+{HBO3C1Q-MVpVF?vnPdRZ1H|6UNT9CXdv?`)=$6BeJ zn+IO!A{-{|Kh9ou2%QSaeF(?|yn~B=RHGe##v^7q5rNySw&i3y34hC$nLTE@F(@0Z z3KvT(y;r5B+7TjJD^NBVZs;tQ5-_Jj$MW1qC=lbOV0z@StN#!VmuQw{ulQ=Y_f}p& zY(5cOM=E7p%htzG3W=Yz`n>95|NXDy<0_gmj}ex0!}X~ZHMGWw3SlXIR53@jpjIMQ zadDFxhI|bX94T3yoU-WOcsU^#0iXs>q`Di-_IS@0<|#uQ+8A%-v};k92ho0(_}wrGNOfHPx?e6BiEBCd z7!Co-yKLxrRc|NbtS&Y13(4c0Jt^6=yTDO+%qy${T4Mf`Ps;~Glgx-Z4A?;?NlgQn z|NCk;{iCy7lm1rPiZL`ilsXfN#c<^{pC3cZ$l!Fl&3u>AwqTBdN>z{&XG^rbgbz; zfW`~GG4eAuS4H(H>4`kJ6F|1TaV@R1X3*A;4XmzmyLKds>fK`s2*kM}pBuRR-dFvi zbya!*P^9@Ph-n!HI8S3|(Q0^^+3RAr@#@Axh{Ruc3TWa#@tDc526Y>!d8&$4iw zH7wa)F7*1fj_1D*f#3q3_^OZiIOmSWpV5~vbvJ=UzC5_-EqRyx3_)F!H5%$Bhpuue zYu2@ps?<1f@+rhVXE-V?HY5DI#MLmcDh5>*IN)4x*VhPB=Zbv(Tuh_%Kd`21ysM0M z(g8ONXTK)4<|{g;CjPt%4W`eJUMlJ8%UcV*4TgyT$NWZwO<&As=CVwxK$y6BljDCm_!Q6hT=7SZktQ}Fy}(8 zojB=;z#d?uN#|(j$2cMKA%d$Z{!`&y?wXYB0V1G`NW5x!rM=VmUM%GII4Jz-qj;ZS zZasX=tPP|i#_rJ)Hmo`}w?aWc2r!=akmvU%Z;>&2Q8#_|l3=^)zxps&bA`SX$Jr35 zq{-S2RVJMRIA;jm9UH$u>;xjVh>X2#K3fs+)dMlyxjrxG+53w`_f$qC5(L*Hg@tjV zr=5K`)ex<}LqI)Nle&n+WKxI`c*Y}F`6_+3h=#kK^i608$+R?MXpA76h!Y)MGr5N7 z9ATp+tW;B){5QbLVFW+jSn;jcschyV`DlLd&TXZ)ETj3}39DwoezU=?ZTP22d%$OygPhaesHvb%FGy+s{i;$bTAocE-Al9c;d~t-$rN5A`vju9hh)-G ztL5m{^j$Ql=bJynw?rV|hpnG792AWtk#(3Dj<60VJLa>K!~`039X?)VnmfuX62OhjoGV?ofp zRfhj=K%52u&xZtO30i*|qCshVcfgBix$!Z8{P%%>a3Ab)#H)omya zfbIvN0+0d9_c?q{LBkSX2aH~uYRa0Br@zOKPi?C)<}4gR%dm7{td%Ru4#Fy!Djy6N zu=dqy^JPGxA*%?8=Z}KneGm*Duvt=7i_dyt5ZeM1NLvg#s0*%>*p@Jy z%NJW8&PgbgV$;QrOk@KzUBBF&#R|A(h)(AtrTE#((+(ur?=0nHbW;kx>mb)2P$hGd;u$t;QDOT zDzF6Cpeldr&nF+ygY3=xDm@YdGntnWZ=-Mec2iMq*+xfjnVnm^X3jseB4Fji>xc#~Ry#uc{VYH3Y`KQry6?P8<@? z!Kf(xC~^dEwh<z^j4RT~nCUHWGlpwAySyf18zp7g#^FfaD z2f_|n^jBgY6p4b(FyL=K@#AIhr@x}lh(Y5MAOX#ueH9c+xdT7M3Kkt|7_P;f0v)Vg z)Ke03C_;d(<2Gg(N%j(|D6%iS;mmD=EPNq%^E9Yzgv18|djxx9^P zh}Yntr)1YE0e=#VGSBa2@A6s?!emgQGTIj1TWudLZnA@edlt@F1GtY1{fXcqD=0XW z`Z=uk#bRn_{Op(bNX{gWbf>w7UXO1$8I0H(m(sxYM1!TVZKspWKFGO@NV%y#I%w^cD5CB_o}^R}uz2MuZY-`mPN;9uF0 zuE}~XzxY2aRF~`00Tv$!3A$)xyxn)-%*91nlQp3=McgJdbbEPja&xv~Lg>Zq5o>XR zQQ$GnhO$FX*0+bB8MTK$YF_j9?BBY;*qVKI2@~AJ{v^}zFqs;x75RR(bQ{W`PI&)! zwA0shl1tzAx4@4L(c8@s%6DsvX(ex#*iooeE%E>N-%tOye<|MDEmPEEnBzbA1O6I- OGSIzzzVMt)$iD&0@)Fko literal 0 HcmV?d00001 diff --git a/tests/testdata/labeling/line_placement_1.qml b/tests/testdata/labeling/line_placement_1.qml new file mode 100644 index 00000000000..f050ae9e271 --- /dev/null +++ b/tests/testdata/labeling/line_placement_1.qml @@ -0,0 +1,272 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + 1 + diff --git a/tests/testdata/labeling/line_placement_2.qml b/tests/testdata/labeling/line_placement_2.qml new file mode 100644 index 00000000000..12920613940 --- /dev/null +++ b/tests/testdata/labeling/line_placement_2.qml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + 1 + diff --git a/tests/testdata/labeling/line_placement_3.qml b/tests/testdata/labeling/line_placement_3.qml new file mode 100644 index 00000000000..12920613940 --- /dev/null +++ b/tests/testdata/labeling/line_placement_3.qml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + 1 + diff --git a/tests/testdata/labeling/line_placement_4.qml b/tests/testdata/labeling/line_placement_4.qml new file mode 100644 index 00000000000..12920613940 --- /dev/null +++ b/tests/testdata/labeling/line_placement_4.qml @@ -0,0 +1,273 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + 1 + diff --git a/tests/testdata/labeling/line_placement_5.qml b/tests/testdata/labeling/line_placement_5.qml new file mode 100644 index 00000000000..2721989ca40 --- /dev/null +++ b/tests/testdata/labeling/line_placement_5.qml @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + generatedlayout + + + + + + 1 + diff --git a/tests/testdata/labeling/pal_features_v3.sqlite b/tests/testdata/labeling/pal_features_v3.sqlite index 5009bea2c29a0d8d849cba400cd925ceab81e111..2deaa810ad8182dd9b8513a7985d19fd68581ebc 100644 GIT binary patch delta 9798 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