84

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

dimensions in technical drawing

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.

6
  • 4
    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) Commented Apr 4, 2011 at 10:45
  • 1
    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. Commented Apr 4, 2011 at 10:51
  • I expect this could be done with Andrew Stacey's tikzmark solution to this braces problem...
    – Seamus
    Commented Apr 4, 2011 at 11:28
  • 1
    If you're happy with manually adding the values, the following question might be interesting: tex.stackexchange.com/questions/12296/…
    – Jake
    Commented Apr 4, 2011 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
    Commented Apr 4, 2011 at 13:14

4 Answers 4

55

enter image description here

-- New -- Horizontal and vertical cotations.

enter image description here

\documentclass{article}
\usepackage{xparse,tikz}
\usetikzlibrary{calc}

\RequirePackage{pdftexcmds}
\makeatletter
\let\pdfstrcmp\pdf@strcmp
\let\pdffilemoddate\pdf@filemoddate

\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 #7H % Cotation traits horizontaux
        \coordinate (@0) at ($($#4!.5!#5$) + (#3,0)$) ; 
        \coordinate (@5) at ($#5+(#3,0)$) ;
        \coordinate (@4) at ($#4+(#3,0)$) ;
    \else
    \if #7V % Cotation traits verticaux
        \coordinate (@0) at ($($#4!.5!#5$) + (#3,0)$) ; 
        \coordinate (@5) at ($#5+(0,#3)$) ;
        \coordinate (@4) at ($#4+(0,#3)$) ;
    \else
    \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\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}[red]

\Cote[.3cm]{(B)}{(C)}{2}[%
    red,Cote node/.append style={sloped}]]

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

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

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

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

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

\end{tikzpicture}

\bigskip

\begin{tikzpicture}
    \draw[thick,blue,fill=blue!25]
        (0,0) coordinate (A)
    --  (2,2) coordinate (B)
    --  (2,4) coordinate (C)
    --  (0,2) coordinate (D)
    --cycle ;

\Cote[.5]{(A)}{(B)}{5}<H>
\Cote[.5]{(D)}{(C)}{5}<V>
\end{tikzpicture}

\end{document}  
7
  • 6
    This looks great! Perhaps it could be integrated in tikz or be released as a separate package.
    – pmav99
    Commented May 24, 2014 at 11:09
  • @pmav99 I don't have the knowledge to do that but you or some one can do it, I'll be very glad.
    – Tarass
    Commented Dec 17, 2015 at 13:06
  • 1
    @pmav99. It has been released as a package! (See Answer below) ctan.org/tex-archive/graphics/pgf/contrib/tikz-dimline?lang=en Commented Dec 17, 2015 at 13:24
  • I am having trouble in the 2016 release of LaTeX3 in getting this to work. Says "undefined control sequence" in the tikzpicture environment. Truthfully, the tikz-dimline package is not as clean or easy to use as the code presented by @Tarass. Any ideas?
    – The Guy
    Commented Mar 8, 2016 at 15:46
  • @TheGuy I don't know what to say, I don't use LaTeX3 actually. Could you give a minimal example that doesn't work. Ask this as a new question. Btw, if some one wants to use this material as a base for a new package, please do. It is open source or what so ever ;-)
    – Tarass
    Commented Mar 9, 2016 at 14:04
50

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:

Result

4
  • 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
    Commented Apr 4, 2011 at 13:12
  • 2
    @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. Commented Apr 4, 2011 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. Commented Apr 4, 2011 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
    Commented Apr 4, 2011 at 14:05
25

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:

Screenshot of the code.

3
  • 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. Commented Apr 4, 2011 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
    Commented Apr 4, 2011 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
    Commented Apr 4, 2011 at 15:47
13

The package tikz-dimline is available in CTAN to that purpose.

3
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
    – Werner
    Commented Jun 15, 2015 at 18:22
  • Do you mean the answer should read. Use the package "tikz-dimline" which can be found here (github.com/renard/tikz-dimline)?
    – pheon
    Commented Jun 15, 2015 at 21:32
  • 2
    No. It would be far better to round off your answer with an example of what the package can do. Also, why use a github reference? Is this package not available as part of the regular distribution(s)?
    – Werner
    Commented Jun 15, 2015 at 21:46

You must log in to answer this question.

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