2

I'm searching a way to resize a tikz image without changing the line thickness, the font size, etc. something working as pgfplots when using the arguments width=15cm, unit vector ratio=1 1 1,.

I've already tried:

  • scale
  • resizebox

what works best at the moment is changing the argument x=1,92cm, y=1,92cm for \begin{tikzpicture} to have an image matching approximately the expected size without changing the lines thickness or the font size. is there anyone having a better approach?

main.tex

%%%%%%%%%%%%%%%%%% INTRODUCTION %%%%%%%%%%%%%%%%%%
\documentclass[border=10pt]{standalone}

%%%%%%%%%%%%%%%%%% PACKAGE %%%%%%%%%%%%%%%%%%
\usepackage{tikz}%  permet de dessiner des figures, des graphiques
\usepackage{adjustbox}% permet de déterminer une taille de fenêtre

%%  FONT
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{tgadventor}% paquet de police de caractère TGadventor
\usepackage{sansmath}%  Copie-colle la police active dans \sfdefault (/!\ N'EST PAS UNE POLICE DE CARACTÈRES)

%%%%%%%%%%%%%%%%%% DOCUMENT %%%%%%%%%%%%%%%%%%
\begin{document}
%\begin{adjustbox}{width={15cm},totalheight={15cm},keepaspectratio}
\begin{tikzpicture}[font={\sansmath\sffamily\Large}, line width=0.4mm, line cap=round, line join=round, >=latex, x=1.92cm, y=1.92cm,]
    \draw[->] (-5-.4,0) -- (2+.4,0);
    \foreach \x in {-5,...,2}
    {   \draw[shift={(\x,0)},color=black] (0pt,2pt) -- (0pt,-2pt);
    }
    \foreach \x in {-1,1}
    {   \draw[shift={(\x,0)},color=black] (0,0) node[inner sep=5pt, above] {$\x$};
    }
    \draw[fill=orange] 
    (-2.9,0) coordinate (O) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$E$}
    (-5,0) coordinate (A) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$F$}
    (1.4,0) coordinate (B) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$G$}
    (-2,0) coordinate (C) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$H$};
\end{tikzpicture}
%\end{adjustbox}
\end{document}
Nilcouv
  • 539

2 Answers2

2

The following is based on my answer here, which itself was based on code from marmot. The idea is to determine the desired scale using an automated, iterative process.

The code given below defines a style named autoscale autoid (in /tikz). When a tikzpicture uses autoscale autoid={width}{height}, its bounding box is measured when finished, and a scale factor is computed from the size of the bounding box and the target dimensions. This scale factor is written to the .aux file, associated with an automatically generated identifier. The next time you compile the picture, thanks to the saved scale factor, the /tikz/scale key is automatically applied to the tikzpicture in order to make it as large as possible without exceeding any of the prescribed width and height, while keeping its aspect ratio.

In your case, since your only constraint is on the width, you can use \maxdimen for the height argument of the autoscale autoid style; this effectively removes the constraint on the height.

When the picture is recompiled using the computed scale, it will in general be close to the “ideal” size, but won't exactly have this size after the first run. This is because of things such as labels that are not affected by the /tikz/scale key. However, the process normally converges rather quickly and the result is already excellent after only two or three compilation runs. In extreme cases, you might want to remove the .aux file in order to start over with a scale of 1 for each picture using the autoscale autoid style.

The following example uses autoscale autoid={15cm}{\maxdimen} in the options of your tikzpicture environment and draws a 15 cm long orange rule above the picture in order to allow one to easily evaluate the result.

\documentclass{article}
\usepackage[hmargin=2cm]{geometry} % for your 15 centimeters wide figure
\usepackage{sansmath}              % only needed for your particular figure
\usepackage{xparse}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\ExplSyntaxOn

\msg_new:nnn { nilcouv } { duplicate-figure-id }
  { duplicate~figure~identifier:~'#1'. }

% Sequence recording all figure identifiers (for the 'scale to max size' TikZ
% style) found so far
\seq_new:N \g__nilcouv_scale_to_max_style_figure_ids_seq
% Counter used when generating automatic figure identifiers for 'autoscale'
\int_new:N \g_nilcouv_last_autogenerated_figure_nb_int

