7

I use \clip to clip a rectangular region of a drawing in a tikzpicture. I would like to have the lines in the clipped region to have a different color than their color in the original drawing. Would there be a simpler way of doing this? Or if this is possible?

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale=0.5]
\clip[draw] (0,0) rectangle (2*1.732,-3);
\def\hexagonpath{ +(30:1) -- +(90:1) -- +(150:1) -- +(210:1) -- +(270:1) -- +(330:1) -- cycle }
\foreach \x in {0,...,3}
    \foreach \y in {0,...,3} {
        \ifodd\x
            \draw (0,0) ++(0,-1/2-3*\x/2) ++(30:1) ++(30:\y * 2) ++(0,-\y) \hexagonpath; 
        \else
            \draw (0,0) ++(0,-3*\x/2) ++(30:\y * 2) ++(0,-\y) \hexagonpath;
        \fi
    }
\end{tikzpicture}
\end{document}
2
  • If I'm not mistaken, lines outside the clipping region are invisible. So why not just draw everything in the color that you want? (I may just not get your problem, though.)
    – ilpssun
    May 11, 2012 at 13:15
  • Shown above is just a trimmed example. What I really want is a very general macro that takes a few arguments, some of which control if a clip is called and the size of the clip.
    – braids
    May 12, 2012 at 13:47

2 Answers 2

7

The easiest thing to do here would be to wrap the whole hexgrid into a command, and then draw it twice, once without clipping, then again clipped and with a different colour.

In principle, first you can draw the complete grid, and then draw the clipped section over it. However, this can lead to the first instance of the grid showing through, especially if you want to draw the clipped grid with a thinner stroke. To avoid this, you can "reverse clip" the first instance of the path (see How can I invert a 'clip' selection within TikZ?).

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{scopes}
\begin{document}
\tikzstyle{reverseclip}=[insert path={(current page.north east) --
  (current page.south east) --
  (current page.south west) --
  (current page.north west) --
  (current page.north east)}
]

\begin{tikzpicture}[scale=0.5,remember picture,overlay]
\def\hexagonpath{ +(30:1) -- +(90:1) -- +(150:1) -- +(210:1) -- +(270:1) -- +(330:1) -- cycle }
\def\hexgrid{
\foreach \x in {0,...,3}
    \foreach \y in {0,...,3} {
        \ifodd\x
            \draw (0,0) ++(0,-1/2-3*\x/2) ++(30:1) ++(30:\y * 2) ++(0,-\y) \hexagonpath; 
        \else
            \draw (0,0) ++(0,-3*\x/2) ++(30:\y * 2) ++(0,-\y) \hexagonpath;
        \fi
    }
}
\begin{scope}
\path[clip] (0,0) rectangle (2*1.732,-3) [reverseclip];
\hexgrid
\end{scope}

\begin{scope}[red]
\draw[clip] (0,0) rectangle (2*1.732,-3);
\hexgrid
\end{scope}
\end{tikzpicture}
\end{document}
1
  • Really cool! I really appreciate!!! I really appreciate your spending so much time on helping me!
    – braids
    May 12, 2012 at 6:31
6

I have a very ugly hack, basically modifying the existing spy library. You can either save it as an additional custom library or just leave it as it is if you are not going to use the spy library in your document.

What I did is pretty simple. Just when TikZ is preparing itself to redraw the part of the original picture in a spy window, I just squeezed in a stroke color changing command \pgfsetstrokecolor{} such that while the drawing is performed TikZ assumes that it has reset the options properly. I also cooked up a custom \spy command such that you can give the line color explicitly via with line color <color spec>.

This will not work if you change the color in \draw commands and pretty much every thing else is a candidate to break it down.

I think it's possible to patch it directly but I don't know how right away because we need to go one level down to catch the drawing. Maybe someone else can so I'll leave it here.

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\makeatletter
\tikzset{
  spy using ugly hack/.style={
    spy scope={
      every spy on node/.style={draw=none},
      every spy in node/.style={draw=none},
      #1
    }
  },
}

\newbox\tikz@lib@spybox

\let\tikz@lib@spy@collection=\pgfutil@empty%

