3

The graph I want to draw is shown below:

enter image description here

Regions A and B are represented by shaded lines. To fill the region A is easy. But I don't know how to draw shadows with lines that are near to the closed curve acdcecba.

\documentclass[varwidth]{standalone} 
\usepackage{tikz}
\usetikzlibrary{patterns}
\tikzstyle{none}=[inner sep=0mm]
\tikzstyle{blacknode}=[fill=black, draw=black, shape=circle, minimum 
size=0.15cm, inner sep=0pt]
\tikzstyle{blackedge}=[-, draw=black, fill=none, line width=0.15mm]
\begin{document}
\begin{tikzpicture}
\node [style=blacknode,label={left:$a$}] (0) at (-7, 3) {};
        \node [style=blacknode] (1) at (-3, 3) {};
        \node [style=blacknode,label={right:$b$}] (2) at (3, 3) {};
        \node [style=none,label={right:$e$}] (3) at (-1, 6.5) {};
        \node [style=none] (6) at (-1, 3.5) {};
        \node [style=none] (7) at (0.75, 3.5) {};
        \node [style=none,label={left:$d$}] (8) at (-3, 6.5) {};
        \node  (9) at (-1.8, 6.2) {$c$};
        \node  (9) at (1, 3) {$A$};
        \node  (9) at (3, 5) {$B$};
        \draw (0) to (1);
        \draw [in=180, out=60, looseness=0.75] (0) to (3.center);
        \draw [bend right=60, looseness=1.25] (0) to (2);
        \draw [style=blackedge, in=360, out=120] (2) to (8.center);
        \draw[pattern color=red!60,pattern=north east lines](6.center)
             to [bend right=330, looseness=1.25] (2.center)
             to [bend left] (1.center)
             to [bend left, looseness=1.25] (7.center);
\end{tikzpicture}
\end{document}

![enter image description here


Edit: Many thanks to Qrrbrbirlbel and Thruston for your answers. I tried to write one myself (another similar example). But it feels like a lot of work as I used some codes a few times. I'd like to simplify this a little bit.

\documentclass[varwidth]{standalone} 
\usepackage{tikz}
\usetikzlibrary{patterns}
\tikzstyle{none}=[inner sep=0mm]
\tikzstyle{blacknode}=[fill=black, draw=black, shape=circle, minimum 
size=0.15cm, inner sep=0pt]
\tikzstyle{blackedge}=[-, draw=black, fill=none, line width=0.15mm]
\begin{document}

\begin{tikzpicture} \node [style=blacknode] (0) at (-7, 3) {}; \node [style=blacknode] (1) at (-3, 3) {}; \node [style=blacknode,label={right:$f$}] (2) at (2, 3) {}; \node [style=none] (3) at (-2, 0) {}; \node [style=none] (8) at (-3.75, 0) {}; \node [style=none] (10) at (-8, 3) {}; \node [style=none] (13) at (3, 3) {}; \node [style=none] (14) at (-1, 4) {}; \node [style=none] (15) at (0, 4) {}; \node [style=none] (16) at (-3.175, 0.2) {}; \node [style=none] (17) at (-4.25, 4) {$F_1$}; \node [style=none] (18) at (-4.5, 2) {$F_2$}; \node[style=none] (19) at (-7, 2.72) {$a$};
\node[style=none] (20) at (-3, 2.72) {$b$}; \draw (0) to (1); \draw (8.center) to [in=240, out=15, looseness=0.75] (2.center) to [in=75, out=105, looseness=1.25] (0.center) to in=180, out=-60, looseness=0.75; \filldraw [draw=none, even odd rule, pattern color= blue!255, pattern=north east lines,opacity=0.1] (16.center) to [in=-120, out=10, looseness=0.75] (2.center) to [bend left=285, looseness=1.25] (0.center) to [in=164, out=-70, looseness=0.64] cycle
(13.center) to [in=-90, out=-90, looseness=1.25] (10.center) to [in=90, out=90, looseness=1.25] cycle; \draw (15.center) to [in=-300, out=150, looseness=1.25] (1.center) to [in=-135, out=-45] (2.center) to [in=30, out=120, looseness=1.25] (14.center); \draw [pattern color= blue!255, pattern=north east lines,opacity=0.1] (15.center) to [in=-300, out=150, looseness=1.25] (1.center) to [in=-135, out=-45] (2.center) to [in=30, out=120, looseness=1.25] (14.center); \end{tikzpicture} \end{document}

enter image description here

licheng
  • 773

2 Answers2

3

There are two problems:

  1. The path from a to b and then over c back to a can't be described by vanilly TikZ.

    However the spath3 library can be used to not only find the intersection (that's delegated to the intersections library), it is also able to cut the paths up and remove the small parts to d and e we don't want. (The author Andrew Stacey is active on this site and does use the library regularly – and updates it often which is why it doesn't surprise me a two year old TeXLive will fail.)

    Of course, if you can describe the paths from a to c and from b to c with TikZ alone, there's no need for this.

  2. Doing something with the outside of a path.

    It doesn't look like it's very trivial (for curved paths) to construct a parallel path with a fixed distance. You could use a shadow with a pattern that's has different xscale and yscale factors as I did in another answer of mine. However, you will need to fill the actual path white or reverse-clip the shadowed path against itself to hide the pattern beneath it.

The spath3 library is somewhat daunting since it offers many keys and options and it isn't immediatly clear what each of them do (at least to me who doesn't handle paths regularly).

I've added a \spathset macro (similar to \tikzset) that executes all keys directly in the /tikz/spath namespace and a build spath key (in the /tikz namespace, though) that might help use this often since it just concatenates all given paths.


I've taken the liberty to rewrite your diagram:

  1. Don't use \tikzstyle.
  2. Don't use style = …, it serves no purpose the way you use it.
  3. Don't use empty minimum sized nodes to reference a coordinate, use a coordinate instead.
  4. I've named the coordinates with letters so that they correspond to the labels attached to them. (It was very confusing to me with all the numbers and letters.)
  5. It is not necessary to put our special path in the background, we could just draw it again or don't draw any of the other paths beforehand but after it but it makes it really easy.
  6. The to paths from/to the border of the node is different than the ones from their center. Since I'm consistently using coordinates, this isn't a problem anymore.

Your edit makes it much easier to construct an ellipsoid shadow instead of a fixed width shadow which is what I'm using here. The even odd rule makes it very easy to punch out the weird path from an ellipse.

Code

\documentclass[tikz,border=3mm]{standalone} 
\usetikzlibrary{patterns,backgrounds,spath3,intersections}
\tikzset{
  blacknode/.style={fill=black, draw=black, shape=circle, minimum size=0.15cm, inner sep=0pt},
  blacknode no label/.style={blacknode, label/.code=},
  my label/.style={fill=white, fill opacity=.7, text opacity=1, rounded corners},
  blackedge/.style={-, draw=black, fill=none, line width=0.15mm}}
\tikzset{
  build spath/.style args={#1,#2}{
   /tikz/spath/use={#1},
   /tikz/spath/append no move/.list={#2}}}
\newcommand*\spathset{\pgfqkeys{/tikz/spath}}
\begin{document}
\begin{tikzpicture}
% 1. Define coordinates
\coordinate (a)  at (-7, 3)
 coordinate (b)  at ( 3, 3)
 coordinate (ab) at (-3, 3)
 coordinate (d)  at (-3, 6.5)
 coordinate (e)  at (-1, 6.5);

% 2. Draw some lines (and name some of them). \draw[blackedge] (a) -- (ab); \draw[blackedge] (a) to[in=180, out=60, looseness=0.75] (e) [spath/save=big eye tl]; \draw[blackedge] (a) to[bend right=60, looseness=1.25] (b) [spath/save=big eye b]; \draw[blackedge] (b) to[in=360, out=120] (d) [spath/save=big eye tr];

% 3. Fill area A (using the literal coordinates here, % doesn't seem like there's any relation to the other points). \draw[pattern color=red!60,pattern=north east lines] (-1, 3.5) to [bend right=330, looseness=1.25] (b) to [bend left] (ab) to [bend left, looseness=1.25] (.75, 3.5); % 4a. Find intersections of named paths and remove the part "above" the intersection \spathset{ split at intersections={big eye tr}{big eye tl}, remove components={big eye tr}{2}, remove components={big eye tl}{2}} % 4b. The intersection point is a good thing to have (the end of path big eye tl). \coordinate (c) at (spath cs:{big eye tl} 1);

% 4c. Use \scoped[on background layer] \path[ pattern color=red!60, pattern=north east lines, even odd rule, % poke holes in path % let's build the weird path: build spath={big eye b, big eye tr, {big eye tl, reverse}} ] % close the path -- cycle % That's it. % But we're not finished, we can do more with that path: (-2,3) circle[x radius=6, y radius=4];

% 5. Place the area labels (above everything else) \node[my label] (A) at (1, 3) {$A$}; \node[my label] (B) at (2.5, 5) {$B$};

% 6. Add nodes (circles) and label them (above everything else) \foreach \st/\p/\t in { blacknode/left/a, blacknode/right/b, /below/c, /left/d, /right/e, blacknode no label//ab} \node[\st, label={[my label]\p:$\t$}] at (\t) {}; \end{tikzpicture} \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
  • 2
    If you want the whole rectangle filled with the pattern that don't use the shadow but an inverse clip that is floating around on this site. – Qrrbrbirlbel Nov 06 '22 at 18:14
  • texlive2020 failed and texlive2022 succeeded. I still need to absorb your codes for a while, and I've written one of my own that looks complicated. – licheng Nov 07 '22 at 11:00
  • 1
    @licheng Since spath3 gets regularly updated it doesn't surprise me that TeXLive 2020 fails. In this case, it's simpler: spath3 wasn't published in 2020. I've updated my answer (and removed the shadow stuff in favor of the ellipse like in your updates Q) and added some comments, hopefully helpfull ones. The spath3 library is daunting (and the manual doesn't help). If you can describe the paths from a to c and b to c with vanilla TikZ, i.e. a simple curve, that we don't need the whole spath3 spiel. – Qrrbrbirlbel Nov 07 '22 at 13:48
2

While you are waiting for Tikz-aid, here is an attempt in plain Metapost, for comparison.

enter image description here

You should be able to produce a PDF that looks like the image above, if you use lualatex to compile the following code:

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
% first define the points - p is the unlabelled one
% The default unit is "bp", so 144 = 2in = 5.08 cm
% You can write "(5cm, 0)" instead of "144 right" if you prefer.
pair a, b, c, d, e, p;
-a = b = 144 right;
p = 4/10[a, b];
e = (21, 89);

% and now the outer set of curved paths path ab, ae, bd;
ab = a {dir -60} .. {dir 60} b; ae = a .. {dir 4} e; bd = ae reflectedabout(up, down);

% plus the two remaining points, derived from the paths d = point 1 of bd; c = ae intersectionpoint bd;

% finally the inner set of curved paths path bq, pr, pb; bq = b .. {dir 200} (42, 13); pr = bq reflectedabout(1/2[p, b], 1/2[p,b] + up); pb = p {dir -30} .. {dir 30} b;

% now capture all the lines and labels as a picture picture P; P = image( draw bq; draw pr; draw pb; draw a -- p; draw p withpen pencircle scaled dotlabeldiam; draw ae; draw bd; draw ab; dotlabel.lft("$a$", a); dotlabel.rt ("$b$", b); label.bot("$c$", c); label.lft("$d$", d); label.rt ("$e$", e); label("$A$", 1/2[p, b]); label("$B$", point 3/8 of bd shifted (34, 13)); );

% use buildcycle to find the enclosed paths path A, notB; A = buildcycle(pb, bq, pr); notB = buildcycle(ab, bd, ae);

% make two copies of a large patch of pink hatch lines picture filler_A, filler_B; filler_A = filler_B = image( for i=-100 upto 100: draw (left--right) scaled 400 rotated 45 shifted (3i, 0) withcolor 3/4[red, white]; endfor );

% clip the patches to the relevant shapes clip filler_A to A; clip filler_B to bbox P;

% now draw the bits in Z-order from back to front beginfig(1); draw filler_B; unfill notB; draw filler_A; draw P; endfig; \end{mplibcode} \end{document}

Thruston
  • 42,268