Skip to content

Instantly share code, notes, and snippets.

@Korto19
Last active March 18, 2022 18:21
Show Gist options
  • Save Korto19/74a686a08765c1e33ca1d72bf62f22a9 to your computer and use it in GitHub Desktop.
Save Korto19/74a686a08765c1e33ca1d72bf62f22a9 to your computer and use it in GitHub Desktop.
A QGIS field calculator expression to generate pie charts to be inserted into an HTML frame in the composer
#Korto19 2021
from qgis.core import *
from qgis.gui import *
import math
@qgsfunction(args='auto', group='Svg')
def svg_Pie(value, donut, pcol, flipper, legenda, feature, parent):
"""
Genera un grafico a torta inseribile in una cornice HTML nel compositore di stampe
<p style="color:Olive"><b>Sintassi</b></p>
<p style="color:blue"><b>svg_Pie</b><mark style="color:black">(</mark>
<mark style="color:red">array(values)</mark><mark style="color:black">,</mark>
<mark style="color:red">donut</mark><mark style="color:black">,</mark>
<mark style="color:red">array(colors)</mark><mark style="color:black">,</mark>
<mark style="color:red">array(descriptions)</mark><mark style="color:black">,</mark>
<mark style="color:red">legenda</mark><mark style="color:black">)</mark>
<p style="color:Olive"><b>Argomenti</b></p>
<p style="color:red"><b>array(values)</b><mark style="color:black"> - array percentuali </mark><br>
<mark style="color:red"><b>donut </b><mark style="color:black"> - raggio del vuoto al centro [0-1]</mark><br>
<mark style="color:red"><b>array(colors) </b><mark style="color:black"> - array colori</mark><br>
<mark style="color:red"><b>array(descriptions) </b><mark style="color:black"> - array descrizioni</mark><br>
<mark style="color:red"><b>legenda</b><mark style="color:black">
<ul>
<li>[-1] torta senza percentuali e legenda completa</li>
<li>[ 0] torta con percentuali senza legenda</li>
<li>[ 1] torta con percentuali e legenda</mark><li>
</ul>
<h2><mark style="color:Olive"><strong>Example usage:</mark></strong></h2>
<ul>
<li><mark style="color:black"><strong>svg_Pie</strong>(array(.5,.1,.3),.8,array('red','cyan','gray'),array('uno','due','tre'),0)<li>
</ul>
<mark style="color:black">
<strong> La somma delle percentuali deve essere pari a 1 o inferiore</strong><br>
<strong> Se la somma delle percentuali e' inferiore al 100% ci sara' un settore vuoto</strong><br>
<strong> Elenco dei colori desiderati, se vuoto o in numero insufficiente saranno utilizzati quelli di default</strong><br>
<strong> Elenco delle descrizioni, se vuoto o in numero insufficiente sara' utilizzato il carattere spazio</strong><br><br>
Colori di default in ordine di utilizzo<br>
Red, Aquamarine, Orange, Cyan, Yellow, Green, Grey, Beige, Gold, DarkKhaki, Royalblue, Fucsia<br>
e' comunque possibile utilizzare qualsiasi colore CSS inserendone il nome
"""
dcol = ['red', 'Aquamarine', 'orange', 'cyan', 'yellow', 'green', 'grey', 'beige', 'Gold', 'DarkKhaki', 'royalblue', 'fucsia']
#aggiunge colori mancanti
if len(pcol) < len(value):
for j in range (0, len(value)-len(pcol)+1):
if dcol[j] not in pcol:
pcol.append(dcol[j])
#aggiunge vuoti se non ci son testi
if len(flipper) < len(value):
for j in range (0, len(value)-len(flipper)+1):
flipper.append('')
vc = 0.85
vt = -0.81
xi = '1'
yi = '0'
if legenda:
riq = '''viewBox="-1.2 -1.2 4 4"'''
else:
riq = '''viewBox="-1.1 -1.1 2.2 2.2"'''
svg_text = '''<svg width="100%" heigth="100%"'''+riq+'''" >
<style>
#legend{
text-anchor: middle;
font-weight: bold;
font-size: .008em;
fill: purple;
}
text{
font-weight: light;
font-size: .006em;
font-family: Arial;
transform: rotate(90deg);
}
#perc{
fill: black;
font-weight: bold;
font-size: .006em;
font-family: Arial;
text-anchor: middle;
}
path{
stroke: white;
stroke-width: 0.01;
}
</style>
<g transform="translate(0,0) rotate(-90)">'''
if sum(value[0:])>1:
svg_text = 'Somma valori maggiore del 100%'
else:
for i in range (0, len(value)):
pr = sum(value[0:i+1])
vx = str(math.cos(2*3.14*pr))
vy = str(math.sin(2*3.14*pr))
if value[i] > 0.5:
larc = '1'
else:
larc = '0'
svg_text = svg_text + '''<path d= "M '''+ xi + ''' ''' + yi +''' A 1 1 0 ''' + larc + ''' 1 '''+ vx + ''' ''' + vy +''' L 0 0" fill="''' + pcol[i] + '''"/>'''
xi = vx
yi = vy
if legenda == -1:
svg_text = svg_text + '''<circle r="0.06" cx="'''+ str(vc) +'''" cy="1.4" fill="''' + pcol[i] + '''"/>
<text x="1.5" y="'''+ str(vt) +'''" >'''+ "{:.2%}".format(value[i]) + " " + flipper[i] + '''</text>'''
vc = vc - .2
vt = vt + .2
if legenda == 1:
svg_text = svg_text + '''<circle r="0.06" cx="'''+ str(vc) +'''" cy="1.4" fill="''' + pcol[i] + '''"/>
<text x="1.5" y="'''+ str(vt) +'''" >'''+ " " + flipper[i] + '''</text>'''
vc = vc - .2
vt = vt + .2
if pr > 0.5:
larc = '0'
else:
larc = '1'
if donut:
svg_text = svg_text + '''<circle r="''' + str(donut) + '''" cx="0" cy="0" fill="white" />'''
if legenda:
svg_text = svg_text + '''<text id="legend" x="1.9" y="-1">Legenda</text>'''
#scrive percentuali entro torta
if legenda >= 0:
pr = 0
for i in range (0, len(value)):
pr = sum(value[0:i+1]) - value[i]/2
vx = 0.8*math.cos(2*3.14*(pr-.25))
vy = 0.8*math.sin(2*3.14*(pr-.25))
svg_text = svg_text + '''<text id="perc" x="''' + str(vx) + '''" y="''' + str(vy) + '''">'''+"{:.2%}".format(value[i]) +'''</text>'''
svg_text = svg_text + '''</g></svg>'''
return svg_text
@Korto19
Copy link
Author

Korto19 commented May 5, 2021

Alcuni esempi di utilizzo
Esempi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment