| | |
| | <!-- Globals --> |
| | + <xsl:variable name="PI">3.14159265358979323846</xsl:variable> |
| | <xsl:variable name="fontAdjustment">1.2</xsl:variable> |
| | <xsl:variable name="fontWidthEstimate">1.8</xsl:variable> |
| | - <xsl:variable name="spacing">5</xsl:variable> |
| | <xsl:variable name="epsilon">0.0001</xsl:variable> |
| | <xsl:variable name="tickWidth">2.5</xsl:variable> |
| | |
| | <!-- Convert XML data into a Pie Chart. --> |
| | - <xsl:template match="dataset" mode="chart"> |
| | + <xsl:template match="dataset" mode="piechart"> |
| | <xsl:variable name="width">100</xsl:variable> |
| | - <xsl:variable name="height">100</xsl:variable> |
| | + <xsl:variable name="height" select="$width - $PI" /> |
| | |
| | - <svg:svg width="50%" height="50%" viewBox="0 0 {$width+30} {$height+30}" version="1.1"> |
| | + <svg:svg width="30%" height="30%" viewBox="0 0 {$width} {$height}" version="1.1"> |
| | <svg:g stroke-width="0" font-family="sans-serif" fill="#000" stroke="#000"> |
| | - <xsl:variable name="depth">0</xsl:variable> |
| | |
| | - <xsl:variable name="maxLegend"> |
| | - <xsl:call-template name="maxLegend" /> |
| | - </xsl:variable> |
| | - |
| | - <xsl:variable name="legendWidth"> |
| | - <xsl:choose> |
| | - <xsl:when test="$maxLegend > 0"> |
| | - <xsl:value-of select="$maxLegend * $fontAdjustment div $fontWidthEstimate + 2*$spacing" /> |
| | - </xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="$spacing" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - |
| | - <xsl:variable name="cols" select="count(data)" /> |
| | - <xsl:variable name="rows" select="count(data)" /> |
| | + <!-- Number of pie pieces --> |
| | + <xsl:variable name="pieces" select="count(data)" /> |
| | |
| | + <!-- Calculate the total value for all pieces --> |
| | + <xsl:variable name="total" select="sum(//value)" /> |
| | |
| | <xsl:for-each select="data"> |
| | - <xsl:variable name="col" select="position()" /> |
| | + <xsl:variable name="piece" select="position()" /> |
| | |
| | <!-- Calculate Fill Color --> |
| | <xsl:variable name="fill"> |
| | - <xsl:variable name="range9"> |
| | - <xsl:choose> |
| | - <xsl:when test="$cols > 9">9</xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="$cols" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <xsl:variable name="hue" select="((($col -1) mod $range9) div $range9 div 3.0 + (($col -1) mod 3) div 3.0) * 0.85" /> |
| | - <xsl:variable name="saturation" select="1.0 - (floor(($col -1) div $range9 * 0.5) mod 2) * 0.5 " /> |
| | - <xsl:variable name="brightness" select="0.8 - floor(($col -1+$range9) div $range9 * 0.5) div (($cols+$range9) div $range9 * 0.5) * 0.4" /> |
| | - <xsl:variable name="b" select="floor($brightness * 255 + 0.5)" /> |
| | - <xsl:variable name="h" select="floor(($hue - floor($hue)) * 6.0)" /> |
| | - <xsl:variable name="f" select="$h - floor($h)" /> |
| | - <xsl:variable name="p" select="floor($brightness * (1.0 - $saturation) * 255 + 0.5)" /> |
| | - <xsl:variable name="q" select="floor($brightness * (1.0 - $saturation * $f) * 255 + 0.5)" /> |
| | - <xsl:variable name="t" select="floor($brightness * (1.0 - ($saturation * (1.0 - $f))) * 255 + 0.5)" /> |
| | - <xsl:choose> |
| | - <xsl:when test="$h = 0">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$t" />,<xsl:value-of select="$p" />)</xsl:when> |
| | - <xsl:when test="$h = 1">rgb(<xsl:value-of select="$q" />,<xsl:value-of select="$b" />,<xsl:value-of select="$p" />)</xsl:when> |
| | - <xsl:when test="$h = 2">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$b" />,<xsl:value-of select="$t" />)</xsl:when> |
| | - <xsl:when test="$h = 3">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$q" />,<xsl:value-of select="$b" />)</xsl:when> |
| | - <xsl:when test="$h = 4">rgb(<xsl:value-of select="$t" />,<xsl:value-of select="$p" />,<xsl:value-of select="$b" />)</xsl:when> |
| | - <xsl:when test="$h = 5">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$p" />,<xsl:value-of select="$q" />)</xsl:when> |
| | - </xsl:choose> |
| | + <xsl:call-template name="fill"> |
| | + <xsl:with-param name="piece" select="$piece" /> |
| | + <xsl:with-param name="pieces" select="$pieces" /> |
| | + </xsl:call-template> |
| | </xsl:variable> |
| | |
| | <xsl:for-each select="value"> |
| | <xsl:variable name="row" select="position()" /> |
| | - <xsl:variable name="total" select="sum(//value[position() = $row])" /> |
| | |
| | <xsl:variable name="title"><xsl:value-of select="../name" /></xsl:variable> |
| | <xsl:variable name="percent" select="concat($title,' (',format-number(. div $total, '0.00%'),')')" /> |
| | |
| | - <xsl:variable name="x" select="($width - $legendWidth) * (position()-1) + $spacing" /> |
| | - <xsl:variable name="y" select="$fontAdjustment+2*$spacing" /> |
| | - <xsl:variable name="rx" select="$width* 0.5" /> |
| | - <xsl:variable name="ry" select="($height -$spacing - $depth) * 0.5" /> |
| | + <xsl:variable name="x" select="0" /> |
| | + <xsl:variable name="y" select="0" /> |
| | + <xsl:variable name="rx" select="$width * 0.5" /> |
| | + <xsl:variable name="ry" select="$height * 0.5" /> |
| | + |
| | + <xsl:variable name="deg"> |
| | + <xsl:choose> |
| | + <xsl:when test="$piece = 1">360</xsl:when> |
| | + <xsl:otherwise> |
| | + <xsl:value-of select="360 * (1-sum(//data[position() <=$piece -1]/value[position() = $row]) div $total)" /> |
| | + </xsl:otherwise> |
| | + </xsl:choose> |
| | + </xsl:variable> |
| | + <xsl:variable name="c"> |
| | + <xsl:call-template name="sine"> |
| | + <xsl:with-param name="deg" select="$deg" /> |
| | + </xsl:call-template> |
| | + </xsl:variable> |
| | + <xsl:variable name="s"> |
| | + <xsl:call-template name="sine"> |
| | + <xsl:with-param name="deg" select="-$deg - 90" /> |
| | + </xsl:call-template> |
| | + </xsl:variable> |
| | |
| | - <xsl:choose> |
| | - <xsl:when test="$cols = 1"> |
| | - <svg:path fill="{$fill}" title="{$percent}" stroke="none" d="{concat('M',$x,' ',$y+$ry,'a',$rx,' ',$ry,' 0 0 1 ',2*$rx,' 0l0 ',$depth,'a',$rx,' ',$ry,' 0 0 1 ',-2*$rx,' 0l0 ',$depth,'z')}" /> |
| | - </xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:variable name="deg"> |
| | - <xsl:choose> |
| | - <xsl:when test="$col = 1">360</xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="360 * (1-sum(//data[position() <=$col -1]/value[position() = $row]) div $total)" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <xsl:variable name="c"> |
| | - <xsl:call-template name="sine"> |
| | - <xsl:with-param name="deg" select="$deg" /> |
| | - </xsl:call-template> |
| | - </xsl:variable> |
| | - <xsl:variable name="s"> |
| | - <xsl:call-template name="sine"> |
| | - <xsl:with-param name="deg" select="-$deg - 90" /> |
| | - </xsl:call-template> |
| | - </xsl:variable> |
| | - <xsl:variable name="deg2" select="360 * (1-sum(//data[position() <=$col]/value[position() = $row]) div $total)" /> |
| | - <xsl:variable name="c2"> |
| | - <xsl:call-template name="sine"> |
| | - <xsl:with-param name="deg" select="$deg2" /> |
| | - </xsl:call-template> |
| | - </xsl:variable> |
| | - <xsl:variable name="s2"> |
| | - <xsl:call-template name="sine"> |
| | - <xsl:with-param name="deg" select="-$deg2 - 90" /> |
| | - </xsl:call-template> |
| | - </xsl:variable> |
| | - <xsl:variable name="opt"> |
| | - <xsl:choose> |
| | - <xsl:when test="$deg - $deg2 < 180">0</xsl:when> |
| | - <xsl:otherwise>1</xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <svg:path fill="{$fill}" title="{$percent}" stroke="none" d="{concat('M',$x+$rx,' ',$y+$ry,'L',$x+$rx+$rx*$c2,' ',$y+$ry+$ry*$s2,'A',$rx,' ',$ry,' 0 ',$opt,' 1 ',$x+$rx + $rx * $c,' ',$y+$ry +$ry*$s,'z')}" /> |
| | - <xsl:if test="$depth > 0 and $deg2 < 270 and $deg > 90"> |
| | - <xsl:variable name="c3"> |
| | - <xsl:choose> |
| | - <xsl:when test="$deg2 < 90">1</xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="$c2" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <xsl:variable name="c4"> |
| | - <xsl:choose> |
| | - <xsl:when test="$deg > 270">-1</xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="$c" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <xsl:variable name="s3"> |
| | - <xsl:choose> |
| | - <xsl:when test="$deg2 < 90">0</xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="$s2" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <xsl:variable name="s4"> |
| | - <xsl:choose> |
| | - <xsl:when test="$deg > 270">0</xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:value-of select="$s" /> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:variable> |
| | - <svg:path fill="{$fill}" stroke="none" d="{concat('M',$x+$rx+$rx*$c3,' ',$y+$ry+$ry*$s3,'A',$rx,' ',$ry,' 0 ',$opt,' 1 ',$x+$rx+$rx*$c4,' ',$y+$ry+$ry*$s4,'l0 ',$depth,'A',$rx,' ',$ry,' 0 ',$opt,' 0 ',$x+$rx+$rx*$c3,' ',$y+$ry+$ry*$s3 +$depth,'z')}" /> |
| | - </xsl:if> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - <xsl:if test="$depth > 0"> |
| | - <svg:path fill="black" opacity="0.25" stroke="none" d="{concat('M',$x,' ',$y+$ry,'a',$rx,' ',$ry,' 0 0 0 ',2*$rx,' 0l0 ',$depth,'a',$rx,' ',$ry,' 0 0 1 ',-2*$rx,' 0z')}" /> |
| | - </xsl:if> |
| | - </xsl:for-each> |
| | + <xsl:variable name="deg2" select="360 * (1-sum(//data[position() <=$piece]/value[position() = $row]) div $total)" /> |
| | + <xsl:variable name="c2"> |
| | + <xsl:call-template name="sine"> |
| | + <xsl:with-param name="deg" select="$deg2" /> |
| | + </xsl:call-template> |
| | + </xsl:variable> |
| | + <xsl:variable name="s2"> |
| | + <xsl:call-template name="sine"> |
| | + <xsl:with-param name="deg" select="-$deg2 - 90" /> |
| | + </xsl:call-template> |
| | + </xsl:variable> |
| | |
| | - <xsl:variable name="yleg" select="((position() -1) ) * $fontAdjustment + 2*$spacing" /> |
| | - <svg:g> |
| | - <xsl:for-each select="//dataset/@*"> |
| | - <xsl:attribute name="{name()}"> |
| | - <xsl:value-of select="'hello'" /> |
| | - </xsl:attribute> |
| | - </xsl:for-each> |
| | - <xsl:if test="$maxLegend > 0"> |
| | - <svg:text x="{$width -$legendWidth + 2*$spacing}" y="{$yleg}"> |
| | - <xsl:for-each select="//data[$col]/@*"> |
| | - <xsl:choose> |
| | - <xsl:when test="name() = 'name'"></xsl:when> |
| | - <xsl:when test="name() = 'color'"></xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:attribute name="{name()}"> |
| | - <xsl:value-of select="'hello'" /> |
| | - </xsl:attribute> |
| | - </xsl:otherwise> |
| | - </xsl:choose> |
| | - </xsl:for-each> |
| | - <xsl:value-of select="@name" /> |
| | - </svg:text> |
| | - <!-- |
| | - <svg:rect x="{$width -$legendWidth + $spacing}" y="{$yleg}" width="{$legendSize}" height="{$legendSize}" fill="{$fill}" stroke-width="0" /> |
| | - --> |
| | - </xsl:if> |
| | - </svg:g> |
| | + <xsl:variable name="opt"> |
| | + <xsl:choose> |
| | + <xsl:when test="$deg - $deg2 < 180">0</xsl:when> |
| | + <xsl:otherwise>1</xsl:otherwise> |
| | + </xsl:choose> |
| | + </xsl:variable> |
| | + |
| | + <!-- Fill the piece. --> |
| | + <svg:path fill="{$fill}" title="{$percent}" stroke="none" d="{concat('M',$x+$rx,' ',$y+$ry,'L',$x+$rx+$rx*$c2,' ',$y+$ry+$ry*$s2,'A',$rx,' ',$ry,' 0 ',$opt,' 1 ',$x+$rx + $rx * $c,' ',$y+$ry +$ry*$s,'z')}" /> |
| | + </xsl:for-each> |
| | </xsl:for-each> |
| | </svg:g> |
| | </svg:svg> |
| | </xsl:template> |
| | - |
| | |
| | <xsl:template name="root"> |
 |
