2

I try to draw the next figure:

What I want to draw

So, I create two paths "background" (the low curve) and "resonance" (the spikes) in this code:

\documentclass[margin=5pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{fillbetween}
\usetikzlibrary{pgfplots.fillbetween}

\begin{document}
\begin{tikzpicture}


\path[name path=background ,draw] (1,2.5) .. controls +(30:3)  and +(160:1) ..(9,2);

\path[name path=resonance ,draw] 
(2.5,2) .. controls +(90:6)  and +(92:4) ..(2.8,2) 
(4.1,1.15) .. controls +(90:6)  and +(92:4) ..(4.4,1.15) 
(5.7,0.7) .. controls +(90:6)  and +(92:4) ..(6.0,0.7) 
(7.3,0.4) .. controls +(90:6)  and +(92:4) ..(7.6,0.4);

\fill [name intersections={of=background and resonance ,sort by=background, name=intersections, total=\t}]
                           [red, opacity=0.5] \foreach \s in {1,...,\t}{(intersections-\s) circle (2pt)};

\path[name path=spectrum, draw=red, intersection segments={of= background and resonance ,sequence={R1 R3 R5 R7 R9 } } ];
\path[name path=spectrum, draw=blue, intersection segments={of= background and resonance ,sequence={R2 R4 R6 R8 } } ];
\path[name path=spectrum, draw=red, intersection segments={of= background and resonance ,sequence={L1 L3 L5 L7 L9} } ];
\path[name path=spectrum, draw=blue, intersection segments={of= background and resonance ,sequence={L2 L4 L6 L8 } } ];

\end{tikzpicture}
\end{document}

Compiling without intersections gives me the two paths:

The two paths

and when I add the intersections, I obtain:

enter image description here

So far so good. Next, I try to draw segments of the paths The odd numbered segments of the 'resonance' spikes are what I would expect:

odd numbered segments of 'resonance' path

But not so when I try the even numbered segments of the 'resonance' path:

even numbered segments of 'resonance' path

And it becomes very strange when I draw the even and add segments of the 'background' path:

even segments background odd segments background

What is going wrong? (first question)

Since the intersections were found, correctly, I could draw my picture IF I could specify to draw only a part of a path in between two point. And so, by concatenating these I would obtain what I am looking for. But is there a command to draw only part of a path between two points? (second question)

2
  • Thanks to Sebastiano for making my question readable (my original was wrongly formatted..)
    – brvbogae
    May 12 '20 at 7:21
  • For the record: I added this to the PGFPlots Tracker as Issue #357. May 13 '20 at 2:11
4

I have just uploaded a new version of my package spath3 to CTAN which provides a few commands for manipulating TikZ/PGF paths after they have been constructed. These include the ability to split a path at the points where it intersects with another path. Using this together with a command that splits a path into its components, it is possible to construct the path you want.

I've provided two ways to do this in the code below. In the first, it constructs a single continuous path (ie, no move gaps). This is particularly suitable for if you are going to fill the region. In the image below, this provides the filled region with the thick black outline (to show that the path is what it is claimed to be).

The second simply draws each component as a separate path. This is useful if you want to apply different styles to each. In the image below, this provides the green and red paths.

It may be useful to know how the key get components of works. It produces a comma separated list of aliases of paths, one for each component. This is designed to be put into a \foreach loop. I've not been able to find a pgf command that extracts a particular element of a list (the array(...,n) command of pgfmath doesn't work here because it then attempts to evaluate the alias further as a mathematical expression) so I've added a wrapper around the appropriate LaTeX3 command. There may be better names for this command ...

\documentclass{article}
%\url{https://tex.stackexchange.com/q/543553/86}
\usepackage{tikz}
\usetikzlibrary{intersections,spath3}

\ExplSyntaxOn

\cs_set_eq:NN \getComponentOf \clist_item:Nn

\ExplSyntaxOff

\begin{document}
\begin{tikzpicture}

\path[name path=background ,draw] (1,2.5) .. controls +(30:3)  and +(160:1) ..(9,2);

\path[name path=resonance ,draw] 
(2.5,2) .. controls +(90:6)  and +(92:4) ..(2.8,2) 
(4.1,1.15) .. controls +(90:6)  and +(92:4) ..(4.4,1.15) 
(5.7,0.7) .. controls +(90:6)  and +(92:4) ..(6.0,0.7) 
(7.3,0.4) .. controls +(90:6)  and +(92:4) ..(7.6,0.4);

\tikzset{
  spath/split at intersections={background}{resonance},
  spath/get components of={background}\bgpath,
  spath/get components of={resonance}\rspath
}


\fill[cyan,draw=black, line width=3pt]
[
  spath/insert=\getComponentOf\bgpath{1},
  spath/append=\getComponentOf\rspath{2},
  spath/append=\getComponentOf\bgpath{3},
  spath/append=\getComponentOf\rspath{5},
  spath/append=\getComponentOf\bgpath{5},
  spath/append=\getComponentOf\rspath{8},
  spath/append=\getComponentOf\bgpath{7},
  spath/append=\getComponentOf\rspath{11},
  spath/append=\getComponentOf\bgpath{9},
] -- +(0,-2) -| (1,.5) -- cycle;
;

\foreach[count=\k] \cpt in \bgpath {
  \ifodd\k\relax
  \draw[ultra thick, red, spath/restore=\cpt];
  \fi
}
\foreach[count=\k, evaluate=\k as \mk using {int(mod(\k + 1,3))}] \cpt in \rspath {
  \ifnum\mk=0\relax
  \draw[ultra thick, green, spath/restore=\cpt];
  \fi
}


\end{tikzpicture}
\end{document}

Composite path created by intersecting two paths

1

Very strange results of the sequence ...

But you can "fake" the result by "cheating". Please have a look at the following code.

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \usetikzlibrary{pgfplots.fillbetween}
\begin{document}
\begin{tikzpicture}
    % just to prevent enlarged bounding box
    % (due to "overshooting" of spike control points)
    \clip (1,2) rectangle (9,6);

    % first draw "background" in `thick` (twice as thick as `thin`)
    % because the "lower" half will be overdrawn later
    \path [
        draw=black,
        thick,
    ]
        (1,2.5) .. controls +(30:3)  and +(160:1) ..(9,2)
    ;

    % second draw the spikes with a fill color to "hide" the parts of the
    % background lines in the spikes
    \path [
        draw=black,
        fill=white,
    ]
        (2.5,2)    .. controls +(90:6) and +(92:4) .. (2.8,2)
        (4.1,1.15) .. controls +(90:6) and +(92:4) .. (4.4,1.15)
        (5.7,0.7)  .. controls +(90:6) and +(92:4) .. (6.0,0.7)
        (7.3,0.4)  .. controls +(90:6) and +(92:4) .. (7.6,0.4)
    ;

    % third draw the "background" again but now just fill it with white to
    % hide the spike parts below the background line
    % (which also overdraws the lower half of the first background path drawing)
    \path [
        fill=white,
    ]
        (1,2.5) .. controls +(30:3)  and +(160:1) ..(9,2)
        % to better close the path for the `fill`
        |- (1,0) -- cycle
    ;
\end{tikzpicture}
\end{document}

image showing the result of above code

6
  • Thank you Stefan. And indeed! that was how I created my drawing of what I want to achieve. But I was curious whether it was possible to achieve things with the partial drawing of paths... say something of \path[draw from=A to=B]{<path definition>};
    – brvbogae
    May 12 '20 at 7:16
  • Here I am not sure what you mean. But to do what you want without faking/cheating I would also have tried to use sequence which seems to either have a bug. Are you willing to report this to the PGFPlots Issue Tracker? May 12 '20 at 10:17
  • Well, I have never reported a bug... and I wasn't sure that it would be one: I could have made a mistake in my code. Meanwhile I tried to find some workaround, like using decorations on parts of a path to actually draw a part of the path, but from what I have read in the manuals (pgfmanual_3.1.5 and pgfplots) I am afraid that won't do. And I do not dare to start working on the basic layer... <br/> But if you think that is a bug, and if you want to report it (I lack experience ..) feel free to do it.
    – brvbogae
    May 12 '20 at 15:31
  • @brvbogae This answer may help: tex.stackexchange.com/questions/547021/…
    – ZhiyuanLck
    Jun 11 '20 at 3:24
  • @ZhiyuanLck, feel free to add another answer. As you can see OP wasn't (fully) satisfied with my answer. Jun 11 '20 at 4:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.