5

I want to make a new shape from rectangle, which has only its top and bottom line drawn, but which can be filled. The answer, thank's to Andrew Stacy and percusse look by now as follows:

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    \documentclass[twoside,reqno,12pt]{amsart}
    \usepackage{a4wide} %% uncomment if a4wide is not installed
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %% T i k Z 
    %%   -- packages
    %%   -- macros & shapes
    \usepackage{tikz}
    \usetikzlibrary{arrows,backgrounds}
    \usetikzlibrary{decorations.pathreplacing}
    \usetikzlibrary{decorations.markings}
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %%
    %% new shape : iso
    %%
    \makeatletter
    \newif\ifpullback
    \pgfkeys{/tikz/pullback/.is if=pullback}
    \pgfkeys{/tikz/pullback=false}
    \pgfdeclareshape{iso}{%
        %
        \inheritsavedanchors[from=rectangle]
        \inheritanchorborder[from=rectangle]
        \inheritanchor[from=rectangle]{north}
        \inheritanchor[from=rectangle]{north west}
        \inheritanchor[from=rectangle]{north east}
        \inheritanchor[from=rectangle]{center}
        \inheritanchor[from=rectangle]{west}
        \inheritanchor[from=rectangle]{east}
        \inheritanchor[from=rectangle]{mid}
        \inheritanchor[from=rectangle]{mid west}
        \inheritanchor[from=rectangle]{mid east}
        \inheritanchor[from=rectangle]{base}
        \inheritanchor[from=rectangle]{base west}
        \inheritanchor[from=rectangle]{base east}
        \inheritanchor[from=rectangle]{south}
        \inheritanchor[from=rectangle]{south west}
        \inheritanchor[from=rectangle]{south east}
        %
        \savedanchor\centerpoint
        {
            \pgf@x=0pt
            \pgf@y=0pt
        }
        \anchor{text}{%
             \pgf@x=0pt
             % adjust vertical positioning
             \pgf@y=0pt
             \advance\pgf@y by -0.2\ht\pgfnodeparttextbox
        }
        %
        \backgroundpath{%
          \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
          \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
          \begingroup
             \tikz@mode
             \iftikz@mode@draw
                % -- draw top and bottom line
                \pgfpathmoveto\northeast
                \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
                \pgfpathmoveto\southwest
                \pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
                \pgfusepath{stroke}
             \fi
             \iftikz@mode@fill
                % -- fill rectangle if demanded
            \pgfsetlinewidth{\pgflinewidth}
                \advance\pgf@ya by -0.5\pgflinewidth%
                \advance\pgf@yb by  0.5\pgflinewidth%
                \pgfpathrectanglecorners{\pgfqpoint{\pgf@xb}{\pgf@yb}}{\pgfqpoint{\pgf@xa}{\pgf@ya}}
                \pgfusepath{fill}
             \fi
             \ifpullback
                % -- if option pullback is given draw hook
            \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
                \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
                \pgf@xc=\pgf@xb
                \advance\pgf@xc by  3\pgflinewidth
                \pgf@yc=\pgf@ya
                \advance\pgf@yc by -2\pgflinewidth
                \pgfpathmoveto{\pgfqpoint{\pgf@xc}{\pgf@ya}}
                \pgfpathlineto{\pgfqpoint{\pgf@xc}{\pgf@yc}}
                \pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@yc}}
                \pgfusepath{stroke}
             \fi
        \endgroup
        }
    }
    \makeatother
    \begin{document}

    \begin{tikzpicture}
      \draw (0,-2) grid (6,3);
      \node[fill=blue!20,line width=2pt,iso,draw,minimum width=2.5cm,inner ysep=0pt] at (2,2){$=$};
      \node[fill=green!20,pullback,line width=1.25pt,iso,draw,minimum width=2.5cm,inner ysep=0pt] at (2,1){$=$};
    \end{tikzpicture}
\end{document}

This solution also takes care of the fact that the rectangle used to fill the box overrides part of the top and bottom lines, halving their width. Hence before drawing the filler rectangle, the northeast and southwest y-coordinates are altered by half \pgflinewidth. On option pullback is added which draws a small hock in the top left corner. [This shape is meant to depict a iso-2-cell in 2-tangles for 2-categories].

3
  • Short answer is that you can't. A path has to have constant width and so you can't have some bits invisible and some visible. So you need two paths, as percusse's answer gives. (Longer explanation at the question I linked to under percusse's answer) Mar 31, 2012 at 20:39
  • It's best to leave the question as the question, otherwise it's hard for others to see what the problem was and so to benefit from the answer. If you feel that the code you actually end up with is interestingly different to the answer you were given the it is quite alright to post your own answer - just make sure to attribute it correctly, and ettiquete says you shouldn't accept your own answer if it was derived from another's. Apr 1, 2012 at 21:23
  • @AndrewStacey I agree with both of you and glad that a simple swap was adequate. Indeed you can show off your end solution with an image that you can upload to your answer (via using the image button on the toolbar).
    – percusse
    Apr 1, 2012 at 21:54

1 Answer 1

3

The following does the job (thanks to Andrew Stacey's nice correction).

\documentclass{article}
\usepackage{tikz}

\makeatletter
\pgfdeclareshape{iso}{%
%
\inheritsavedanchors[from=rectangle]
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{north west}
\inheritanchor[from=rectangle]{north east}
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\inheritanchor[from=rectangle]{mid}
\inheritanchor[from=rectangle]{mid west}
\inheritanchor[from=rectangle]{mid east}
\inheritanchor[from=rectangle]{base}
\inheritanchor[from=rectangle]{base west}
\inheritanchor[from=rectangle]{base east}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{south west}
\inheritanchor[from=rectangle]{south east}
%
\savedanchor\centerpoint
{
    \pgf@x=0pt
    \pgf@y=0pt
}
\anchor{text}{%
  \pgf@process{\centerpoint}
  \advance\pgf@y by -0.2pt
}
%
\backgroundpath{%
\northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\begingroup
\tikz@mode

\iftikz@mode@fill
\pgfpathrectanglecorners{\northeast}{\southwest}
\pgfusepath{fill}
\fi
\iftikz@mode@draw

\pgfpathmoveto\northeast
\pgfpathlineto{\pgfqpoint{\pgf@xb}{\pgf@ya}}
\pgfpathmoveto\southwest
\pgfpathlineto{\pgfqpoint{\pgf@xa}{\pgf@yb}}
\pgfusepath{stroke}
    \fi
    \endgroup
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[iso,draw,fill=yellow] (a) at (0,0) {slight yellow};
\end{tikzpicture}
\end{document} 

enter image description here

13
  • You need to test \iftikz@mode@fill. See this question for an example: tex.stackexchange.com/q/45567/86 Mar 31, 2012 at 20:35
  • @AndrewStacey I took a slightly different path but I am not sure if it is indeed robust.
    – percusse
    Mar 31, 2012 at 20:36
  • You're restricting your options that way. You can't use color and you can't turn off the drawn lines. Okay, so it's hard to imagine wanting to do those with this example, but it's good discipline to not impose unnecessary restrictions. Mar 31, 2012 at 20:48
  • @AndrewStacey That's indeed my motivation since if you don't need the lines you don't use the iso key anyway.
    – percusse
    Mar 31, 2012 at 20:50
  • True. But you could do an every node/.style={iso} if you only had a few that didn't need the lines, then not draw those lines on the few rather than changing the shapes. Mar 31, 2012 at 20:52

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.