1

This is a follow-up question to this one. My goal is to draw a vertical line to any path or a function, but the main requirement is to avoid temporal paths that are used to get the intersection.

Here is the desired result: enter image description here

And that's my attempt to define a macro that finds the intersection point, but it doesn't work:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{intersections}

\makeatletter \newcommand\topath[1]{ \path[name path=t] (\the\tikz@lastxsaved,\pgfkeysvalueof{/pgfplots/ymin}) -- (\the\tikz@lastxsaved,\pgfkeysvalueof{/pgfplots/ymax}); \coordinate[name intersections={of=#1 and t}] at (intersection-1) } \newcommand\currentcoordinate{\the\tikz@lastxsaved,\the\tikz@lastysaved} \makeatother

\begin{document}

\begin{tikzpicture} \begin{axis}[ axis lines = center, samples=200, clip=false ] \def\ymaxv{\pgfkeysvalueof{/pgfplots/ymax}}

\addplot[blue, name path=f, restrict y to domain=-3:5] {x^4-3*x^2+x+2};

% ↓ doesn't work ↓ %\draw[red] (1,0) -- \topath{f}; %\draw[red] (-1.5,0) -- \topath{f};

\end{axis} \end{tikzpicture} % \qquad % \begin{tikzpicture} \begin{axis}[ axis lines = center, samples=200, clip=false ]

\addplot[blue, name path=b, smooth, tension=1] coordinates {(0,1) (1,2) (1,0) (0.5,0) (0.5,1) (1.5,0.5) (2,0.7)};

% ↓ doesn't work ↓ %\draw[red] (0.2,0) -- \topath{b}; %\draw[red] (1.5,0) -- \topath{b};

\end{axis} \end{tikzpicture}

\end{document}

antshar
  • 4,238
  • 9
  • 30
  • As before, can you define macro that generates unique path name automatically? Or is it because it would make the syntax less nice (need separate macro call etc.)? (in the latter case just write into the question that you want to keep the usage syntax simple. There might be solutions that do that as well as creating temporary path) – user202729 Dec 27 '21 at 11:48
  • @user202729 I don't mind macros, but I don't find auto-unique name generator convenient, because it still requires me to remember a name with postfix that's been created automatically with macros. Suitable usage is presented in my attempt, that's unfortunately, doesn't work. – antshar Dec 27 '21 at 12:01
  • Remember what? You can definitely make macro such that these information are only kept internally. – user202729 Dec 27 '21 at 12:05
  • So what exactly do you need? A macro that expands e.g. \drawtopath{\draw[red] (0.2,0) -- }{b} to what you want is possible. Is that okay? – user202729 Dec 27 '21 at 12:06
  • @user202729, it would be enough for me to have a macros that returns coordinates of the path, by giving any x coordinate to it. – antshar Dec 27 '21 at 12:10
  • Okay, so what you want is to compute the intersection of a vertical line (given some x coordinate) and an arbitrary path expandably. That one makes much more sense but... – user202729 Dec 27 '21 at 12:12
  • Because you can't use nonexpandable things from expandable things (maybe except in LuaTeX), it might be very hard to impossible. So explain the actual uses case and people may post best alternatives. – user202729 Dec 27 '21 at 12:18
  • @user202729 anything will work as long as I can get x coordinate as an input and it will draw a line to x-axis and it won't require me to deal with temporal path name. postaction decorators are also appealing, but I didn't manage to make them work correctly. – antshar Dec 27 '21 at 12:31
  • Sorry, I also don't have a general solution for that. At least for \addplot commands this will be possible when (some parts of) https://github.com/pgf-tikz/pgfplots/issues/295 will be implemented ... – Stefan Pinnow Dec 27 '21 at 18:25
  • In that case, you should edit the question to state "How can I without dealing with temporary path names?" instead. (The current question implies that the solution can't use any temporary path in its implementation, which is a weird restriction.) – user202729 Dec 28 '21 at 02:41

2 Answers2

1

Use expl3 to generate path names automatically (tempintersectionpath1, tempintersectionpath2, etc.):

If drawing lines from x-axis to intersection point of a named path is all you want you can do this, but otherwise it doesn't look possible to compute the intersection expandably using TikZ interface.

%! TEX program = lualatex

\documentclass{article} \usepackage{pgfplots} \pgfplotsset{compat=newest} \usetikzlibrary{intersections}

\ExplSyntaxOn

% example usage: \topath{\draw[red]}{1.5}{-- (intersection-1)}{f} % 1.5 is x coordinate

\int_new:N \my__path_index \int_gset:Nn \my__path_index {0} \cs_generate_variant:Nn \regex_replace_all:nnN {nVN} \NewDocumentCommand\topath{mmmm}{ \int_gset:Nn \my__path_index {\my__path_index+1} \tl_set:Nn \my__tmp { \path [name~path=tempintersectionpath\my__path_index] (#2, \pgfkeysvalueof{/pgfplots/ymin}) -- (#2, \pgfkeysvalueof{/pgfplots/ymax}); \path [name~intersections={of=#4~and~tempintersectionpath\my__path_index}]; #1 (#2, 0) #3; } \regex_replace_all:nVN {\c{my__path_index}} \my__path_index \my__tmp %\nonstopmode \tl_show:N \my__tmp \errorstopmode \tl_use:N \my__tmp } \ExplSyntaxOff

\begin{document}

\begin{tikzpicture} \begin{axis}[ axis lines = center, samples=200, clip=false ] \def\ymaxv{\pgfkeysvalueof{/pgfplots/ymax}}

\addplot[blue, name path=f, restrict y to domain=-3:5] {x^4-3*x^2+x+2};

\topath{\draw[red]}{1}{-- (intersection-1)}{f} \topath{\draw[red]}{-1.5}{-- (intersection-1)}{f}

\end{axis} \end{tikzpicture} % \qquad % \begin{tikzpicture} \begin{axis}[ axis lines = center, samples=200, clip=false ]

\addplot[blue, name path=b, smooth, tension=1] coordinates {(0,1) (1,2) (1,0) (0.5,0) (0.5,1) (1.5,0.5) (2,0.7)};

\topath{\draw[red]}{0.2}{-- (intersection-1)}{b} \topath{\draw[red]}{0.8}{-- (intersection-1)}{b} \topath{\draw[red]}{1.5}{-- (intersection-1)}{b}

\end{axis} \end{tikzpicture}

\end{document}

user202729
  • 7,143
  • Also, \my__ macro names violates expl3 variable naming convention. Fix yourself if you want to. – user202729 Dec 28 '21 at 02:42
  • Note that if the first path is a straight line it might have some issues https://tex.stackexchange.com/questions/622315/tikz-single-intersection-between-curve-and-horizontal-line-not-found – user202729 Dec 28 '21 at 02:45
  • I edited the command for my needs so that I only need to specify the coordinate and the path. Thank you for the core of macro with expl3. – antshar Dec 28 '21 at 11:42
0

Using the tzplot package:

enter image description here

\documentclass[border=1mm]{standalone}

\usepackage{tzplot}

\begin{document}

\begin{tikzpicture}[yscale=.5,font=\tiny] \tzaxes(-2,-2)(2,5) \tzticks(-2pt:2pt){-2/$-2$,-1/$-1$,1}(-1pt:1pt){2,4} \def\Fx{(\x)^4-3(\x)^2+\x+2} \tzfn[blue]\Fx[-2:1.8] \tzvXpointat{Fx}{-1.5}(A) \tzvXpointat{Fx}{1}(B) \tzprojxred,solid \tzprojxred,solid \end{tikzpicture} \quad %%% \begin{tikzpicture}[font=\tiny] \tzaxes*(-1,-1)(3,2.5) \tzticks(-1pt:1pt){0.5,1,1.5,2}(-1pt:1pt){0.5,1,1.5,2} \tzplotcurve[blue]"curve"(0,1)(1,2)(1,0)(0.5,0)(0.5,1)(1.5,0.5)(2,0.7); \tzvXpointat{curve}{0.2}(A) \tzvXpointat{curve}{1.5}(B) \tzprojxred,solid \tzprojxred,solid \end{tikzpicture}

\end{document}

I. Cho
  • 2,985