drawing two curved arrows with ellipse between them

how can I draw two curved arrows with two ellipses between them like attached image?

To get a better result, the major axes of the ellipse must be normal to both curves. Here I used Mathematica to find numerically the coordinates.

F[x_] := x^3/4 + 1;
G[x_] := (x - 1/2)^3/5 + 1/6;
Plot[{F[x], G[x]}, {x, -2, 4}]
Solve[{F'[a] == G'[b], F'[a] == (b - a)/(F[a] - G[b])}, {a, b}] // N


Maximal Working Example

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

\def\f{x^3/4+1}
\def\g{(x-1/2)^3/5+1/6}

\psset
{
algebraic,
saveNodeCoors,
NodeCoorPrefix=N,
PointName=none,
PointSymbol=none,
}

\def\Ellipse(#1,#2){%
\pstGeonode(*#1 {\f}){F}(*#2 {\g}){G}
\pstMiddleAB{F}{G}{H}
\pcline[nodesep=-.5,linecolor=ForestGreen!50](F)(G)% you can comment this line to remove the normal line
\psellipse[rot={!NGy NFy sub NGx NFx sub atan}](H)(!NGy NFy sub 2 exp NGx NFx sub 2 exp add sqrt 2 div dup 4 div)
}

\begin{document}
\begin{pspicture}[showgrid=true](-2,-1)(5,9)
\begingroup
\psset{arrows=->,linecolor=NavyBlue}
\psplot{-1.8}{3.15}{\f}
\psplot{-1.3}{4.0}{\g}
\endgroup
\Ellipse(-0.798555,-0.392812)
\Ellipse(0.221492,0.252365)
\Ellipse(1.01476,1.63454)
\Ellipse(2.86997,3.70873)
\end{pspicture}
\end{document}


Final Release

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

\def\f{x^3/4+1}
\def\g{(x-1/2)^3/5+1/6}

\psset
{
algebraic,
saveNodeCoors,
NodeCoorPrefix=N,
PointName=none,
PointSymbol=none,
}

\def\Ellipse(#1,#2){%
\pstGeonode(*#1 {\f}){F}(*#2 {\g}){G}
\pstMiddleAB{F}{G}{H}
\psellipse[rot={!NGy NFy sub NGx NFx sub atan}](H)(!NGy NFy sub 2 exp NGx NFx sub 2 exp add sqrt 2 div dup 3 div)
}

\begin{document}
\begin{pspicture}[showgrid=false](-2,-1)(4,8)
\begingroup
\psplot{-1.8}{3.0}{\f}
\psplot{-1.0}{3.85}{\g}
\endgroup
\psset{opacity=0.5}
\begingroup
\psset{fillstyle=solid,fillcolor=Cyan}
\Ellipse(-0.798555,-0.392812)
\endgroup
\uput[90](F){$\textrm{d}S_1$}
\begingroup
\psset{fillstyle=solid,fillcolor=ForestGreen}
\Ellipse(0.221492,0.252365)
\endgroup
\uput[90](F){$\textrm{d}S_2$}
\begingroup
\psset{fillstyle=solid,fillcolor=Orange}
\Ellipse(1.01476,1.63454)
\endgroup
\uput{6pt}[45](H){$\textrm{d}S_3$}
\begingroup
\psset{fillstyle=solid,fillcolor=Maroon}
\Ellipse(2.86997,3.70873)
\endgroup
\uput{6pt}[90](H){$\textrm{d}S_4$}
\end{pspicture}
\end{document}


• It is also possible with TikZ I think. Jul 28 '14 at 9:22
• This condition is not always possible for all points on a curve. Consider, for example, two straight non-parallel lines: no ellipses then? Jul 28 '14 at 14:09
• @g.kov: Yes. Of course. It had been taken into account. Jul 28 '14 at 14:51

This an attempt with tikz skills --- \draw let ... in ... command.

1. The tube is constructed via 2 segements(blue and red) through [bend left] and [bend right] curves.
2. Use pos=xx to determined the ellipse contact points, which is labelled as (a) and (b) respectively, then compute the distance to determine the long radius, the short one is 0.3 times the longer one.
3. Need to find the rotation angle via atan2
4. Two macros are defined, taking two postition arguments to set the (a) and (b) points. Basically these two macros are the same, except for different segment.

Code

\documentclass[2cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,arrows,calc}

\begin{document}
\newcommand{\ellpsA}[2]{
\draw[->,>=stealth] (0,0) to[bend left]node[pos=#1](a){} (2,2) to[bend right](4,4);
\draw[->,>=stealth] (1,0) to[bend left]node[pos=#2](b){} (2,1) to[bend right] (5,3);
\path (a) --node[midway](centeri){} (b);
\draw[blue] let \p1=($(a)-(b)$),             % find distance
\n2={atan2(\x1,\y1)}         % find rotation angle
in
[rotate=\n2] (centeri) ellipse (\n1 and \n1*0.3);
}

\newcommand{\ellpsB}[2]{
\draw[->,>=stealth] (0,0) to[bend left] (2,2) to[bend right]node[pos=#1](a){}(4,4);
\draw[->,>=stealth] (1,0) to[bend left] (2,1) to[bend right]node[pos=#2](b){} (5,3);
\path (a) --node[midway](centerii){} (b);
\draw[red] let \p1=($(a)-(b)$),
\n1={veclen(\x1,\y1)*0.5},
\n2={atan2(\x1,\y1)}
in
[rotate=\n2] (centerii) ellipse (\n1 and \n1*0.3);
}
\begin{tikzpicture}

% On first segment A

\ellpsA{0}{0}
\ellpsA{0.5}{0.5}
\ellpsA{0.99}{0.99}

% On second segment B

\ellpsB{0.01}{0.01}
\ellpsB{0.3}{0.5}
\ellpsB{1}{1}

\end{tikzpicture}
\end{document}

• Even though it is not a requirement, I think that your major axes are not always normal to both curves. :-) Jul 28 '14 at 7:56
• @Pleasedon'ttouch -- you are good, thanks. I would say pos=xx needs some fine tuned to achieve that, but theoretically you are correct. Jul 28 '14 at 8:06

Asymptote MWE

The endpoints p and q are defined as points on the bottom and top curve located at a fraction of the total curve length (arclength) along the curve, then the function drawEll is used to transform the unitcircle in order to place it between p and q. el.asy:

import graph; import fontsize;
size(6cm);

defaultpen(fontsize(9pt));
pen linepen=deepblue+1bp;
pen elpen=orange+0.6bp;

texpreamble("\usepackage{lmodern}");

pair[] pbot={(23,8),(108,70),(146,81),(194,83),(269,118),(316,174),};
pair[] ptop={(10,33),(88,107),(130,125),(178,136),(241,184),(278,242),};

guide gtop, gbot;

for(int i=0;i<ptop.length;++i){
gtop=gtop..ptop[i];
gbot=gbot..pbot[i];
}

void drawEll(pair p, pair q, pen fillpen, pen drawpen){ // draws an ellipse between p and q
real a=abs(p-q), fr=0.382;
path el=shift(p+(q-p)/2)*rotate(degrees(dir(q-p)))*scale(a/2,a*fr/2)*unitcircle;
filldraw(el,fillpen, drawpen);
}

draw(gtop,linepen,arr);
draw(gbot,linepen,arr);

real[] pathfrac={0, 0.318, 0.682, 0.9}; // fractions of the curve length
//    to locate points
pair p; // point on the bottom curve
pair q; // point on the top curve

pen[] fillpen={lightred, lightgreen, lightblue};
pen[] drawpen={deepred, deepgreen, deepblue};

for(int i=0;i<pathfrac.length;++i){
p=relpoint(gbot,pathfrac[i]);
q=relpoint(gtop,pathfrac[i]);
drawEll(p,q,fillpen[i%fillpen.length],drawpen[i%drawpen.length]);
label("$dS_{"+string(i)+"}$",q,NW);
}


To get el.pdf run asy -f pdf el.asy .

Run with xelatex or latex->dvips->ps2pdf. Needs an up-to-date version of pstricks.tex. It knows \psellipseAB which simplifies things for the user:

\documentclass[border=10pt,pstricks]{standalone}
\usepackage{pst-node}
\begin{document}

\begin{pspicture}[showgrid=false](7,7)%% showgrid=true
\pnodes{a}(1,0)(2.3,2)(5.2,2.5)(6.25,3)(7,5)
\pnodes{b}(0,1)(1.7,3)(4.75,4)(5.5,5)(6,7)
\pscurve[arrowscale=2,linewidth=1.2pt]{->}(a0)(a1)(a2)(a3)(a4)
\pscurve[arrowscale=2,linewidth=1.2pt]{->}(b0)(b1)(b2)(b3)(b4)
\psellipseAB(a0)(b0){0.1}
\psellipseAB[fillcolor=red!40,fillstyle=solid](a1)(b1){0.15}
\psellipseAB(a2)(b2){0.2}
\psellipseAB[fillcolor=blue!40,fillstyle=solid](a3)(b3){0.25}
\uput[135](b1){$dS_1$}\uput[135](b2){$dS_2$}
\end{pspicture}

\end{document}


Here's a simple approach in plain Metapost using the convenient direction .. of .. construction.

To get an ellipse I've used fullcircle xscaled xx yscaled yy, and I've exploited the fact that there are 8 points on its path (with point 0 at 3 o'clock and point 4 at 9 o'clock). I have defined four ellipses, but two of them are left invisible.

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);

u := 1mm;

path ds[];
ds1 = fullcircle xscaled 5u yscaled u rotated -50;
ds2 = ds1 scaled 1.4 rotated -5 shifted (20u,9u);
ds0 = ds1 scaled 0.9 shifted (-10u,-10u);
ds3 = ds1 scaled 1.5 rotated 10 shifted (32u,28u);

% draw only the two we want visible
draw ds1; draw ds2;

% draw arrows tangent to extremes of the ellipses
drawarrow point 0 of ds0 for i=1 upto 3: .. { direction 0 of ds[i] } point 0 of ds[i] endfor;
drawarrow point 4 of ds0 for i=1 upto 3: .. { direction 0 of ds[i] } point 4 of ds[i] endfor;

label.ulft(btex $dS_1$ etex, point 4 of ds1);
label.ulft(btex $dS_2$ etex, point 4 of ds2);

endfig;
end.