summaryrefslogtreecommitdiff
path: root/graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex')
-rw-r--r--graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex685
1 files changed, 651 insertions, 34 deletions
diff --git a/graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex b/graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex
index 8979b313be..690515707d 100644
--- a/graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex
+++ b/graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex
@@ -20,8 +20,8 @@
\csname PSTEuclideLoaded\endcsname
\let\PSTEuclideLoaded\endinput
%
-\def\fileversion{1.66}
-\def\filedate{2019/10/20}
+\def\fileversion{1.67}
+\def\filedate{2019/10/28}
%%
\message{`PST-Euclide v\fileversion, \filedate\space (dr,hv)}%
%% prologue for postcript
@@ -587,7 +587,6 @@
\def\pst@circle@node{#3}
\@ifnextchar[\pstCircleOA@i{\pstCircleOA@i[0][360]}}%
\def\pstCircleOA@i[#1][#2]{%
- \rput(\pst@circle@center){%
\begin@OpenObj
\def\pst@linetype{4}%
\addto@pscode{%
@@ -605,7 +604,6 @@
#1 #2 arc}%
\showpointsfalse
\end@OpenObj
- }%
\endgroup%
}%
%% #2 #3 -> 2 nodes defining a diameter of the circle
@@ -618,19 +616,17 @@
\@ifnextchar[\pstCircleAB@i{\pstCircleAB@i[0][360]}}%
\def\pstCircleAB@i[#1][#2]{%
\Pst@MiddleAB[PointSymbol=none, PointName=none]{\pst@circle@diameter@B}{\pst@circle@diameter@A}{PST@CIRCLE@MAB}
- \rput(\pst@circle@diameter@A){%
- \begin@OpenObj
- \def\pst@linetype{4}%
- \addto@pscode{%
- tx@NodeDict begin
- tx@NodeDict /N@PST@CIRCLE@MAB load GetCenter
- end
- 2 copy
- tx@EcldDict begin /N@\pst@circle@diameter@B\space GetNode ABDist end
- \psk@dimen\space CLW mul sub #1 #2 arc}%
- \showpointsfalse
- \end@OpenObj
- }%
+ \begin@OpenObj
+ \def\pst@linetype{4}%
+ \addto@pscode{%
+ tx@NodeDict begin
+ tx@NodeDict /N@PST@CIRCLE@MAB load GetCenter
+ end
+ 2 copy
+ tx@EcldDict begin /N@\pst@circle@diameter@B\space GetNode ABDist end
+ \psk@dimen\space CLW mul sub #1 #2 arc}%
+ \showpointsfalse
+ \end@OpenObj
\endgroup%
}%
%% #2 #3 #4 -> 3 nodes defining the center and two points on the circle
@@ -1673,25 +1669,100 @@
}%
%
%% Distance between two points
-\def\pstDistAB#1#2{%
+\def\pstDist#1#2{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist end
+}
+\def\pstDistAB#1#2{% Obsoleted
tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist end
\ifx\psk@DistCoef\@none\else
\psk@DistCoef\space mul
\fi
}
+%
+% \pstDistMul{A}{B}{\lambda} -> \lambda * |AB|
+%% Distance |AB| multiply with coefficient \lambda
+\def\pstDistMul#1#2#3{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist #3 mul end
+}
+%
+% \pstDistAdd{A}{B}{C}{D} -> |AB| + |CD|
+%% Distance sum of two segments AB and CD
+\def\pstDistAdd#1#2#3#4{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ /N@#3 GetNode /N@#4 GetNode ABDist add end
+}
+%
+% \pstDistAddVal{A}{B}{coef1}{val} -> |AB| * coef1 + val
+\def\pstDistAddVal#1#2#3#4{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ #3 mul #4 add end
+}
+%
+% \pstDistAddCoef{A}{B}{coef1}{C}{D}{coef2} -> |AB| * coef1 + |CD| * coef2
+\def\pstDistAddCoef#1#2#3#4#5#6{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ #3 mul /N@#4 GetNode /N@#5 GetNode ABDist #6 mul add end
+}
+%
+%% Distance difference between two segments AB and CD
+\def\pstDistSub#1#2#3#4{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ /N@#3 GetNode /N@#4 GetNode ABDist sub abs end
+}
+%
+% \pstDistSubVal{A}{B}{coef1}{val} -> |AB| * coef1 - val
+\def\pstDistSubVal#1#2#3#4{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ #3 mul #4 sub abs end
+}
+%
+% \pstDistSubCoef{A}{B}{coef1}{C}{D}{coef2} -> |AB| * coef1 - |CD| * coef2
+\def\pstDistSubCoef#1#2#3#4#5#6{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ #3 mul /N@#4 GetNode /N@#5 GetNode ABDist #6 mul sub abs end
+}
+%
+%% Distance ratio of two segments AB and CD
+\def\pstDistDiv#1#2#3#4{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist
+ /N@#3 GetNode /N@#4 GetNode ABDist div end
+}
+%
%% Distance specified with a number
-\def\pstDistVal#1{%
- #1 \pst@number\psxunit mul
+\def\pstDistConst#1{#1 \pst@number\psxunit mul\space}
+\def\pstDistVal#1{% Obsoleted
+ #1 \pst@number\psxunit mul
\ifx\psk@DistCoef\@none\else
\psk@DistCoef\space mul
\fi
}
-\def\pstDistCalc#1{%
+\def\pstDistExpr#1{\pscalculate{#1} \pst@number\psxunit mul\space}
+\def\pstDistCalc#1{% Obsoleted
\pscalculate{#1} \pst@number\psxunit mul
\ifx\psk@DistCoef\@none\else
\psk@DistCoef\space mul
\fi
}
+%
+\def\pstDistCoef#1{#1 \ifx\psk@DistCoef\@none\else\psk@DistCoef\space mul\space\fi}
+\def\pstUserDist#1{#1 \pst@number\psxunit div\space}
+\def\pstScreenDist#1{#1 \pst@number\psxunit mul\space}
+%
+% \pstDistABC{A}{B}{C} -> return the distance from C to AB.
+\def\pstDistABC#1#2#3{%
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode /N@#3 GetNode
+ % x1 y1 x2 y2 x3 y3
+ 5 index 5 index 5 index 5 index ABDist % |AB|
+ 6 index 6 index 4 index 4 index ABDist % |AC|
+ 5 index 5 index 5 index 5 index ABDist % |BC|
+ 2 index 2 index add 1 index add 2 div % p
+ 0 index 4 index sub % p-|AB|
+ 1 index 4 index sub % p-|AC|
+ 2 index 4 index sub % p-|BC|
+ mul mul mul sqrt 3 index div 2 mul
+ 10 1 roll pop pop pop pop pop pop pop pop pop end
+}
+%
%% angle defined by three points
\def\pstAngleAOB#1#2#3{%
% \pstGeonode[PointName=none,PointSymbol=none](#1){temp@1}(#2){temp@2}(#3){temp@3}%
@@ -1837,6 +1908,128 @@
\endgroup%
}%
%
+%% \pstProportionNode[Options]{A}{B}{lambda}{C}{C'}
+%% Create node C and C' which satisified the definite proportion function |AC|:|BC|=lamba,
+%% where lambda is positive, C is inside segment AB, and C' is outside segment AB.
+%% According to the definite proportion equation, we have
+%% $$x_{C}=\dfrac{x_{A}+\lambda{}x_{B}}{1+\lambda},y_{C}=\dfrac{y_{A}+\lambda{}y_{B}}{1+\lambda}$$
+%% and
+%% $$x_{C'}=\dfrac{x_{A}-\lambda{}x_{B}}{1-\lambda},y_{C'}=\dfrac{y_{A}+-lambda{}y_{B}}{1-\lambda}$$
+%% Parameters:
+%% #1 -> options
+%% #2 -> the given segment start node A
+%% #3 -> the given segment end node B
+%% #4 -> the definite proportion $\lambda$
+%% #5 -> the target node C inside segment AB
+%% #6 -> the target node C' outside segment AB
+\def\pstProportionNode{\@ifnextchar[\Pst@ProportionNode{\Pst@ProportionNode[]}}
+\def\Pst@ProportionNode[#1]{%
+ \begingroup
+ \@InitListMng %
+ \psset{#1}%
+ \Pst@ProportionNode@i}
+\def\Pst@ProportionNode@i#1#2#3#4#5{%
+ \pst@getcoor{#1}\pst@tempA%
+ \pst@getcoor{#2}\pst@tempB%
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ #3 abs % \lambda
+ 4 index 1 index 4 index mul add 1 index 1 add div % (x1+\lambda*x2)/(1+\lambda)
+ 4 index 2 index 4 index mul add 2 index 1 add div % (y1+\lambda*y2)/(1+\lambda)
+ 7 2 roll pop pop pop pop pop
+ ){#4}%
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ #3 abs % \lambda
+ dup 1 sub abs 1E-5 lt {
+ pop pop pop pop pop 0 0
+ } {
+ 4 index 1 index 4 index mul sub 1 index 1 exch sub div % (x1-\lambda*x2)/(1-\lambda)
+ 4 index 2 index 4 index mul sub 2 index 1 exch sub div % (y1-\lambda*y2)/(1-\lambda)
+ 7 2 roll pop pop pop pop pop
+ } ifelse
+ ){#5}%
+ \Pst@ManageParamList{#4}%
+ \Pst@ManageParamList{#5}%
+ \endgroup%
+}%
+%
+%% \pstFourthHarmonicNode[Options]{A}{B}{C}{D}
+%% Create node D such that the four collinear points A,B,C,D form harmonic conjugate points,
+%% that is, $(AB,CD)=\dfrac{AC}{BC}:\dfrac{AD}{BD}=-1$.
+%% Parameters:
+%% #1 -> options
+%% #2 -> the given collinear base node A
+%% #3 -> the given collinear base node B
+%% #4 -> the given collinear proportion node C
+%% #5 -> the output proportion node D
+\def\pstFourthHarmonicNode{\@ifnextchar[\Pst@FourthHarmonicNode{\Pst@FourthHarmonicNode[]}}
+\def\Pst@FourthHarmonicNode[#1]{%
+ \begingroup
+ \@InitListMng %
+ \psset{#1}%
+ \Pst@FourthHarmonicNode@i}
+\def\Pst@FourthHarmonicNode@i#1#2#3#4{%
+ \pst@getcoor{#1}\pst@tempA%
+ \pst@getcoor{#2}\pst@tempB%
+ \pst@getcoor{#3}\pst@tempC%
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ \pst@tempC \tx@UserCoor % x3,y3
+ 5 index 4 index sub abs 1E-5 lt { % if x1=x2
+ 5 index 2 index sub abs 1E-5 lt { % if x1=x3
+ 4 index 1 index mul 3 index 2 index mul add 5 index 4 index mul 2 mul sub % y1y3+y2y3-2y1y2
+ 1 index 2 mul 6 index sub 4 index sub % 2y3-y1-y2
+ dup abs 1E-5 lt {
+ pop pop pop pop pop pop pop pop
+ 0 0
+ } {
+ div % y=\dfrac{y1y3+y2y3-2y1y2}{2y3-y1-y2}
+ 2 index exch % x=x3
+ 8 2 roll pop pop pop pop pop pop
+ } ifelse
+ } {
+ % C is not collinear with AB.
+ pop pop pop pop pop pop
+ 0 0
+ } ifelse
+ } {
+ 5 index 2 index sub abs 1E-5 lt { % if x1=x3
+ pop pop pop pop pop pop 0 0
+ } {
+ 2 index 5 index sub 4 index 7 index sub div % k(AB)=\dfrac{y2-y1}{x2-x1}
+ 4 index 6 index mul 7 index 5 index mul sub 5 index 8 index sub div % d(AB)=\dfrac{x2y1-x1y2}{x2-x1}
+ 2 index 7 index sub 4 index 9 index sub div % k(AC)=\dfrac{y3-y1}{x3-x1}
+ 4 index 8 index mul 9 index 5 index mul sub 5 index 10 index sub div % d(AC)=\dfrac{x3y1-x1y3}{x3-x1}
+ 3 index 2 index sub abs 1E-5 lt 3 index 2 index sub abs 1E-5 lt and { % k(AB)=k(AC) and d(AB)=d(AC)
+ % x=\dfrac{x1x3+x2x3-2x1x2}{2x3-x1-x2}; y=k(AC)x+d(AC)
+ 9 index 6 index mul 8 index 7 index mul add 10 index 9 index mul 2 mul sub
+ 6 index 2 mul 11 index sub 9 index sub
+ dup abs 1E-5 lt {
+ pop pop pop pop pop pop
+ pop pop pop pop pop pop
+ 0 0
+ } {
+ div
+ 2 index 1 index mul 2 index add
+ 12 2 roll pop pop pop pop pop
+ pop pop pop pop pop
+ } ifelse
+ } {
+ % C is not collinear with AB.
+ pop pop pop pop pop pop pop pop
+ 0 0
+ } ifelse
+ } ifelse
+ } ifelse
+ ){#4}%
+ \Pst@ManageParamList{#4}%
+ \endgroup%
+}%
+%
%% \pstLine[Options]{node}{node}
%% \pstLine[Options]{node}(coor)
%% \pstLine[Options](coor){node}
@@ -1960,6 +2153,184 @@
\endgroup%
}%
%
+%% \pstLocateAB[Options]{A}{B}{distance}{C}
+%% Locate node C on segment AB such that |AC|=distance, then create node C.
+%% Note that locate C on BA will get the node C in the reverse order.
+%% Parameters:
+%% #1 -> options
+%% #2 -> the given segment start node A
+%% #3 -> the given segment end node B
+%% #4 -> the specified length in screen coordinate
+%% #5 -> the target node C
+\def\pstLocateAB{\@ifnextchar[\Pst@LocateAB{\Pst@LocateAB[]}}
+\def\Pst@LocateAB[#1]{%
+ \begingroup
+ \psset{#1}%
+ \Pst@LocateAB@i}
+\def\Pst@LocateAB@i#1#2#3#4{%
+ \pst@getcoor{#1}\pst@tempA%
+ \pst@getcoor{#2}\pst@tempB%
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ #3 abs \pst@number\psxunit div % User distance
+ 4 index 3 index sub abs 1E-5 lt { % if x1=x2
+ 3 index 2 index lt { % if y1 < y2
+ 3 index 1 index add % y1 + l
+ } {
+ 3 index 1 index sub % y1 - l
+ } ifelse
+ 3 index exch
+ 7 2 roll pop pop pop pop pop
+ } {
+ 1 index 4 index sub 3 index 6 index sub div % k = (y2-y1)/(x2-x1)
+ 1 index 1 index dup mul 1 add sqrt div % l/sqrt(k^2+1)
+ 4 index 7 index lt { % if x2<x1
+ 6 index exch sub % x1 - l/sqrt(k^2+1)
+ } {
+ 6 index add % x1 + l/sqrt(k^2+1)
+ } ifelse
+ 3 index 1 index 6 index sub 3 index mul add % y = y2+(x-x2)k
+ 8 2 roll pop pop pop pop pop pop
+ } ifelse
+ ){#4}%
+ \Pst@geonodelabel{#4}%
+ \endgroup%
+}%
+%
+%% \pstLabelAB[Options]{A}{B}{label}
+%% Print the label for segment AB.
+%% Options:
+%% - linestyle: the line style to control the ruler bar
+%% - arrows: the line arrows to control the ruler bar
+%% - offset: the seperation between label and segment
+%% - nrot: the rotation of the label
+%% - npos: the proportion of the label
+\def\pstLabelAB{\@ifnextchar[\Pst@LabelAB{\Pst@LabelAB[]}}
+\def\Pst@LabelAB[#1]#2#3#4{%
+ \begingroup
+ \psset{linestyle=none} % default not show the rule bar.
+ \psset{offset=10pt} % default offset is 10pt
+ \psset{nrot=:U} % default rotation is :U
+ \psset{npos=0.5} % default label proportion from A to B is 0.5
+ \psset{#1}\ncline{#2}{#3}\ncput*{#4}
+ \endgroup%
+}%
+%% \pstExtendAB[Options]{A}{B}{distance}{C}
+%% Extend AB to C such that |BC|=distance, then create node C.
+%% Note that extend BA to C will get the node C in the reverse order.
+%% Parameters:
+%% #1 -> options
+%% #2 -> the given segment start node A
+%% #3 -> the given segment end node B
+%% #4 -> the specified length in screen coordinate
+%% #5 -> the target node C
+\def\pstExtendAB{\@ifnextchar[\Pst@ExtendAB{\Pst@ExtendAB[]}}
+\def\Pst@ExtendAB[#1]{%
+ \begingroup
+ \psset{#1}%
+ \Pst@ExtendAB@i}
+\def\Pst@ExtendAB@i#1#2#3#4{%
+ \pst@getcoor{#1}\pst@tempA%
+ \pst@getcoor{#2}\pst@tempB%
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ #3 abs \pst@number\psxunit div % User distance
+ 4 index 3 index sub abs 1E-5 lt { % if x1=x2
+ 3 index 2 index lt { % if y1 < y2
+ 1 index 1 index add % y2 + l
+ } {
+ 1 index 1 index sub % y2 - l
+ } ifelse
+ 3 index exch
+ 7 2 roll pop pop pop pop pop
+ } {
+ 1 index 4 index sub 3 index 6 index sub div % k = (y2-y1)/(x2-x1)
+ 1 index 1 index dup mul 1 add sqrt div % l/sqrt(k^2+1)
+ 4 index 7 index lt { % if x2<x1
+ 4 index exch sub % x2 - l/sqrt(k^2+1)
+ } {
+ 4 index add % x2 + l/sqrt(k^2+1)
+ } ifelse
+ 3 index 1 index 6 index sub 3 index mul add % y = y2+(x-x2)k
+ 8 2 roll pop pop pop pop pop pop
+ } ifelse
+ ){#4}%
+ \Pst@geonodelabel{#4}%
+ \endgroup%
+}%
+%
+%% \pstInversion[Options]{O}{A}{C}{C'}
+%% Find the inversion point $C'$ of $C$ such that $|OC|*|OC'|=|OA|^2$, then create node $C'$.
+%% We call $O$ as the inversion center, and |OA| as the inversion radius.
+%% Parameters:
+%% #1 -> options
+%% #2 -> the inversion center O
+%% #3 -> the inversion radius OA, or the specified Radius/Diameter if empty
+%% #4 -> the initial node C
+%% #5 -> the target node C'
+\def\pstInversion{\@ifnextchar[\Pst@Inversion{\Pst@Inversion[]}}
+\def\Pst@Inversion[#1]{%
+ \begingroup
+ \psset{#1}%
+ \Pst@Inversion@i}
+\def\Pst@Inversion@i#1#2#3#4{%
+ \pstLocateAB{#1}{#3}{%
+ tx@EcldDict begin /N@#1 GetNode /N@#3 GetNode ABDist end % |OC|
+ % use Radius or Diameter to get the inversion radius.
+ \ifx\psk@Radius\@none
+ \ifx\psk@Diameter\@none
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist end
+ \else
+ \psk@Diameter\space 2 div
+ \fi
+ \else
+ \psk@Radius\space
+ \fi
+ dup mul exch div % |OA|^2/|OC|
+ }{#4}
+ \endgroup%
+}%
+%
+%% \pstGeometricMean[Options]{A}{B}{l1}{l2}{C}
+%% Find the point $C$ on segment AB such that $|AC|^2=l_1*l_2$, then create node $C$.
+%% Parameters:
+%% #1 -> options
+%% #2 -> the first node A on the given segment
+%% #3 -> the second node B on the given segment
+%% #4 -> the given segment length l1
+%% #5 -> the given segment length l2
+%% #6 -> the target node C
+\def\pstGeometricMean{\@ifnextchar[\Pst@GeometricMean{\Pst@GeometricMean[]}}
+\def\Pst@GeometricMean[#1]{%
+ \begingroup
+ \psset{#1}%
+ \Pst@GeometricMean@i}
+\def\Pst@GeometricMean@i#1#2#3#4#5{%
+ \pstLocateAB{#1}{#2}{#3 #4 mul sqrt}{#5}
+ \endgroup%
+}%
+%
+%% \pstHarmonicMean[Options]{A}{B}{l1}{l2}{C}
+%% Find the point $C$ on segment AB such that $1/|AC|=(1/l_1+1/l_2)/2$, then create node $C$.
+%% Parameters:
+%% #1 -> options
+%% #2 -> the first node A on the given segment
+%% #3 -> the second node B on the given segment
+%% #4 -> the given segment length l1
+%% #5 -> the given segment length l2
+%% #6 -> the target node C
+\def\pstHarmonicMean{\@ifnextchar[\Pst@HarmonicMean{\Pst@HarmonicMean[]}}
+\def\Pst@HarmonicMean[#1]{%
+ \begingroup
+ \psset{#1}%
+ \Pst@HarmonicMean@i}
+\def\Pst@HarmonicMean@i#1#2#3#4#5{%
+ \pstLocateAB{#1}{#2}{#3 #4 2 copy mul 3 1 roll add div 2 mul}{#5}
+ \endgroup%
+}%
+%
%% \pstCircleAbsNode[Options]{O}{A}{$x_0$}{C}{D}
%% Create the new nodes C and D on the Circle O whose abscissas are the given value $x_0$.
%% The circle O is defined by center O and point A on the circle or Radius in parameter.
@@ -2006,6 +2377,40 @@
\endgroup%
}%
%
+%% \pstCircleNode[Options]{O}{A}{anglge}{X}
+%% Create a new node X on the Circle O whose angle is the given value.
+%% The circle O is defined by center O and point A on the circle or Radius in parameter.
+%% Parameters:
+%% #1 -> options
+%% #2 -> [input] the circle center O
+%% #3 -> [input] the circle point A or empty with Radius parameter
+%% #4 -> [input] the input angle value
+%% #4 -> [output] the target node name
+\def\pstCircleNode{\@ifnextchar[\Pst@CircleNode{\Pst@CircleNode[]}}
+\def\Pst@CircleNode[#1]{%
+ \begingroup
+ \psset{#1}%
+ \Pst@CircleNode@i}
+\def\Pst@CircleNode@i#1#2#3#4{%
+ \pnode(!
+ tx@EcldDict begin
+ /N@#1 GetNode
+ \ifx\psk@Radius\@none
+ \ifx\psk@Diameter\@none
+ 2 copy /N@#2 GetNode ABDist
+ \else\psk@Diameter 2 div
+ \fi
+ \else\psk@Radius\space
+ \fi
+ end
+ #3 dup sin exch cos
+ 2 index mul 4 index add \pst@number\psxunit\space div %
+ 5 1 roll mul add \pst@number\psyunit\space div exch pop%
+ ){#4}%
+ \Pst@geonodelabel{#4}%
+ \endgroup%
+}%
+%
%% \pstCircleRotNode[Options]{O}{A}{X}
%% Create a new node X on the Circle O whose RotAngle is the given value.
%% The circle O is defined by center O and point A on the circle or Radius in parameter.
@@ -2032,7 +2437,7 @@
\else\psk@Radius\space
\fi
end
- \psk@RotAngle\space sin \psk@RotAngle\space cos %
+ \psk@RotAngle\space dup sin exch cos %
2 index mul 4 index add \pst@number\psxunit\space div %
5 1 roll mul add \pst@number\psyunit\space div exch pop%
){#3}%
@@ -2181,18 +2586,21 @@
%% The circle B(O1) is defined by center O2 and point B on the circle or RadiusB/DiameterB in parameter.
%% Parameters:
%% #1 -> options
-%% #2 -> [input] the circle center O
-%% #3 -> [input] the circle point A or empty with Radius parameter
-%% #4 -> [input] the node name T out of circle
-%% #5 -> [output] the first target name on the circle
-%% #6 -> [output] the second target name on the circle
+%% #2 -> [input] the first circle center O1
+%% #3 -> [input] the first circle point A or empty with RadiusA/DiameterA parameter
+%% #4 -> [input] the second circle center O2
+%% #5 -> [input] the second circle point B or empty with RadiusB/DiameterB parameter
+%% #6 -> [output] the first node name T1 lies on circle A(O1)
+%% #7 -> [output] the second node name T2 lies on circle A(O1)
+%% #8 -> [output] the first node name T3 lies on circle B(O2)
+%% #9 -> [output] the second node name T4 lies on circle B(O2)
\def\pstCircleExternalCommonTangent{\@ifnextchar[\Pst@CircleExternalCommonTangent{\Pst@CircleExternalCommonTangent[]}}
\def\Pst@CircleExternalCommonTangent[#1]{%
\begingroup
\@InitListMng %
\psset{#1}%
- \Pst@CircleExternCommonTangent@i}
-\def\Pst@CircleExternCommonTangent@i#1#2#3#4#5#6#7#8{%
+ \Pst@CircleExternalCommonTangent@i}
+\def\Pst@CircleExternalCommonTangent@i#1#2#3#4#5#6#7#8{%
% use edef to save the second Radius or Diameter.
\edef\pst@RadiusB@temp{\psk@RadiusB}
\edef\pst@DiameterB@temp{\psk@DiameterB}
@@ -2262,11 +2670,14 @@
%% The circle B(O1) is defined by center O2 and point B on the circle or RadiusB/DiameterB in parameter.
%% Parameters:
%% #1 -> options
-%% #2 -> [input] the circle center O
-%% #3 -> [input] the circle point A or empty with Radius parameter
-%% #4 -> [input] the node name T out of circle
-%% #5 -> [output] the first target name on the circle
-%% #6 -> [output] the second target name on the circle
+%% #2 -> [input] the first circle center O1
+%% #3 -> [input] the first circle point A or empty with RadiusA/DiameterA parameter
+%% #4 -> [input] the second circle center O2
+%% #5 -> [input] the second circle point B or empty with RadiusB/DiameterB parameter
+%% #6 -> [output] the first node name T1 lies on circle A(O1)
+%% #7 -> [output] the second node name T2 lies on circle A(O1)
+%% #8 -> [output] the first node name T3 lies on circle B(O2)
+%% #9 -> [output] the second node name T4 lies on circle B(O2)
\def\pstCircleInternalCommonTangent{\@ifnextchar[\Pst@CircleInternalCommonTangent{\Pst@CircleInternalCommonTangent[]}}
\def\Pst@CircleInternalCommonTangent[#1]{%
\begingroup
@@ -2336,6 +2747,212 @@
\endgroup%
}%
%
+%% \pstCircleRadicalAxis[Options]{O1}{A}{O2}{B}{C}{D}
+%% Draw the radical axis of the circle A(O1) and B(O2), and create two nodes $C$ and $D$ on the axis.
+%% The circle A(O1) is defined by center O1 and point A on the circle or RadiusA/DiameterA in parameter.
+%% The circle B(O1) is defined by center O2 and point B on the circle or RadiusB/DiameterB in parameter.
+%% For any point P(x,y) on the radical axis, we have
+%% $$(x-x_1)^2+(y-y_1)^2-r_1^2=(x-x_2)^2+(y-y_2)^2-r_2^2$$
+%% case 1. when $x_1=x_2$, we have
+%% $$2(y_2-y_1)y+y_1^2-r_1^2=y_2^2-r_2^2$$
+%% case 1.1. when $y_1=y_2$, there is none radical axis.
+%% case 1.2. else we have
+%% $$y=\dfrac{(y_2^2-r_2^2)-(y_1^2-r_1^2)}{2(y_2-y_1)}$$
+%% case 1.2.1. when $r_1^2-(y-y_1)^2<0$, there is none intersection of two circle, we select $x=x_1$ and $x=x_1+1$ at this time.
+%% case 1.2.2. else we select $x=x_1\pm\sqrt{r_1^2-(y-y_1)^2}$
+%% case 2. when $x_1\neq{}x_2$, we have
+%% case 2.1. when $y_1=y_2$, we have
+%% $$x=\dfrac{(x_2^2-r_2^2)-(x_1^2-r_1^2)}{2(x_2-x_1)}$$
+%% case 2.1.1. when $r_1^2-(x-x_1)^2<0$, there is none intersection of two circle, we select $y=y_1$ and $y=y_1+1$ at this time.
+%% case 2.1.2. else we select $y=y_1\pm\sqrt{r_1^2-(x-x_1)^2}$
+%% case 2.2. else we have
+%% $$2(x_2-x_1)x+2(y_2-y_1)y=(x_2^2+y_2^2-r_2^2)-(x_1^2+y_1^2-r_1^2)$$
+%% set $a=2(x_2-x_1)$,$b=2(y_2-y_1)$,$m=x_2^2+y_2^2-r_2^2$,$n=x_1^2+y_1^2-r_1^2$, $d=m-n$,we have
+%% $$ax+by=d$$
+%% when $(x-x_1)^2+(y-y_1)^2-r_1^2=0$, let $X=x-x_1$, $Y=y-y_1$, we have
+%% $$X^2+Y^2=r_1^2$$
+%% and
+%% $$aX+bY=d-ax_1-by_1$$
+%% let $e=d-ax_1-by_1$, then
+%% $$(a^2+b^2)X^2-2aeX+e^2-b^2r_1^2=0$$
+%% case 2.2.1 when $(a^2+b^2)r_1^2-e^2>0$, we have
+%% $$x=x_1+\dfrac{ae\pm{}b\sqrt{(a^2+b^2)r_1^2-e^2}}{a^2+b^2}$$
+%% $$y=y_1+\dfrac{be\mp{}a\sqrt{(a^2+b^2)r_1^2-e^2}}{a^2+b^2}$$
+%% case 2.2.2 else we select $x=\dfrac{r_1x_1+r_2x_2}{r_1+r_2}$ and $x=\dfrac{r_2x_1+r_1x_2}{r_1+r_2}$.
+%% Parameters:
+%% #1 -> options
+%% #2 -> [input] the first circle center O1
+%% #3 -> [input] the first circle point A or empty with RadiusA/DiameterA parameter
+%% #4 -> [input] the second circle center O2
+%% #5 -> [input] the second circle point B or empty with RadiusB/DiameterB parameter
+%% #6 -> [output] the first node name C lies on radical axis
+%% #7 -> [output] the second node name D lies on radical axis
+\def\pstCircleRadicalAxis{\@ifnextchar[\Pst@CircleRadicalAxis{\Pst@CircleRadicalAxis[]}}
+\def\Pst@CircleRadicalAxis[#1]{%
+ \begingroup
+ \@InitListMng %
+ \psset{#1}%
+ \Pst@CircleRadicalAxis@i}
+\def\Pst@CircleRadicalAxis@i#1#2#3#4#5#6{%
+ \pst@getcoor{#1}\pst@tempA%
+ \pst@getcoor{#3}\pst@tempB%
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ \ifx\psk@RadiusA\@undef
+ \ifx\psk@DiameterA\@undef
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist end
+ \else
+ \psk@DiameterA\space 2 div
+ \fi
+ \else\psk@RadiusA\space\fi
+ \pst@number\psxunit div %r1
+ \ifx\psk@RadiusB\@undef
+ \ifx\psk@DiameterB\@undef
+ tx@EcldDict begin /N@#3 GetNode /N@#4 GetNode ABDist end
+ \else
+ \psk@DiameterB\space 2 div
+ \fi
+ \else\psk@RadiusB\space\fi
+ \pst@number\psxunit div %r2
+ 5 index 4 index sub abs 1E-5 lt { % if x1=x2
+ 4 index 3 index sub abs 1E-5 lt { % if y1=y2
+ pop pop pop pop pop pop 0 0
+ } {
+ % x1 y1 x2 y2 r1 r2
+ 2 index dup mul 1 index dup mul sub % y2^2-r2^2
+ 5 index dup mul 3 index dup mul sub % y1^2-r1^2
+ sub 3 index 6 index sub 2 mul div % y=\dfrac{(y2^2-r2^2)-(y1^2-r1^2)}{2(y2-y1)}
+ 6 index 3 index dup mul 2 index 8 index sub dup mul sub
+ dup 0 lt {
+ pop % x=x1
+ } {
+ sqrt sub % x=x1\pm\sqrt{r1^2-(y-y1)^2)}
+ } ifelse
+ exch 8 2 roll pop pop pop pop pop pop
+ } ifelse
+ } {
+ 4 index 3 index sub abs 1E-5 lt { % if y1=y2
+ % x1 y1 x2 y2 r1 r2
+ 3 index dup mul 1 index dup mul sub % x2^2-r2^2
+ 6 index dup mul 3 index dup mul sub % x1^2-r1^2
+ sub 4 index 7 index sub 2 mul div % x=\dfrac{(x2^2-r2^2)-(x1^2-r1^2)}{2(x2-x1)}
+ 5 index 3 index dup mul 2 index 9 index sub dup mul sub
+ dup 0 lt {
+ pop % y=y1
+ } {
+ sqrt sub % y=y1\pm\sqrt{r1^2-(x-x1)^2)}
+ } ifelse
+ 8 2 roll pop pop pop pop pop pop
+ } {
+ % x1 y1 x2 y2 r1 r2
+ 3 index dup mul 3 index dup mul add 1 index dup mul sub % m=x2^2+y2^2-r2^2
+ 6 index dup mul 6 index dup mul add 3 index dup mul sub % n=x1^2+y1^2-r1^2
+ 1 index 1 index sub % d=m-n
+ 6 index 9 index sub 2 mul % a=2(x2-x1)
+ 6 index 9 index sub 2 mul % b=2(y2-y1)
+ 2 index 2 index 12 index mul sub 1 index 11 index mul sub % e=d-ax1-by1
+ 2 index dup mul 2 index dup mul add 8 index dup mul mul 1 index dup mul sub % f=(a^2+b^2)r1^2-e^2
+ dup 0 lt {
+ % we select x=\dfrac{r1x1+r2x2}{r1+r2}
+ 8 index 13 index mul 8 index 12 index mul add 9 index 9 index add div % x
+ % y=\dfrac{d-ax}{b}
+ 5 index 5 index 2 index mul sub 4 index div
+ 15 2 roll pop pop pop pop pop pop pop
+ pop pop pop pop pop pop
+ } {
+ sqrt % sqrt(f)
+ % x=x_1+\dfrac{ae\pm{}b\sqrt{(a^2+b^2)r_1^2-e^2}}{a^2+b^2}
+ 0 index 3 index mul 4 index 3 index mul exch sub 4 index dup mul 4 index dup mul add div 13 index add
+ % y=y_1+\dfrac{be\mp{}a\sqrt{(a^2+b^2)r_1^2-e^2}}{a^2+b^2}
+ 1 index 5 index mul 4 index 4 index mul add 5 index dup mul 5 index dup mul add div 13 index add
+ 15 2 roll pop pop pop pop pop pop
+ pop pop pop pop pop pop pop
+ } ifelse
+ } ifelse
+ } ifelse
+ ){#5}
+ \pnode(!
+ \pst@tempA \tx@UserCoor % x1,y1
+ \pst@tempB \tx@UserCoor % x2,y2
+ \ifx\psk@RadiusA\@undef
+ \ifx\psk@DiameterA\@undef
+ tx@EcldDict begin /N@#1 GetNode /N@#2 GetNode ABDist end
+ \else
+ \psk@DiameterA\space 2 div
+ \fi
+ \else\psk@RadiusA\space\fi
+ \pst@number\psxunit div %r1
+ \ifx\psk@RadiusB\@undef
+ \ifx\psk@DiameterB\@undef
+ tx@EcldDict begin /N@#3 GetNode /N@#4 GetNode ABDist end
+ \else
+ \psk@DiameterB\space 2 div
+ \fi
+ \else\psk@RadiusB\space\fi
+ \pst@number\psxunit div %r2
+ 5 index 4 index sub abs 1E-5 lt { % if x1=x2
+ 4 index 3 index sub abs 1E-5 lt { % if y1=y2
+ pop pop pop pop pop pop 0 0
+ } {
+ % x1 y1 x2 y2 r1 r2
+ 2 index dup mul 1 index dup mul sub % y2^2-r2^2
+ 5 index dup mul 3 index dup mul sub % y1^2-r1^2
+ sub 3 index 6 index sub 2 mul div % y=\dfrac{(y2^2-r2^2)-(y1^2-r1^2)}{2(y2-y1)}
+ 6 index 3 index dup mul 2 index 8 index sub dup mul sub
+ dup 0 lt {
+ pop 1 add % x=x1+1
+ } {
+ sqrt add % x=x1\pm\sqrt{r1^2-(y-y1)^2)}
+ } ifelse
+ exch 8 2 roll pop pop pop pop pop pop
+ } ifelse
+ } {
+ 4 index 3 index sub abs 1E-5 lt { % if y1=y2
+ 3 index dup mul 1 index dup mul sub % x2^2-r2^2
+ 6 index dup mul 3 index dup mul sub % x1^2-r1^2
+ sub 4 index 7 index sub 2 mul div % x=\dfrac{(x2^2-r2^2)-(x1^2-r1^2)}{2(x2-x1)}
+ 5 index 3 index dup mul 2 index 9 index sub dup mul sub
+ dup 0 lt {
+ pop 1 add % y=y1+1
+ } {
+ sqrt add % y=y1\pm\sqrt{r1^2-(x-x1)^2)}
+ } ifelse
+ 8 2 roll pop pop pop pop pop pop
+ } {
+ % x1 y1 x2 y2 r1 r2
+ 3 index dup mul 3 index dup mul add 1 index dup mul sub % m=x2^2+y2^2-r2^2
+ 6 index dup mul 6 index dup mul add 3 index dup mul sub % n=x1^2+y1^2-r1^2
+ 1 index 1 index sub % d=m-n
+ 6 index 9 index sub 2 mul % a=2(x2-x1)
+ 6 index 9 index sub 2 mul % b=2(y2-y1)
+ 2 index 2 index 12 index mul sub 1 index 11 index mul sub % e=d-ax1-by1
+ 2 index dup mul 2 index dup mul add 8 index dup mul mul 1 index dup mul sub % f=(a^2+b^2)r1^2-e^2
+ dup 0 lt {
+ % we select x=\dfrac{r2x1+r1x2}{r1+r2}
+ 7 index 13 index mul 9 index 12 index mul add 9 index 9 index add div % x
+ % y=\dfrac{d-ax}{b}
+ 5 index 5 index 2 index mul sub 4 index div
+ 15 2 roll pop pop pop pop pop pop pop
+ pop pop pop pop pop pop
+ } {
+ sqrt % sqrt(f)
+ % x=x_1+\dfrac{ae\pm{}b\sqrt{(a^2+b^2)r_1^2-e^2}}{a^2+b^2}
+ 0 index 3 index mul 4 index 3 index mul add 4 index dup mul 4 index dup mul add div 13 index add
+ % y=y_1+\dfrac{be\mp{}a\sqrt{(a^2+b^2)r_1^2-e^2}}{a^2+b^2}
+ 1 index 5 index mul 4 index 4 index mul exch sub 5 index dup mul 5 index dup mul add div 13 index add
+ 15 2 roll pop pop pop pop pop pop
+ pop pop pop pop pop pop pop
+ } ifelse
+ } ifelse
+ } ifelse
+ ){#6}
+ \Pst@ManageParamList{#5}%
+ \Pst@ManageParamList{#6}%
+ \pstLineAB{#5}{#6}%
+ \endgroup%
+}%
+%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Here are some functions to operate the conic curves.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%