\cs_new_protected:Npn \__nilcouv_check_unique_id:n #1
  {
    \seq_if_in:NnTF \g__nilcouv_scale_to_max_style_figure_ids_seq {#1}
      { \msg_error:nnn { nilcouv } { duplicate-figure-id } {#1} }
      { \seq_gput_right:Nn \g__nilcouv_scale_to_max_style_figure_ids_seq {#1} }
  }

% Automatic generation of figure ids (the pattern is defined here)
\cs_new:Npn \__nilcouv_autogenerated_id:n #1 { nilcouv~autogenerated~id~#1 }

\cs_generate_variant:Nn \__nilcouv_autogenerated_id:n { V }

\cs_new_protected:Npn \__nilcouv_autoscale:nnn #1#2#3
  { \tikzset { scale~to~max~size={#1}{#2}{#3} } }

\cs_generate_variant:Nn \__nilcouv_autoscale:nnn { x }

\cs_new_protected:Npn \__nilcouv_autoscale_autoid:nn #1#2
  {
    % Increment the counter
    \int_gincr:N \g_nilcouv_last_autogenerated_figure_nb_int
    % Call the 'autoscale' style with the new id
    \__nilcouv_autoscale:xnn
      { \__nilcouv_autogenerated_id:V
        \g_nilcouv_last_autogenerated_figure_nb_int
      }
      {#1}
      {#2}
  }

% Set up aliases using LaTeX2e naming style
\cs_new_eq:NN \nilcouv@check@unique@id \__nilcouv_check_unique_id:n
\cs_new_eq:NN \nilcouv@autoscale@autoid \__nilcouv_autoscale_autoid:nn
\ExplSyntaxOff

% Autoscaling technique that doesn't affect font sizes in TikZ pictures.
% (based on code from marmot: <https://tex.stackexchange.com/a/497749/73317>)
%
% #1: unique per-picture id allowing several pictures to use this mechanism
%     in a given document (it should contain no control sequence token nor
%     active character)
% #2: target width
% #3: target height
\newcommand*{\nilcouv@ExportBB}[3]{%
  \path let
    \p1=($(current bounding box.north east)-(current bounding box.south west)$),
    \n1={#2/\x1},\n2={#3/\y1}
  in \pgfextra{\pgfmathsetmacro{\nilcouv@figscale}{min(\n1,\n2)}%
               \expandafter\xdef\csname nilcouv@auto@figscale@#1\endcsname{%
                 \nilcouv@figscale}};
  \immediate\write\@mainaux{%
    \string\expandafter
    \gdef\string\csname\space nilcouv@auto@figscale@#1\string\endcsname{%
      \csname nilcouv@auto@figscale@#1\endcsname}}%
}

\tikzset{
  % Arguments: figure identifier, target width, target height
  scale to max size/.style n args={3}{
    execute at end picture={\nilcouv@ExportBB{#1}{#2}{#3}},
    /utils/exec={\nilcouv@check@unique@id{#1}%
                 \ifcsname nilcouv@auto@figscale@#1\endcsname
                   \wlog{Found autoscale value for picture '#1'}%
                 \else
                   \typeout{Automatically-scaled pictures: please recompile
                            for picture '#1'.}%
                   \expandafter\gdef
                     \csname nilcouv@auto@figscale@#1\endcsname{1}%
                 \fi},
    scale=\csname nilcouv@auto@figscale@#1\endcsname,
  },
  % Same style except the id is automatically generated using a counter
  autoscale autoid/.style 2 args={%
    /utils/exec={\nilcouv@autoscale@autoid{#1}{#2}}},
}
% End of the code based on <https://tex.stackexchange.com/a/497749/73317>
\makeatother

\begin{document}

\noindent
\textcolor{orange}{\rule{15cm}{0.4pt}}\\ % print a 15cm long rule for comparison
\begin{tikzpicture}[
  font={\sansmath\sffamily\Large}, line width=0.4mm, line cap=round,
  line join=round, >=latex, x=1.92cm, y=1.92cm,
  autoscale autoid={15cm}{\maxdimen} % <---------- this
  ]
    \draw[->] (-5-.4,0) -- (2+.4,0);
    \foreach \x in {-5,...,2} {
      \draw[shift={(\x,0)},color=black] (0pt,2pt) -- (0pt,-2pt);
    }
    \foreach \x in {-1,1} {
      \draw[shift={(\x,0)},color=black] (0,0) node[inner sep=5pt, above] {$\x$};
    }
    \draw[fill=orange]
    (-2.9,0) coordinate (O) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$E$}
    (-5,0) coordinate (A) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$F$}
    (1.4,0) coordinate (B) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$G$}
    (-2,0) coordinate (C) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$H$};
\end{tikzpicture}

\end{document}

enter image description here

frougon
  • 24,283
  • 1
  • 32
  • 55
1

You can use pgfplots for that, and thus set the width. Here is your plot and a pgfplots version thereof. If you produce many of those, I think you will be better off with pgfplots because you can store all these keys in a style.

%%%%%%%%%%%%%%%%%% INTRODUCTION %%%%%%%%%%%%%%%%%%
\documentclass[tikz,border=10pt]{standalone}

%%%%%%%%%%%%%%%%%% PACKAGE %%%%%%%%%%%%%%%%%%
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\usepackage{adjustbox}% permet de déterminer une taille de fenêtre

%%  FONT
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{tgadventor}% paquet de police de caractère TGadventor
\usepackage{sansmath}%  Copie-colle la police active dans \sfdefault (/!\ N'EST PAS UNE POLICE DE CARACTÈRES)

%%%%%%%%%%%%%%%%%% DOCUMENT %%%%%%%%%%%%%%%%%%
\begin{document}
%\begin{adjustbox}{width={15cm},totalheight={15cm},keepaspectratio}
\begin{tikzpicture}[font={\sansmath\sffamily\Large}, line width=0.4mm, line cap=round, line join=round, >=latex, x=1.92cm, y=1.92cm,]
    \draw[->] (-5-.4,0) -- (2+.4,0);
    \foreach \x in {-5,...,2}
    {   \draw[shift={(\x,0)},color=black] (0pt,2pt) -- (0pt,-2pt);
    }
    \foreach \x in {-1,1}
    {   \draw[shift={(\x,0)},color=black] (0,0) node[inner sep=5pt, above] {$\x$};
    }
    \draw[fill=orange] 
    (-2.9,0) coordinate (O) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$E$}
    (-5,0) coordinate (A) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$F$}
    (1.4,0) coordinate (B) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$G$}
    (-2,0) coordinate (C) node[circle, draw=black, fill=orange, scale=0.4] {} node[inner sep=7pt, anchor=north, scale= 1] {$H$};
\end{tikzpicture}
%\end{adjustbox}

\pgfplotsset{Nilcouv/.style={width=16.5cm,
    axis y line=none,axis x line=center,
    xticklabel={\pgfmathtruncatemacro\itest{(\tick==1 ? 1 : (\tick==-1 ? -1 : 0))}%
    \unless\ifnum\itest=0\relax $\itest$\fi},xtick distance=1,
    every inner x axis line/.append style={line width=0.4mm, line
    cap=round,-latex},x tick label style={above=4pt},
    major tick length=6pt,every tick/.style={thick},
    every node near coord/.append style={anchor=north,yshift=-2pt,execute at begin node=$,
    execute at end node=$},enlarge x limits={rel=0.15}}}

\begin{tikzpicture}[font={\sansmath\sffamily\Large}, line join=round]
 \begin{axis}[Nilcouv]
 \addplot[nodes near coords,only marks,mark=*,
       mark options={fill=orange,draw=black,thick},
       point meta=explicit symbolic]
        table [meta=label,y expr=0] {
        x  label
        -2.9 E
        -5 F
        1.4 G
        -2 H
    };
 \end{axis}
\end{tikzpicture}
\end{document}

enter image description here