\tikzset{spy scope/.style={
    size/.style={minimum size=##1},
    height/.style={minimum height=##1},
    width/.style={minimum width=##1},
    execute at begin scope={%
      \let\tikz@lib@spy@save=\tikz@lib@spy@collection%
      \setbox\tikz@lib@spybox=\hbox\bgroup%
      \let\spy=\tikz@lib@spy@parse
    },
    execute at end scope={%
      \egroup%
      {%
        \copy\tikz@lib@spybox%
        \tikz@lib@spy@collection%
      }%
      \global\let\tikz@lib@spy@collection=\tikz@lib@spy@save%
    },%
    tikz@lib@spy@style/.style={#1},
    tikz@lib@reset@gs
  },
  lens/.store in=\tikz@lib@spy@lens,
  lens=,
  magnification/.style={lens={scale=#1}},
  spy connection path/.store in=\tikz@lib@spy@path,
  spy connection path=
}

\tikzset{
  tikz@lib@reset@gs/.style={black,thin,solid,opaque,line cap=butt,line join=miter}
}

\def\tikz@lib@spy@parse{%
  \pgfutil@ifnextchar[{\tikz@lib@spy@parse@opt}{\tikz@lib@spy@parse@opt[]}%]
}
\def\tikz@lib@spy@parse@opt[#1]{
  \pgfutil@ifnextchar x{\tikz@lib@spy@parse@opta[#1]}{\tikz@lib@spy@parse@opta[#1]}%]
}
\def\tikz@lib@spy@parse@opta[#1]on#2in node#3 with line color #4;{%
  \pgfutil@g@addto@macro\tikz@lib@spy@collection{\tikz@lib@spy@do{#1}{#2}{#3}{#4}}%
}

\def\tikz@lib@spy@do#1#2#3#4{%
  \scope[tikz@lib@spy@style,#1]
    \node [alias=tikzspyonnode,inner sep=0pt,outer sep=0pt,every spy on node/.try,
    /utils/exec={
      {%
        \let\tikz@transform=\relax
        \pgftransformreset%
        \expandafter\tikzset\expandafter{\tikz@lib@spy@lens}
        \pgftransforminvert%
        \pgfgettransformentries\a\b\c\d\e\f%
        \global\let\pgf@lib@svg@a=\a%
        \global\let\pgf@lib@svg@b=\b%
        \global\let\pgf@lib@svg@c=\c%
        \global\let\pgf@lib@svg@d=\d%
      }%
      \tikz@addtransform{%
        \tikz@scan@one@point\pgftransformshift#2%
        \pgftransformcm{\pgf@lib@svg@a}{\pgf@lib@svg@b}{\pgf@lib@svg@c}{\pgf@lib@svg@d}{\pgfpointorigin}%
      }
    }]{};
    \node [alias=tikzspyinnode,inner sep=0pt,outer sep=0pt,at={#2},every spy in node/.try,
    path picture={\node[anchor=center,tikz@lib@reset@gs]{\nullfont%
        \pgftransformreset%
        \pgfsetstrokecolor{#4}
        \let\tikz@transform=\relax%
        \expandafter\tikzset\expandafter{\tikz@lib@spy@lens}%
        \pgflowlevelsynccm%
        \tikz@scan@one@point\tikz@lib@spy@shift#2%
        \pgflowlevelsynccm%
        \copy\tikz@lib@spybox};}]#3{};
    \tikz@lib@spy@path
  \endscope
}

\def\tikz@lib@spy@shift#1{%
  \pgf@process{#1}%
  \pgf@x=-\pgf@x%
  \pgf@y=-\pgf@y%
  \pgftransformshift{}%
}
\makeatother



\begin{document}
\begin{tikzpicture}[spy using ugly hack={magnification=1,size=2cm}]
%\clip[draw] (0,0) rectangle (2*1.732,-3);
\def\hexagonpath{ +(30:1) -- +(90:1) -- +(150:1) -- +(210:1) -- +(270:1) -- +(330:1) -- cycle }
\foreach \x in {0,...,3}
    \foreach \y in {0,...,3} {
        \ifodd\x
            \draw[thick] (0,0) ++(0,-1/2-3*\x/2) ++(30:1) ++(30:\y * 2) ++(0,-\y) \hexagonpath; 
        \else
            \draw[thick] (0,0) ++(0,-3*\x/2) ++(30:\y * 2) ++(0,-\y) \hexagonpath;
        \fi
    }
\spy on (3.5,-1.5) in node  with line color blue;
\spy on (0,-3) in node with line color yellow;
\spy on (6,-4) in node with line color red;
\end{tikzpicture}

\end{document}

enter image description here

1
  • Wow, thank you so much!!! I really appreciate your spending so much time on helping me!
    – braids
    May 12, 2012 at 6:29

You must log in to answer this question.

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