TeX - LaTeX Asked on April 4, 2021
I’m trying to create a format for arrows in tikzcd which is effectively a stretched tilde:
I have drawn this example using Option 1 in this answer, but I have had to manually calculate the correct segment length for the snake.
Is there a way to calculate this automatically? Say for example:
arrows={decorate, decoration={snake, segment length=DISTANCE/2, amplitude=0.5mm}}
If not, is there an alternative approach?
Any help would be much appreciated.
I have a partial solution based on this answer.
I have copied their helper macro in its entirety, along with most of the first half of their style definition. The only code I am responsible for is that which is below the comment "Draw the wave":
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
deffindedgesourcetarget#1#2{
letsourcecoordinatepgfutil@empty
ifxtikzcd@startanchorpgfutil@empty % Check that the source doesn't have a specified anchor
deftempa{pgfpointanchor{#1}{center}}% if so, start by taking the center of that coordinate
else
edeftempa{noexpandpgfpointanchor{#1}{expandafter@gobbletikzcd@startanchor}} % If it has an anchor, use that
letsourcecoordinatetempa
fi
ifxtikzcd@endanchorpgfutil@empty % check that the target doesn't have a specified anchor
deftempb{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
edeftempb{noexpandpgfpointanchor{#2}{expandafter@gobbletikzcd@endanchor}}% If it has a specified anchor, use that
fi
lettargetcoordinatetempb
ifxsourcecoordinatepgfutil@empty%
defsourcecoordinate{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
ifxtikzcd@startanchorpgfutil@empty
deftikzcd@startanchor{.center}
fi
ifxtikzcd@endanchorpgfutil@empty
deftikzcd@endanchor{.center}
fi
pgfmathanglebetweenpoints{pgfpointanchor{tikzcd@ar@start}{expandafter@gobbletikzcd@startanchor}}{pgfpointanchor{tikzcd@ar@target}{expandafter@gobbletikzcd@endanchor}}
pgftransformrotate{pgfmathresult}
% Draw the wave
newdimenxdiff
pgfextractx{xdiff}{pgfpointdiff{sourcecoordinate}{targetcoordinate}}
newdimenydiff
pgfextracty{ydiff}{pgfpointdiff{sourcecoordinate}{targetcoordinate}}
newdimenfinalDist
pgfmathparse{abs(veclen(xdiff,ydiff))*0.85}
pgfmathsetlengthfinalDist{pgfmathresult pt}
pgfmathsetlengthpgfdecorationsegmentlength{finalDist}
pgfmathparse{0.038*finalDist+0.6}
pgfmathsetlengthpgfdecorationsegmentamplitude{pgfmathresult pt}
pgfsetarrows{->}
pgfpathmoveto{sourcecoordinate}
pgfpathsnaketo{snake}{targetcoordinate}
pgfusepath{stroke}
}}}}
makeatother
Using the helper macro, I retrieve the points to be joined and calculate the distance between them. I then use this to define the amplitude and segment length of the snake.
The constants I use in these definitions appear arbitrary, I found them through trial and improvement, but I'll work on a more rigorous approach.
Then
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}
My main issue currently is that labels above the arrows no longer work. I will try to fix this, and update this answer if I can.
If anybody has a simpler approach which avoids such problems then please let me know!
Answered by Dave on April 4, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP