jeudi 4 décembre 2014

Wrong intersection and position computations \anchorborder of \pgfdeclareshape


I'm trying to define a "labeled icon" shape (LIS), that is an icon (drawn with pgf commands, but replaced by a simple rectangle here for simplicity) with a label that is stuck to the icon (not the case in this minimal example for simplicity) and is part of the shape (border anchors are at the border of the icon AND of the label).


By using this shape I would get a result similar to the following image; except that, when the label is on the way of the edge, the edge would stop at the border of the label instead of crossing it.


Near desired result


The above image was obtained by the code:



\documentclass{article}

\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\fill[red] (0,0) circle (1pt);
\node[draw, label=-90:{Some text}] (node) at (0,0) {};
\foreach \angle in {0,30,...,330} {
\node[draw, label=-\angle:{Some text}] (node-\angle) at (\angle:5cm) {};
\draw (node) -- (node-\angle);
}
\end{tikzpicture}

\end{document}


Using the LIS shape, I would write:



\documentclass{article}

\usepackage{tikz}
\usepackage{minimal-shapes}

\begin{document}

\begin{tikzpicture}
\fill[red] (0,0) circle (1pt);
\node[lis, align=center] (lis) at (0,0) {Some\\text};
\foreach \angle in {0,30,...,330} {
\node[lis, lis label pos=-\angle, align=center] (lis-\angle) at (\angle:4cm) {LIS \\ \angle};
\draw (lis) -- (lis-\angle);
}
\end{tikzpicture}

\end{document}


I have defined the LIS shape in the file minimal-shapes.sty. Everything works fine except for the computations of the border anchors where it seems that the saved values are wrong and the text position and other points are shifted by 180 degrees. Here is the adapted shape declaration that emphasizes the problem. For debugging, the anchor border returned is always the one of the icon, but a small circle is drawn where the anchor border should be on the label border.



\usepgflibrary{intersections}

\pgfkeyssetvalue{/tikz/lis label pos}{-90}

\newlength{\lis@textWidth} \newlength{\lis@textHeight}

\newcommand{\setTextCenterCoords}[0]{
%% SIMPLIFIED VERSION
\pgfmathsetlength{\pgfutil@tempdima}{\wd\pgfnodeparttextbox / 2 + 1.5em}
\pgfpointpolar{\lis@labelPos}{\pgfutil@tempdima}
}

\pgfdeclareshape{lis}{
%% DIMENs
\saveddimen{\textWidth}{
\pgf@x=\wd\pgfnodeparttextbox
\ifdim\pgf@x<\pgfshapeminwidth
\pgf@x=\pgfshapeminwidth
\fi
}
\saveddimen{\textHeight}{\pgf@x=\ht\pgfnodeparttextbox}
%% MACROs
\savedmacro{\computeActorDimens}{
\setlength{\lis@textHeight}{\ht\pgfnodeparttextbox}
\setlength{\lis@textWidth}{\wd\pgfnodeparttextbox}
}
\savedmacro{\lis@labelPos}{
\pgfmathsetmacro{\lis@labelPos}{Mod((\pgfkeysvalueof{/tikz/lis label pos} + 180), 360) - 180}
\pgfwarning{Lis label pos: \pgfkeysvalueof{/tikz/lis label pos} -> \lis@labelPos}
}
%% SAVEDANCHORs
\savedanchor{\upperRightIconCorner}{
\pgfpoint{1em}{1em}
}
\savedanchor{\textCenter}{
\setTextCenterCoords
}
\savedanchor{\upperRightTextCorner}{
\computeActorDimens % Saveddimen do not seem available when declaring saved anchors
\setTextCenterCoords
\pgfmathsetlength{\pgf@x}{\pgf@x + (.5 * \lis@textWidth)}
\pgfmathsetlength{\pgf@y}{\pgf@y + (.5 * \lis@textHeight)}
}
%% ANCHORs
\anchor{center}{\pgfpointorigin}
\anchor{text}{
\textCenter
\pgfmathsetlength{\pgf@x}{\pgf@x - (.5 * \textWidth)}
\pgfmathsetlength{\pgf@y}{\pgf@y - (.5 * \textHeight)}
}
%% BORDER ANCHORs
\anchorborder{%
\@tempdima=\pgf@x \@tempdimb=\pgf@y
%
%\computeActorDimens
\textCenter
\upperRightTextCorner
\pgfintersectionofpaths{
\pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfpoint{\@tempdima}{\@tempdimb}}
\pgfgetpath\temppath
%\pgfusepath{stroke}
\pgfsetpath\temppath
}{
\pgfpathrectanglecorners{
\pgfpointlineattime{-1}{
\textCenter
}{
\upperRightTextCorner
}
}{
\upperRightTextCorner
}
\pgfgetpath\temppath
%\pgfusepath{stroke}
\pgftext[at=\textCenter]{\footnotesize \lis@labelPos}
\pgfsetpath\temppath
}
%
\pgfwarning{Nb intersections: \pgfintersectionsolutions}
%
\ifnum\pgfintersectionsolutions=0
\pgfpointborderrectangle{\pgfpoint{\@tempdima}{\@tempdimb}}{\upperRightIconCorner}
\else
\pgfintersectionsortbyfirstpath
\pgfpathcircle{\pgfpointintersectionsolution{\pgfintersectionsolutions}}{3pt}
\fi
\pgfpointborderrectangle{\pgfpoint{\@tempdima}{\@tempdimb}}{\upperRightIconCorner}
}
%% DRAWINGs
\backgroundpath{
%% SIMPLIFIED VERSION
\upperRightIconCorner \@tempdima=\pgf@x \@tempdimb=\pgf@y
\pgfpathrectanglecorners{
\pgfpointlineattime{-1}{\pgfpointorigin}{\pgfpoint{\@tempdima}{\@tempdimb}}
}{\pgfpoint{\@tempdima}{\@tempdimb}}
\pgfusepath{stroke}
}
}


With the above code, I get the following result:


Near desired result


It seems to nearly work fine for the central node. But the peripheral nodes have a wrong value for \lis@labelPos (which as been displayed to show the problem). An intersection (displayed as circles) is found when there should be one, but it appears on the wrong side of the node. If I unquote the first "\pgfusepath{stroke}", the lines go towards the outside of the figure instead of going towards the central node (the values \pgf@x and \pgf@y provided to \anchorborder seem to be wrong).


I don't understand what's happening. Can someone help ? Thanks





Aucun commentaire:

Enregistrer un commentaire