You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
618 lines
16 KiB
618 lines
16 KiB
% Copyright 2006 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{tikzlibrarycalc.code.tex}
|
|
|
|
%
|
|
%
|
|
% Part I: The let path command
|
|
%
|
|
%
|
|
|
|
|
|
%
|
|
% Syntax: let \p{name1} = (coord), \p{name2} = (coord), ... in ...
|
|
%
|
|
% Currently (this may get more fancy in the future), the (coord)s are
|
|
% evaluated one by one. If the first evaluates to, say, (10pt,20pt),
|
|
% the macro \p{name1} is set to "10pt,20pt" (without parentheses), the
|
|
% macro \x{name1} is set to "10pt" and the macro \y{name1} is set to
|
|
% "20pt".
|
|
%
|
|
% If you use a number for {name}, you need no parentheses, so you
|
|
% could write:
|
|
%
|
|
% \draw let
|
|
% \p1 = (1,1),
|
|
% \p2 = ($ 2.5*(3,2) $)
|
|
% in
|
|
% (\x1,\x2) -- (\y1,\y2);
|
|
|
|
\def\tikz@let@command et{%
|
|
\let\p=\tikz@cc@dop%
|
|
\let\x=\tikz@cc@dox%
|
|
\let\y=\tikz@cc@doy%
|
|
\let\n=\tikz@cc@don%
|
|
\pgfutil@ifnextchar i{\tikz@cc@stop@let}{\tikz@cc@handle@line}%
|
|
}%
|
|
\def\tikz@cc@handle@line{%
|
|
\pgfutil@ifnextchar\p{%
|
|
\tikz@cc@handle@coor%
|
|
}{%
|
|
\pgfutil@ifnextchar\n{%
|
|
\tikz@cc@handle@num%
|
|
}{%
|
|
\pgfutil@ifnextchar i{%
|
|
\tikz@cc@stop@let
|
|
}{%
|
|
\tikzerror{``\string\p'' or ``\string\n'' expected}%
|
|
}%
|
|
}%
|
|
}%
|
|
}%
|
|
\def\tikz@cc@handle@num\n#1#2=#3{%
|
|
\pgfmathparse{#3}%
|
|
\expandafter\edef\csname tikz@cc@n@#1\endcsname{\pgfmathresult\ifpgfmathunitsdeclared pt\fi}
|
|
\pgfutil@ifnextchar,{\tikz@cc@handle@nextline}{\tikz@cc@stop@let}%
|
|
}%
|
|
\def\tikz@cc@handle@coor\p#1#2={%
|
|
\def\tikz@cc@coord@name{#1}%
|
|
\tikz@scan@one@point\tikz@cc@dolet%
|
|
}%
|
|
\def\tikz@cc@dolet#1{%
|
|
\pgf@process{#1}%
|
|
\expandafter\edef\csname tikz@cc@p@\tikz@cc@coord@name\endcsname{\the\pgf@x,\the\pgf@y}%
|
|
\expandafter\edef\csname tikz@cc@x@\tikz@cc@coord@name\endcsname{\the\pgf@x}%
|
|
\expandafter\edef\csname tikz@cc@y@\tikz@cc@coord@name\endcsname{\the\pgf@y}%
|
|
\pgfutil@ifnextchar,{\tikz@cc@handle@nextline}{\tikz@cc@stop@let}%
|
|
}%
|
|
\def\tikz@cc@handle@nextline,{%
|
|
\tikz@cc@handle@line%
|
|
}%
|
|
\def\tikz@cc@stop@let in{%
|
|
\tikz@scan@next@command%
|
|
}%
|
|
|
|
\def\tikz@cc@dop#1{\csname tikz@cc@p@#1\endcsname}%
|
|
\def\tikz@cc@dox#1{\csname tikz@cc@x@#1\endcsname}%
|
|
\def\tikz@cc@doy#1{\csname tikz@cc@y@#1\endcsname}%
|
|
\def\tikz@cc@don#1{\csname tikz@cc@n@#1\endcsname}%
|
|
|
|
|
|
|
|
%
|
|
%
|
|
% Part II: The ($...$) parser
|
|
%
|
|
%
|
|
|
|
\def\tikz@parse@calculator#1(${%$
|
|
\def\tikz@cc@command{#1}%
|
|
\begingroup%
|
|
%
|
|
% Parse main computation. It's a series of optional factors in front
|
|
% of coordinates.
|
|
%
|
|
\pgf@xa=0pt% We accumulate the result in here.
|
|
\pgf@ya=0pt%
|
|
\tikz@cc@parse+%
|
|
}%
|
|
|
|
\def\tikz@cc@parse{%
|
|
\pgfutil@ifnextchar${%$
|
|
% Ok, we found the end...
|
|
\tikz@cc@end%
|
|
}
|
|
{\pgfutil@ifnextchar+{%
|
|
% Ok, we found a coordinate...
|
|
\tikz@cc@add%
|
|
}{%
|
|
\pgfutil@ifnextchar-{%
|
|
\tikz@cc@sub%
|
|
}{%
|
|
\tikzerror{+ or - expected}%
|
|
\tikz@cc@end$%$
|
|
}%
|
|
}%
|
|
}%
|
|
}%
|
|
|
|
%
|
|
% The end is reached with $
|
|
%
|
|
\def\tikz@cc@end$#1){%$
|
|
\xdef\tikz@marshal{\noexpand\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
|
|
\endgroup%
|
|
\expandafter\tikz@cc@command\expandafter{\tikz@marshal}%
|
|
}%
|
|
|
|
|
|
%
|
|
% Another coordinate with +/-, possibly with a factor
|
|
%
|
|
\def\tikz@cc@add+{%
|
|
\def\tikz@cc@factor{1}%
|
|
\tikz@cc@factororcoordinate%
|
|
}%
|
|
\def\tikz@cc@sub-{%
|
|
\def\tikz@cc@factor{-1}%
|
|
\tikz@cc@factororcoordinate%
|
|
}%
|
|
|
|
%
|
|
% Check for a factor: If we see a (, its a coordinate...
|
|
%
|
|
\def\tikz@cc@factororcoordinate{%
|
|
\pgfutil@ifnextchar({%)
|
|
% Ok, found coordinate
|
|
\tikz@cc@coordinate%
|
|
}{%
|
|
\tikz@cc@parse@factor%
|
|
}%
|
|
}%
|
|
|
|
%
|
|
% ... otherwise it's a factor. It ends at ...*(
|
|
%
|
|
\def\tikz@cc@parse@factor#1*({%
|
|
\pgfmathparse{#1*\tikz@cc@factor}%
|
|
\let\tikz@cc@factor=\pgfmathresult%
|
|
\tikz@cc@coordinate(%)
|
|
}%
|
|
|
|
\def\tikz@cc@coordinate{%
|
|
\tikz@scan@absolute\tikz@cc@after@coordinate%
|
|
}%
|
|
\def\tikz@cc@after@coordinate#1{%
|
|
\pgf@process{#1}%
|
|
\pgf@xb=\pgf@x%
|
|
\pgf@yb=\pgf@y%
|
|
\tikz@cc@mid@checks%
|
|
}%
|
|
|
|
|
|
%
|
|
% A coordinate can be followed by !...!(...)
|
|
%
|
|
|
|
\def\tikz@cc@mid@checks{%
|
|
\ifnum\the\catcode`\!=\active\relax
|
|
\expandafter\tikz@cc@mid@checks@active
|
|
\else
|
|
\expandafter\tikz@cc@mid@checks@nonactive
|
|
\fi
|
|
}%
|
|
|
|
\def\tikz@cc@mid@checks@nonactive{%
|
|
\pgfutil@ifnextchar!{%
|
|
\tikz@cc@mid@nonactive%
|
|
}{%
|
|
\advance\pgf@xa by\tikz@cc@factor\pgf@xb
|
|
\advance\pgf@ya by\tikz@cc@factor\pgf@yb
|
|
\tikz@cc@parse%
|
|
}%
|
|
}%
|
|
|
|
\def\tikz@cc@mid@nonactive!{%
|
|
\pgfutil@ifnextchar({%
|
|
\tikz@scan@one@point\tikz@cc@project%
|
|
}{%
|
|
\tikz@cc@mid@num@nonactive%
|
|
}%
|
|
}%
|
|
|
|
\begingroup
|
|
\catcode`\!=\active
|
|
\gdef\tikz@cc@mid@checks@active{%
|
|
\pgfutil@ifnextchar!{%
|
|
\tikz@cc@mid@active%
|
|
}{%
|
|
\advance\pgf@xa by\tikz@cc@factor\pgf@xb
|
|
\advance\pgf@ya by\tikz@cc@factor\pgf@yb
|
|
\tikz@cc@parse%
|
|
}%
|
|
}%
|
|
|
|
\gdef\tikz@cc@mid@active!{%
|
|
\pgfutil@ifnextchar({%
|
|
\tikz@scan@one@point\tikz@cc@project%
|
|
}{%
|
|
\tikz@cc@mid@num@active%
|
|
}%
|
|
}%
|
|
\endgroup
|
|
|
|
%
|
|
% Partway case: (coord a)!number!(coord b)
|
|
%
|
|
% Returns the position that is at <number> fraction on the way from a
|
|
% to b. This, (a)!0!(b) is (a), (a)!.5!(b) is the middle and (a)!1!(b)
|
|
% is (b)
|
|
%
|
|
|
|
\def\tikz@cc@mid@num@nonactive#1!{\tikz@cc@mid@num{#1}}%
|
|
|
|
\begingroup
|
|
\catcode`\!=\active
|
|
\gdef\tikz@cc@mid@num@active#1!{\tikz@cc@mid@num{#1}}%
|
|
\endgroup
|
|
|
|
\def\tikz@cc@mid@num#1{%
|
|
\pgfmathparse{#1}%
|
|
\ifpgfmathunitsdeclared%
|
|
\let\tikz@cc@mid@unit=\pgfmathresult%
|
|
\expandafter\tikz@cc@scan@rot\expandafter\tikz@cc@after@unit%
|
|
\else%
|
|
\let\tikz@cc@mid@factor=\pgfmathresult%
|
|
\pgfmathparse{1-\tikz@cc@mid@factor}%
|
|
\let\tikz@cc@mid@factor@one=\pgfmathresult%
|
|
\expandafter\tikz@cc@scan@rot\expandafter\tikz@cc@after@num%
|
|
\fi%
|
|
}%
|
|
|
|
\def\tikz@cc@after@num#1{%
|
|
\pgf@process{#1}%
|
|
\pgf@xb=\tikz@cc@mid@factor@one\pgf@xb%
|
|
\pgf@yb=\tikz@cc@mid@factor@one\pgf@yb%
|
|
\advance\pgf@xb by\tikz@cc@mid@factor\pgf@x%
|
|
\advance\pgf@yb by\tikz@cc@mid@factor\pgf@y%
|
|
\tikz@cc@mid@checks%
|
|
}%
|
|
|
|
|
|
|
|
%
|
|
% Distance case: (coord a)!dimension!(coord b)
|
|
%
|
|
% Returns the position that is at <dimension> removed from (coord a)
|
|
% in the direction of (coord b).
|
|
%
|
|
|
|
\def\tikz@cc@after@unit#1{%
|
|
\pgf@process{#1}%
|
|
\advance\pgf@x by-\pgf@xb%
|
|
\advance\pgf@y by-\pgf@yb%
|
|
\pgf@process{\pgfpointnormalised{}}%
|
|
\advance\pgf@xb by\tikz@cc@mid@unit\pgf@x%
|
|
\advance\pgf@yb by\tikz@cc@mid@unit\pgf@y%
|
|
\tikz@cc@mid@checks%
|
|
}%
|
|
|
|
%
|
|
% Projection case: (a)!(p)!(b)
|
|
%
|
|
% Projection of p on line from a to b
|
|
%
|
|
\def\tikz@cc@project#1{%
|
|
\pgf@process{#1}%
|
|
% Save in c
|
|
\pgf@xc=\pgf@x%
|
|
\pgf@yc=\pgf@y%
|
|
\begingroup
|
|
\ifnum\the\catcode`\!=\active
|
|
\def\tikz@next{%
|
|
\endgroup
|
|
\expandafter\tikz@cc@scan@rot\expandafter\tikz@cc@after@project
|
|
\tikz@cc@scan@ex@active}%
|
|
\else
|
|
\def\tikz@next{%
|
|
\endgroup
|
|
\expandafter\tikz@cc@scan@rot\expandafter\tikz@cc@after@project
|
|
\tikz@cc@scan@ex@nonactive}%
|
|
\fi
|
|
\tikz@next%
|
|
}%
|
|
|
|
\def\tikz@cc@scan@ex@nonactive!{}%
|
|
|
|
\begingroup
|
|
\catcode`\!=\active
|
|
\gdef\tikz@cc@scan@ex@active!{}%
|
|
\endgroup
|
|
|
|
\def\tikz@cc@after@project#1{%
|
|
\pgf@process{#1}%
|
|
% Ok, now we need to project (xc,yc) on the line (xb,xc) to (x,y)
|
|
\advance\pgf@x by-\pgf@xb%
|
|
\advance\pgf@y by-\pgf@yb%
|
|
\advance\pgf@xc by-\pgf@xb%
|
|
\advance\pgf@yc by-\pgf@yb%
|
|
\pgf@process{\pgfpointnormalised{}}%
|
|
% Scalar product
|
|
\pgf@xc=\pgf@sys@tonumber{\pgf@xc}\pgf@x%
|
|
\advance\pgf@xc by\pgf@sys@tonumber{\pgf@yc}\pgf@y%
|
|
% and add
|
|
\advance\pgf@xb by\pgf@sys@tonumber{\pgf@xc}\pgf@x%
|
|
\advance\pgf@yb by\pgf@sys@tonumber{\pgf@xc}\pgf@y%
|
|
\tikz@cc@mid@checks%
|
|
}%
|
|
|
|
%
|
|
% Rotational scanner: radius:(x)
|
|
%
|
|
|
|
\def\tikz@cc@scan@rot#1{%
|
|
\pgfutil@ifnextchar({%)
|
|
\tikz@scan@one@point#1% normal
|
|
}%
|
|
{%
|
|
\def\tikz@cc@scan@rot@cmd{#1}%
|
|
\ifnum\the\catcode`\:=\active\relax
|
|
\expandafter\tikz@cc@scan@one@rot@active%
|
|
\else
|
|
\expandafter\tikz@cc@scan@one@rot@nonactive%
|
|
\fi
|
|
}%
|
|
}%
|
|
|
|
\def\tikz@cc@scan@one@rot@nonactive#1:{%
|
|
\def\tikz@cc@scan@rot@angle{#1}%
|
|
\tikz@scan@one@point\tikz@cc@handle@rot%
|
|
}%
|
|
|
|
\begingroup
|
|
\catcode`\:=\active
|
|
\gdef\tikz@cc@scan@one@rot@active#1:{%
|
|
\def\tikz@cc@scan@rot@angle{#1}%
|
|
\tikz@scan@one@point\tikz@cc@handle@rot%
|
|
}%
|
|
\endgroup
|
|
|
|
\def\tikz@cc@handle@rot#1{%
|
|
\pgf@process{#1}%
|
|
% Ok, now we need to rotate x/y around xb/xb by ...rot@angle
|
|
{%
|
|
\pgftransformreset%
|
|
% Save them...
|
|
\pgf@xc=\pgf@x%
|
|
\pgf@yc=\pgf@y%
|
|
\pgftransformshift{\pgfqpoint{\pgf@xb}{\pgf@yb}}%
|
|
\pgftransformrotate{\tikz@cc@scan@rot@angle}%
|
|
\pgftransformshift{\pgfqpoint{-\pgf@xb}{-\pgf@yb}}%
|
|
\pgfpointtransformed{\pgfqpoint{\pgf@xc}{\pgf@yc}}%
|
|
\expandafter
|
|
}%
|
|
\edef\tikz@marshal{\noexpand\tikz@cc@scan@rot@cmd{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}}%
|
|
\tikz@marshal%
|
|
}%
|
|
|
|
|
|
|
|
|
|
%
|
|
%
|
|
% Part III: Calculation coordinate systems
|
|
%
|
|
%
|
|
|
|
% Tangent cs: Keys are a node and a point. Depending on the type of
|
|
% node, the appropriate tangent computation should be done.
|
|
|
|
\tikzdeclarecoordinatesystem{tangent}
|
|
{%
|
|
\tikzset{cs/.cd,#1}%
|
|
\expandafter\ifx\csname tikz@tangent@\tikz@cs@type\endcsname\relax%
|
|
\tikzerror{I do not know how to compute the tangent to
|
|
a \tikz@cs@type}%
|
|
\pgfpointorigin%
|
|
\else%
|
|
\expandafter\tikz@scan@one@point\expandafter\tikz@lib@do@tangent\tikz@cs@point%
|
|
\fi%
|
|
}%
|
|
|
|
\tikzset{cs/node/.code=\tikz@cs@unpack{\tikz@cs@node}{\tikz@cs@type}{#1}}%
|
|
\tikzset{cs/point/.store in=\tikz@cs@point}%
|
|
|
|
\def\tikz@lib@do@tangent{\csname tikz@tangent@\tikz@cs@type\endcsname}%
|
|
|
|
\def\tikz@tangent@coordinate#1{%
|
|
\pgfpointanchor{\tikz@cs@node}{center}%
|
|
}%
|
|
|
|
\def\tikz@tangent@circle#1{%
|
|
{%
|
|
% Step 1: Compute the transformed position of the input:
|
|
\pgf@process{\pgfpointtransformed{#1}}%
|
|
\pgf@xa=\pgf@x%
|
|
\pgf@ya=\pgf@y%
|
|
%
|
|
% Step 2: Compute vector from center of circle to transformed #1
|
|
%
|
|
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikz@cs@node}{center}}}%
|
|
\advance\pgf@xa by-\pgf@x%
|
|
\advance\pgf@ya by-\pgf@y%
|
|
%
|
|
% Step 2: Reset transformations, they distract...
|
|
%
|
|
\pgftransformreset%
|
|
%
|
|
% Step 3: Transform to the center of the circle.
|
|
%
|
|
\pgftransformshift{\pgfpointanchor{\tikz@cs@node}{center}}%
|
|
%
|
|
% Step 4: Compute the radius
|
|
%
|
|
\pgf@process{\pgfpointanchor{\tikz@cs@node}{east}}%
|
|
\pgf@xc=\pgf@x%
|
|
%
|
|
% Now, (xa,ya) is a point. Compute the tangent from this point to
|
|
% a circle around the origin of radius xc.
|
|
%
|
|
% acos(radius/veclen(xa,ya)) is the angle of the tangent.
|
|
\pgfmathparse{veclen(\the\pgf@xa,\the\pgf@ya)}
|
|
\pgfmathparse{acos(\the\pgf@xc/\pgfmathresult)}
|
|
\ifnum\pgfkeysvalueof{/tikz/cs/solution}>1\relax%
|
|
\pgfmathparse{0-\pgfmathresult}%
|
|
\fi%
|
|
\let\tikz@lib@temp=\pgfmathresult%
|
|
%
|
|
% Now \pgfmathparse contains the desired angle. Use this to
|
|
% compute the correct position on the circle...
|
|
%
|
|
% But, first, rotate to the point.
|
|
\pgf@process{\pgfpointnormalised{\pgfqpoint{\pgf@xa}{\pgf@ya}}}%
|
|
\pgf@ya=-\pgf@y%
|
|
\pgftransformcm{\pgf@sys@tonumber{\pgf@x}}{\pgf@sys@tonumber{\pgf@y}}{\pgf@sys@tonumber{\pgf@ya}}{\pgf@sys@tonumber{\pgf@x}}{\pgfpointorigin}%
|
|
% Finally, rotate...
|
|
\pgf@process{\pgfpointtransformed{\pgfpointpolar{\tikz@lib@temp}{\the\pgf@xc}}}%
|
|
%
|
|
% Ok, undo transformations...
|
|
}%
|
|
% \pgf@x, \pgf@y have been smuggled outside by \pgf@process
|
|
{%
|
|
\pgftransforminvert%
|
|
\pgf@process{\pgfpointtransformed{}}%
|
|
}%
|
|
}%
|
|
|
|
|
|
% Implementation of intersections
|
|
|
|
|
|
\def\tikz@intersect@circle@and@circle{%
|
|
{%
|
|
\pgftransformreset% transformations only confuse us, here...
|
|
%
|
|
% Compute origin and radius of first circle
|
|
%
|
|
\pgf@process{\pgfpointanchor{\tikz@cs@node@a}{center}}%
|
|
\pgf@xa=\pgf@x%
|
|
\pgf@ya=\pgf@y%
|
|
\pgf@process{\pgfpointanchor{\tikz@cs@node@a}{east}}%
|
|
\advance\pgf@x by-\pgf@xa%
|
|
\pgf@xc=\pgf@x% ok, pgf@xc is first radius, (xa,ya) is center
|
|
%
|
|
% Compute origin and radius of second circle
|
|
%
|
|
\pgf@process{\pgfpointanchor{\tikz@cs@node@b}{center}}%
|
|
\pgf@xb=\pgf@x%
|
|
\pgf@yb=\pgf@y%
|
|
\pgf@process{\pgfpointanchor{\tikz@cs@node@b}{east}}%
|
|
\advance\pgf@x by-\pgf@xb%
|
|
\pgf@yc=\pgf@x% \pgf@yc is second radius, (xb,yb) is center
|
|
%
|
|
\pgf@process{%
|
|
\pgfpointintersectionofcircles{\pgfqpoint{\pgf@xa}{\pgf@ya}}{\pgfqpoint{\pgf@xb}{\pgf@yb}}{\pgf@xc}{\pgf@yc}{\pgfkeysvalueof{/tikz/cs/solution}}%
|
|
}%
|
|
}%
|
|
% \pgf@x, \pgf@y have been smuggled outside by \pgf@process,
|
|
% reinstall transformations...
|
|
{%
|
|
\pgftransforminvert%
|
|
\pgf@process{\pgfpointtransformed{}}%
|
|
}%
|
|
}%
|
|
|
|
|
|
\def\tikz@intersect@line@and@circle{%
|
|
{%
|
|
%
|
|
% Step 1: Get line
|
|
%
|
|
\expandafter\tikz@scan@one@point\expandafter\tikz@parse@line\tikz@cs@line@a%
|
|
\pgf@process{\pgfpointtransformed{}}%
|
|
\pgf@xb=\pgf@x%
|
|
\pgf@yb=\pgf@y%
|
|
\pgf@process{\pgfpointtransformed{\pgfqpoint{\pgf@xc}{\pgf@yc}}}%
|
|
\pgf@xa=\pgf@x%
|
|
\pgf@ya=\pgf@y%
|
|
%
|
|
% Step 2: Subtract center of circle
|
|
%
|
|
\pgf@process{\pgfpointtransformed{\pgfpointanchor{\tikz@cs@node@b}{center}}}%
|
|
\advance\pgf@xa by-\pgf@x%
|
|
\advance\pgf@ya by-\pgf@y%
|
|
\advance\pgf@xb by-\pgf@x%
|
|
\advance\pgf@yb by-\pgf@y%
|
|
%
|
|
% Step 3: Reset transformations, they distract...
|
|
%
|
|
\pgftransformreset%
|
|
%
|
|
% Step 4: Transform to the center of the circle.
|
|
%
|
|
\pgftransformshift{\pgfpointanchor{\tikz@cs@node@b}{center}}%
|
|
%
|
|
% Step 5: Compute the radius
|
|
%
|
|
\pgf@process{\pgfpointanchor{\tikz@cs@node@b}{east}}%
|
|
\edef\tikz@lib@saved@radius{\pgf@sys@tonumber{\pgf@x}}%
|
|
%
|
|
% Step 6: Compute projection of origin on line (xa,ya) -- (xb,yb),
|
|
% store in (xa,ya)
|
|
\pgf@x=\pgf@xb%
|
|
\pgf@y=\pgf@yb%
|
|
\advance\pgf@x by-\pgf@xa%
|
|
\advance\pgf@y by-\pgf@ya%
|
|
\pgf@process{\pgfpointnormalised{}}%
|
|
% Scalar product
|
|
\pgf@xc=\pgf@sys@tonumber{\pgf@xa}\pgf@x%
|
|
\advance\pgf@xc by\pgf@sys@tonumber{\pgf@ya}\pgf@y%
|
|
\pgf@xc=-\pgf@xc%
|
|
% and add
|
|
\advance\pgf@xa by\pgf@sys@tonumber{\pgf@xc}\pgf@x%
|
|
\advance\pgf@ya by\pgf@sys@tonumber{\pgf@xc}\pgf@y%
|
|
%
|
|
% Now, we have a triangle with a right angle at (xa,ya). The
|
|
% second point of the triangle is the origin. The third point is
|
|
% sought.
|
|
% Save x/y
|
|
\pgf@xc=\pgf@x%
|
|
\pgf@yc=\pgf@y%
|
|
% Square radius
|
|
\pgf@xb=\tikz@lib@saved@radius pt%
|
|
%
|
|
% First, make numbers smaller, in case they are too large
|
|
%
|
|
\c@pgf@counta=1\relax%
|
|
\loop%
|
|
\ifdim\pgf@xb>50pt%
|
|
\multiply\c@pgf@counta by2\relax%
|
|
\divide\pgf@xa by2\relax%
|
|
\divide\pgf@ya by2\relax%
|
|
\divide\pgf@xb by2\relax%
|
|
\repeat%
|
|
\pgf@xb=\pgf@sys@tonumber{\pgf@xb}\pgf@xb%
|
|
% Subtract xa^2 + ya^2
|
|
\pgf@yb=\pgf@sys@tonumber{\pgf@xa}\pgf@xa%
|
|
\advance\pgf@xb by-\pgf@yb%
|
|
\pgf@yb=\pgf@sys@tonumber{\pgf@ya}\pgf@ya%
|
|
\advance\pgf@xb by-\pgf@yb%
|
|
% Square root
|
|
\ifdim\pgf@xb<0pt%
|
|
\pgf@xb=0pt%
|
|
\fi%
|
|
\pgfmathsqrt@{\pgf@sys@tonumber{\pgf@xb}}%
|
|
\pgfmathmultiply@{\pgfmathresult}{\the\c@pgf@counta}%
|
|
\multiply\pgf@xa by\c@pgf@counta\relax%
|
|
\multiply\pgf@ya by\c@pgf@counta\relax%
|
|
\ifnum\pgfkeysvalueof{/tikz/cs/solution}>1\relax%
|
|
\pgfmathsubtract{0}{\pgfmathresult}%
|
|
\fi%
|
|
% Ok, now add things...
|
|
\advance\pgf@xa by \pgfmathresult\pgf@xc%
|
|
\advance\pgf@ya by \pgfmathresult\pgf@yc%
|
|
\pgf@process{\pgfpointtransformed{\pgfqpoint{\pgf@xa}{\pgf@ya}}}%
|
|
% Ok, undo transformations...
|
|
}%
|
|
% \pgf@x, \pgf@y have been smuggled outside by \pgf@process
|
|
{%
|
|
\pgftransforminvert%
|
|
\pgf@process{\pgfpointtransformed{}}%
|
|
}%
|
|
}%
|
|
|
|
\def\tikz@intersect@circle@and@line{%
|
|
% Swap
|
|
{%
|
|
\let\tikz@cs@node@b=\tikz@cs@node@a%
|
|
\let\tikz@cs@line@a=\tikz@cs@line@b%
|
|
\tikz@intersect@line@and@circle%
|
|
}%
|
|
}%
|
|
|