diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/pstricks/contrib/pst-eucl/Changes | 20 | ||||
-rw-r--r-- | graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.pdf | bin | 1189759 -> 1341324 bytes | |||
-rw-r--r-- | graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.tex | 829 | ||||
-rw-r--r-- | graphics/pstricks/contrib/pst-eucl/tex/pst-eucl.tex | 685 |
4 files changed, 1361 insertions, 173 deletions
diff --git a/graphics/pstricks/contrib/pst-eucl/Changes b/graphics/pstricks/contrib/pst-eucl/Changes index f05be18cb4..585f6936d3 100644 --- a/graphics/pstricks/contrib/pst-eucl/Changes +++ b/graphics/pstricks/contrib/pst-eucl/Changes @@ -4,13 +4,25 @@ pst-eucl.pro -------- pst-eucl.tex -------- +1.67 2019/10/28 - add macros to add/subtract/divide the length of two segment, \pstDistAdd, \pstDistSub, and \pstDistDiv etc. + - add macros to reduce or enlarge the distance, \pstDistMul, \pstDistCoef. + - add macro to get the distance from point C to line AB, \pstDistABC. + - add macro to get the definite proportion node on segment, \pstProportionNode. + - add macro to get the fourth harmonic point, \pstFourthHarmonicNode. + - add macro to put the label for the segment, \pstLabelAB. + - add macro to locate a point on segment with specified length, \pstLocateAB. + - add macro to extend a segment to a new point with specified length, \pstExtendAB. + - add macro to get the inversion mapping of a point to the inversion center, \pstInversion. + - add macro to get the Geometric Mean of two segment, \pstGeometricMean. + - add macro to get the Harmonic Mean of two segment, \pstHarmonicMean. + - add macro to get the radical axis of two circles, \pstCircleRadicalAxis. 1.66 2019/10/20 - add macros to operate the node coordinates, \pstAbscissa, \pstOrdinate, \pstMoveNode etc. - add optional parameters angleA and angleB for \pstCircleOA and \pstCircleAB. - add optional parameters to output the inner circle center and outer circle center for \pstTriangleIC and \pstTriangleOC. - add macros to draw the tangent line and tangent node of circle. - add macros to draw the external and internal common tangent lines of two circles. - add macros to draw conics (ellipse, parabola and hyperbola) and their geometrical elements, such as focus, directrix and intersections. -1.65 2019/08/19 - new type for angle +1.65 2019/08/19 - new type for angle 1.64 2019/01/31 - fix for PointName and pstInterCC 1.63 2019/01/27 - fix for PointSymbol=none for pstTriangle 1.62 2019/01/13 - added fillstyle for angles @@ -23,10 +35,10 @@ pst-eucl.tex -------- 1.58 2018/08/07 - allow PointSymbol?=none 1.57 2017/11/28 - fix bug with StandardSyml->StandardSymL 1.56 2017/04/18 - \psGetAngleABC: - - added dec -1 le { /dec 15 def } if + - added dec -1 le { /dec 15 def } if - added \pst@usecolor\pslinecolor in line 1616 -1.55 2016/10/11 - fix for \pstRightAngle -1.54 2016/09/01 - added MarkArrow, MarkArroww,MarkArrowww +1.55 2016/10/11 - fix for \pstRightAngle +1.54 2016/09/01 - added MarkArrow, MarkArroww,MarkArrowww 1.53 2016/05/03 - revert changes of CodeFig(A|B) 1.52 2015/10/19 - added more optional arguments (ts) 1.51 2014/05/17 - added two new functions for angles and distances diff --git a/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.pdf b/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.pdf Binary files differindex 7f37a4e7ae..1766af0c73 100644 --- a/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.pdf +++ b/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.pdf diff --git a/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.tex b/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.tex index 25aefc7487..dc97768b52 100644 --- a/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.tex +++ b/graphics/pstricks/contrib/pst-eucl/doc/pst-eucl-doc.tex @@ -216,7 +216,7 @@ sometimes it results the numbers more than 9 fraction digits, which are not supported good by \PST\space with '! number too big' issue.} to generate the numerical values, or the expandable command \Lcs{fpeval}\footnote{Provided by package \texttt{xfp}, it can truncate the fraction part digits using the \texttt{trunc} function perfectly, -e.g. \texttt{\textbackslash{}fpeval\{trunc(18/7,3)\}}.} to get a purely numerical result, +e.g. \texttt{\textbackslash{}fpeval\{trunc(18/7,3)\}}.} to get a purely numerical result. The macro \Lcs{pstMoveNode} use them to move node $A$ by abscissa increment $dx$ and ordinate increment $dy$ to get the target node $B$. @@ -316,26 +316,60 @@ controled by the parameter \Lkeyword{MarkAngle} (default is 45). Their width and depends of the width and color of the line when the drawing is done, as shown is the next example. - - \begin{LTXexample}[width=5cm,pos=l] \begin{pspicture}[showgrid=true](-2,-2)(2,2) - \rput{18}{% - \pstGeonode[PosAngle={0,90,180,-90}](2,0){A}(2;72){B} - (2;144){C}(2;216){D}(2;288){E}} - \pstSegmentMark[SegmentSymbol=none]{A}{B} - \pstSegmentMark[linecolor=green]{B}{C} - \psset{linewidth=2\pslinewidth} - \pstSegmentMark[linewidth=2\pslinewidth]{C}{D} - \pstSegmentMark[MarkAngle=90]{D}{E} - \pstSegmentMark{E}{A} +\rput{18}{% + \pstGeonode[PosAngle={0,90,180,-90}](2,0){A}(2;72){B} + (2;144){C}(2;216){D}(2;288){E}} +\pstSegmentMark[SegmentSymbol=none]{A}{B} +\pstSegmentMark[linecolor=green]{B}{C} +\psset{linewidth=2\pslinewidth} +\pstSegmentMark[linewidth=2\pslinewidth]{C}{D} +\pstSegmentMark[MarkAngle=90]{D}{E} +\pstSegmentMark{E}{A} \end{pspicture} \end{LTXexample} - The length and the separation of multiple hases can be set by \Lkeyword{MarkHashLength} and \Lkeyword{MarkHashSep}. +\subsection{Segment labels} + +According to the manual of \PST, you can use the macros \Lcs{naput}, \Lcs{ncput} and \Lcs{nbput} +to put the label \textit{above}, \textit{cover}, \textit{below} the segment. The macro \Lcs{pstLabelAB} +just use them to draw a ruler bar and put the label on the ruler bar. + +\begin{BDef} +\Lcs{pstLabelAB}\OptArgs\Largb{A}\Largb{B}\Largb{label} +\end{BDef} + +You can use the parameters of \Lcs{ncline} to control the ruler bar, +such as \Lkeyword{linestyle}, \Lkeyword{linecolor}, \Lkeyword{linewidth}, +\Lkeyword{arrows}, \Lkeyword{nodesep} etc; and use the parameters of \Lcs{ncput} +to control the label position, such as \Lkeyword{nrot}, \Lkeyword{npos} etc; +there is another parameter \Lkeyword{offset} to control the separation between +the rule bar and the segment. + +It does not display the ruler bar as default, and you need to setup \Lkeyword{linestyle} +to display it. +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(4,4) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\pstGeonode[PosAngle=-90](0.5,1.5){A} +\pstGeonode[PosAngle=-90](2.5,1.5){B}\pstLineAB{A}{B} +\pstLabelAB{A}{B}{$\sqrt{a^2+b^2}$} +\pstGeonode[PosAngle=0](0,0.5){C} +\pstGeonode[PosAngle=0](0,3.5){D}\pstLineAB{C}{D} +\pstLabelAB[linestyle=dashed]{C}{D}{$\sqrt{a^2+b^2}$} +\pstGeonode[PosAngle=190](-1,-1){E} +\pstGeonode[PosAngle=10](3,0){F}\pstLineAB{E}{F} +\pstLabelAB[linestyle=dashed,arrows=|-|,offset=10pt,linecolor=blue!50]{E}{F}{$\sqrt{a^2+b^2}$} +\pstLabelAB[linestyle=dashed,arrows=|<->|,offset=10pt,nrot=:D]{F}{E}{$\sqrt{a^2+b^2}$} +\pstGeonode[PosAngle=100](0,4){G} +\pstGeonode[PosAngle=-50](4,2){H}\pstLineAB{G}{H} +\pstLabelAB[linestyle=solid,linecolor=red!50,arrows=|-|,offset=15pt,nrot=:U,npos=0.7]{G}{H}{\textcolor{red!50}{$\dfrac{a}{b}$}} +\end{pspicture} +\end{LTXexample} \subsection{Triangles} @@ -536,6 +570,8 @@ parameters is equal to 0. \end{pspicture} \end{LTXexample} +\vspace{10pt} + The macro \Lcs{pstLine} draws a new line with two nodes, or two coordinates or one node and one coordinate. This macro is similar with \Lcs{pstLineAB}, but more compatible. @@ -547,6 +583,8 @@ but more compatible. \Lcs{pstLine}\OptArgs\cAny\cAny \end{BDef} +\vspace{10pt} + The macros \Lcs{pstLineAA} and \Lcs{pstLineAS} draw a new line with one node, the slope \texttt{angle} between the line and the horizontal axis, or the slope \texttt{gradient} of the line, and create a new node $B$ on the line. @@ -572,6 +610,8 @@ Here are some examples: \end{pspicture} \end{LTXexample} +\vspace{10pt} + The macro \Lcs{pstLineAbsNode} creates a new node $C$ whose abscissa is the given value $x_1$ on the line $AB$. The macro \Lcs{pstLineOrdNode} creates a new node $C$ whose ordinate is the given value $y_1$ on the line $AB$. You can input $x_1$ or $y_1$ as any number(e.g, 2.0), @@ -596,65 +636,460 @@ For example, \end{pspicture} \end{LTXexample} +\vspace{10pt} + +The macro \Lcs{pstProportionNode} creates the nodes $C$ and $C'$ on segment $AB$ which are satisfied $|AC|:|BC|=\lambda,\;(\lambda>0)$. +The node $C$ is inside the segment $AB$ and the node $C'$ is outside the segment $AB$, we have +\begin{equation*} +\left\{ +\begin{array}{l} +x_{C}=\dfrac{x_{A}+\lambda{}x_{B}}{1+\lambda}\\ +y_{C}=\dfrac{y_{A}+\lambda{}y_{B}}{1+\lambda} +\end{array} +\right. +\quad\text{and}\quad +\left\{ +\begin{array}{l} +x_{C'}=\dfrac{x_{A}-\lambda{}x_{B}}{1-\lambda}\\ +y_{C'}=\dfrac{y_{A}-\lambda{}y_{B}}{1-\lambda} +\end{array} +\right. +\end{equation*} + +\begin{BDef} +\Lcs{pstProportionNode}\OptArgs\Largb{A}\Largb{B}\Largb{$\lambda$}\Largb{C}\Largb{C'} +\end{BDef} + +You can use \Lcs{pstDistDiv} to get the ratio of two segments to $\lambda$, +we will introduce \Lcs{pstDistDiv} later. + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(4,4) +\pstGeonode[PosAngle=-40,PointSymbol=|](0.5,1.5){A} +\pstGeonode[PosAngle=-40,PointSymbol=|](3.0,3.0){B} +\pstGeonode[PosAngle=90,linecolor=purple!60,CurveType=polyline](3,0){X}(4,0){Y} +\pstGeonode[PosAngle=90,linecolor=brown!60,CurveType=polyline](1.5,-1){X'}(4,-1){Y'} +\pstLineAB[linecolor=red,nodesep=-2.5]{A}{B} +\psset{PosAngle=-40,PointSymbol=*,dotscale=1.5} +\pstProportionNode[linecolor=yellow]{A}{B}{3.0}{C}{C'} +\pstProportionNode[linecolor=blue]{A}{B}{1.0}{D}{D'} +\pstProportionNode[linecolor=green]{A}{B}{0.2}{E}{E'} +\pstProportionNode[linecolor=brown]{A}{B}{\pstDistDiv{X}{Y}{X'}{Y'}}{F}{F'} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +The four collinear points $A,B,C,D$ are called \texttt{Harmonic Conjugation Points} if their cross ratio is $-1$, +that is +$$(AB,CD)=\dfrac{AC}{BC}:\dfrac{AD}{BD}=-1$$ +If given three collinear points $A,B,C$, how can we get the fourth harmonic point? +The following macro \Lcs{pstFourthHarmonicNode} is used to get the fourth harmonic point. +It create a new node $X$ on the same line, but when $A,B,C$ are not collinear, we put it at origin. + +\begin{BDef} +\Lcs{pstFourthHarmonicNode}\OptArgs\Largb{A}\Largb{B}\Largb{C}\Largb{X} +\end{BDef} + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-2,-2)(3,3)\footnotesize +\psset{unit=0.6cm}\psset{dotscale=0.5}\psset{PointSymbol=*} +\pstGeonode[PosAngle=-90](-2,-2){A}(5,-2){I}(-1,-2){J} +\pstLineAA[linestyle=none,PointName=none,PointSymbol=none]{A}{38}{A'} +\pstLineAbsNode[PosAngle=-80]{A}{A'}{0}{B} +\pstLineAbsNode[PosAngle=20]{A}{A'}{2.5}{C} +\pstFourthHarmonicNode[PosAngle=180,PointNameSep=0.2]{A}{B}{C}{X} +% check if A,N,M are also collinear. +\pstInterLL[PosAngle=90]{J}{X}{I}{C}{P} +\pstLineAB[linestyle=dashed]{J}{P} +\pstLineAB[linestyle=dashed]{I}{P} +\pstInterLL[PosAngle=20]{J}{B}{I}{P}{M} +\pstInterLL[PosAngle=140]{I}{B}{J}{P}{N} +\pstLineAB[linestyle=dashed]{J}{M} +\pstLineAB[linestyle=dashed]{I}{N} +\pstLineAB[linestyle=dashed]{A}{M} +\pstLineAB[linestyle=dashed]{A}{I} +\pstLineAB{A}{C} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +If you want to draw a node like \textsf{'Given $EF$, please find node $C$ on $AB$ such that $AC=EF$'}, +you can use the macro \Lcs{pstLocateAB} to do this, it can seek the node $C$ from $A$ to $B$ with the +specified length, which can be got from \Lcs{pstDist}, \Lcs{pstDistConst}, \Lcs{pstDistAdd}, \Lcs{pstDistSub}, +etc. + +\begin{BDef} +\Lcs{pstLocateAB}\OptArgs\Largb{A}\Largb{B}\Largb{$L$}\Largb{C} +\end{BDef} + +Note that seek from $B$ will get the node $C$ in the reverse order, for example, + +\begin{LTXexample}[width=5cm,pos=l] +\begin{pspicture}[showgrid=true](-3,-3)(3,3)\footnotesize +\psset{unit=0.5cm}\psset{dotscale=0.5}\psset{PointSymbol=*} +\pstGeonode[PosAngle=90,CurveType=polyline](-2,0){A}(-1,0){B} +\pstGeonode[PosAngle=90,CurveType=polyline](-2,1){A'}(0,1){B'} +\pstLocateAB[PosAngle=90]{A}{B}{\pstDist{A'}{B'}}{C} +\pstLocateAB[PosAngle=90]{B}{A}{\pstDist{A'}{B'}}{C'} +\psset{linestyle=dashed,SegmentSymbol=MarkHashh,MarkAngle=90} +\pstSegmentMark{A'}{B'}\pstSegmentMark{B}{C'}\pstSegmentMark{A}{C} +\pstGeonode[PosAngle=90,CurveType=polyline](-3,-2){D}(3,-4){E} +\pstGeonode[PosAngle=90,CurveType=polyline](-4,2){D'}(-3,4){E'} +\pstLocateAB[PosAngle=90]{D}{E}{\pstDist{D'}{E'}}{F} +\pstLocateAB[PosAngle=90]{E}{D}{\pstDist{D'}{E'}}{F'} +\psset{linestyle=dashed,SegmentSymbol=MarkHashhh,MarkAngle=90} +\pstSegmentMark{D'}{E'}\pstSegmentMark{E}{F'}\pstSegmentMark{D}{F} +\pstGeonode[PosAngle=0,CurveType=polyline](2,0){I}(2,1){J} +\pstGeonode[PosAngle=0,CurveType=polyline](3,2){I'}(3,4){J'} +\pstLocateAB[PosAngle=0]{I}{J}{\pstDist{I'}{J'}}{K} +\pstLocateAB[PosAngle=0]{J}{I}{\pstDist{I'}{J'}}{K'} +\psset{linestyle=dashed,SegmentSymbol=MarkHashhh,MarkAngle=45} +\pstSegmentMark{I'}{J'}\pstSegmentMark{J}{K'}\pstSegmentMark{I}{K} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +If you want to draw a node like \textsf{'Given $EF$, please extend $AB$ to $C$ such that $BC=EF$'}, +you can use the macro \Lcs{pstExtendAB} to do this, it can extend $AB$ from $B$ to one node with the +specified length, which can be got from \Lcs{pstDist}, \Lcs{pstDistConst}, \Lcs{pstDistAdd}, \Lcs{pstDistSub}, +etc. + +\begin{BDef} +\Lcs{pstExtendAB}\OptArgs\Largb{A}\Largb{B}\Largb{$L$}\Largb{C} +\end{BDef} + +Note that extend $BA$ to $C$ will get the node $C$ in the reverse order, for example, + +\begin{LTXexample}[width=5cm,pos=l] +\begin{pspicture}[showgrid=true](-3,-3)(3,3)\footnotesize +\psset{unit=0.5cm}\psset{dotscale=0.5}\psset{PointSymbol=*} +\pstGeonode[PosAngle=90,CurveType=polyline](-2,0){A}(-1,0){B} +\pstGeonode[PosAngle=90,CurveType=polyline](-2,1){A'}(0,1){B'} +\pstExtendAB[PosAngle=90]{A}{B}{\pstDist{A'}{B'}}{C} +\pstExtendAB[PosAngle=90]{B}{A}{\pstDist{A'}{B'}}{C'} +\psset{linestyle=dashed,SegmentSymbol=MarkHashh,MarkAngle=90} +\pstSegmentMark{A'}{B'}\pstSegmentMark{B}{C}\pstSegmentMark{A}{C'} +\pstGeonode[PosAngle=90,CurveType=polyline](-2,-2){D}(0,-3){E} +\pstGeonode[PosAngle=90,CurveType=polyline](-4,2){D'}(-3,4){E'} +\pstExtendAB[PosAngle=90]{D}{E}{\pstDist{D'}{E'}}{F} +\pstExtendAB[PosAngle=90]{E}{D}{\pstDist{D'}{E'}}{F'} +\psset{linestyle=dashed,SegmentSymbol=MarkHashhh,MarkAngle=90} +\pstSegmentMark{D'}{E'}\pstSegmentMark{E}{F}\pstSegmentMark{D}{F'} +\pstGeonode[PosAngle=0,CurveType=polyline](2,0){I}(2,1){J} +\pstGeonode[PosAngle=0,CurveType=polyline](3,2){I'}(3,4){J'} +\pstExtendAB[PosAngle=0]{I}{J}{\pstDist{I'}{J'}}{K} +\pstExtendAB[PosAngle=0]{J}{I}{\pstDist{I'}{J'}}{K'} +\psset{linestyle=dashed,SegmentSymbol=MarkHashhh,MarkAngle=45} +\pstSegmentMark{I'}{J'}\pstSegmentMark{J}{K}\pstSegmentMark{I}{K'} +\end{pspicture} +\end{LTXexample} + +You can find the node $C$ on segment $AB$ satisfied $|AC|$:$|AB|$=\Lkeyword{DistCoef} +using \Lcs{pstTranslation}, but it can't do the same thing like \Lcs{pstLocateAB} and \Lcs{pstExtendAB} +when the given segment $EF$ is not parallel with $AB$, it will be introduced in the later sections. + +\vspace{10pt} + +If you want to find the inversion point $C'$ of $C$ to the inversion center $O$ with inversion raduis $R$, +that is, the point $C'$ is satisfied the inversion transform equation +$$|OC|\times|OC'|=R^2$$ +you can use the macro \Lcs{pstInversion} to do this work. +In fact, we use the macro \Lcs{pstLocateAB} to implement this macro +by passing the value $\dfrac{R^2}{|OC|}$ to parameter length. + +\begin{BDef} +\Lcs{pstInversion}\OptArgs\Largb{O}\Largb{A}\Largb{C}\Largb{C'} +\end{BDef} + +It is possible to omit the parameter $A$ and then to specify the inversion radius or +the inversion diameter using the parameters \Lkeyword{Radius} and \Lkeyword{Diameter}, +which will be introduced in the next section. + +It is clear that the inversion mapping of a line is a circle, and the inversion mapping +of a point on the inversion circle is itself. + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-2)(4,3) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\def\ra{1.5} +\pstGeonode[PosAngle=180](1,1){O} +\pstCircleOA[linecolor=red!50,Radius=\pstDistVal{\ra}]{O}{} +\pstCircleRotNode[PosAngle=180,RotAngle=180,Radius=\pstDistVal{\ra}]{O}{}{A} +\pstInversion[PosAngle=0,Radius=\pstDistVal{\ra}]{O}{}{A}{A'} +\pstGeonode[PosAngle=0](3,3){C} +\pstInversion[PosAngle=100,Radius=\pstDistVal{\ra}]{O}{}{C}{C'} +\pstLineAB{O}{C}\pstLineAB{O}{C'} +\pstGeonode[PosAngle=0](3,1.5){D} +\pstInversion[PosAngle=90,Radius=\pstDistVal{\ra}]{O}{}{D}{D'} +\pstLineAB{O}{D}\pstLineAB{O}{D'} +\pstGeonode[PosAngle=0](3,0){E} +\pstInversion[PosAngle=-90,Radius=\pstDistVal{\ra}]{O}{}{E}{E'} +\pstLineAB{O}{E}\pstLineAB{O}{E'} +\pstGeonode[PosAngle=0](3,-2){F} +\pstInversion[PosAngle=-120]{O}{A}{F}{F'} +\pstLineAB{O}{F}\pstLineAB{O}{F'} +\pstLineAB[linecolor=black!50]{C}{F} +\pstCircleABC[linestyle=dashed,linecolor=blue!40,PosAngle=0]{C'}{D'}{E'}{O'} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +If you want to find the node $C$ from $A$ to $B$, such that $AC$ is the geometric mean of two +given segments $DE$ of $FG$, that is, +$$|AC|^2=|DE|\times|FG|$$ +you can use the macro \Lcs{pstGeometricMean} to do this work. +It also can be used to draw a circle when given two points on the circle, +and a line tangents to the circle. + +\begin{BDef} +\Lcs{pstGeometricMean}\OptArgs\Largb{A}\Largb{B}\Largb{$L_1$}\Largb{$L_2$}\Largb{C} +\end{BDef} + +In fact, we use the macro \Lcs{pstLocateAB} to implement this macro +by passing the value $\sqrt{L_1\times{}L_2}$ to parameter length. +The length $L_1$ and $L_2$ can be got from \Lcs{pstDist}, \Lcs{pstDistConst}, +\Lcs{pstDistAdd}, \Lcs{pstDistSub}, etc. + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](0,-3)(4,3) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\pstGeonode[PosAngle=90](0,1){A} +\pstGeonode[PosAngle=0](3.2,2){C}(3.2,1){D}(3.2,-2){E} +\pstGeometricMean[PosAngle=90]{C}{A}{\pstDistAB{C}{D}}{\pstDistAB{D}{E}}{B} +\pstCircleABC[linecolor=gray!60]{B}{D}{E}{O} +\pstLineAB[linecolor=red!40]{C}{D} +\pstLineAB[linecolor=blue!40]{D}{E} +\psset{linestyle=dashed} +\pstLineAB[linecolor=purple!80]{C}{A} +\pstLineAB{D}{B}\pstLineAB{E}{B} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +If you want to find the node $C$ from $A$ to $B$, such that $AC$ is the harmonic mean of two +given segments $DE$ of $FG$, that is, +$$\dfrac{1}{|AC|}=\dfrac{1}{2}(\dfrac{1}{|DE|}+\dfrac{1}{|FG|})$$ +you can use the macro \Lcs{pstHarmonicMean} to do this work. + +\begin{BDef} +\Lcs{pstHarmonicMean}\OptArgs\Largb{A}\Largb{B}\Largb{$L_1$}\Largb{$L_2$}\Largb{C} +\end{BDef} + +In fact, we use the macro \Lcs{pstLocateAB} to implement this macro +by passing the value $\dfrac{2L_1L_2}{L_1+L_2}$ to parameter length. +The length $L_1$ and $L_2$ can be got from \Lcs{pstDist}, \Lcs{pstDistConst}, +\Lcs{pstDistAdd}, \Lcs{pstDistSub}, etc. + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](0,-3)(4,3) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\pstGeonode[PosAngle=90](1,2){A} +\pstGeonode[PosAngle=-90](0,-2){C}(2.5,-2){D}(4,-2){E} +\pstHarmonicMean[PosAngle=60]{D}{A}{\pstDistAB{C}{D}}{\pstDistAB{D}{E}}{B} +\pstLineAB[linecolor=red!40]{C}{D} +\pstLineAB[linecolor=blue!40]{D}{E} +\pstLineAB[linecolor=purple!80]{A}{D} +\pstLineAB[linestyle=dashed]{C}{B} +\pstLineAB[linestyle=dashed]{E}{B} +\pstLineAB{C}{A}\pstLineAB{E}{A} +\end{pspicture} +\end{LTXexample} + +\subsection{Distance} +Like as coordinates, the distance works at the PostScript level, +that is, it should be used where the code is interpreted by PostScript engine, +but not \TeX\ engine. There were three macros to operate the distance before v1.66: + +\begin{BDef} +\Lcs{pstDistAB}\Largb{A}\Largb{B}\\ +\Lcs{pstDistVal}\Largb{l}\\ +\Lcs{pstDistCalc}\Largb{expr} +\end{BDef} + +The first specifies a distance between two points. The second macro can be used to +specify an explicit numerical value $l$, which is in \texttt{User coordinate}. +The third one uses the \Lcs{pscalculate} to calculate +the result of the input expression, which is in \texttt{User coordinate} too. +The parameter \Lkeyword{DistCoef} can be used to specify +a coefficient to reduce or enlarge the result distance. +This parameter will come into effect if it is specified before these macros. + +After v1.66, We provide three macros which disable the effect of parameter \Lkeyword{DistCoef} +one to one as following: + +\begin{BDef} +\Lcs{pstDist}\Largb{A}\Largb{B}\\ +\Lcs{pstDistConst}\Largb{l}\\ +\Lcs{pstDistExpr}\Largb{expr} +\end{BDef} + +We provide the macro \Lcs{pstDistCoef} to reduce or enlarge a given distance explicitly, +for example: \verb|\pstDistCoef{\pstDist{A}{B}}|, or use macro \Lcs{pstDistMul} to multiply +the input coefficient. + +\vspace{10pt}\noindent{}{\large{\textbf{Note}}}: +The series of macros \verb|\pstDist*| get the length result in the \texttt{Screen coordinate}, +so you need to convert the length to the \texttt{User coordinate} by macro \Lcs{pstUserDist}, +when use them where need the user coordinate numbers, e.g, + +\begin{lstlisting} +\pnode(! 1 \pstUserDist{\pstDistAdd{A}{B}{C}{D}}){A} +\pstMoveNode(0,\pstUserDist{\pstDistAdd{A}{B}{C}{D}}){A}{E} +\end{lstlisting} + +You can convert the distance in \texttt{User coordinate} to \texttt{Screen coordinate} by +macro \Lcs{pstScreenDist}, it is just another name of \Lcs{pstDistConst}. As we said before, +macros \Lcs{pstAbscissa} and \Lcs{pstOrdinate} give the coordinate of one node in +\texttt{User coordinate}, so if you want to draw a circle using them, you should type:\\[8pt] +\verb|\pstCircleOA[Radius=\pstDistConst{\pstAbscissa{A}}]{A}{}| + +\vspace{10pt} + +It is possible to use the raw PostScript command to make more complex arithmetic operations. +In order to hide the lower level Postscipt language, we add more macros for distance +addition and subtraction, such as \Lcs{pstDistAdd}[Val/Coef] and \Lcs{pstDistSub}[Val/Coef], etc. +These macros can be used to calculate the Radius or Diameter to define a circle. + +The macros \Lcs{pstDistAdd} and \Lcs{pstDistSub} are used to get the addition and subtraction +of the given segments $AB$ and $CD$. The macro \Lcs{pstDistDiv} is used to +get the length ratio of the given segments $AB$ and $CD$, you can pass the ratio to +macro \Lcs{pstProportionNode}, or setup the ratio to parameter \Lkeyword{DistCoef} in +macro \Lcs{pstTranslation}, or pass the ratio to any \verb|\pstDist|* macros which need +a $\lambda$ parameter. + +\begin{BDef} +\Lcs{pstDistMul}\Largb{A}\Largb{B}\Largb{$\lambda$}\\ +\Lcs{pstDistAdd}\Largb{A}\Largb{B}\Largb{C}\Largb{D}\\ +\Lcs{pstDistAddVal}\Largb{A}\Largb{B}\Largb{$\lambda$}\Largb{$L$}\\ +\Lcs{pstDistAddCoef}\Largb{A}\Largb{B}\Largb{$\lambda_1$}\Largb{C}\Largb{D}\Largb{$\lambda_2$}\\ +\Lcs{pstDistSub}\Largb{A}\Largb{B}\Largb{C}\Largb{D}\\ +\Lcs{pstDistSubVal}\Largb{A}\Largb{B}\Largb{$\lambda$}\Largb{$L$}\\ +\Lcs{pstDistSubCoef}\Largb{A}\Largb{B}\Largb{$\lambda_1$}\Largb{C}\Largb{D}\Largb{$\lambda_2$}\\ +\Lcs{pstDistDiv}\Largb{A}\Largb{B}\Largb{C}\Largb{D} +\end{BDef} + +In these macros, the length $L$ is a numerical value in the \texttt{Screen Coordinate}, +so it is possible to pass the result of any macros like \verb|\pstDist| to it. +$\lambda$ is a numerical value to multiply, and most important is that the parameter +\Lkeyword{DistCoef} doesn't take effect any more. +It is better to describe in formula: +\\ +- macro \Lcs{pstDistAB} get the screen length of $\text{DistCoef}*|AB|$\\ +- macro \Lcs{pstDistVal} get the screen length of $\text{DistCoef}*l$\\ +- macro \Lcs{pstDistCalc} get the screen length of $\text{DistCoef}*\text{expr}$\\ +- macro \Lcs{pstDistCoef} get the screen length of $\text{DistCoef}*\text{<arg>}$\\ +- macro \Lcs{pstDist} get the screen length of $|AB|$\\ +- macro \Lcs{pstDistConst} get the screen length of $l$\\ +- macro \Lcs{pstDistExpr} get the screen length of $\text{expr}$\\ +- macro \Lcs{pstDistMul} get the screen length of $\lambda{}|AB|$\\ +- macro \Lcs{pstDistAdd} get the screen length of $|AB|+|CD|$\\ +- macro \Lcs{pstDistAddVal} get the screen length of $\lambda{}|AB|+L$\\ +- macro \Lcs{pstDistAddCoef} get the screen length of $\lambda_1{}|AB|+\lambda_2{}|CD|$\\ +- macro \Lcs{pstDistSub} get the screen length of $abs(|AB|-|CD|)$\\ +- macro \Lcs{pstDistSubVal} get the screen length of $abs(\lambda{}|AB|-L)$\\ +- macro \Lcs{pstDistSubCoef} get the screen length of $abs(\lambda_1{}|AB|-\lambda_2{}|CD|)$\\ +- macro \Lcs{pstDistDiv} get the the ratio of length $|AB|:|CD|$ + +For example, the following one draw a circle with radius length $2|AB|+3|CD|+4|EF|$, +it shows how to operate more than two distances. +\begin{lstlisting} +\pstCircleOA[Radius=\pstDistAddVal{A}{B}{2.0}{\pstDistAddCoef{C}{D}{3.0}{E}{F}{4.0}}]{A}{} +\end{lstlisting} + +Another example is for \Lcs{pstDistMul}, the old code like as +\begin{lstlisting} +\pstCircleOA[DistCoef=1 3 div,Radius=\pstDistAB{A}{B}]{O}{} +\pstCircleOA[DistCoef=1 3 div,Radius=\pstDistAB{A}{B}]{A}{B}{O}{}{I}{J} +\pstInterCC[DistCoef=1 3 div,RadiusA=\pstDistAB{A}{B},DistCoef=none,RadiusA=\pstDistAB{C}{D}]{O1}{}{O2}{}{I}{J} +\end{lstlisting} +could be simplified to +\begin{lstlisting} +\pstCircleOA[Radius=\pstDistMul{A}{B}{1 3 div}]{O}{} +\pstInterLC[Radius=\pstDistMul{A}{B}{1 3 div}]{A}{B}{O}{}{I}{J} +\pstInterCC[RadiusA=\pstDistMul{A}{B}{1 3 div},RadiusA=\pstDistAB{C}{D}]{O1}{}{O2}{}{I}{J} +\end{lstlisting} + +\vspace{10pt}\noindent{}{\Large{\textbf{Important}}}! +We recommend that you should use the distance macros which disable the parameter \Lkeyword{DistCoef} +instead of \verb|\pstDistAB|, \verb|\pstDistVal| or \verb|\pstDistCalc|, +when you need to pass their result into \Lcs{pstDistAddVal} or \Lcs{pstDistSubVal}, +as it will give you the error result sometimes. +For example, the following code \\[8pt] +\verb|\pstDistAddVal{A}{B}{2.0}{\pstDistAB{C}{D}}|\\[8pt] +is expected to get the length of $2|AB|+|CD|$. If current \Lkeyword{DistCoef} is $\lambda$, +then it will give the error result as $2|AB|+\lambda|CD|$. +The right way is \\[8pt] +\verb|\pstDistAddVal{A}{B}{2.0}{\pstDist{C}{D}}| + +\vspace{10pt} +At last, we provide a macro named \Lcs{pstDistABC} to get the distance from $C$ to line $AB$. + +\begin{BDef} +\Lcs{pstDistABC}\Largb{A}\Largb{B}\Largb{C} +\end{BDef} + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(3,3) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\pstGeonode[PosAngle=-90](0,0){O} +\pstGeonode[PosAngle=-90](2,0){A} +\pstGeonode[PosAngle=90](1,1.5){B} +\pstCircleOA[linecolor=red,Radius=\pstDistABC{O}{A}{B}]{B}{} +\pstCircleOA[linecolor=blue,Radius=\pstDistABC{B}{O}{A}]{A}{} +\pstCircleOA[linecolor=green,Radius=\pstDistABC{A}{B}{O}]{O}{} +\pstLineAB[linecolor=red]{O}{A} +\pstLineAB[linecolor=blue]{B}{O} +\pstLineAB[linecolor=green]{A}{B} +\end{pspicture} +\end{LTXexample} + \subsection{Circles} A circle can be defined either with its center and a point of its -circumference, or with two diameterly opposed points. There is two -commands : +circumference, or with two diameterly opposed points. There are two +commands: \begin{BDef} \Lcs{pstCircleOA}\OptArgs\Largb{O}\Largb{A}\OptArg{angleA}\OptArg{angleB}\\ -\Lcs{pstCircleAB}\OptArgs\Largb{O}\Largb{A}\OptArg{angleA}\OptArg{angleB} +\Lcs{pstCircleAB}\OptArgs\Largb{A}\Largb{B}\OptArg{angleA}\OptArg{angleB} \end{BDef} -\Lcs{pstCircleOA} draws the circle of center $O$ crossing $A$ from \Lkeyword{angleA} to \Lkeyword{angleB}, going counter clockwise. -Possible options are \Lkeyword{Radius} and \Lkeyword{Diameter}. +\Lcs{pstCircleOA} draws the circle of center $O$ crossing $A$ from \Lkeyword{angleA} to \Lkeyword{angleB}, +going counter clockwise. Possible options are \Lkeyword{Radius} and \Lkeyword{Diameter}. \Lcs{pstCircleAB} draws the circle of diameter $AB$ with the same options. - For the first macro, it is possible to omit the second point and then to specify a radius or a diameter using the parameters \Lkeyword{Radius} -and \Lkeyword{Diameter}. The values of these parameters must be specified -with one of the two following macros : - -\begin{BDef} -\Lcs{pstDistAB}\OptArgs\Largb{A}\Largb{B}\\ -\Lcs{pstDistVal}\OptArgs\Largb{x} -\end{BDef} +\footnote{The package \texttt{pst-fractal} also defines an optional key +named \texttt{Radius}, if you need to use this package with \texttt{pst-eucl}, +you need to setup the key \texttt{Radius} as following: +\texttt{\textbackslash{}psset[pst-eucl]\{Radius=\textbackslash{}pstDistVal\{3\}\}}.} +and \Lkeyword{Diameter}. The values of these parameters can be specified +with one of the \verb|\pstDist|* series macros. -%\Lcs{pstDistAB} Specifies distance $AB$ for the parameters -% \Lkeyword{Radius}, \Lkeyword{Diameter} and \Lkeyword{DistCoef}. -% -%\Lcs{pstDistVal} Specifies a numerical value for the parameters -% \Lkeyword{Radius}, \Lkeyword{Diameter}, and \Lkeyword{DistCoef}. - -The first specifies a distance between two points. The parameter -\Lkeyword{DistCoef} can be used to specify a coefficient to reduce or -enlarge this distance. To be taken into account this last parameter -must be specified before the distance. The second macro can be used to -specify an explicit numeric value. -% We will see later how to draw the circle crossing three points. -% - With this package, it becomes possible to draw: - \begin{compactitem} - \item {\color{red} the circle of center $A$ crossing $B$;} - \item {\color{green} the circle of center $A$ whose radius is $AC$;} - \item {\color{blue} the circle of center $A$ whose radius is $BC$;} - \item {\color{Sepia} the circle of center $B$ whose radius is $AC$;} - \item {\color{Aquamarine} the circle of center $B$ of diameter $AC$;} - \item {\color{RoyalBlue} the circle whose diameter is $BC$.} - \end{compactitem} - -\clearpage +With this package, it becomes possible to draw: +\begin{compactitem} +\item {\color{red} the circle of center $A$ crossing $B$;} +\item {\color{green} the circle of center $A$ whose radius is $AC$;} +\item {\color{blue} the circle of center $A$ whose radius is $BC$;} +\item {\color{Sepia} the circle of center $B$ whose radius is $AC$;} +\item {\color{Aquamarine} the circle of center $B$ of diameter $AC$;} +\item {\color{RoyalBlue} the circle whose diameter is $BC$.} +\end{compactitem} -\begin{LTXexample}[width=\linewidth,pos=t] -\begin{pspicture}[showgrid](-4,-3.3)(4,3) -\psset{linewidth=2\pslinewidth} +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid](-3,-3)(3,3)\footnotesize +\psset{unit=0.65cm}\psset{dotscale=0.5}\psset{PointSymbol=*} \pstGeonode[PosAngle={0,-135,90},PointSymbol={*,*,square}](1,0){A}(-2,-1){B}(0,1){C} \pstCircleOA[linecolor=red]{A}{B} -\pstCircleOA[linecolor=green, DistCoef=2 3 div, Radius=\pstDistAB{A}{C}]{A}{} +\pstCircleOA[linecolor=green, Radius=\pstDistMul{A}{C}{2 3 div}]{A}{} \pstCircleOA[linecolor=blue, Radius=\pstDistAB{B}{C}]{A}{}[45][270] \pstCircleOA[linecolor=Sepia, Radius=\pstDistAB{A}{C}]{B}{} \pstCircleOA[linecolor=Aquamarine, Diameter=\pstDistAB{A}{C}]{B}{}[80][320] @@ -662,6 +1097,35 @@ We will see later how to draw the circle crossing three points. \end{pspicture} \end{LTXexample} +\vspace{10pt} + +The following example show how to use the more complex distance macros, +and the parameter to fill the circle. + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-3,-3)(3,3)\footnotesize +\psset{unit=0.65cm}\psset{dotscale=0.5}\psset{PointSymbol=*} +\pstGeonode[PosAngle=90,CurveType=polyline](0,0){A}(1,0){B} +\pstGeonode[PosAngle=90,CurveType=polyline](0,1){A'}(2,1){B'} +\pstCircleOA[linecolor=gray,Radius=\pstDistAdd{A}{B}{A'}{B'}]{A}{} +\pstCircleOA[linecolor=red,Radius=\pstDistAddVal{A}{B}{1.0}{\pstDistConst{0.5}}]{A}{} +\pstCircleOA[linecolor=blue,Radius=\pstDistAddCoef{A}{B}{0.5}{A'}{B'}{1.5}]{A}{} +\pstCircleOA[linecolor=green,Radius=\pstDistSub{A}{B}{A'}{B'}]{B'}{} +\pstCircleOA[linecolor=brown,Radius=\pstDistSubCoef{A}{B}{1.8}{A'}{B'}{0.5}]{A}{} +\pnode(-1.5,-2){D} +\pstCircleOA[linecolor=pink,fillstyle=solid,fillcolor=pink!40,Radius=\pstDistMul{A}{B}{0.8}]{D}{} +\psdot(D)\uput{0.2}[-45](D){$D$} +\pstCircleOA[linecolor=purple,Radius=\pstDistConst{\pstAbscissa{D}} abs]{D}{} +\end{pspicture} +\end{LTXexample} + +The last row set the absolute value of the abscissa of node $D$ to \Lkeyword{Radius}, +and then draw a circle at center $D$. Note that it does not work before v1.67, +as the \Lcs{pstCircleOA} and \Lcs{pstCircleAB} were implemented with a \Lcs{rput} command, +which will set the center $D$'s coordinate to origin, it causes that the Radius was set to zero +and none circle will be draw out, so we remove the \Lcs{rput} code in v1.67, +and everything works well now. + \subsection{Circle arcs} \begin{BDef} @@ -669,7 +1133,6 @@ We will see later how to draw the circle crossing three points. \Lcs{pstArcnOAB}\OptArgs\Largb{O}\Largb{A}\Largb{B} \end{BDef} - These two macros draw circle arcs, $O$ is the center, the radius defined by $OA$, the beginning angle given by $A$ and the final angle by $B$. Finally, the first macro draws the arc in the direct way, @@ -688,6 +1151,97 @@ two points are at the same distance of $O$. \end{pspicture} \end{LTXexample} +\subsection{Circle nodes} + +Do you want to draw a point on the circle? A point can be positioned on a circle +using its rotation angle by macro \Lcs{pstCircleNode} or \Lcs{pstCircleRotNode}. +The first \Lcs{pstCircleNode} requires an explicit parameter angle $\theta$ to calculate the point; +but the second \Lcs{pstCircleRotNode} requires an implicit parameter \Lkeyword{RotAngle} to calculate the point, +If you not set \Lkeyword{RotAngle}, the default value is $60^\circ$. + +The circle is defined by center $O$ and point $A$ on the circle or \Lkeyword{Radius} or \Lkeyword{Diameter} in parameter. + +\begin{BDef} +\Lcs{pstCircleNode}\OptArgs\Largb{O}\Largb{A}\Largb{$\theta$}\Largb{X}\\ +\Lcs{pstCircleRotNode}\OptArgs\Largb{O}\Largb{A}\Largb{X} +\end{BDef} + +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(4,4) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\psset{Radius=\pstDistVal{2.0}} +\pstGeonode[PosAngle=0](1.5,1.5){O} +\pstCircleOA[linecolor=red]{O}{} +\pstCircleRotNode[PosAngle=0,RotAngle=0]{O}{}{A} +\pstCircleRotNode[PosAngle=60]{O}{}{B} % default 60 degree +\pstCircleRotNode[PosAngle=90,RotAngle=90]{O}{}{C} +\pstCircleRotNode[PosAngle=150,RotAngle=\pscalculate{3*360/7}]{O}{}{D} +\pstCircleRotNode[PosAngle=180,RotAngle=180]{O}{}{E} +\pstCircleRotNode[PosAngle=230,RotAngle=230]{O}{}{F} +\pstCircleRotNode[PosAngle=270,RotAngle=270]{O}{}{G} +\pstCircleNode[PosAngle=-45]{O}{}{-45}{H} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +A point can be positioned on a circle using its absolute abscissa or ordinate too. +You can input $x_1$ or $y_1$ as any number(e.g, 2.0), or use \Lcs{pscalculate} or \Lcs{fpeval} to generate the value, +or use \Lcs{pstAbscissa} and \Lcs{pstOrdinate} to get the abscissa and ordinate of any other node. + +\begin{BDef} +\Lcs{pstCircleAbsNode}\OptArgs\Largb{O}\Largb{A}\Largb{$x_1$}\Largb{C}\Largb{D}\\ +\Lcs{pstCircleOrdNode}\OptArgs\Largb{O}\Largb{A}\Largb{$y_1$}\Largb{C}\Largb{D} +\end{BDef} + +for example, +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(4,4) +\pstGeonode[PosAngle=60](1.5,1.5){O} +\pstGeonode[PosAngle=-30](2.5,0){A} +\pstCircleOA[linecolor=red]{O}{A} +\pstCircleAbsNode[PosAngleA=-60,PosAngleB=60,PointSymbol=*]{O}{A}{1.0}{C}{D} +\pstCircleOrdNode[PosAngleA=150,PosAngleB=30,PointSymbol=*]{O}{A}{1.0}{E}{F} +\pstLineAB[linestyle=dashed,linecolor=gray!40,nodesep=-0.5]{C}{D} +\pstLineAB[linestyle=dashed,linecolor=gray!40,nodesep=-0.5]{E}{F} +\end{pspicture} +\end{LTXexample} + +\vspace{10pt} + +A point can be positioned on a circle using its curved abscissa, that is, +the arc length from a given node. + +\begin{BDef} +\Lcs{pstCurvAbsNode}\OptArgs\Largb{O}\Largb{A}\Largb{B}\Largb{Abs} +\end{BDef} + +\begin{sloppypar} +Possible optional arguments are \Lkeyword{PointSymbol}, \Lkeyword{PosAngle}, + \Lkeyword{PointName}, \Lkeyword{PointNameSep}, \Lkeyword{PtNameMath}, and \Lkeyword{CurvAbsNeg}. +% +The point \Argsans{$B$} is positioned on the circle of center +\Argsans{$O$} crossing \Argsans{$A$}, with the curved abscissa +\Argsans{Abs}. The origin is \Argsans{$A$} and the direction is +anti-clockwise by default. The parameter \Lkeyword{CurvAbsNeg} +\DefaultVal{false} can change this behavior. +\end{sloppypar} + +If the parameter \Lkeyword{PosAngle} is not specified, the point label is put +automatically in oirder to be alined with the circle center and the point. + +\begin{LTXexample}[width=5cm,pos=l] +\begin{pspicture}[showgrid](-2.5,-2.5)(2.5,2.5) +\pstGeonode{O}(2,0){A} +\pstCircleOA{O}{A} +\pstCurvAbsNode{O}{A}{M_1}{\pstDistVal{5}} +\pstCurvAbsNode[CurvAbsNeg=true]% + {O}{A}{M_2}{\pstDistAB{A}{M_1}} +\end{pspicture} +\end{LTXexample} + + + \subsection{Circle tangent} The macro \Lcs{pstCircleTangentLine} is used to draw a tangent line $AT$ from a point $A$ on the circle, @@ -756,85 +1310,84 @@ You also can use \Lkeyword{DiameterA} and \Lkeyword{DiameterB} to define the two \end{pspicture} \end{LTXexample} -\subsection{Curved abscissa} - -A point can be positioned on a circle using its curved abscissa. +\subsection{Circle radical axis} +If you want to draw the \texttt{Radical Axis} of two given circles, read the following sentenses. +For given $\odot{O_1}$ with radius $r_1$ and $\odot{O_2}$ with radius $r_2$, and the center +$O_1(x_1,y_1)$, $O_2(x_2,y_2)$, then any point $P(x,y)$ on the \texttt{Radical Axis} is satisfied: +$$(x-x_1)^2+(y-y_1)^2-r_1^2=(x-x_2)^2+(y-y_2)^2-r_2^2$$ +It can be simplified to a equation of a line: +$$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)$$ +It is clear that the circles with same center have no radical axis, +and the radical axis is perpendicular to the line of centers. +We provide the macro \Lcs{pstCircleRadicalAxis} to draw the \texttt{Radical Axis} of two given circles. +It can handler every position relations of circles such as separation, intersection and inclusion. \begin{BDef} -\Lcs{pstCurvAbsNode}\OptArgs\Largb{O}\Largb{A}\Largb{B}\Largb{Abs} +\Lcs{pstCircleRadicalAxis}\OptArgs\Largb{$O_1$}\Largb{A}\Largb{$O_2$}\Largb{B}\Largb{C}\Largb{D} \end{BDef} -\begin{sloppypar} -Possible optional arguments are \Lkeyword{PointSymbol}, \Lkeyword{PosAngle}, - \Lkeyword{PointName}, \Lkeyword{PointNameSep}, \Lkeyword{PtNameMath}, and \Lkeyword{CurvAbsNeg}. -% -The point \Argsans{$B$} is positioned on the circle of center -\Argsans{$O$} crossing \Argsans{$A$}, with the curved abscissa -\Argsans{Abs}. The origin is \Argsans{$A$} and the direction is -anti-clockwise by default. The parameter \Lkeyword{CurvAbsNeg} -\DefaultVal{false} can change this behavior. -\end{sloppypar} +Both parameter $A$ and $B$ can be omitted and then to specify the each radius or +diameter using the parameters \Lkeyword{RadiusA}, \Lkeyword{DiameterA}, and \Lkeyword{RadiusB}, \Lkeyword{DiameterB}. +This macro create two new nodes $C$ and $D$ on the radical axis, you can find them in following examples. -If the parameter \Lkeyword{PosAngle} is not specified, the point label is put -automatically in oirder to be alined with the circle center and the point. +When they are intersected, we can see the radical axis is the intersected chord line. -\begin{LTXexample}[width=5cm,pos=l] -\begin{pspicture}[showgrid](-2.5,-2.5)(2.5,2.5) -\pstGeonode{O}(2,0){A} -\pstCircleOA{O}{A} -\pstCurvAbsNode{O}{A}{M_1}{\pstDistVal{5}} -\pstCurvAbsNode[CurvAbsNeg=true]% - {O}{A}{M_2}{\pstDistAB{A}{M_1}} +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(4,4) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\def\ra{1.2}\def\rb{2.0} +\pstGeonode[PosAngle=0](0,1){O1}(1.5,1.5){O2} +\pstCircleOA[linecolor=red!50,Radius=\pstDistVal{\ra}]{O1}{} +\pstCircleOA[linecolor=blue!50,Radius=\pstDistVal{\rb}]{O2}{} +\pstCircleRadicalAxis[PosAngle={0,0},RadiusA=\pstDistVal{\ra},RadiusB=\pstDistVal{\rb},nodesep=-1,linecolor=brown]{O1}{}{O2}{}{A}{B} \end{pspicture} \end{LTXexample} +When they are tangent, we can see the radical axis is the common tangent line. -A point can be positioned on a circle using its absolute abscissa or ordinate too. -You can input $x_1$ or $y_1$ as any number(e.g, 2.0), or use \Lcs{pscalculate} or \Lcs{fpeval} to generate the value, -or use \Lcs{pstAbscissa} and \Lcs{pstOrdinate} to get the abscissa and ordinate of any other node. +\begin{LTXexample}[width=6cm,pos=l] +\begin{pspicture}[showgrid=true](-1,-1)(3,4) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\def\ra{1.2}\def\rb{2.0} +\pstGeonode[PosAngle=-90,PointName={O_1,O_2}](1,1){O1}(1,1.8){O2} +\pstCircleOA[linecolor=red!50,Radius=\pstDistVal{\ra}]{O1}{} +\pstCircleOA[linecolor=blue!50,Radius=\pstDistVal{\rb}]{O2}{} +\pstCircleRadicalAxis[nodesep=-2,PosAngle={-90,-90},RadiusA=\pstDistVal{\ra},RadiusB=\pstDistVal{\rb}]{O1}{}{O2}{}{A}{B} +\pstLineAB[linecolor=red,nodesep=-3]{A}{B} +\end{pspicture} +\end{LTXexample} -\begin{BDef} -\Lcs{pstCircleAbsNode}\OptArgs\Largb{O}\Largb{A}\Largb{$x_1$}\Largb{C}\Largb{C}\\ -\Lcs{pstCircleOrdNode}\OptArgs\Largb{O}\Largb{A}\Largb{$y_1$}\Largb{C}\Largb{C} -\end{BDef} +When one of them contains the other, the radical axis is out of the circles. -for example, \begin{LTXexample}[width=6cm,pos=l] -\begin{pspicture}[showgrid=true](-1,-1)(4,4) -\pstGeonode[PosAngle=60](1.5,1.5){O} -\pstGeonode[PosAngle=-30](2.5,0){A} -\pstCircleOA[linecolor=red]{O}{A} -\pstCircleAbsNode[PosAngleA=-60,PosAngleB=60,PointSymbol=*]{O}{A}{1.0}{C}{D} -\pstCircleOrdNode[PosAngleA=150,PosAngleB=30,PointSymbol=*]{O}{A}{1.0}{E}{F} -\pstLineAB[linestyle=dashed,linecolor=gray!40,nodesep=-0.5]{C}{D} -\pstLineAB[linestyle=dashed,linecolor=gray!40,nodesep=-0.5]{E}{F} +\begin{pspicture}[showgrid=true](-1,-2)(4,3) +\psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize +\def\ra{1.2}\def\rb{2.0} +\pstGeonode[PosAngle=0](1.2,1){O1}(1.5,1.5){O2} +\pstCircleOA[linecolor=red!50,Radius=\pstDistVal{\ra}]{O1}{} +\pstCircleOA[linecolor=blue!50,Radius=\pstDistVal{\rb}]{O2}{} +\pstCircleRadicalAxis[PosAngle={-90,90},RadiusA=\pstDistVal{\ra},RadiusB=\pstDistVal{\rb},nodesepA=-1,nodesepB=-3,linecolor=brown]{O1}{}{O2}{}{A}{B} \end{pspicture} \end{LTXexample} -A point can be positioned on a circle using its rotation angle by macro \Lcs{pstCircleRotNode}. -The rotation angle should be passed by the \Lkeyword{RotAngle} in the \texttt{Options}. -The circle is defined by center $O$ and point $A$ on the circle or \Lkeyword{Radius} in parameter. -If you not set \Lkeyword{RotAngle}, the default value is $60^\circ$. - -\begin{BDef} -\Lcs{pstCircleRotNode}\OptArgs\Largb{O}\Largb{A}\Largb{X} -\end{BDef} +When they are separated, the radical axis is between of the circles. \begin{LTXexample}[width=6cm,pos=l] -\begin{pspicture}[showgrid=true](-1,-1)(4,4) +\begin{pspicture}[showgrid=true](-1,-2)(4,3) \psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize -\psset{Radius=\pstDistVal{2.0}} -\pstGeonode[PosAngle=0](1.5,1.5){O} -\pstCircleOA[linecolor=red]{O}{} -\pstCircleRotNode[PosAngle=0,RotAngle=0]{O}{}{A} -\pstCircleRotNode[PosAngle=60]{O}{}{B} % default 60 degree -\pstCircleRotNode[PosAngle=90,RotAngle=90]{O}{}{C} -\pstCircleRotNode[PosAngle=150,RotAngle=\pscalculate{3*360/7}]{O}{}{D} -\pstCircleRotNode[PosAngle=180,RotAngle=180]{O}{}{E} -\pstCircleRotNode[PosAngle=230,RotAngle=230]{O}{}{F} -\pstCircleRotNode[PosAngle=270,RotAngle=270]{O}{}{G} -\pstCircleRotNode[PosAngle=-45,RotAngle=-45]{O}{}{H} +\def\ra{1.2}\def\rb{2.0} +\pstGeonode[PosAngle=0](-1,0){O1}(2.5,1.5){O2} +\pstCircleOA[linecolor=red!50,Radius=\pstDistVal{\ra}]{O1}{} +\pstCircleOA[linecolor=blue!50,Radius=\pstDistVal{\rb}]{O2}{} +\pstCircleRadicalAxis[PosAngle={-90,90},RadiusA=\pstDistVal{\ra},RadiusB=\pstDistVal{\rb},nodesep=-1,linecolor=brown]{O1}{}{O2}{}{A}{B} +\psset{linestyle=dashed,linecolor=gray!40} +\pstCircleTangentNode[Radius=\pstDistVal{\ra},PosAngle={90,200}]{O1}{}{A}{P}{Q} +\pstCircleTangentNode[Radius=\pstDistVal{\rb},PosAngle={10,100}]{O2}{}{A}{X}{Y} +\pstCircleOA{A}{P} +\pstCircleTangentNode[Radius=\pstDistVal{\ra},PosAngle={210,200}]{O1}{}{B}{I}{J} +\pstCircleTangentNode[Radius=\pstDistVal{\rb},PosAngle={10,-10}]{O2}{}{B}{R}{S} +\pstCircleOA{B}{I} \end{pspicture} \end{LTXexample} @@ -873,6 +1426,8 @@ used to modify the increment from a point to the next one \end{pspicture} \end{LTXexample} +\clearpage + \section{Conics} \subsection{Standard Ellipse} The Standard Ellipse $E$ with coordinate translation is defined by center $O(x_0,y_0)$, @@ -902,7 +1457,7 @@ the macro will draw the whole ellipse. \begin{LTXexample}[width=6cm,pos=l] \begin{pspicture}[showgrid=true](0,0)(4,4) \psset{dotscale=0.5}\psset{PointSymbol=*}\footnotesize -\def\ra{2.4}\def\rb{0.8}\def\rot{56} +\def\ra{2.4}\def\rb{0.8} \pstGeonode[PosAngle=-90,PointNameSep=0.2](2,2){O} %\psellipse[linecolor=red!60](O)(\ra,\rb) \pstEllipse[linecolor=red!60](O)(\ra,\rb)[0][120] @@ -1226,8 +1781,8 @@ Using macro \Lcs{pstGeneralEllipseFocusNode} to find the two focus nodes, and ma \Lcs{pstGeneralEllipseDirectrixLine} to get the two directrix lines. \begin{BDef} -\Lcs{pstGeneralEllipseFocusNode}\OptArgs\Largr{O}\Largr{$a,\,b$}\OptArg{$\theta$}\Largb{$t$}\Largb{A}\\ -\Lcs{pstGeneralEllipseDirectrixLine}\OptArgs\Largr{O}\Largr{$a,\,b$}\OptArg{$\theta$}\Largb{A} +\Lcs{pstGeneralEllipseFocusNode}\OptArgs\Largr{O}\Largr{$a,\,b$}\OptArg{$\theta$}\Largb{$t$}\Largb{$F_1$}\Largb{$F_2$}\\ +\Lcs{pstGeneralEllipseDirectrixLine}\OptArgs\Largr{O}\Largr{$a,\,b$}\OptArg{$\theta$}\Largb{$L_x$}\Largb{$L_y$}\Largb{$R_x$}\Largb{$R_y$} \end{BDef} for example, @@ -1303,8 +1858,6 @@ please refer to Theorem \ref{EllipseTangentPointTheorem}. \end{pspicture} \end{LTXexample} -\clearpage - \subsection{Standard Parabola} The Standard Parabola $P$ with coordinate translation is defined by vertex $O(x_0,y_0)$, the half of the focus chord axis $abs(p)$. @@ -1434,7 +1987,7 @@ If you don't know the focus $F$, or the directrix line, we will find them automa \pstParabolaFocusNode[linecolor=red!40](O){\p}{F} \pstLine[linecolor=gray!40,nodesepA=-0.8,nodesepB=-0.8]{0,2}{4,1} \pstParabolaLineInter[linecolor=gray!40,PosAngle={120,210}](O){\p}{0,2}{4,1}{P}{Q} -% if you know focus F, but don't known directrix line +% if you know focus F, but don't know directrix line \pstParabolaPolarNode[linecolor=purple!40,PosAngle=-90](O){\p}(F){P}{Q}{T} \end{pspicture} \end{LTXexample} @@ -2204,7 +2757,7 @@ The macro \Lcs{pstHyperbolaTangentNode} is used to find the tangent point $A$ an We use the following theorem to find the tangent points $A$ and $B$ of $T$: \begin{theorem}\label{HyperbolaTangentPointTheorem} Let $T$ is a point out of the hyperbola, for any two chords $TPQ$ and $TRS$ of the hyperbola, suppose $PR$ and $QS$ intersect at $X$, -$RQ$ and $PS$ intersect at $Y$, then the intersection point $A$ and $B$ of $XY$ and the hyperbola are the tangent points from $T$. +$RQ$ and $PS$ intersect at $Y$, then the intersection points $A$ and $B$ of $XY$ and the hyperbola are the tangent points from $T$. \end{theorem} \begin{LTXexample}[width=6cm,pos=l] @@ -2356,7 +2909,7 @@ The macro \Lcs{pstIHyperbolaTangentNode} is used to find the tangent point $A$ a \Lcs{pstIHyperbolaTangentNode}\OptArgs\Largr{O}\Largr{$a,\,b$}\Largb{$T$}\Largb{$A$}\Largb{$B$} \end{BDef} -We also use the following theorem \ref{HyperbolaTangentPointTheorem} to find the tangent points $A$ and $B$ of $T$. +We also use the theorem \ref{HyperbolaTangentPointTheorem} to find the tangent points $A$ and $B$ of $T$. \begin{LTXexample}[width=6cm,pos=l] \begin{pspicture}[showgrid=true](-2,-1)(4,3) @@ -2539,7 +3092,7 @@ The macro \Lcs{pstGeneralHyperbolaTangentNode} is used to find the tangent point \Lcs{pstGeneralHyperbolaTangentNode}\OptArgs\Largr{O}\Largr{$a,\,b$}\OptArg{$\theta$}\Largb{$T$}\Largb{$A$}\Largb{$B$} \end{BDef} -We also use the following theorem \ref{HyperbolaTangentPointTheorem} to find the tangent points $A$ and $B$ of $T$. +We also use the theorem \ref{HyperbolaTangentPointTheorem} to find the tangent points $A$ and $B$ of $T$. \begin{LTXexample}[width=6cm,pos=l] \begin{pspicture}[showgrid=true](-2,-1)(4,3) @@ -2725,7 +3278,7 @@ The macro \Lcs{pstGeneralIHyperbolaTangentNode} is used to find the tangent poin \Lcs{pstGeneralIHyperbolaTangentNode}\OptArgs\Largr{O}\Largr{$a,\,b$}\OptArg{$\theta$}\Largb{$T$}\Largb{$A$}\Largb{$B$} \end{BDef} -We also use the following theorem \ref{HyperbolaTangentPointTheorem} to find the tangent points $A$ and $B$ of $T$. +We also use the theorem \ref{HyperbolaTangentPointTheorem} to find the tangent points $A$ and $B$ of $T$. \begin{LTXexample}[width=6cm,pos=l] \begin{pspicture}[showgrid=true](-2,-1)(4,3) @@ -3204,8 +3757,8 @@ the circle of centre $O$ and with radius $OC$. The circle is specified with its center and either a point of its circumference or with a radius specified with parameter \Lkeyword{radius} or its diameter specified with parameter \Lkeyword{Diameter}. These two -parameters can be modify by coefficient \Lkeyword{DistCoef}. - +parameters can be specified by macros \Lcs{pstDist},\Lcs{pstDistMul},\Lcs{pstDistAdd}, +\Lcs{pstDistSub} etc. The position of the wo points is such that the vectors $\vec{AB}$ abd $\vec{M_1M_2}$ are in the same direction. Thus, if the points @@ -3222,9 +3775,9 @@ at the center of the circle. \pstCircleOA[linecolor=red]{O}{A} \pstInterLC[PosAngle=-80]{C}{B}{O}{A}{D}{E} \pstInterLC[PosAngleB=60, Radius=\pstDistAB{O}{D}]{I}{C}{O}{}{F}{G} -\pstInterLC[PosAngleB=180,DistCoef=1.3,Diameter=\pstDistAB{O}{D}] +\pstInterLC[PosAngleB=180,Diameter=\pstDistMul{O}{D}{1.3}] {I}{B}{O}{}{H}{J} -\pstCircleOA[linecolor=red,DistCoef=1.3,Diameter=\pstDistAB{O}{D}]{O}{} +\pstCircleOA[linecolor=red,Diameter=\pstDistMul{O}{D}{1.3}]{O}{} \psset{nodesep=-1} \pstLineAB[linecolor=green]{E}{C} \pstLineAB[linecolor=cyan]{I}{C} @@ -3269,21 +3822,27 @@ specification using radius and diameter. For such specifications it exists the parameters \Lkeyword{RadiusA}, \Lkeyword{RadiusB}, \Lkeyword{DiameterA} and \Lkeyword{DiameterB}. +The macro \Lcs{pstInterCC} will not display the intersections as default, if you want to display +the label or symbol of the intersections, you must setup the parameters \Lkeyword{PosAngleA} +and \Lkeyword{PosAngleB} to change the default behavior. + \begin{LTXexample} \begin{pspicture}[showgrid](-3,-4)(7,3) \pstGeonode[PointName={\Omega,O}](3,-1){Omega}(1,-1){O} \pstGeonode[PointSymbol=square, PosAngle={-90,90}](0,3){A}(2,2){B} \psset{PointSymbol=o} -\pstCircleOA[linecolor=red, DistCoef=1 3 10 div add, Radius=\pstDistAB{A}{B}]{O}{} +\pstCircleOA[linecolor=red, Radius=\pstDistMul{A}{B}{1 3 10 div add}]{O}{} \pstCircleOA[linecolor=Orange, Diameter=\pstDistAB{A}{B}]{O}{} \pstCircleOA[linecolor=Violet, Radius=\pstDistAB{A}{B}]{Omega}{} \pstCircleOA[linecolor=Purple, Diameter=\pstDistAB{A}{B}]{Omega}{} -\pstInterCC[DistCoef=1 3 10 div add, RadiusA=\pstDistAB{A}{B}, - DistCoef=none, RadiusB=\pstDistAB{A}{B}]{O}{}{Omega}{}{D}{E} -\pstInterCC[DiameterA=\pstDistAB{A}{B}, RadiusB=\pstDistAB{A}{B}]{O}{}{Omega}{}{F}{G} -\pstInterCC[DistCoef=1 3 10 div add, RadiusA=\pstDistAB{A}{B}, - DistCoef=none, DiameterB=\pstDistAB{A}{B}]{O}{}{Omega}{}{H}{I} -\pstInterCC[DiameterA=\pstDistAB{A}{B}, DiameterB=\pstDistAB{A}{B}]{O}{}{Omega}{}{J}{K} +\pstInterCC[RadiusA=\pstDistMul{A}{B}{1 3 10 div add}, + RadiusB=\pstDistAB{A}{B}]{O}{}{Omega}{}{D}{E} +\pstInterCC[DiameterA=\pstDistAB{A}{B}, RadiusB=\pstDistAB{A}{B}, + PosAngleA=90,PosAngleB=-90]{O}{}{Omega}{}{F}{G} +\pstInterCC[RadiusA=\pstDistMul{A}{B}{1 3 10 div add}, DiameterB=\pstDistAB{A}{B}, + PosAngleA=90,PosAngleB=-90]{O}{}{Omega}{}{H}{I} +\pstInterCC[DiameterA=\pstDistAB{A}{B}, DiameterB=\pstDistAB{A}{B}, + PosAngleA=90,PosAngleB=-90]{O}{}{Omega}{}{J}{K} \end{pspicture} \end{LTXexample} 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. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |