Dimensioning of a technical drawing in TikZ

Is there is an easy way to mark dimensions in a technical drawing with TikZ?

Is there a library or something?

Edit

I am using XeLaTeX.

Update

I chose Martin's answer because it serves me well for the moment. Ultimately the best solution would be a library that, in an easy and consistent manner, would allow to change the arrow/dimension lines styles, would support polar coordinates, would allow to choose 2 nodes and the vertical distance that you want the dimension to be typeseted etc.

-
Very good question! However, be careful with the expression dimensions. Normally it is used for TeX dimen registers, aka. LaTeX lengths. (Update: I edited the question to make it clear that it is about dimensions in technical drawings) –  Martin Scharrer Apr 4 '11 at 10:45
I was planning to add something similar to my tikz-timing package to draw time differences, but never found time doing it. I was under the impression that this has to be done manually. –  Martin Scharrer Apr 4 '11 at 10:51
I expect this could be done with Andrew Stacey's tikzmark solution to this braces problem... –  Seamus Apr 4 '11 at 11:28
If you're happy with manually adding the values, the following question might be interesting: tex.stackexchange.com/questions/12296/… –  Jake Apr 4 '11 at 11:39
@Jake Thank you mate! I don't care about manually adding values. Actually I am mostly intrested in parametric values rather than numeric ones. –  pmav99 Apr 4 '11 at 13:14

\documentclass[tikz,margin=5pt]{standalone}
\usepackage{xparse}
\usetikzlibrary{calc}

\tikzset{%
Cote node/.style={%
midway,
sloped,
fill=white,
inner sep=1.5pt,
outer sep=2pt
},
Cote arrow/.style={%
<->,
>=latex,
very thin
}
}

