# How to draw smooth curves with PSTricks?

Consider the following example:

\documentclass{article}

\begin{document}

\begin{pspicture}(0,-0.25)(4,6.25)
\pnode(2,0){A}
\pnode(0,4){B}
\pnode(2,6){C}
\pnode(4,4){D}
\rput(1.5,3.5){\small{$A$}}
\rput(1.5,4.5){\small{$B$}}
\rput(2.5,4.5){\small{$C$}}
\rput(2.5,3.5){\small{$D$}}
\multido{\iA=0+1}{7}{\psline[linestyle=dashed,linecolor=blue](0,\iA)(4,\iA)}
\multido{\iB=0+1}{5}{\psline[linestyle=dashed,linecolor=blue](\iB,0)(\iB,6)}
\psline[linewidth=1.25pt](A)(C)
\psline[linewidth=1.25pt](B)(D)
\pspolygon[linewidth=2pt,linecolor=red](A)(B)(C)(D)
\pscurve[linewidth=1pt]{->}(2.75,4.75)(2.8,5.25)(2.65,5.75)(2,6.25)(1.25,6)(0.75,5.25)
\pscurve[linewidth=1pt]{->}(2.5,2.5)(2.95,1)(2.65,0.2)(2,-0.25)(1,0)(0.5,1.5)
\end{pspicture}

\end{document}


How do I make the curved arrows smooth?

I guess the \psbezier function is the way to do it but I cannot make it look nice, so help will be much appreciated.

Update

In case someone finds the figure useful, here is a generalization of the code:

\documentclass[a4paper]{article}

\usepackage[hmargin=2.4cm,vmargin=3cm]{geometry}
\usepackage{subcaption}
\usepackage{expl3}

\ExplSyntaxOn
\cs_new_eq:NN
\calculate
\fp_eval:n
\ExplSyntaxOff

\newcommand*{\betegn}[3]{%
\rput(!#1 4 div \figur\space mul #2 4 div \figur\space mul){\small{$#3$}}
}

\begin{document}

\begin{figure}[htbp]
% Figure number.
\def\figur{2}
% Constants.
\def\hoejde{\calculate{3*\figur}}
\def\bredde{\calculate{2*\figur}}
\def\faktorA{\calculate{\hoejde+1}}
\def\faktorB{\calculate{\bredde+1}}
\def\faktorC{\calculate{\hoejde-1}}
\def\faktorD{\calculate{\figur-1}}
\def\skalering{\calculate{2.5/\figur}}
\centering
\psset{
unit=\skalering
}
\begin{subfigure}{0.58\textwidth}
\centering
\begin{pspicture}(\bredde,\hoejde)
\pnode(!\figur\space 0){A}
\pnode(!0 \bredde\space){B}
\pnode(!\figur\space \hoejde\space){C}
\pnode(!\bredde\space \bredde\space){D}
\betegn{3}{7}{A}
\betegn{3}{9}{B}
\betegn{5}{9}{C}
\betegn{5}{7}{D}
\psset{
linestyle=dashed,
linecolor=blue
}
\multido{\iA=0+1}{\faktorA}{\psline(0,\iA)(\bredde\space,\iA)}
\multido{\iB=0+1}{\faktorB}{\psline(\iB,0)(\iB,\hoejde\space)}
\psset{
linewidth=1.25pt,
linestyle=solid,
linecolor=black
}
\psline(A)(C)
\psline(B)(D)
\pspolygon[linewidth=2pt,linecolor=red](A)(B)(C)(D)
\end{pspicture}
\subcaption{Before the rearrangement.}
\end{subfigure}
\begin{subfigure}{0.38\textwidth}
\centering
\begin{pspicture}(\figur,\hoejde)
\pnode(0,0){A}
\pnode(!0 \bredde\space){B}
\pnode(!0 \hoejde\space){C}
\pnode(!\figur\space \hoejde\space){D}
\pnode(!\figur\space \bredde\space){E}
\pnode(!\figur\space 0){F}
\betegn{3}{7}{A}
\betegn{3}{9}{B}
\betegn{1}{11}{C}
\betegn{1}{1}{D}
\psset{
linestyle=dashed,
linecolor=blue
}
\multido{\iC=1+1}{\faktorC}{\psline(0,\iC)(\figur\space,\iC)}
\multido{\iD=1+1}{\faktorD}{\psline(\iD,0)(\iD,\hoejde\space)}
\psset{
linewidth=1.25pt,
linestyle=solid,
linecolor=black
}
\pspolygon(A)(C)(D)(F)
\psline(B)(E)
\psline[linewidth=2pt,linecolor=red](F)(B)(D)
\end{pspicture}
\subcaption{After the rearrangement.}
\end{subfigure}
\caption{Figure~$\figur$.}
\end{figure}

\end{document}


All you have to do is change the value of \figur.

The document can be compiled with pdflatex -shell-escape filename.tex.

• You can try psecurve Commented Feb 17, 2013 at 18:01
• That is what I have already done but the curve is not very smooth. Commented Feb 17, 2013 at 18:03
• use the ncurv parameter setting.
– user2478
Commented Feb 17, 2013 at 18:48
• @Herbert Would you mind showing me how to apply this to change the shape of the curves? I cannot see any difference when I use this, unfortunately. Is it because I have too many control points and the differences are then too small to notice? Commented Feb 17, 2013 at 19:09
• sorry, I meant curvature. But it is better to use splines. See my answer.
– user2478
Commented Feb 17, 2013 at 21:22

You can use the package \pst-bezier which gives you a nicer bezier function \psbcurve. This package also allows various modifiers that help you tweak the curve. The only problem with this approach is that arrows don't work.

\documentclass{article}

\usepackage{pst-bezier}

\begin{document}

\begin{pspicture}[showgrid=true](0,-0.25)(4,6.25)
\pnode(2,0){A}
\pnode(0,4){B}
\pnode(2,6){C}
\pnode(4,4){D}
\pnode(2,4){E}
\rput(1.5,3.5){\small{$A$}}
\rput(1.5,4.5){\small{$B$}}
\rput(2.5,4.5){\small{$C$}}
\rput(2.5,3.5){\small{$D$}}
% \multido{\iA=0+1}{7}{\psline[linestyle=dashed,linecolor=blue](0,\iA)(4,\iA)}
% \multido{\iB=0+1}{5}{\psline[linestyle=dashed,linecolor=blue](\iB,0)(\iB,6)}
\psline[linewidth=1.25pt](A)(C)
\psline[linewidth=1.25pt](B)(D)
\pspolygon[linewidth=2pt,linecolor=red](A)(B)(C)(D)
\pscurve[linecolor=blue,linewidth=1pt]{->}(2.75,4.75)(2.8,5.25)(2.65,5.75)(2,6.25)(1.25,6)(0.75,5.25)
\pscurve[linecolor=blue,linewidth=1pt]{->}(2.5,2.5)(2.95,1)(2.65,0.2)(2,-0.25)(1,0)(0.5,1.5)

\psset{showpoints=false,linecolor=red,linewidth=2pt,arrows=->,arrowscale=1.5}
\psbcurve(2.75,4.75)(2.5,6)(1.5,6.5)(0.75,5.25)
\psbcurve(2.5,2.5)(3,0.5)(1,0)(0.5,1.5)

\end{pspicture}

\end{document}


I've superimposed my bezier curves (red) on your curves (blue).

# Arrows

To get the arrows, you'll have to do a tad more work....

The lines passing through the end points and the first and last control interpolation will be tangent to the curve. If you can figure out the value of those interpolation points, you can create arrows by doing something like:

\ncnode[nodesepA=<value>,arrows=->]{interpolation_point}{end_point}


You'll have to create nodes to do this. If you set showpoints=true that can help with guessing where to define the node for the interpolation point. In fact, you don't really have to get the interpolation point, you just need to get a point that will match the curve formed by the last interpolation point and the end point of the curve.

After a bit of tweaking (using the show lines feature)

  \pnode(0.50,0){interpolationA}
\pnode(0.5,1.5){endpointA}
\ncline[nodesepA=4em,nodesepB=-0.1]{interpolationA}{endpointA}


Resulting in:

You can do something similar for the other side.

\documentclass{article}
\usepackage{pst-node}
\usepackage{pst-bezier}
\pagestyle{empty}
\begin{document}

\begin{pspicture}[showgrid=true](0,-0.25)(4,6.25)
\pnode(2,0){A}
\pnode(0,4){B}
\pnode(2,6){C}
\pnode(4,4){D}
\pnode(2,4){E}
\rput(1.5,3.5){\small{$A$}}
\rput(1.5,4.5){\small{$B$}}
\rput(2.5,4.5){\small{$C$}}
\rput(2.5,3.5){\small{$D$}}
% \multido{\iA=0+1}{7}{\psline[linestyle=dashed,linecolor=blue](0,\iA)(4,\iA)}
% \multido{\iB=0+1}{5}{\psline[linestyle=dashed,linecolor=blue](\iB,0)(\iB,6)}
\psline[linewidth=1.25pt](A)(C)
\psline[linewidth=1.25pt](B)(D)
\pspolygon[linewidth=2pt,linecolor=red](A)(B)(C)(D)
% \pscurve[linecolor=blue,linewidth=1pt]{->}(2.75,4.75)(2.8,5.25)(2.65,5.75)(2,6.25)(1.25,6)(0.75,5.25)
% \pscurve[linecolor=blue,linewidth=1pt]{->}(2.5,2.5)(2.95,1)(2.65,0.2)(2,-0.25)(1,0)(0.5,1.5)

\psset{showpoints=false,linecolor=red,linewidth=2pt,arrows=->,arrowscale=1.5}
\psbcurve(2.75,4.75)(2.5,6)(1.5,6.5)(0.75,5.25)
\psbcurve(2.5,2.5)(3,0.5)(1,0)(0.5,1.5)

\pnode(0.50,0){interpolationA}
\pnode(0.5,1.5){endpointA}
\ncline[nodesepA=4em,nodesepB=-0.1]{interpolationA}{endpointA}

%\psset{linecolor=black}
\pnode(1.15,6.5){interpolationB}
\pnode(0.75,5.25){endpointB}
\ncline[nodesepA=4em,nodesepB=-0.2]{interpolationB}{endpointB}

\end{pspicture}

\end{document}


Notice that I tweak both ends of the curve with nodesepA and nodesepB.

• It looks like this is a good choice but I have a few problems: (1) How do I get arrows? (I can only get curves without an arrowhead at the end.) (2) The curve doesn't look nice at all if I replace \pscurve by \psbezier. I would much appreciate it if someone would show me how to draw the curved arrow. Commented Feb 17, 2013 at 18:17

The only way to get a better shape is by adjusting the points. Turn on showpoints to make us easily adjust the points.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-eucl}