| | |
| | <xsl:template name="sine"> |
| | - <!-- deg or rad --> |
| | <xsl:param name="deg" /> |
| | - <xsl:param name="rad"> |
| | - <xsl:value-of select="$deg div 180 * 3.14159265358979323846" /> |
| | + <xsl:param name="radians"> |
| | + <xsl:value-of select="$deg div 180 * $PI" /> |
| | </xsl:param> |
| | - <xsl:param name="ans"> |
| | - <xsl:value-of select="$rad" /> |
| | + <xsl:param name="answer"> |
| | + <xsl:value-of select="$radians" /> |
| | </xsl:param> |
| | <xsl:param name="loc">1</xsl:param> |
| | <xsl:param name="fract"> |
| | - <xsl:value-of select="$rad" /> |
| | + <xsl:value-of select="$radians" /> |
| | </xsl:param> |
| | - <xsl:variable name="fract2" select="-1 * $fract * $rad * $rad div ($loc *2 * ($loc * 2 + 1))" /> |
| | + <xsl:variable name="fract2" select="-1 * $fract * $radians * $radians div ($loc *2 * ($loc * 2 + 1))" /> |
| | <xsl:choose> |
| | <!-- Exit when at end of precision --> |
| | <xsl:when test="$fract2 < $epsilon and $fract2 > -$epsilon"> |
| | - <xsl:value-of select="$ans" /> |
| | + <xsl:value-of select="$answer" /> |
| | </xsl:when> |
| | <xsl:otherwise> |
| | <xsl:call-template name="sine"> |
| | - <xsl:with-param name="rad" select="$rad" /> |
| | - <xsl:with-param name="ans" select="$ans + $fract2" /> |
| | + <xsl:with-param name="radians" select="$radians" /> |
| | + <xsl:with-param name="answer" select="$answer + $fract2" /> |
| | <xsl:with-param name="loc" select="$loc+1" /> |
| | <xsl:with-param name="fract" select="$fract2" /> |
| | </xsl:call-template> |
| | </xsl:otherwise> |
| | </xsl:choose> |
| | </xsl:template> |
| | - |
| | - <xsl:template name="maxLegend"> |
| | - <xsl:param name="loc">1</xsl:param> |
| | - <xsl:param name="min">0</xsl:param> |
| | - <xsl:variable name="current" select="string-length(//data[$loc]/@name)" /> |
| | - <xsl:variable name="max"> |
| | + |
| | + <xsl:template name="fill"> |
| | + <xsl:param name="piece" /> |
| | + <xsl:param name="pieces" /> |
| | + |
| | + <xsl:variable name="range9"> |
| | <xsl:choose> |
| | - <xsl:when test="$min < $current"> |
| | - <xsl:value-of select="$current" /> |
| | - </xsl:when> |
| | + <xsl:when test="$pieces > 9">9</xsl:when> |
| | <xsl:otherwise> |
| | - <xsl:value-of select="$min" /> |
| | + <xsl:value-of select="$pieces" /> |
| | </xsl:otherwise> |
| | </xsl:choose> |
| | </xsl:variable> |
| | + <xsl:variable name="hue" select="((($piece -1) mod $range9) div $range9 div 3.0 + (($piece -1) mod 3) div 3.0) * 0.85" /> |
| | + <xsl:variable name="saturation" select="1.0 - (floor(($piece -1) div $range9 * 0.5) mod 2) * 0.5 " /> |
| | + <xsl:variable name="brightness" select="0.8 - floor(($piece -1+$range9) div $range9 * 0.5) div (($pieces+$range9) div $range9 * 0.5) * 0.4" /> |
| | + <xsl:variable name="b" select="floor($brightness * 255 + 0.5)" /> |
| | + <xsl:variable name="h" select="floor(($hue - floor($hue)) * 6.0)" /> |
| | + <xsl:variable name="f" select="$h - floor($h)" /> |
| | + <xsl:variable name="p" select="floor($brightness * (1.0 - $saturation) * 255 + 0.5)" /> |
| | + <xsl:variable name="q" select="floor($brightness * (1.0 - $saturation * $f) * 255 + 0.5)" /> |
| | + <xsl:variable name="t" select="floor($brightness * (1.0 - ($saturation * (1.0 - $f))) * 255 + 0.5)" /> |
| | <xsl:choose> |
| | - <xsl:when test="$loc = count(//data)"> |
| | - <xsl:value-of select="$max" /> |
| | - </xsl:when> |
| | - <xsl:otherwise> |
| | - <xsl:call-template name="maxLegend"> |
| | - <xsl:with-param name="min" select="$max" /> |
| | - <xsl:with-param name="loc" select="$loc + 1" /> |
| | - </xsl:call-template> |
| | - </xsl:otherwise> |
| | + <xsl:when test="$h = 0">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$t" />,<xsl:value-of select="$p" />)</xsl:when> |
| | + <xsl:when test="$h = 1">rgb(<xsl:value-of select="$q" />,<xsl:value-of select="$b" />,<xsl:value-of select="$p" />)</xsl:when> |
| | + <xsl:when test="$h = 2">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$b" />,<xsl:value-of select="$t" />)</xsl:when> |
| | + <xsl:when test="$h = 3">rgb(<xsl:value-of select="$p" />,<xsl:value-of select="$q" />,<xsl:value-of select="$b" />)</xsl:when> |
| | + <xsl:when test="$h = 4">rgb(<xsl:value-of select="$t" />,<xsl:value-of select="$p" />,<xsl:value-of select="$b" />)</xsl:when> |
| | + <xsl:when test="$h = 5">rgb(<xsl:value-of select="$b" />,<xsl:value-of select="$p" />,<xsl:value-of select="$q" />)</xsl:when> |
| | </xsl:choose> |
| | </xsl:template> |
| | - |
| | </xsl:stylesheet> |
| | |