summaryrefslogtreecommitdiff
path: root/graphics/pgf/base/tex/pgflibrarydatavisualization.polar.code.tex
blob: a7d493491fffb9ed6c6034e05e0d727aa215896b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
% Copyright 2018 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{pgflibrarydatavisualization.polar.code.tex}

\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 polar 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%
            \pgfdvmathenter{\pgf@dv@val}{\pgf@dv@angle}%
            \pgfdvmathexitbyscientificformat{\pgf@dv@angle}{\pgf@dv@val}%
            \pgfdvmathenter{\pgf@dv@val}{\pgf@dv@radius}%
            \pgfdvmathexitbyscientificformat{\pgf@dv@radius}{\pgf@dv@val}%
            \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
          \ifx\pgf@dv@current@rad\pgf@dv@prev@rad%
            \pgfooget{prev angle}\pgf@dv@prev@angle
            \pgfkeysgetvalue{/data point/\pgfoovalueof{angle}}\pgf@dv@current@angle
            \ifx\pgf@dv@current@angle\relax
            \else
              \ifx\pgf@dv@current@angle\pgf@dv@prev@angle%
              % do nothing
              \else%
                % Do arc:
                \pgfdvmathenter{\pgf@dv@val}{\pgf@dv@prev@angle}%
                \pgfdvmathexitbyscientificformat{\pgf@dv@prev@angle}{\pgf@dv@val}%
                \pgfdvmathenter{\pgf@dv@val}{\pgf@dv@prev@rad}%
                \pgfdvmathexitbyscientificformat{\pgf@dv@prev@rad}{\pgf@dv@val}%
                \pgfdvmathenter{\pgf@dv@val}{\pgf@dv@current@angle}%
                \pgfdvmathexitbyscientificformat{\pgf@dv@current@angle}{\pgf@dv@val}%
                \pgfdvmathenter{\pgf@dv@val}{\pgf@dv@current@rad}%
                \pgfdvmathexitbyscientificformat{\pgf@dv@current@rad}{\pgf@dv@val}%
                \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 from 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\ifx#1\pgfdvdirectiontotoken%
      % Record to angle and radius
      \xdef\pgf@dv@polar@to@angle{\pgfkeysvalueof{/data point/\pgfoovalueof{angle}}}
      \xdef\pgf@dv@polar@to@radius{\pgfkeysvalueof{/data point/\pgfoovalueof{radius}}}
    \else%
      \ifx\pgf@dv@polar@from@radius\pgf@dv@polar@to@radius%
        \pgfdvmathenter{\pgf@dv@a}{\pgf@dv@polar@from@angle}%
        \pgfdvmathenter{\pgf@dv@b}{\pgf@dv@polar@to@angle}%
        \pgfdvmathifless{\pgf@dv@a}{\pgf@dv@b}{\def\pgf@dv@temp@sign{+}}{\def\pgf@dv@temp@sign{-}}%
        \pgfkeysgetvalue{/data point/\pgfoovalueof{angle}}\pgf@temp%
        \ifx\pgf@temp\relax%
        \else%
          \pgfdvmathenter{\pgf@dv@val}{\pgf@temp}%
          \pgfdvmathexitbyscientificformat{\pgf@dv@polar@angle}{\pgf@dv@val}%
          \pgf@process{\pgfpointpolar{\pgf@dv@polar@angle\pgf@dv@temp@sign90}{1pt}}%
          \pgfdvhandledtrue%
        \fi%
      \fi%
    \fi\fi%
  }%
}%


\endinput