Align edges with anchor other than center

I'm not sure to understand exactly the question . I understand that : you want an edge between two nodes but you want to draw the edge only between the intersections of the edges and the shapes of the nodes.

With intersections (the problem is to make a choice between the points) but in the second method I just fill the node's background.

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{positioning,intersections}
\begin{document}

\begin{tikzpicture}
  \node[name path= c1] (foo)  at (0,0)[circle] {$x$};
  \node[name path= c2] (bar) at (2,2)[circle] {$x+1$};
  \path[name path=line] (foo.south) -- (bar.center);
  \fill [name intersections={of=c1 and line, name=i, total=\t}]
 [red, opacity=0.5, every node/.style={left=.25cm, black, opacity=1}] 
 \foreach \s in {1,...,\t}{(i-\s) circle (2pt) node {}};
  \fill [name intersections={of=c2 and line, name=j, total=\t}]
 [red, opacity=0.5, every node/.style={left=.25cm, black, opacity=1}] 
 \foreach \s in {1,...,\t}{(j-\s) circle (2pt) node {}};   
  \draw[red] (i-1) -- (j-1);  
\end{tikzpicture} 
\begin{tikzpicture}
  \node[name path= c1] (foo)  at (0,0)[circle] {$x$};
  \node[name path= c2] (bar) at (2,2)[circle] {$x+1$};
  \path[name path=line] (foo.south) -- (bar.center);
  \path [name intersections={of=c1 and line, name=i, total=\t}] ;
  \path [name intersections={of=c2 and line, name=j, total=\t}];  
  \draw[red] (i-1) -- (j-1);  
\end{tikzpicture}
\begin{tikzpicture}
  \node (foo)  at (0,0)[circle] {\hphantom{$x$}};
  \node (bar) at (2,2)[circle] {\hphantom{$x+1$}};
  \draw[red] (foo.south) -- (bar.center);
  \node[circle,fill=white] at (foo.center){$x$} ;
  \node[circle,fill=white] at (bar.center){$x+1$} ; 
\end{tikzpicture}  
\end{document}

enter image description here


Thinking about this mathematically, it is going to be very hard to do properly. I mean, so that \draw[->] (a) -- (b); draws an arrow from a towards the desired point on b and stops at the boundary with the arrowhead. To do that, one is going to have to calculate the point on the boundary where the line from a to the anchor of b reaches the boundary of b and that will depend on many parameters.

Here's a slightly different approach, which is presented more as a "proof of concept" than as usable code. The idea is that for a simple shape such as a rectangle, one can define some auxiliary nodes whose boundary coincides with the boundary of the original node when seen from certain directions but which are centred at the correct place. The trick is then to pick the right one of these auxiliary nodes upon approach (this is the main bit that I haven't thought how to do).

\documentclass{standalone}
\usepackage{tikz}

\makeatletter
\newlength\relocate@minx
\newlength\relocate@maxx
\newlength\relocate@miny
\newlength\relocate@maxy
\def\relocatenode#1#2{%
  \path (#1.south east);
  \pgfgetlastxy{\relocate@east}{\relocate@south}
  \path (#1.north west);
  \pgfgetlastxy{\relocate@west}{\relocate@north}
  \path (#1) ++(#2);
  \pgfgetlastxy{\relocate@x}{\relocate@y}
  \pgfmathsetlength{\relocate@minx}{2 * min(\relocate@east - \relocate@x, \relocate@x - \relocate@west)}
  \pgfmathsetlength{\relocate@maxx}{2 * max(\relocate@east - \relocate@x, \relocate@x - \relocate@west)}
  \pgfmathsetlength{\relocate@miny}{2 * min(\relocate@north - \relocate@y, \relocate@y - \relocate@south)}
  \pgfmathsetlength{\relocate@maxy}{2 * max(\relocate@north - \relocate@y, \relocate@y - \relocate@south)}
  \path (#1) ++(#2) node[minimum width=\relocate@minx,minimum height=\relocate@miny] (#1-minx-miny) {};
  \path (#1) ++(#2) node[minimum width=\relocate@maxx,minimum height=\relocate@miny] (#1-maxx-miny) {};
  \path (#1) ++(#2) node[minimum width=\relocate@minx,minimum height=\relocate@maxy] (#1-minx-maxy) {};
  \path (#1) ++(#2) node[minimum width=\relocate@maxx,minimum height=\relocate@maxy] (#1-maxx-maxy) {};
}
\makeatother
\begin{document}
\begin{tikzpicture}[every path/.style={->}]
\node[draw,align=left] (a) at (0,0) {hello world\\greetings mars};
\relocatenode{a}{1,.3}
\fill (a) circle (2pt);
\fill (a) ++(1,.3) circle (2pt);

\path (a) ++(1,.3) node (b) {};

\foreach \pt in {30,60,...,360} {
  \draw (a) ++(\pt:5) -- (a);
}

\foreach \pt in {0,10,...,80} {
  \draw[red] (a) ++(\pt:5) -- (a-minx-miny);
}
\foreach \pt in {90,100,...,170} {
  \draw[red] (a) ++(\pt:5) -- (a-maxx-miny);
}
\foreach \pt in {180,190,...,260} {
  \draw[red] (a) ++(\pt:5) -- (a-maxx-maxy);
}
\foreach \pt in {270,280,...,360} {
  \draw[red] (a) ++(\pt:5) -- (a-minx-maxy);
}
\end{tikzpicture}
\end{document}

Result:

relocated node


Is this the sort of thing you want? I've replaced the code with an example closer to the sort of thing mentioned in the question.

\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\begin{document}
\begin{tikzpicture}
  \node (a) {A};
  \node (b)  [below=of a] {B};
  \node (c)  [right=of a] {C};
  \node (d)  [right=of b] {D};
  \begin{scope}
    \clip (a.north east) -- (a.east) -- (a.south east) -- (c.south west) -- (c.west) -- (c.north west) -- (a.north east);
    \draw (a.mid) -- (c.mid);
    \draw[red] (a)--(c);
  \end{scope}
  \begin{scope}
    \clip (a.south) -- (a.south east) -- (a.east) --(d.north) -- (d.north west) -- (d.west) -- (a.south);
    \draw (a.mid) -- (d.mid);
    \draw[red] (a)--(d);
  \end{scope}
\end{tikzpicture}
\end{document}

Better image

The trick is to clip to a box around the relevant anchors, but keep the clip within a scope so the whole picture doesn't get clipped...