% Copyright 2008 by Till Tantau % % This file may be distributed and/or modified % % 1. under the LaTeX Project Public License and/or % 2. under the GNU Public License. % % See the file doc/generic/pgf/licenses/LICENSE for more details. \ProvidesFileRCS[v\pgfversion] $Header: /cvsroot/pgf/pgf/generic/pgf/libraries/datavisualization/pgflibrarydatavisualization.polar.code.tex,v 1.2 2008/11/24 18:31:22 tantau Exp $ \usepgfmodule{datavisualization} % This file defines code for doing plots involving polar % coordinates. This includes not only standard polar plots, but also % pie charts. \pgfooclass{polar transformer} { % Class plor mapper % % A polar mapper is used to transform attributes given as (2d) polar % coordinates to canvas coordinates. Note that no special ranges % can be specified and that the angle must be given in degrees. You % can, however, use a standard mapper to change these things. \attribute angle; % The attribute from which the angle is read. \attribute radius; % The attribute from which the radius is read. \attribute unit vector 0 degrees; % The unit vector 0 degrees \attribute unit vector 90 degrees; % The unit vector 90 degrees % Constructor % % #1 = angle attribute. Example: rotation. % #2 = radius attribute. Example: height. % #3 = unit vector 0 degrees % #4 = unit vector 90 degrees % \method polar transformer(#1,#2,#3,#4) { \pgfooset{angle}{#1} \pgfooset{radius}{#2} \pgfooset{unit vector 0 degrees}{#3} \pgfooset{unit vector 90 degrees}{#4} } % Method \method default connects() { \pgfoothis.get handle(\pgf@dv@me) \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,transform,transform datapoint signal) \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,path,path signal) \pgfkeysvalueof{/pgf/data visualization/obj}.connect(\pgf@dv@me,direction,direction signal) } % Getters \method get angle attribute(#1) { \pgfooget{angle}{#1} } \method get radius attribute(#1) { \pgfooget{radius}{#1} } % Slot % % This slot should be connected to the transform datapoint % signal. When this signal is emitted, the coordinate system will be % shifted according to the current value of the attribute. \method transform() { \pgfkeysgetvalue{/data point/\pgfoovalueof{angle}/const}\pgf@dv@angle% \ifx\pgf@dv@angle\relax \pgfkeysgetvalue{/data point/\pgfoovalueof{angle}}\pgf@dv@angle% \fi \ifx\pgf@dv@angle\relax\else% \ifx\pgf@dv@angle\pgfutil@empty\else% \pgfkeysgetvalue{/data point/\pgfoovalueof{radius}/const}\pgf@dv@radius% \ifx\pgf@dv@radius\relax \pgfkeysgetvalue{/data point/\pgfoovalueof{radius}}\pgf@dv@radius% \fi \ifx\pgf@dv@radius\pgfutil@empty\else% \ifx\pgf@dv@radius\relax\else% \pgfmathsincos{\pgf@dv@angle}% \pgfmathmultiply{\pgfmathresultx}{\pgf@dv@radius}% \let\pgf@dv@polar@temp=\pgfmathresult \pgftransformshift{\pgfpointscale{\pgf@dv@polar@temp}{\pgfoovalueof{unit vector 0 degrees}}}% \pgfmathmultiply{\pgfmathresulty}{\pgf@dv@radius}% \let\pgf@dv@polar@temp=\pgfmathresult \pgftransformshift{\pgfpointscale{\pgf@dv@polar@temp}{\pgfoovalueof{unit vector 90 degrees}}}% \fi% \fi% \fi% \fi% } % Reaction to the path signal % % Here is what we do: When a pgfdvpathmoveto is done, the radius and % the angle are recorded. When a pgfdvpathlineto is done, the saved % radius and angle are compared with the new angle and radius. If, % and only if, the radius is the same, but the angle is different, % the lineto is caught and replaced by an arc from the previous % position to the new position. \attribute prev angle; \attribute prev radius; \method path(#1) {% \ifpgfdvhandled% \else% \ifx#1\pgfdvpathlinetotoken % Ok, let us have a look... \pgfooget{prev radius}\pgf@dv@prev@rad \pgfkeysgetvalue{/data point/\pgfoovalueof{radius}}\pgf@dv@current@rad \ifx\pgf@dv@current@rad\relax \else \ifdim\pgf@dv@current@rad pt=\pgf@dv@prev@rad pt% \pgfooget{prev angle}\pgf@dv@prev@angle \pgfkeysgetvalue{/data point/\pgfoovalueof{angle}}\pgf@dv@current@angle \ifx\pgf@dv@current@angle\relax \else \ifdim\pgf@dv@current@angle pt=\pgf@dv@prev@angle pt% % do nothing \else% % Do arc: \pgfpatharcaxes{\pgf@dv@prev@angle}{\pgf@dv@current@angle} {\pgfpointscale{\pgf@dv@current@rad}{\pgfoovalueof{unit vector 0 degrees}}} {\pgfpointscale{\pgf@dv@current@rad}{\pgfoovalueof{unit vector 90 degrees}}}% \pgfdvhandledtrue% \fi% \fi% \fi% \fi% \fi% \fi% % No matter what, record the current position \pgfooeset{prev angle}{\pgfkeysvalueof{/data point/\pgfoovalueof{angle}}} \pgfooeset{prev radius}{\pgfkeysvalueof{/data point/\pgfoovalueof{radius}}} } % Method % % React to direction signals. See pgfpointdvdirection for an % explanation % \method direction(#1) {% \ifx#1\pgfdvdirectionfromtoken % Record angle and radius \xdef\pgf@dv@polar@from@angle{\pgfkeysvalueof{/data point/\pgfoovalueof{angle}}} \xdef\pgf@dv@polar@from@radius{\pgfkeysvalueof{/data point/\pgfoovalueof{radius}}} \else% \pgfkeysgetvalue{/data point/\pgfoovalueof{radius}}\pgf@dv@polar@to@radius \ifx\pgf@dv@polar@to@radius\relax \else \ifdim\pgf@dv@polar@to@radius pt=\pgf@dv@polar@from@radius pt% \pgfkeysgetvalue{/data point/\pgfoovalueof{angle}}\pgf@dv@polar@to@angle \ifx\pgf@dv@polar@to@angle\relax \else \ifdim\pgf@dv@polar@to@angle pt=\pgf@dv@polar@from@angle pt% % do nothing \else% % Output vector that it orthogonal to start angle: \ifdim\pgf@dv@polar@to@angle pt>\pgf@dv@polar@from@angle pt% \pgf@process{\pgfpointpolar{\pgf@dv@polar@from@angle+90}{1pt}} \else \pgf@process{\pgfpointpolar{\pgf@dv@polar@from@angle-90}{1pt}} \fi \pgfdvhandledtrue \fi% \fi% \fi% \fi% \fi% } } \endinput