So beheben Sie relative Koordinaten in der Tikz-Bibliothek svg.path

So beheben Sie relative Koordinaten in der Tikz-Bibliothek svg.path

Bei der Verwendung relativer Befehle scheint ein Fehler aufzutreten. In meinem Fall habe ich einen Fall gefunden, in dem beim Zeichnen einer glatten Kurve die Kurve falsch gezeichnet wird.

Überprüfen Sie die folgenden Fälle (der erste ist vollständig relativ und der letzte ist vollständig absolut), in denen die relative Verwendung der Befehle fehlerhaft ist, während die absoluten wie erwartet funktionieren.

\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}

Antwort1

In der Definition des sOperators

\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
}

Die folgende Zeile (aktuell die Zeile 386 vonpgflibrarysvg.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}}%

ist falsch. Dies liegt daran, dass \pgf@lib@svg@get@num{2}und {3}der Endpunkt der vorherigen Kurve ist. Der Standard besagt jedoch, dass der zweite Kontrollpunkt der vorherigen Kurve gespeichert werden soll. Wenn Sie die Zahlen in {0}und ändern {1}, funktioniert es wie erwartet.

(Ich vermute, dass diese Zeile aus Zeile 300 kopiert wurde, während im COperator „ {2}und {3}“ den zweiten Kontrollpunkt bedeuten.)

Hier ist das 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}

verwandte Informationen