I want to achieve a very similar thing like in this post Line tangent to a a curve (using plot or controls), starting at a point. But I need a more simple solution. I can create a first tangent curve by connecting three points. That's enough for my purpose (visual judgement).

Is there a way to 'shift' the gray curve and make it hit the red line as a tangent? Maybe with some intersection package? I don't want to calculate further points of intersection by hand.

    % Axis and coordinates
    \coordinate (y) at (0,6);
    \coordinate (o) at (0,0);
    \coordinate (x) at (6,0);
    \draw[<->,line width=1.5pt] (y) node[above]{$C_{t+1}$} -- (o) -- (x) node[below,yshift=-2mm]{$C_t$};

        \draw[thick, blue] (0,5) -- (5,0);
        \draw[dash pattern=on 6pt off 3pt,thick, red] (0,2.5) -- (5,0);
        \draw[dash pattern=on 6pt off 3pt,thick, green] (0,3.5) -- (3.5,0);

        \filldraw [black] (3,2) circle (2pt) node[right]{A};
        \coordinate (A) at (3,2);

        \filldraw [black] (1.5,4) circle (2pt);
        \filldraw [black] (5,0.5) circle (2pt);
        \coordinate (ul) at (1.5,4);
        \coordinate (ur) at (5,0.5);

        \draw [ultra thick,gray] (ul) to[out=-60,in=133] (A) to[out=90-133,in=152] (ur);

enter image description here

PS: I know the system is atm relative small to illustrate the tangent point anyway. I may adjust overall size to 8 units later. Thank you very much, Mac.

Update: There is a small but crucial mistake in my request ^.° of course I need more than a y-shift but a parallel curve, with identical perpendicular distance.

Update 2: To make matters worse, both suggested solutions give a good solution to my conrecte example diagram. But it's hard (for me) to modify them in order to show different aspects. I need another version of a tangent condition (of the same parallel curves) in which there a curve which both tangents the red and the green line.

Maybe it would be a better idea to start with the lower curve, constructing it from two given point on the red/green line?

enter image description here

  • The question is what do you want to NOT shift? What sort of constraints are there on the tangent curve? Oct 30, 2015 at 16:50
  • I added a new picture (just paint-edited). All other things being equal, I like a second identical gray curve, somehow downwards shifted, to hit the dashed red line. Regards
    – Mac
    Oct 30, 2015 at 16:54
  • Looks like the savings/consumption decision! If I'm right, than the gray lines are utility curves…Why do want them to be shifted copies of each other? That would be a very special case, most standard consumption theory wouldn't give you curves like that. I made the graph before for my own teaching; I can post my code, but it doesn't have shifted curves, so I'm not sure whether it would be what you're looking for.
    – Matthijs
    Oct 31, 2015 at 16:58
  • @Matthijs they're rather supposed to be utility-levels, so called indifference curves, which have to be parallel (to keep it simple). But the context is right; though I'm looking for a way to apply copying and shifting of elements to more different areas (diagrams).
    – Mac
    Nov 1, 2015 at 13:28
  • Note that a "parallel curve" will, in general, have different form from the original. See math.stackexchange.com/a/61185/455 for examples of parallels to parabolas; these parallel curves are not, themselves, parabolas. Is this what you want? Nov 1, 2015 at 17:06

4 Answers 4


The following may need some fine tuning, and also relies on you not needing exactly those coordinates for ul and ur.

So what I do is, instead of drawing the grey lines with a to[in=...,out=...], I draw a circular arc. Well, actually two. To avoid having to calculate the start of the arc, I draw two arcs starting in A, using (A) arc[start angle=225,delta angle=20,radius=9cm]; The start angle is due to the fact that the blue line has an angle of 45 degrees with the horizontal. The delta angle decides how far to draw the line, and I draw one with a positive delta angle, one with a negative. The radius is just trial and error.

The second arc is drawn mostly the same way, but with a slightly different delta angle on one side, and a larger radius, so the arcs are from concentric circles. The starting point is shifted by a certain distance (0.41cm - trial and error) away from A in a direction of 225 degrees, and this distance is the same as the difference in radius.

enter image description here