{
gridcolor=blue!50,
griddots=10,
gridlabels=0pt,
}

\begin{document}
\begin{pspicture}(0,-0.25)(4,6.25)
\pstGeonode[PointName=none,PointSymbol=none]
(2,0){A}
(0,4){B}
(2,6){C}
(4,4){D}
%(2,4){E} <-- I don't know why the questioner defined this unused node.
\rput(1.5,3.5){\small{$A$}}
\rput(1.5,4.5){\small{$B$}}
\rput(2.5,4.5){\small{$C$}}
\rput(2.5,3.5){\small{$D$}}
\psgrid[style=gridstyle](0,0)(0,0)(4,6)
\psset{linewidth=1.25pt}
\psline(A)(C)
\psline(B)(D)
\pspolygon[linewidth=2pt,linecolor=red](A)(B)(C)(D)
\psset{linewidth=1pt,arrows=->,showpoints}
\pscurve(2.75,4.75)(2.8,5.25)(2.65,5.75)(2,6.25)(1.25,6)(0.75,5.25)
\pscurve(2.5,2.5)(2.95,1)(2.65,0.2)(2,-0.25)(1,0)(0.5,1.5)
\end{pspicture}
\end{document}

• Thanks! This is a nice answer, so I would accept this if I hadn't already accepted the other one. Commented Feb 17, 2013 at 18:41
• Note: the grid in PSTricks has no linestyle option so I hope someday this option will be available. Commented Feb 17, 2013 at 18:54
• Unfortunately not. That was why I drew the grid with \multido and \psline with the appropriate options. Commented Feb 17, 2013 at 19:11
• Using Geogebra to interactively obtain the points seems to be a good idea, doesn't it? Commented Feb 17, 2013 at 20:03
• It might very well. :) I have only used GeoGebra very few times and it is a rather long time ago. P.S. I forgot to remove the node E, which I used for something at as earlier stage. Commented Feb 17, 2013 at 20:20

with package pst-bspline

 \psBspline[linewidth=1pt,arrows=->]{A}(2.75,4.75)(2.8,5.25)(2.65,5.75)(2,6.25)(1.25,6)(0.75,5.25)
\psBspline[linewidth=1pt,arrows=->]{B}(2.5,2.5)(2.95,1)(2.65,0.2)(2,-0.25)(1,0)(0.5,1.5)

• This is definitely the way to do it. Thank you. Commented Feb 17, 2013 at 21:29