I'd like to compute the intersection between a node and a path, here I'd like the coordinate of the intersection in the green box:
My goal is to define a style that draws lines similar to \draw[mystyle] (A) to (E);
, except that the line starts at the green position. I saw \pgfpointshapeborder{hnodei}{hpointi}
but it's only between the center
of the node and a point, here I want from a point which is not in the center of the node.
What I don't want: I don't want to manually fake this style using A.20
or similar; I want to programmatically compute this value, so that I can use it later in complex styles.
Thanks.
MWE:
\documentclass[options]{article}
\author{}
\usepackage{tikz-cd}
\usetikzlibrary{shapes.misc, positioning,calc}
\begin{document}
\begin{tikzpicture}[
myC/.style={
to path={(\tikztostart.west) -- (\tikztotarget) \tikztonodes}
}
]
\node[rounded rectangle, draw] (A) at (0,0) {ABCD};
\node[circle, draw] (E) at (1,-1) {E};
\draw[thick,red] (E.center) -- (A.center);
\draw[] (E) -- (A);
\draw[thick,blue] ($(A.north east)!.5!(A.south east)$) -- (E.center);
\end{tikzpicture}
\end{document}
EDIT
Using this code, I can define a new anchor named fake center east
at the beginning of the blue line:
\def\zx@pgfaddtoshape#1#2{%
\begingroup
\def\pgf@sm@shape@name{#1}%
\let\anchor\pgf@sh@anchor
#2%
\endgroup
}
\def\zx@useanchor#1#2{\csname pgf@anchor@#1@#2\endcsname}
\zx@pgfaddtoshape{rounded rectangle}{
\anchor{fake center east}{%
\zx@useanchor{rounded rectangle}{north east}%
\pgf@yc=.5\pgf@y% final y = 0.5*this y + 0.5*other y.
\zx@useanchor{rounded rectangle}{south east}%
\pgf@y=.5\pgf@y%
\advance\pgf@y by \pgf@yc%
}%
}
However, my issue is that I'm not sure how to combine it with the intersection library in order to create a style. I tried:
\documentclass[]{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.misc, positioning,intersections}
\begin{document}
\makeatletter
\tikzset{
defaultNodeStyle/.code={
\pgfkeysalso{
shape=rounded rectangle,
draw,
anchor=center,
}
},
N/.style={
to path={\pgfextra{%
\pgfintersectionofpaths{%
%%%% /!\ This lines is the one I'm not sure how to write:
\pgfsetpath{tikz@intersect@path@name@ABCD}
}{%
\pgfpathmoveto{\pgfpointanchor{\tikztostart}{center}}%
\pgfpathlineto{\pgfpointanchor{\tikztotarget}{center}}%
}
\pgfpointintersectionsolution{1}
\def\zx@tikztostart{\pgf@x,\pgf@y}%
} (\zx@tikztostart) -- (tikztotarget) \tikztonodes}
},
}
\begin{tikzcd}
%% Right now we fix the path --v, later this must be automatically added (\tikz@fig@name is always defined in a matrix... hopefully we are.)
|[defaultNodeStyle,name path=ABCD,alias=X]| ABCD \ar[rd,N] & |[defaultNodeStyle]| EFG\\
|[defaultNodeStyle]| ABCD & |[defaultNodeStyle]| EFG
\end{tikzcd}
\makeatother
\end{document}
But seems like \pgfintersectionofpaths{\pgfsetpath{tikz@intersect@path@name@ABCD}}{my other path}
is not the good syntax...
This other try compiles, but result is bad:
\documentclass[]{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.misc, positioning,intersections}
\begin{document}
\makeatletter
\tikzset{
defaultNodeStyle/.code={
\pgfkeysalso{
shape=rounded rectangle,
draw,
anchor=center,
}
},
N/.style={
to path={\pgfextra{%
\def\tikz@intersect@path@a{ABCD}%
\pgfintersectionofpaths{%
%%%% /!\ This lines is the one I'm not sure how to write:
\expandafter\pgfsetpath\csname tikz@intersect@path@name@\tikz@intersect@path@a\endcsname
}{%
\pgfpathmoveto{\pgfpointanchor{\tikztostart}{center}}%
\pgfpathlineto{\pgfpointanchor{\tikztotarget}{center}}%
}
\pgfpointintersectionsolution{1}
\def\zx@tikztostart{\pgf@x,\pgf@y}%
} (\zx@tikztostart) -- (\tikztotarget) \tikztonodes}
},
}
\begin{tikzcd}
%% Right now we fix the path --v, later this must be automatically added (\tikz@fig@name is always defined in a matrix... hopefully we are.)
|[defaultNodeStyle,name path=ABCD,alias=X]| ABCD \ar[rd,N] & |[defaultNodeStyle]| EFG\\
|[defaultNodeStyle]| ABCD & |[defaultNodeStyle]| EFG
\end{tikzcd}
\makeatother
\end{document}
EDIT
Oh, actually it looks like this is a problem with matrices which does not put the parent node at the good position (see Intersections with border of matrix node):
Does that mean that I've no solution for matrix entries?
\documentclass[]{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.misc, positioning,intersections}
\begin{document}
\makeatletter
\tikzset{
defaultNodeStyle/.code={
\pgfkeysalso{
shape=rounded rectangle,
draw,
anchor=center,
}
},
N/.style={
to path={\pgfextra{%
\def\tikz@intersect@path@a{ABCD}%
\pgfintersectionofpaths{%
%%%% /!\ This lines is the one I'm not sure how to write:
\expandafter\pgfsetpath\csname tikz@intersect@path@name@\tikz@intersect@path@a\endcsname
\pgfgetpath\temppath
\pgfusepath{stroke}
\pgfsetpath\temppath
}{%
\pgfpathmoveto{\pgfpointanchor{\tikztostart}{center}}%
\pgfpathlineto{\pgfpointanchor{\tikztotarget}{center}}%
\pgfgetpath\temppath
%\pgfusepath{stroke}
\pgfsetpath\temppath
}
\pgfpointintersectionsolution{1}
\def\zx@tikztostart{\pgf@x,\pgf@y}%
} (\zx@tikztostart) -- (\tikztotarget) \tikztonodes}
},
}
It fails with tikzcd (the node ABCD is put at the wrong position):
\begin{tikzcd}
%% Right now we fix the path --v, later this must be automatically added (\tikz@fig@name is always defined in a matrix... hopefully we are.)
|[defaultNodeStyle,name path=ABCD]| ABCD \ar[rd,N] & |[defaultNodeStyle]| EFG\\
|[defaultNodeStyle]| ABCD & |[defaultNodeStyle]| EFG
\end{tikzcd}
But works with tikz pictures:
\begin{tikzpicture}
\node[defaultNodeStyle,name path=ABCD] (A) {ABCD};
\node[defaultNodeStyle] (F) at (1,-1) {F};
\draw[red] (A) to[red,<->,N] (F);
\end{tikzpicture}
\makeatother
\end{document}
I also tried to configure automatically the name path
using name path/.expand once=zx@path@\tikz@fig@name
, but LaTeX freezes:
\documentclass[]{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.misc, positioning,intersections}
\begin{document}
\makeatletter
\tikzset{
defaultNodeStyle/.code={
name path/.expand once=zx@path@\tikz@fig@name,
\pgfkeysalso{
shape=rounded rectangle,
draw,
anchor=center,
}
},
N/.style={
to path={\pgfextra{%
\def\tikz@intersect@path@a{ABCD}%
\pgfintersectionofpaths{%
%%%% /!\ This lines is the one I'm not sure how to write:
\expandafter\pgfsetpath\csname tikz@intersect@path@name@zx@path@\tikztostart\endcsname
\pgfgetpath\temppath
\pgfusepath{stroke}
\pgfsetpath\temppath
}{%
\pgfpathmoveto{\pgfpointanchor{\tikztostart}{center}}%
\pgfpathlineto{\pgfpointanchor{\tikztotarget}{center}}%
\pgfgetpath\temppath
%\pgfusepath{stroke}
\pgfsetpath\temppath
}
\pgfpointintersectionsolution{1}
\def\zx@tikztostart{\pgf@x,\pgf@y}%
} (\zx@tikztostart) -- (\tikztotarget) \tikztonodes}
},
}
It fails with tikzcd (the node ABCD is put at the wrong position):
\begin{tikzcd}
|[defaultNodeStyle]| ABCD \ar[rd,N] & |[defaultNodeStyle]| EFG\\
|[defaultNodeStyle]| ABCD & |[defaultNodeStyle]| EFG
\end{tikzcd}
But works with tikz pictures:
\begin{tikzpicture}
\node[defaultNodeStyle] (A) {ABCD};
\node[defaultNodeStyle] (F) at (1,-1) {F};
\draw[red] (A) to[red,<->,N] (F);
\end{tikzpicture}
\makeatother
\end{document}
EDIT
Whooo I managed to correct the fact that the path is centered by shifting everything (I'm not sure why but sometimes when I draw the x axis only is inverted, and then both axis are inverted). I still need to find how to automatically give the name path
\documentclass[]{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.misc, positioning,intersections}
\begin{document}
\makeatletter
%% Create anchors
\def\zx@pgfaddtoshape#1#2{%
\begingroup
\def\pgf@sm@shape@name{#1}%
\let\anchor\pgf@sh@anchor
#2%
\endgroup
}
\def\zx@useanchor#1#2{\csname pgf@anchor@#1@#2\endcsname}
\zx@pgfaddtoshape{rounded rectangle}{
\anchor{fake center east}{%
\zx@useanchor{rounded rectangle}{north east}%
\pgf@yc=.5\pgf@y% final y = 0.5*this y + 0.5*other y.
\zx@useanchor{rounded rectangle}{south east}%
\pgf@y=.5\pgf@y%
\advance\pgf@y by \pgf@yc%
}%
}
\tikzset{
defaultNodeStyle/.code={
\pgfkeysalso{
shape=rounded rectangle,
draw,
anchor=center,
}
},
N/.style={
to path={\pgfextra{%
%% We compute the intersection
\def\tikz@intersect@path@a{ABCD}%
\pgfintersectionofpaths{%
%%%% /!\ This lines is the one I'm not sure how to write:
\expandafter\pgfsetpath\csname tikz@intersect@path@name@\tikz@intersect@path@a\endcsname%
\pgfgetpath\temppath%
%\pgfusepath{stroke} % We draw it, useful to debug, and realize the shape is moved.
\pgfsetpath\temppath%
}{% The first path is moved to the center... So we need to shift it also here.
%% Not idea why, but x axis is inverted???
\pgfextractx{\pgf@xa}{\pgfpointdiff{\pgfpointanchor{\tikztostart}{fake center east}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfextracty{\pgf@ya}{\pgfpointdiff{\pgfpointanchor{\tikztostart}{fake center east}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfpathmoveto{\pgfpoint{-\pgf@xa}{\pgf@ya}}%
%% What, no both axis are inverted???
\pgfextractx{\pgf@xa}{\pgfpointdiff{\pgfpointanchor{\tikztotarget}{center}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfextracty{\pgf@ya}{\pgfpointdiff{\pgfpointanchor{\tikztotarget}{center}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}}%
\pgfgetpath\temppath%
%\pgfusepath{stroke} % We draw it, useful to debug
\pgfsetpath\temppath%
}
\pgfpointintersectionsolution{1}%
%% Store the intersection (warning: the center of the shape is moved to the center!)
\edef\zx@relinter@x{\the\pgf@x}%
\edef\zx@relinter@y{\the\pgf@y}%
%% Because the shape was moved to center, we shift it back by adding the coord of the shape:
\pgfextractx\pgf@xa{\pgfpointanchor{\tikztostart}{center}}
\pgfextractx\pgf@xb{\pgfpointanchor{\tikztostart}{center}}
% WARNING! pgfmath removes the dimension (converted in pt). Make sure to put them back after
\pgfmathsetmacro{\zx@inter@x}{\pgf@x+\zx@relinter@x}
\pgfmathsetmacro{\zx@inter@y}{\pgf@y+\zx@relinter@y}
\edef\zx@tikztostart{\zx@inter@x pt,\zx@inter@y pt}%
}
(\zx@tikztostart) -- (\tikztotarget)
\tikztonodes}
},
}
It fails with tikzcd (the node ABCD is put at the wrong position):
\begin{tikzcd}[execute at end picture={
\node[]at(0,0){};
}]
%% Right now we fix the path --v, later this must be automatically added (\tikz@fig@name is always defined in a matrix... hopefully we are.)
|[defaultNodeStyle,rounded rectangle west arc=concave,name path=ABCD]| ABCD
\ar[->,rd,N,line width=.5mm,red]
\ar[rd,start anchor=fake center east,end anchor=center]
& |[defaultNodeStyle]| EFG\\
|[defaultNodeStyle]| ABCD & |[defaultNodeStyle]| EFG
\end{tikzcd}
But works with tikz pictures:
\begin{tikzpicture}
\node[defaultNodeStyle,name path=ABCD] (A) {ABCD};
\node[defaultNodeStyle] (F) at (1,-1) {F};
\draw[red] (A) to[red,<->,N] (F);
\end{tikzpicture}
\makeatother
\end{document}
EDIT
The code works now completely for matrices! But it fails for nodes, I'm not sure why but \tikz@fig@name
is not defined in that case...
\documentclass[]{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.misc, positioning,intersections}
\begin{document}
\makeatletter
%% Create anchors
\def\zx@pgfaddtoshape#1#2{%
\begingroup
\def\pgf@sm@shape@name{#1}%
\let\anchor\pgf@sh@anchor
#2%
\endgroup
}
\def\zx@useanchor#1#2{\csname pgf@anchor@#1@#2\endcsname}
\zx@pgfaddtoshape{rounded rectangle}{
\anchor{fake center east}{%
\zx@useanchor{rounded rectangle}{north east}%
\pgf@yc=.5\pgf@y% final y = 0.5*this y + 0.5*other y.
\zx@useanchor{rounded rectangle}{south east}%
\pgf@y=.5\pgf@y%
\advance\pgf@y by \pgf@yc%
}%
}
\tikzset{
defaultNodeStyle/.code={
\edef\zx@name@path{name@path@\tikz@fig@name}
\message{HHH \zx@name@path}
\pgfkeysalso{
shape=rounded rectangle,
draw,
anchor=center,
name path=\zx@name@path,
}
},
N/.style={
to path={\pgfextra{%
%% We compute the intersection
\edef\tikz@intersect@path@a{name@path@\tikztostart}%
\message{JJJJ \tikz@intersect@path@a}%
\pgfintersectionofpaths{%
%%%% /!\ This lines is the one I'm not sure how to write:
\expandafter\pgfsetpath\csname tikz@intersect@path@name@\tikz@intersect@path@a\endcsname%
\pgfgetpath\temppath%
%\pgfusepath{stroke} % We draw it, useful to debug, and realize the shape is moved.
\pgfsetpath\temppath%
}{% The first path is moved to the center... So we need to shift it also here.
%% Not idea why, but x axis is inverted???
\pgfextractx{\pgf@xa}{\pgfpointdiff{\pgfpointanchor{\tikztostart}{fake center east}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfextracty{\pgf@ya}{\pgfpointdiff{\pgfpointanchor{\tikztostart}{fake center east}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfpathmoveto{\pgfpoint{-\pgf@xa}{\pgf@ya}}%
%% What, no both axis are inverted???
\pgfextractx{\pgf@xa}{\pgfpointdiff{\pgfpointanchor{\tikztotarget}{center}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfextracty{\pgf@ya}{\pgfpointdiff{\pgfpointanchor{\tikztotarget}{center}}{\pgfpointanchor{\tikztostart}{center}}}%
\pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}}%
\pgfgetpath\temppath%
%\pgfusepath{stroke} % We draw it, useful to debug
\pgfsetpath\temppath%
}
\pgfpointintersectionsolution{1}%
%% Store the intersection (warning: the center of the shape is moved to the center!)
\edef\zx@relinter@x{\the\pgf@x}%
\edef\zx@relinter@y{\the\pgf@y}%
%% Because the shape was moved to center, we shift it back by adding the coord of the shape:
\pgfextractx\pgf@xa{\pgfpointanchor{\tikztostart}{center}}
\pgfextractx\pgf@xb{\pgfpointanchor{\tikztostart}{center}}
% WARNING! pgfmath removes the dimension (converted in pt). Make sure to put them back after
\pgfmathsetmacro{\zx@inter@x}{\pgf@x+\zx@relinter@x}
\pgfmathsetmacro{\zx@inter@y}{\pgf@y+\zx@relinter@y}
\edef\zx@tikztostart{\zx@inter@x pt,\zx@inter@y pt}%
}
(\zx@tikztostart) -- (\tikztotarget)
\tikztonodes}
},
}
It fails with tikzcd (the node ABCD is put at the wrong position):
\begin{tikzcd}[execute at end picture={
\node[]at(0,0){};
}]
%% Right now we fix the path --v, later this must be automatically added (\tikz@fig@name is always defined in a matrix... hopefully we are.)
|[defaultNodeStyle,rounded rectangle west arc=concave]| ABCD
\ar[->,rd,N,line width=.5mm,red]
\ar[rd,start anchor=fake center east,end anchor=center]
& |[defaultNodeStyle]| EFG\\
|[defaultNodeStyle]| ABCD & |[defaultNodeStyle]| EFG
\end{tikzcd}
% But works with tikz pictures:
% \begin{tikzpicture}
% \node[defaultNodeStyle] (A) {ABCD};
% \node[defaultNodeStyle] (F) at (1,-1) {F};
% \draw[red] (A) to[red,<->,N] (F);
% \end{tikzpicture}
\makeatother
\end{document}
\draw[thick,blue] (A.340) -- (E.center);
?