Sóng đơn trong dòng tikzcd

Jan 10 2021

Tôi đang cố gắng tạo định dạng cho các mũi tên trong tikzcd, đây là một dấu ngã kéo dài thực sự:

Tôi đã vẽ ví dụ này bằng cách sử dụng Tùy chọn 1 trong câu trả lời này , nhưng tôi đã phải tính toán thủ công độ dài đoạn chính xác cho con rắn.

Có cách nào để tính toán điều này tự động không? Ví dụ:

arrows={decorate, decoration={snake, segment length=DISTANCE/2, amplitude=0.5mm}}

Nếu không, có cách nào khác không?

Bất kì sự trợ giúp nào đều được đánh giá cao.

Trả lời

2 Dave Jan 11 2021 at 04:03

Tôi có một giải pháp một phần dựa trên câu trả lời này .

Tôi đã sao chép toàn bộ macro trợ giúp của họ, cùng với hầu hết phần đầu của định nghĩa kiểu của họ. Mã duy nhất mà tôi chịu trách nhiệm là mã nằm bên dưới nhận xét "Vẽ sóng":

\makeatletter

% This helper macro finds the start and endpoints of a line between the source and target nodes and stores them in \sourcecoordinate and \targetcoordinate.
% #1 -- source node
% #2 -- target node
\def\findedgesourcetarget#1#2{
\let\sourcecoordinate\pgfutil@empty
\ifx\tikzcd@startanchor\pgfutil@empty % Check that the source doesn't have a specified anchor
    \def\tempa{\pgfpointanchor{#1}{center}}% if so, start by taking the center of that coordinate
\else
    \edef\tempa{\noexpand\pgfpointanchor{#1}{\expandafter\@gobble\tikzcd@startanchor}} % If it has an anchor, use that
    \let\sourcecoordinate\tempa
\fi
\ifx\tikzcd@endanchor\pgfutil@empty % check that the target doesn't have a specified anchor
    \def\tempb{\pgfpointshapeborder{#2}{\tempa}}% if so, our end point is the point on the boundary of node b that is in the direction of our initial start coordinate
\else
    \edef\tempb{\noexpand\pgfpointanchor{#2}{\expandafter\@gobble\tikzcd@endanchor}}% If it has a specified anchor, use that
\fi
\let\targetcoordinate\tempb
\ifx\sourcecoordinate\pgfutil@empty%
    \def\sourcecoordinate{\pgfpointshapeborder{#1}{\tempb}}%
\fi
}

\tikzset{wave/.style = {
-,
to path={\pgfextra{
        \findedgesourcetarget{\tikzcd@ar@start}{\tikzcd@ar@target} % find endpoints
    % Rotate coordinate system so that line goes in x direction
    \ifx\tikzcd@startanchor\pgfutil@empty
        \def\tikzcd@startanchor{.center}
    \fi
    \ifx\tikzcd@endanchor\pgfutil@empty
        \def\tikzcd@endanchor{.center}
    \fi
    \pgfmathanglebetweenpoints{\pgfpointanchor{\tikzcd@ar@start}{\expandafter\@gobble\tikzcd@startanchor}}{\pgfpointanchor{\tikzcd@ar@target}{\expandafter\@gobble\tikzcd@endanchor}}
    \pgftransformrotate{\pgfmathresult}
    % Draw the wave
    \newdimen\xdiff
    \pgfextractx{\xdiff}{\pgfpointdiff{\sourcecoordinate}{\targetcoordinate}}
    \newdimen\ydiff
    \pgfextracty{\ydiff}{\pgfpointdiff{\sourcecoordinate}{\targetcoordinate}}
    \newdimen\finalDist
    \pgfmathparse{abs(veclen(\xdiff,\ydiff))*0.85}
    \pgfmathsetlength\finalDist{\pgfmathresult pt}

    \pgfmathsetlength\pgfdecorationsegmentlength{\finalDist}

    \pgfmathparse{0.038*\finalDist+0.6}
    \pgfmathsetlength\pgfdecorationsegmentamplitude{\pgfmathresult pt}

    \pgfsetarrows{->}

    \pgfpathmoveto{\sourcecoordinate}
    \pgfpathsnaketo{snake}{\targetcoordinate}

    \pgfusepath{stroke}
}}}}

\makeatother

Sử dụng macro trợ giúp, tôi truy xuất các điểm được nối và tính toán khoảng cách giữa chúng. Sau đó, tôi sử dụng điều này để xác định biên độ và độ dài đoạn của con rắn.

Các hằng số tôi sử dụng trong các định nghĩa này có vẻ tùy ý, tôi đã tìm thấy chúng qua quá trình thử nghiệm và cải tiến, nhưng tôi sẽ làm việc theo một cách tiếp cận nghiêm ngặt hơn.


Sau đó

\begin{center}
    Original method:
    \begin{tikzcd}[arrows={decorate, decoration={snake,segment length=7.3mm, amplitude=0.5mm}}]
        A \arrow[r,"",decorate=true] & B
    \end{tikzcd}
\end{center}
\hspace{2cm}
\begin{center}
    Custom style
    \begin{tikzcd}
        A \arrow[r, wave] & B & & \\
        A \arrow[rr, wave] & & B & \\
        A \arrow[rrr, wave] & & & B
    \end{tikzcd}
\end{center}

cho


Vấn đề chính của tôi hiện tại là các nhãn phía trên các mũi tên không còn hoạt động. Tôi sẽ cố gắng sửa lỗi này và cập nhật câu trả lời này nếu tôi có thể.

Nếu ai có cách tiếp cận đơn giản hơn mà tránh được những vấn đề như vậy thì vui lòng cho tôi biết!