% Axis and coordinates
\coordinate (y) at (0,6);
\coordinate (o) at (0,0);
\coordinate (x) at (6,0);
\draw[<->,line width=1.5pt] (y) node[above]{$C_{t+1}$} -- (o) -- (x) node[below,yshift=-2mm]{$C_t$};
\draw[thick, blue] (0,5) -- (5,0);
\draw[dash pattern=on 6pt off 3pt,thick, red] (0,2.5) -- (5,0);
\draw[dash pattern=on 6pt off 3pt,thick, green] (0,3.5) -- (3.5,0);
\filldraw [black] (3,2)   coordinate[label=right:A] (A) circle[radius=2pt];

\pgfmathsetlengthmacro{\radB}{\radA + \RadOffset}
\draw [ultra thick,gray] (A)
  arc[start angle=225,delta angle=-15,radius=\radA] coordinate (ul)
  arc[start angle=225,delta angle=15,radius=\radA] coordinate (ur);

\fill (ul) circle[radius=2pt] (ur) circle[radius=2pt];

\draw [ultra thick,gray] (A) ++(225:\RadOffset) arc[start angle=225,delta angle=-15,radius=\radB]  (A)++(225:\RadOffset) arc[start angle=225,delta angle=20,radius=\radB];

Old answer

You can always add [yshift=-0.5cm] at the start of each of the coordinates, e.g. ([yshift=-0.5cm]ur). To shift both horizontally and vertically use e.g. ([shift={(x,y)}]ur)

enter image description here


% Axis and coordinates
\coordinate (y) at (0,6);
\coordinate (o) at (0,0);
\coordinate (x) at (6,0);
\draw[<->,line width=1.5pt] (y) node[above]{$C_{t+1}$} -- (o) -- (x) node[below,yshift=-2mm]{$C_t$};
\draw[thick, blue] (0,5) -- (5,0);
\draw[dash pattern=on 6pt off 3pt,thick, red] (0,2.5) -- (5,0);
\draw[dash pattern=on 6pt off 3pt,thick, green] (0,3.5) -- (3.5,0);
\filldraw [black] (3,2)   coordinate[label=right:A] (A);
\filldraw [black] (1.5,4) coordinate (ul) circle[radius=2pt];
\filldraw [black] (5,0.5) coordinate (ur) circle[radius=2pt];

\draw [ultra thick,gray] (ul) to[out=-60,in=133] (A) to[out=90-133,in=152] (ur);

\draw [ultra thick,gray] ([shift=\curveshift]ul) to[out=-60,in=133] ([shift=\curveshift]A) to[out=90-133,in=152] ([shift=\curveshift]ur);

  • I do understand your code, it looks nice. But the curves don't look parallel, do they? Maybe some optic illusion. Thanks so far :)
    – Mac
    Oct 31, 2015 at 9:03
  • @Mac The two grey ones? They are exactly the same, but because the left part is more vertical they appear closer there. Or rather, the vertical distance is exactly the same all along the path, but the perpendicular distance is smaller in the left end. Oct 31, 2015 at 9:34
  • @Mac By the way, the code can be simplified a bit, making the black dots and specifying coordinates in the same command, so there's less repetition of coordinates, I updated the code in my answer. Oct 31, 2015 at 9:37
  • Thx for simplification of the code. Now I have to ask myself whether the perpendicular distance is what I wanted to be the same.. of course what I wanted to achieve is perfect parallel curves, which cannot be done by just y-shifting.. my bad
    – Mac
    Oct 31, 2015 at 16:12
  • @Mac New suggestion. Wont make any claims about this being elegant and flexible, but I think it does what you're after. Oct 31, 2015 at 16:48

Here's an Asymptote version. The idea is to rotate everything virtually so that the red line is horizontal, and then compute the bounding box of the gray curve. Its minimum coordinate (i.e., "height") is the desired shifting distance.

Update: Abstracted shifting/tangent code into function. Added a curve tangent to the green dashed line as well.

pair y = (0,6);
pair o = (0,0);
pair x = (6,0);
draw(y -- o -- x, arrow=Arrows(TeXHead), p=linewidth(1.5pt));
label("$C_{t+1}$", position=y, align=N);
label("$C_t$", position=x, align=2S);

