% 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

  
