9

I would like to create some nodes having a parametrized shape to create some schematic vehicles shown in the picture below. The picture shows a hierachical representation of a vehicle chassis platform. The green elements should be scaled along the x-axis, to represent different sized cars. The blue shapes (except the tires) are not part of the question, I will plot them using some x,y-data.

Desired result.

The picture is drawn in power point, but I appreciate a tikz solution for my Latex document. My first attempt was:

\documentclass[x11names]{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}
% =================================================
% Start the picture
\begin{tikzpicture}
    \tikzstyle{architecture}=[decoration={markings,  
        mark connection node=dmp,
        mark=at position 0 with 
        {
            \filldraw[color=red!25,draw=black] (-0.5,-0.45) -- (-0.5,-0.3) arc(-90:90:0.2) -- (-0.5,0.45) -- (-0.2,0.45) -- (0,0.75) -- (0.2,0.45) -- (0.5,0.45) -- (0.5,0.1) arc(90:270:0.2) -- (0.5,-0.45) -- cycle;
            \node (dmp) {#1};
        }
    }, decorate]
    \tikzstyle{segmentl}=[decoration={markings,  
        mark connection node=dmp,
        mark=at position 0 with 
        {
            \filldraw[color=green!25,draw=black] (-0.4,-0.4) -- (-0.4,-0.2) -- (-0.6,-0.2)-- (-0.6,0.2) -- (-0.4,0.2) -- (-0.4,0.4) --  (0.4,0.4) -- (0.4,0.2) arc(90:-90:0.2) -- (0.4,-0.4) -- cycle;
            \node (dmp) {#1};
        }
    }, decorate]
    \tikzstyle{segmentr}=[decoration={markings,  
        mark connection node=dmp,
        mark=at position 0 with 
        {
            \filldraw[color=green!25,draw=black] (-0.4,-0.4) -- (-0.4,-0.2) arc(270:90:0.2) -- (-0.4,0.4) --  (0.4,0.4) -- (0.4,0.2) -- (0.6,0.2)-- (0.6,-0.2) -- (0.4,-0.2) -- (0.4,-0.4) -- cycle;
            \node (dmp) {#1};
        }
    }, decorate]
    \tikzstyle{tire}=[decoration={markings,  
        mark connection node=dmp,
        mark=at position 0 with 
        {
            \filldraw[color=blue!25,draw=black,rounded corners=3pt] (0.2,-0.2) -- (0.2,-0.6) -- (-0.2,-0.6) -- (-0.2,0.6) --  (0.2,0.6) -- (0.2,0.2) -- cycle;
            \node (dmp) {};
        }
    }, decorate]

    \draw (0,0) node[architecture=$A$] {};
    \draw (-1.5,-0.1) node[tire] {};
    \draw (1.5,-0.1) node[tire] {};
    \draw (0.9,-0.1) node[segmentr=$S1$] {};
    \draw (-0.9,-0.1) node[segmentl=$S1$] {};

\end{tikzpicture}
% =================================================
\end{document}

Resulting in:enter image description here

But my approach is not flexible enough. I think that using decoration marks is the wrong way. I know that there is a possibility to declare new shapes (see 101.5 Declaring New Shapes in the manual), but I don't get it. Anybody got an idea?

  • The big decision is whether to make the shapes expand to fit the text or not. TikZ normally uses expanding shapes, but Circuitikz (for example) does not. Needless to say, non-expanding shapes are easier. The down side of creating your own shapes is that you need to use graphics primitives like \pgfpathmoveto and \pgfpathlineto. – John Kormylo Jun 9 '16 at 17:49
  • OK, so it would be a more user friendly approach to create seperate non-expanding shapes for "S1" and "S2". I also thought about creating a specific style for each element. But Is it possible to define a path in a style? Am I able to rotate it afterwards like for the left and right "S1"-element? – Runkelhuhn Jun 10 '16 at 5:43
  • You can also connect them together at specific anchor points. I have a tutorial on creating a new shape (Multipole) at elfsoft2000.com/projects/index.htm. – John Kormylo Jun 10 '16 at 11:43
  • What about using pics? They are a little less flexible than nodes, but they are much easier to define because you can define them using regular TikZ code. – cfr Jun 13 '16 at 0:45
3

pics are not as flexible as nodes but they are much easier to design, especially for complex shapes. For example, I've created pics for cats, aliens, cauldrons and trams. I would not like to create a cat node - catcodes being quite bad enough!

Here's a simple translation of your styles into pics. The example demonstrates some of the things you can do with them. You would need to experiment further in light of your specific needs to determine if pics would suffice for your needs.

\documentclass[tikz,border=10pt,multi,x11names]{standalone}
% original MWE from Runkelhuhn's question at http://tex.stackexchange.com/q/313899/
\usetikzlibrary{fit,positioning}
\begin{document}
\tikzset{% \tikzstyle is deprecated
  architecture/.pic={%
    \tikzset{architect/architecture/.cd, #1, /tikz/.cd}%
    \begin{scope}[local bounding box/.expanded=\archname]
      \begin{scope}[inner sep=0pt, outer sep=0pt, x=\archsize, y=\archsize, pic actions]
        \filldraw [fill=architecturefill] node (-dmp)  [inner sep=0pt, outer sep=0pt] {\tikzpictext} (-5,-4.5) -- (-5,-3) arc(-90:90:2) -- (-5,4.5) -- (-2,4.5) -- (0,7.5) -- (2,4.5) -- (5,4.5) -- (5,1) arc(90:270:2) -- (5,-4.5) -- cycle;
      \end{scope}
    \end{scope}
  },
  segment/.pic={
    \tikzset{architect/segment/.cd, #1, /tikz/.cd}%
    \begin{scope}[local bounding box/.expanded=\archname]
      \begin{scope}[inner sep=0pt, outer sep=0pt, x=\archsize, y=\archsize, pic actions]
        \filldraw [fill=segmentfill] node (-dmp)  [inner sep=0pt, outer sep=0pt] {\tikzpictext} (-4,-4) -- (-4,-2) -- (-6,-2)-- (-6,2) -- (-4,2) -- (-4,4) --  (4,4) -- (4,2) arc(90:-90:2) -- (4,-4) -- cycle;
      \end{scope}
    \end{scope}
  },
  tire/.pic={
    \tikzset{architect/tire/.cd, #1, /tikz/.cd}%
    \begin{scope}[local bounding box/.expanded=\archname]
      \begin{scope}[inner sep=0pt, outer sep=0pt, x=\archsize, y=\archsize, pic actions]
        \filldraw [fill=tirefill, rounded corners=3pt] node (-dmp)  [inner sep=0pt, outer sep=0pt] {\tikzpictext} (2,-2) -- (2,-6) -- (-2,-6) -- (-2,6) --  (2,6) -- (2,2) -- cycle;
      \end{scope}
    \end{scope}
  },
  architect/.search also={/tikz},
  architect/.cd,
  size/.store in=\archsize,
  name/.store in=\archname,
  architecture fill/.code={\colorlet{architecturefill}{#1}},
  segment fill/.code={\colorlet{segmentfill}{#1}},
  tire fill/.code={\colorlet{tirefill}{#1}},
  architecture/.search also={/tikz/architect,/tikz},
  architecture/.cd,
  fill/.forward to={/tikz/architect/architecture fill},
  /tikz/architect/.cd,
  segment/.search also={/tikz/architect,/tikz},
  segment/.cd,
  fill/.forward to={/tikz/architect/segment fill},
  /tikz/architect/.cd,
  tire/.search also={/tikz/architect,/tikz},
  tire/.cd,
  fill/.forward to={/tikz/architect/tire fill},
  /tikz/architect/.cd,
  size=1mm,
  name=,
  architecture fill=red!25,
  segment fill=green!25,
  tire fill=blue!25,
  draw=black,
}
\begin{tikzpicture}
  \pic [pic text=$A$] {architecture={name=a}} ;
  \pic at (-1.5,-.1) {tire={name=t1}};
  \pic at (1.5,-.1) {tire={name=t2}};
  \pic [pic text=$S1$, xscale=-1] at (0.9,-0.1) {segment={name=sr}};
  \pic [pic text=$S1$] at (-0.9,-0.1) {segment={name=sl}};
  \path (a) ++(0,-20mm) pic [pic text=$B$] {architecture={name=b,fill=cyan!75!blue}} ;
  \path (a) ++(0,-21mm) coordinate (p);
  \path (p -| t1)  pic [rotate=2.5] {tire={fill=magenta, name=t3}};
  \pic [rotate=-2.5] at (p -| t2) {tire={fill=orange, name=t4}};
  \pic at (sr |- p) [pic text=$S2$, xscale=-1] {segment={fill=green!50!cyan} } ;
  \pic at (sl |- p) [pic text=$S2$] {segment={fill=yellow} } ;
  \node (w) [below=of b.south] {Dodgy Wheels};
  \draw [->] (w) edge (t3.south east) -- (t4.south west);
\end{tikzpicture}
\end{document}

non-dodgy & dodgy with pics

  • Thanks cfr, I will try your solution. Hopefully it fits. – Runkelhuhn Jun 19 '16 at 19:24

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.