\makeatletter
\NewDocumentCommand{\Cote}{%
s       % cotation avec les flèches à l'extérieur
D<>{1.5pt} % offset des traits
O{.75cm}    % offset de cotation
m       % premier point
m       % second point
m       % étiquette
D<>{o}  % () coordonnées -> angle
% h -> horizontal,
% v -> vertical
% o or what ever -> oblique
O{}     % parametre du tikzset
}{%

{\tikzset{#8}

\coordinate (@1) at #4 ;
\coordinate (@2) at #5 ;

\if #7v % Cotation verticale
\coordinate (@0) at ($($#4!.5!#5$) + (#3,0)$) ;
\coordinate (@4) at (@0|-@1) ;
\coordinate (@5) at (@0|-@2) ;
\else
\if #7h % Cotation horizontale
\coordinate (@0) at ($($#4!.5!#5$) + (0,#3)$) ;
\coordinate (@4) at (@0-|@1) ;
\coordinate (@5) at (@0-|@2) ;
\else % cotation encoche
\ifnum\pdfstrcmp{\unexpanded\expandafter{\@car#7\@nil}}{(}=\z@
\coordinate (@5) at ($#7!#3!#5$) ;
\coordinate (@4) at ($#7!#3!#4$) ;
\else % cotation oblique
\coordinate (@5) at ($#5!#3!90:#4$) ;
\coordinate (@4) at ($#4!#3!-90:#5$) ;
\fi\fi\fi

\draw[very thin,shorten >= #2,shorten <= -2*#2] (@4) -- #4 ;
\draw[very thin,shorten >= #2,shorten <= -2*#2] (@5) -- #5 ;

\IfBooleanTF #1 {% avec étoile
\draw[Cote arrow,-] (@4) -- (@5)
node[Cote node] {#6\strut};
\draw[Cote arrow,<-] (@4) -- ($(@4)!-6pt!(@5)$) ;
\draw[Cote arrow,<-] (@5) -- ($(@5)!-6pt!(@4)$) ;
}{% sans étoile
\ifnum\pdfstrcmp{\unexpanded\expandafter{\@car#7\@nil}}{(}=\z@
\draw[Cote arrow] (@5) to[bend right]
node[Cote node] {#6\strut} (@4) ;
\else
\draw[Cote arrow] (@4) -- (@5)
node[Cote node] {#6\strut};
\fi
}}
}
\makeatother

\begin{document}
\begin{tikzpicture}
\small
\draw[thick,blue,fill=blue!25]
(0,1) coordinate (A)
--  (3,1) coordinate (B)
--  (5,2) coordinate (C)
--  (5,4) coordinate (D)
--  (3,4) coordinate (E)
--  (2.5,3) coordinate (F)
--  (2,4) coordinate (G)
--  (0,4) coordinate (H)
--cycle ;

\draw[red,fill=red!25] (2.5,3.9) circle (.39) ;

\Cote{(A)}{(B)}{1}

\Cote{(B)}{(C)}{2}

\Cote{(B)}{(C)}{2 bis}<h>[Cote node/.append style={fill=blue!25}]

\Cote[.3cm]{(C)}{(D)}{3 bis}
\Cote[.7cm]{(C)}{(D)}{3}[Cote node/.append style={rotate=-90}]
\Cote[1.1cm]{(C)}{(D)}{3 ter}[%
Cote node/.append style={right,rotate=-90}]

\Cote[2cm]{(G)}{(E)}{?$^\circ$}<(F)>

\Cote*[1.2cm]{(2.11,3.9)}{(2.89,3.9)}{4}[%
Cote node/.append style={below=-1pt,fill=blue!25}]

\Cote[-2cm]{(A)}{(2.5,4.29)}{5}<v>

\end{tikzpicture}
\end{document}

-
This looks great! Perhaps it could be integrated in tikz or be released as a separate package. –  pmav99 May 24 at 11:09

I don't know about any library which allows dimensions to be easily added to technical drawings in TikZ. You can however add some manually. Simple rectangle and circles could be done using nodes which simplifies the drawing of additional material because the node anchors can be used. Differently shaped objects must be drawn using polygons.

Here an example of how to might be done. I can image some macros which take two points/coordiantes and some options like direction (left, right, above, below) and distance and then draw the dimension labels automatically. Wouldn't be that hard to code.

\usepackage{tikz}
\usetikzlibrary{patterns}
\usetikzlibrary{arrows}
% Adapted from the 'patterns' library: enlarged the distance between the lines from 4pt to 10pt
\pgfdeclarepatternformonly{north east lines wide}{\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{10pt}{10pt}}{\pgfqpoint{9pt}{9pt}}%
{
\pgfsetlinewidth{0.4pt}
\pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
\pgfpathlineto{\pgfqpoint{9.1pt}{9.1pt}}
\pgfusepath{stroke}
}

\tikzset{%
body/.style={inner sep=0pt,outer sep=0pt,shape=rectangle,draw,thick,pattern=north east lines wide},
dimen/.style={<->,>=latex,thin,every rectangle node/.style={fill=white,midway,font=\sffamily}},
symmetry/.style={dashed,thin},
}

\begin{document}
\begin{tikzpicture}
% A body
\node [body,minimum height=4cm,minimum width=1.5cm,anchor=south west] (body1) at (0,0) {};
% Dimensions
\draw (body1.south west) -- ++(-1,0) coordinate (D1) -- +(-5pt,0);
\draw (body1.north west) -- ++(-1,0) coordinate (D2) -- +(-5pt,0);
\draw [dimen] (D1) -- (D2) node {4.00};
% Helper nodes can be reused
\draw (body1.south west) -- ++(0,-1) coordinate (D1) -- +(0,-5pt);
\draw (body1.south east) -- ++(0,-1) coordinate (D2) -- +(0,-5pt);
\draw [dimen] (D1) -- (D2) node {1.50};

% Non-rectangle shapes must be drawn as polygone
\begin{scope}[shift={(3,0)}]
\draw [body] (0,0) -- (0,4) -- (.5,4) -- (.5,5) -- (1.,5) -- (1.,4) -- (1.5,4) -- (1.5,0) -- cycle;
% Draw symmetry lines
\draw [symmetry] (.75,-.25) -- (.75,5.25);
% Dimensions
\draw (1.5,0) -- ++(1,0) coordinate (D1) -- +(5pt,0);
\draw (1.5,4) -- ++(1,0) coordinate (D2) -- +(5pt,0);
\draw [dimen] (D1) -- (D2) node {4.00};
\draw (0.0,0) -- ++(0,-1) coordinate (D1) -- +(0,-5pt);
\draw (1.5,0) -- ++(0,-1) coordinate (D2) -- +(0,-5pt);
\draw [dimen] (D1) -- (D2) node {1.50};
\draw (0.5,5) -- ++(0,1) coordinate (D1) -- +(0,5pt);
\draw (1.0,5) -- ++(0,1) coordinate (D2) -- +(0,5pt);
\draw [dimen,-] (D1) -- (D2) node [above=5pt] {0.50};
\draw [dimen,<-] (D1) -- ++(-5pt,0);
\draw [dimen,<-] (D2) -- ++(+5pt,0);
\end{scope}
\end{tikzpicture}
\end{document}


Result:

-
Thank you very much for your great answer. Unfortunately it doesn't work out of the box for me, as I am using xelatex and I get compilation warnings (pgfsys-xetex.def does not support patterns). The only difference that I can notice with the produced output is that instead of the hatch the polygons are filled with black - the dimensions are being typeset correctly. My tikz knowledge is limited to very basic stuff. Is pattern declaration necessary for the macro to work? –  pmav99 Apr 4 '11 at 13:12
@pmav99: Unfortunately XeTeX doesn't support patterns yet. See this answer for a discussion about it. One solution (which is shown there) is to compile the drawing standalone using pdflatex and include it as PDF image. –  Martin Scharrer Apr 4 '11 at 13:20
@pmav99: Also, if it is just about the pattern, you could draw it manually, e.g. using a loop inside a larger rectangle behind the shapes and then use them as clipping path so that everything outside their borders is clipped away. –  Martin Scharrer Apr 4 '11 at 13:30
I just removed the pattern code and it works fine for me. I don't care for the hatch at the moment at least. Thank you again for your help! –  pmav99 Apr 4 '11 at 14:05

Here is a quick solution extending Jake's work on this question:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{arrows,calc,decorations.markings}

\begin{document}
\pgfarrowsdeclarecombine{|<}{>|}{|}{|}{latex}{latex}
\def\Dimline[#1][#2][#3]{
\begin{scope}[>=latex] % redef arrow for dimension lines
\draw let \p1=#1, \p2=#2, \n0={veclen(\x2-\x1,\y2-\y1)} in [|<->|,
decoration={markings, % switch on markings
mark=at position .5 with {\node[#3] at (0,0) {\DimScale{\n0}};},
},
postaction=decorate] #1 -- #2 ;
\end{scope}
}

%% The following macro is used to scale a dimension from points to the
%% display scale.  The following code divides the number of points by
%% 28.4 to roughly get the width in centimeters (rounding to the
%% nearest millimeter):
\def\DimScale#1{\pgfmathparse{round(#1/28.4*10.0)/10.0}\pgfmathresult cm}

\begin{tikzpicture}

\node at (0,0) (nA) {A};
\node at (3,0) (nB) {B};
\Dimline[($(nA)+(0,1)$)][($(nB)+(0,1)$)][above];

\node at (0,-3) (nC) {C};
\Dimline[($(nA)+(-1,0)$)][($(nC)+(-1,0)$)][left];
\Dimline[($(nC)+(0.3,-0.3)$)][($(nB)+(0.3,-0.3)$)][right];

\node at (3,-3) (nD) {D};
\Dimline[($(nC)+(0,-1)$)][($(nD)+(0,-1)$)][below];
\Dimline[($(nB)+(1,0)$)][($(nD)+(1,0)$)][right];

\end{tikzpicture}

\end{document}


Basically, what is going on here is we are automatically calculating the distance between points in units of pt by using PGF/TikZ's veclen function. My new macro \DimScale then converts that length into centimeters (you could of course change it to convert to whichever units you want). Here is the result:

-
Nice! But why are you using three [ ] arguments? The first two should be mandatory { } arguments. You still need to draw connection lines from the points to the arrow tips. Simply having the ->| style isn't enough. –  Martin Scharrer Apr 4 '11 at 14:01
The [ ] arguments are a carryover from Jake's solution (I didn't bother changing them). As for the connection lines, I wasn't sure if the question was asking more for that part (which you have already solved) or if the question was asking for an automated way to calculate/annotate the dimensions. –  ESultanik Apr 4 '11 at 14:10
Thank you very much for your answer! Personally I don't need an automated way to calculate the dimensions, but maybe somebody else needs this feature. It is always good to have options –  pmav99 Apr 4 '11 at 15:47