TikZ node placement and arrow drawing
There's a good chance some more elegant solution will appear soon, but here goes:
By using the
calc
library you can add node halfway betweensensors
andresources
, and positioninformation
with relation to this. I actually used the corners of these,resources.south west
andsensors.north west
, and put the new node midway between these.One way is to use relative coordinates to first go a little right of
processing
, then up, left toplanning
. By using|-
/-|
you can access coordinates that lie on the intersection of the horizontal line from one node and vertical line from another. That way you can end the arrow directly abovesensors.north east
, for example.I first add a new node,
lowerright
while drawing the line fromresources
toplanning
.(lowerright |- container.east)
is the point that lies on the vertical line fromlowerright
and the horizontal line fromcontainer.east
. Similar for(container.east -| resources.south east)
.You can add a node above the top left corner of
container
.Add
inner sep=<dimension>
to the container node, instead of defining width and height. This sets the distance from the contents of the node to the edge of the node.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fit,arrows,calc,positioning}
\begin{document}
\tikzstyle{b} = [rectangle, draw, fill=blue!20, node distance=3cm, text width=6em, text centered, rounded corners, minimum height=4em, thick]
\tikzstyle{c} = [rectangle, draw, inner sep=0.5cm, dashed]
\tikzstyle{l} = [draw, -latex',thick]
\begin{tikzpicture}[auto]
\node [b] (planning) {Planning};
\node [b, below=of planning] (resources) {Resources};
\node [b, below=of resources] (sensors) {Sensors};
\coordinate (RSmid) at ($(resources.south west)!0.5!(sensors.north west)$);
\node [b, left=of RSmid, node distance=4cm] (information) {Information system};
\node [b, below=of sensors] (processing) {Processing};
\node [c,fit=(resources) (sensors)] (container) {};
\path [l] (planning) -- (resources);
\path [l] (resources) -- (sensors);
\path [l] (sensors) -- (processing);
\path [l] (information) |- (planning);
\path [l] (information) |- (processing);
\node at (container.north west) [above right] {Desc};
\draw [l] (processing.east) -- ++(2,0) node(lowerright){} |- (planning.east);
\draw [l] (lowerright |- container.east) -- (container.east -| resources.south east);
\end{tikzpicture}
\end{document}
The problem with answers based on positioning is that very difficult to scale the picture. Here an answer with the possibility to scale the picture without modify the texts.
\documentclass{article}
\usepackage{tikz,fullpage}
\usetikzlibrary{arrows,calc,fit}
\begin{document}
\tikzstyle{b} = [rectangle, draw, fill=blue!20, text width=6em,
text centered, rounded corners, minimum height=4em, thick]
\tikzstyle{c} = [rectangle, draw, dashed]
\tikzstyle{l} = [draw, -latex',thick]
\begin{tikzpicture}[auto,scale=1.25]
\node [b] (planning) {Planning};
\node [b] (resources) at ([shift={(0,-3)}] planning) {Resources};
\node [b] (sensors) at ([shift={(0,-6)}] planning) {Sensors};
\coordinate (RSmid) at ($(resources)!0.5!(sensors)$);
\node [b] (information) at ([shift={(-4,0)}] RSmid) {Information system};
\node [b] (processing) at ([shift={(0,-9)}] planning) {Processing};
% here I need to use `transform shape` because I need to transform `inner sep` ,
% the node is empty, ouf !!!
\node [c,transform shape,inner sep=0.5cm,fit=(resources) (sensors)] (container) {};
\path [l] (planning) -- (resources);
\path [l] (resources) -- (sensors);
\path [l] (sensors) -- (processing);
\path [l] (information) |- (planning);
\path [l] (information) |- (processing);
\node at (container.north west) [above right] {Desc};
\draw [l] (processing.east) -- ++(2,0) node(lowerright){} |- (planning.east);
\draw [l] (lowerright |- container.east) -- (container.east -| resources.south east);
\end{tikzpicture}
\end{document}
Is this what you are looking for? I have made the following changes:
First (minor), I am using the
positioning
library to place the nodes rather than the defaultright of =
syntax, which the manual tells me is deprecated. Basically, you writeright = of
instead :)Second (minor), I am using the syntax
\tikzset{key/.style = }
rather than\tikzstyle
, since the manual also says this is deprecated (actually, I think it's not even in there anymore). It's good to get in the habit of using\tikzset
and, by extension,pgfkeys
, directly, and no more writing.Enough lecturing. You actually have most of the elements already. I placed
information
left = of container
to get it in the middle where you wanted it, and I created a fictitiouscoordinate
calledfit right
to the right ofcontainer
through which I could pass some piecewise-rectilinear paths. I also used "incremental coordinates" to get the arrow fromfit right
to move a desired distance left.I fixed the spacing of your rectangle by creating some more fictitious coordinates (also using incremental coordinates, rather than the
calc
library) to stretch the corners to the desired distance. It is not totally automated, but it is right there in the code. An alternative solution would be to useouter sep
on the nodesresources
andsensors
, which pushes their anchors away from their borders, but that also affects the placement of the arrows, so it's not useful here.I did use
outer sep
to place the label, as well as some more relative positioning.
Just a comment: you should have given a full document in your example. I had to guess which tikz libraries you used.
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,fit,arrows}
\tikzset{
b/.style
= {rectangle, draw, fill=blue!20, node distance=3cm, text width=6em,
text centered, rounded corners, minimum height=4em, thick},
c/.style
= {rectangle, draw, dashed,inner sep = 0pt},
l/.style
= {draw, -latex',thick}
}
\begin{document}
\begin{tikzpicture}[auto]
\node [b] (planning) {Planning};
\node [b, below = of planning] (resources) {Resources};
\node [b, below = of resources] (sensors) {Sensors};
\node [b, below = of sensors] (processing) {Processing};
\path
(resources.north west) ++(-1cm,1cm) coordinate (resources fit)
(sensors.south east) ++(1cm,-1cm) coordinate (sensors fit)
;
\node [c,fit=(resources fit) (sensors fit)] (container) {};
\node [above left = 0pt of container, anchor = south, draw, outer sep = 6pt] (container label) {Resources and sensors};
\node [b, left = 4cm of container] (information) {Information system};
\coordinate [right = 4cm of container] (fit right) {};
\path [l] (planning) -- (resources);
\path [l] (resources) -- (sensors);
\path [l] (sensors) -- (processing);
\path [l] (information) |- (planning);
\path [l] (information) |- (processing);
\path [l] (processing) -| (fit right) |- (planning);
\path [l] (fit right) -- ++(-4.5cm,0);
\end{tikzpicture}
\end{document}