Como calcular caixas delimitadoras giradas?

Como calcular caixas delimitadoras giradas?

Editar:Conforme sugerido pela resposta de percusse, posso usar transform shapea opção. Minha primeira dúvida já está resolvida. Mas embora a segunda caixa delimitadora esteja agora alinhada localmente, ela não está correta. Na verdade, local bounding boxsempre calcula umglobalmentecaixa delimitadora alinhada (pontos verdes) e fitinclui north, east, southe westâncoras desta caixa delimitadora.

Minha pergunta agora é: como calcular umlocal bounding box localmentealinhado?

Novo exemplo (o retângulo azul à direita não cabe no caminho vermelho):

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  pt/.style={circle,minimum size=3pt,fill=#1,inner sep=0},
  red pt/.style={pt=red},
  green pt/.style={pt=green},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}[rotate=20]
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \begin{scope}[transform shape]
    \node[fit=(a)(b)(c)(d),draw=blue]{};
  \end{scope}

  % second case: fitting arbitrary path
  \begin{scope}[local bounding box=bb]
    \draw[red] (4,1) to[bend right] (6,1) -- (5,2);
  \end{scope}
  \node[green pt] at (bb.north west){};
  \node[green pt] at (bb.north east){};
  \node[green pt] at (bb.south west){};
  \node[green pt] at (bb.south east){};
  % how to find correct bounding box locally aligned ?
  \begin{scope}[transform shape]
    \node[fit=(bb),draw=blue]{};
  \end{scope}
\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Pergunta original:

Quero calcular algumas caixas delimitadoras. Aqui estão meus dois casos:

  1. para ajustar alguns nós (ou coordenadas), posso usar fita biblioteca.
  2. para ajustar caminhos arbitrários, posso usar um escopo com local bounding box=bb.

O código a seguir mostra esses dois casos:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  red pt/.style={circle,minimum size=3pt,fill=red,inner sep=0},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \node[fit=(a)(b)(c)(d),draw=blue]{};

  % second case: fitting arbitrary path
  \begin{scope}[local bounding box=bb]
    \draw[red] (4,1) to[bend right] (6,1) -- (5,2);
  \end{scope}
  \node[fit=(bb),draw=blue]{};
\end{tikzpicture}

insira a descrição da imagem aqui

Agora, eu quero fazer as mesmas coisasdentro de uma imagem girada!

Minhas duas perguntas:

  1. No meu primeiro caso (alguns nós), tenho que adicionar rotateuma opção ao meu nó de ajuste (já que rotatea opção não gira os nós).Como encontrar automaticamente o valor correto para esta opção (ex.: o ângulo entre o sistema de coordenadas atual e o sistema de coordenadas da tela)?

  2. No meu segundo caso (caminhos arbitrários), posso calcular a caixa delimitadora local, mas alinhada globalmente.Como calcular a caixa delimitadora local alinhada localmente de um caminho arbitrário?

Aqui está minha tentativa:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}
\tikzset{
  red pt/.style={circle,minimum size=3pt,fill=red,inner sep=0},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}[rotate=20]
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  % how to find the good value for rotate (here 20)?
  \node[rotate=20,fit=(a)(b)(c)(d),draw=blue]{};

  % second case: fitting arbitrary path
  \begin{scope}[local bounding box=bb]
    \draw[red] (4,1) to[bend right] (6,1) -- (5,2);
  \end{scope}
  % how to find bounding box locally aligned ?
  \node[rotate=20,rotate fit=-20,fit=(bb),draw=blue]{};
\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Responder1

Estou perdendo o foco? transform shapee redefinir a rotação parece uma solução.


EDIT: Espero que desta vez eu tenha entendido seu ponto. Caso contrário, eu realmente apreciaria explicar em termos de retângulos e formas girados, em vez delocaleglobalque são terminologia relativa em relação ao ambiente de imagem Tikz girado.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}

\tikzset{
  pt/.style={circle,minimum size=3pt,fill=#1,inner sep=0},
  red pt/.style={pt=red},
  green pt/.style={pt=green},
  every picture/.style={line width=1pt,inner sep=0pt},
}
\begin{document}
\begin{tikzpicture}[rotate=20]
  \draw[gray,line width=.4pt] (0,0) grid (6.5,2.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \begin{scope}[transform shape]
    \node[fit=(a)(b)(c)(d),draw=blue]{};
  \end{scope}
\pgfgettransform{\currtrafo}     %Save the current trafo 

  % second case: fitting arbitrary path
\begin{scope}[local bounding box=bb]
\pgftransformresetnontranslations % Now there is no rotation and it doesn't know 
                                  % things are going to be rotated
\begin{scope}                     % We open a new scope and restore the outer trafo
\pgfsettransform{\currtrafo}      % inside the scope

\draw[red] (4,1) to[bend right] (6,1) -- (5,2);  % Draw anything
\end{scope}                                      % Now the trafo is reset again

\node[fit=(bb),draw=blue]{};     % Externally it doesn't know the content is
                                 % rotated or not

  \end{scope}                    % Back to original trafo.
\end{tikzpicture}
\end{document}

insira a descrição da imagem aqui

Responder2

Observação:Finalmente encontrei uma solução... mas não posso me dar minha própria recompensa. ;-)

Eu defino três estilos:

  1. memoize pointsnomeia cada ponto de um caminho (com ajuda do memoizepointscontador) e acumula esses nomes em uma macro global (seu argumento).

  2. cont memoize pointsé igual a memoize points, mas sem redefinir a macro global (seu argumento).

  3. init memoize pointsredefine a macro global (seu argumento) e o memoizepointscontador.

Aqui está o preâmbulo:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fit,intersections,decorations.pathreplacing,decorations.markings}

O memoizepointscontador e os três estilos:

\newcounter{memoizepoints}
\tikzset{
  init memoize points/.code={\xdef#1{}\setcounter{memoizepoints}{0}},  
  cont memoize points/.style={postaction={
      decorate,decoration={show path construction,
        moveto code={},
        lineto code={
          \foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentlast}{
            \addtocounter{memoizepoints}{1}
            \coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
            \xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
          }
        },
        curveto code={
          \foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentsupporta,%
            \tikzinputsegmentsupportb,\tikzinputsegmentlast}{
            \addtocounter{memoizepoints}{1}
            \coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
            \xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
          }
        },
        closepath code={
          \foreach \coord in {\tikzinputsegmentfirst,\tikzinputsegmentlast}{
            \addtocounter{memoizepoints}{1}
            \coordinate(memoizepoints-\arabic{memoizepoints}) at (\coord);
            \xdef#1{#1 (memoizepoints-\arabic{memoizepoints})}
          }
        },
      },
    },
  },
  memoize points/.style={init memoize points=#1,cont memoize points=#1},
}

Em seguida, um exemplo seguido de seu código:

insira a descrição da imagem aqui

\begin{document}
\begin{tikzpicture}[rotate=30,inner sep=0pt,line width=1pt]
  \tikzset{
    pt/.style={circle,minimum size=3pt,fill=#1,inner sep=0},
    red pt/.style={pt=red},
  }
  \draw[gray,line width=.4pt] (0,0) grid (9.5,5.5);
  % first case: fitting some nodes
  \node[red pt] (a) at (.5,.5){};
  \node[red pt] (b) at (.5,2){};
  \node[red pt] (c) at (3,.5){};
  \node[red pt] (d) at (2,2.2){};
  \begin{scope}[transform shape]
    \node[fit=(a)(b)(c)(d),draw=blue]{};
  \end{scope}

  % second case: fitting arbitrary path
  \draw[red,memoize points=\allpoints] (4,1) to[bend right] (6,1) -- (5,2);
  \begin{scope}[transform shape]
    \node[fit=\allpoints,draw=blue]{};
  \end{scope}

  % another example of fitting arbitrary path
  \draw[red,memoize points=\allpoints] (8,1.2) circle ();
  \begin{scope}[transform shape]
    \node[fit=\allpoints,draw=blue]{};
  \end{scope}

  % another example of fitting arbitrary paths
  \begin{scope}[yshift=2cm]
    \draw[red,memoize points=\allpoints]
    plot[domain=4:8,samples=100] (\x,{2+sin(3 * \x r)});
    \draw[red,cont memoize points=\allpoints]
    plot[domain=4:8,samples=100] (\x,{2.1+cos(3 * \x r)});
  \end{scope}
  \begin{scope}[transform shape]
    \node[fit=\allpoints,draw=blue]{};
  \end{scope}
\end{tikzpicture}

informação relacionada