Como corrigir coordenadas relativas na biblioteca svg.path tikz

Como corrigir coordenadas relativas na biblioteca svg.path tikz

Parece haver um bug ou erro ao usar comandos relativos. No meu caso, encontrei um caso em que desenhar uma curva suave desenharia a curva incorretamente.

Verifique os seguintes casos (o primeiro é full relativo e o último é full absoluto), onde o uso relativo dos comandos desenha erroneamente, enquanto os absolutos estão funcionando conforme o esperado.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{svg.path}

\begin{document}
  % Original
  \begin{tikzpicture}
    \draw svg "M 256 8 C 119 8 8 119 8 256 s 111 248 248 248 s 248 -111 248 -248 S 393 8 256 8 z";
  \end{tikzpicture}
  % Mix of relative
  \begin{tikzpicture}
  \draw svg "M 256 8 C 119 8 8 119 8 256 s 111 248 248 248 S 504 393 504 256 S 393 8 256 8 z";
  \end{tikzpicture}
  % Mix of relative
  \begin{tikzpicture}
  \draw svg "M 256 8 C 119 8 8 119 8 256 S 119 504 256 504 s 248 -111 248 -248 S 393 8 256 8 z";
  \end{tikzpicture}
  % Full absolute
  \begin{tikzpicture}
  \draw svg "M256 8 C 119 8 8 119 8 256 S 119 504 256 504 S 504 393 504 256 S 393 8 256 8 z";
  \end{tikzpicture}
\end{document}

Responder1

Na definição de soperador

\pgfparserdef{svgpath}{all}{the letter s}
{
  \pgf@lib@svg@finish@prev
  \pgf@lib@svg@read@nums{4}{\pgf@lib@svg@curveto@rel@smooth}
}

\def\pgf@lib@svg@curveto@rel@smooth{%
  \ifnum\pgf@lib@svg@count=0\relax% nothing read
  \else%
    % Draw curve
    % Compute first control point
    \ifx\pgf@lib@svg@bezier@last\pgfutil@empty%
      \def\pgf@lib@svg@first@cp{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}
    \else
      \def\pgf@lib@svg@first@cp{
        \pgfpointadd
        {\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}
        {\pgfpointdiff
          {\pgf@lib@svg@bezier@last}
          {\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}
        }
      }
    \fi
    \pgfpathcurveto
    {\pgf@lib@svg@first@cp}
    {\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{0}pt}{\pgf@lib@svg@get@num{1}pt}}}%
    {\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{2}pt}{\pgf@lib@svg@get@num{3}pt}}}%
    % Clear quadratic last point and save new last control point:
    \let\pgf@lib@svg@quad@last=\pgfutil@empty%
    \pgf@process{\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{2}pt}{\pgf@lib@svg@get@num{3}pt}}}
    \edef\pgf@lib@svg@bezier@last{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
    % update
    \advance\pgf@lib@svg@last@x by\pgf@lib@svg@get@num{2}pt%
    \advance\pgf@lib@svg@last@y by\pgf@lib@svg@get@num{3}pt%
    % Go on
    \pgf@lib@svg@read@nums{4}{\pgf@lib@svg@curveto@rel@smooth}
  \fi
}

A seguinte linha (atualmente a linha 386 dopgflibrarysvg.path.code.tex

\pgf@process{\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{2}pt}{\pgf@lib@svg@get@num{3}pt}}}
\edef\pgf@lib@svg@bezier@last{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%

está errado. Isso ocorre porque \pgf@lib@svg@get@num{2}e {3}é o ponto final da curva anterior. Mas a norma diz que deve lembrar-se do segundo ponto de controle da curva anterior. Se você alterar os números para {0}e {1}funcionará conforme o esperado.

(Suspeito que essa linha seja copiada da linha 300, enquanto no Coperador {2}e {3}significa o segundo ponto de controle.)

Aqui está o MWE

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{svg.path}
\makeatletter

\def\pgf@lib@svg@curveto@rel@smooth{%
  \ifnum\pgf@lib@svg@count=0\relax% nothing read
  \else%
    % Draw curve
    % Compute first control point
    \ifx\pgf@lib@svg@bezier@last\pgfutil@empty%
      \def\pgf@lib@svg@first@cp{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}
    \else
      \def\pgf@lib@svg@first@cp{
        \pgfpointadd
        {\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}
        {\pgfpointdiff
          {\pgf@lib@svg@bezier@last}
          {\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}
        }
      }
    \fi
    \pgfpathcurveto
    {\pgf@lib@svg@first@cp}
    {\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{0}pt}{\pgf@lib@svg@get@num{1}pt}}}%
    {\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{2}pt}{\pgf@lib@svg@get@num{3}pt}}}%
    % Clear quadratic last point and save new last control point:
    \let\pgf@lib@svg@quad@last=\pgfutil@empty%
    \pgf@process{\pgfpointadd{\pgfqpoint{\pgf@lib@svg@last@x}{\pgf@lib@svg@last@y}}{\pgfqpoint{\pgf@lib@svg@get@num{0}pt}{\pgf@lib@svg@get@num{1}pt}}} %%%%%% fixing this line
    \edef\pgf@lib@svg@bezier@last{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
    % update
    \advance\pgf@lib@svg@last@x by\pgf@lib@svg@get@num{2}pt%
    \advance\pgf@lib@svg@last@y by\pgf@lib@svg@get@num{3}pt%
    % Go on
    \pgf@lib@svg@read@nums{4}{\pgf@lib@svg@curveto@rel@smooth}
  \fi
}


\begin{document}
  % Original
  \begin{tikzpicture}
    \draw svg "M 256 8 C 119 8 8 119 8 256 s 111 248 248 248 s 248 -111 248 -248 S 393 8 256 8 z";
  \end{tikzpicture}
  % Mix of relative
  \begin{tikzpicture}
  \draw svg "M 256 8 C 119 8 8 119 8 256 s 111 248 248 248 S 504 393 504 256 S 393 8 256 8 z";
  \end{tikzpicture}
  % Mix of relative
  \begin{tikzpicture}
  \draw svg "M 256 8 C 119 8 8 119 8 256 S 119 504 256 504 s 248 -111 248 -248 S 393 8 256 8 z";
  \end{tikzpicture}
  % Full absolute
  \begin{tikzpicture}
  \draw svg "M256 8 C 119 8 8 119 8 256 S 119 504 256 504 S 504 393 504 256 S 393 8 256 8 z";
  \end{tikzpicture}
\end{document}

informação relacionada