pen tkzthick = linewidth(0.6pt);
pen tkzultrathick = linewidth(1.6pt);
pen mydashpattern = linetype(new real[] {6pt, 3pt});

draw((0,5) -- (5,0), tkzthick + blue);
pair redstart = (0,2.5), redend = (5,0);
pair greenstart = (0,3.5), greenend = (3.5,0);
draw(redstart -- redend, mydashpattern + tkzthick + red);
draw(greenstart -- greenend, mydashpattern + tkzthick + green);

pair A = (3,2);
dot(A, L="$A$", align=E);

pair ul = (1.5,4);
pair ur = (5,0.5);

path curve = ul {dir(-60)} .. A {dir(90-133)} .. {-dir(152)} ur;
draw(curve, tkzultrathick + gray);

path touchline(path curve, pair a, pair b) {
  pair vector = b - a;
  // Compute the angle of the line segment.
  real angle = degrees(atan2(vector.y, vector.x));
  // Find the transformation to make the line coincide with the x-axis.
  transform T = rotate(-angle) * shift(-a);
  // What is the y-coordinate of the bottom of the curve after this transformation?
  real height = min(T * curve).y;
  // Apply the transformation, lower the curve to touch the line, and then put
  // it all back in place.
  return inverse(T) * shift((0,-height)) * T * curve;

draw(touchline(curve, redstart, redend), tkzultrathick + gray);
// Uncomment next line to add tangent to the green line:
// draw(touchline(curve, greenstart, greenend), tkzultrathick + gray);
  • I'm going crazy about this. I cannot install the asymptote package onthefly and not with the package manager. Updated/synchronized the database. But still not locating the error. I'm working on it. Your result looks good, but the syntax is new to me.
    – Mac
    Oct 31, 2015 at 16:40
  • I've written about installing Asymptote in the appendix to my tutorial. You might also be interested in the asypictureB package, which automatically runs the Asymptote program for you using shell escape. Oct 31, 2015 at 20:50
  • One other option: compile your diagram on overleaf. Nov 1, 2015 at 17:09

My try of using the tzplot package:

enter image description here



% budget lines
% upper curve
\tzvXpointat*{bgtA}{3}(A){$A$}[45] % point A
% lower curve
\tzvXpointat*{bgtB}{3.5}(E){$E$}   % point E
% shifted budget line: with some trial and errors
\clip (0,0) rectangle (6,6);
\tzline[green,densely dashed]<0,-1.135>"bgtAA"(A0)(B0) % shift

  • Step 1: Draw blue and red budget lines.
  • Step 2: Pin down the point A on the blue line and draw the upper curve.
  • Step 3: Pin down the point E on the red line and draw the lower curve.
  • Step 4: Shift the blue line until it touches the lower curve.
    • You may need some trial and errors to get the (final) green line.

If you don't have exact requirements, cheat.

Wwe can use the nfold library to draw a parallel curve (offset) and we can place a picture at any position along a curve where TikZ sets up the coordinate system so that it is parallel (sloped) to the curve.

We can also instruct both nodes and pics along a curve to be yshifted by the same amount.


\usetikzlibrary{arrows.meta, nfold, quotes}
  dot/.style={edge node={
    node[shape=circle, sloped, allow upside down, fill,
      inner sep=+.1em, #1, anchor=center]{}}},
  pics/tangent line/.style={
    /tikz/sloped, /tikz/allow upside down, background code={
    \draw[thin, pic actions] (intersection of O--x and {0,0}--right:1)
                          -- (intersection of O--y and {0,0}--left:1);}}]
\coordinate["$C_t$"     below] (x) at (right:5)
 coordinate["$C_{t+1}$" above] (y) at (   up:5)
 coordinate (O) at (0, 0)
 coordinate (ul) at (1.5, 3) coordinate (ur) at (4, 1);
\path[draw=gray, thick, postaction={draw, offset=1cm}, bend left]
  (ur) to["$A$"', dot/.list={at start, midway, at end,
                             {near start, yshift=1cm}, {near end, yshift=1cm}}]
  pic [blue]                                  {tangent line}
  pic [green, dashed, yshift=1cm, near   end] {tangent line}
  pic [red,   dashed, yshift=1cm, near start] {tangent line} (ul);
\draw[thick, <->] (y)  |- (x);


enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .