# How to use pgfkeys with “to path”

I'm not sure if the title is correct but I'll try to explain my problem correctly.

I always work on the pgfvectorian package and I try to add some useful macros. One of these macros is to place an vector ornament between two nodes.

The next code give you a vector object named \myobject the I define a macro \pgfobj to draw this object. In this example I added 3 options : scale , width and anchor. width is to draw the object with a predefined width and anchor is used to place the object.

I also defined a style object to easily place the object between two points. I calculate the distance between the 2 points and then I place the object with sloped and pos.

My problem : I would like to extend the style object. I would like for example change the value of pos and the value of anchor but I can't find a solution to this.

I would like a syntax like \draw [black] (A) to [object,pos=.2,anchor=north] (B); but apply these values at node [anchor=south,pos=.5,sloped,allow upside down,inner sep=0pt]

Sorry fot the long code but I think it's necessary to understand the question :

\documentclass[landscape]{scrartcl}
\usepackage{fullpage,tikz}
\usetikzlibrary{shapes.geometric,calc}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\def\myobject{%
\pgfpathmoveto{\pgfqpoint{0bp}{0bp}}
\pgfpathcurveto{\pgfqpoint{50bp}{0bp}}
{\pgfqpoint{150bp}{0bp}}
{\pgfqpoint{200bp}{16bp}}
\pgfpathcurveto{\pgfqpoint{250bp}{0bp}}
{\pgfqpoint{350bp}{0bp}}
{\pgfqpoint{400bp}{0bp}}
\pgfpathlineto{\pgfqpoint{400bp}{1bp}}
\pgfpathcurveto{\pgfqpoint{350bp}{0bp}}
{\pgfqpoint{250bp}{0bp}}
{\pgfqpoint{200bp}{22bp}}
\pgfpathcurveto{\pgfqpoint{150bp}{0bp}}
{\pgfqpoint{50bp}{0bp}}
{\pgfqpoint{0bp}{1bp}}
\pgfpathlineto{\pgfqpoint{0bp}{0bp}}
\pgfusepath{fill,stroke}}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\makeatletter
\pgfkeys{
/obj/.cd,
scale/.code     =  {\def\pgfogjscale{#1}},
width/.code     =  {\def\pgfogjwidth{#1}},
anchor/.code    =  {\def\pgfobjanchor{#1}}
}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\def\pgfobj{\pgfutil@ifnextchar[{\pgf@obj}{\pgf@obj[]}}
\def\pgf@obj[#1]{%
\pgfkeys{%
/obj/.cd,
scale    =  1,
width    =  {},
anchor   = south
}%
\pgfqkeys{/obj}{#1}%
\begin{tikzpicture}[baseline=(current bounding box.\pgfobjanchor)]
\ifx\pgfogjwidth\empty  \else
\pgfmathsetmacro{\pgfogjscale}{\pgfogjwidth /400 bp}%
\fi
\pgftransformscale{\pgfogjscale}%
\myobject
\end{tikzpicture}%
}%
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\tikzset{%
object/.style={to path={%
\pgfextra{%
\tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
\pgf@xb=\pgf@x
\pgf@yb=\pgf@y
\pgfmathveclen{\pgf@xa}{\pgf@ya}
\global\let\objlen\pgfmathresult
\path (\tikztostart)  -- node [anchor=south,pos=.5,
sloped,allow upside down,inner sep=0pt]%
{\pgfobj[width=\objlen]} (\tikztotarget) ;
}%end pgfextra
}% end to path
}% end style
}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\makeatother
\begin{document}
vector ornament with \texttt{scale=.5}: \pgfobj[scale=.5]

vector ornament between 2 nodes :
\begin{tikzpicture}
\node (A) at (0,0) {};  \node (B) at (7,5) {};
\draw [help lines]  (0,0) grid (7,5);
\draw [fill=black]  (A) circle (2pt)
(B) circle (2pt);
\draw [black]       (A) to [object]  (B);

\end{tikzpicture}

Ornaments with a pentagon :
\begin{tikzpicture}
\node[regular polygon, regular polygon sides=5,
minimum size=8cm,inner sep=0pt](h)  {};
\foreach \i [count=\next from 2] in {1,...,5}
{%
\draw (h.corner \i) to [object] (h.corner \next);
\pgfmathtruncatemacro{\next}{mod(\next,5)} }
\end{tikzpicture}

\end{document}


Remark 1) I can use another code to draw the object like :

        \pgfmathsetmacro{\objangle}{atan2(\pgf@xa,\pgf@ya)}
\node[anchor=south,rotate=\objangle,inner sep=0pt] at
($(\tikztostart)!.5!(\tikztotarget)$){\pgfobj[width=\objlen]} ;


2) In fact I work with several objects also the syntax is something like :

   \draw [black]   (A) to [object = integer]  (B); % integer = numero of the object


3) Perhaps I may have taken a wrong way also if you have a better idea, I'm listening !

-

(This is really a long comment, but I want to post a picture. Are you still interested in this question?)

I'm not sure what effect you are trying to achieve with this. Here's a small adaptation of your code where I've added some keys which get passed on to the drawing code, but I don't have a picture in my head of what you want the output to look like. I define a couple of new keys, /tikz/obj/anchor and /tikz/obj/pos, which set macros that then get used in the construction. To make [object,pos=.2,anchor=south] work as is then I have the object style sneakily change directory to /tikz/obj so that /tikz/obj/anchor and /tikz/obj/pos are used for pos and anchor. To do this properly, I ought to put in an .unknown handler to ensure that any other key gets passed on to /tikz/. Or one could use obj/pos and obj/anchor explicitly without the sneaky change of directory.

Here's the code:

\documentclass[landscape]{scrartcl}
\usepackage{fullpage,tikz}
\usetikzlibrary{shapes.geometric,calc}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\def\myobject{%
\pgfpathmoveto{\pgfqpoint{0bp}{0bp}}
\pgfpathcurveto{\pgfqpoint{50bp}{0bp}}
{\pgfqpoint{150bp}{0bp}}
{\pgfqpoint{200bp}{16bp}}
\pgfpathcurveto{\pgfqpoint{250bp}{0bp}}
{\pgfqpoint{350bp}{0bp}}
{\pgfqpoint{400bp}{0bp}}
\pgfpathlineto{\pgfqpoint{400bp}{1bp}}
\pgfpathcurveto{\pgfqpoint{350bp}{0bp}}
{\pgfqpoint{250bp}{0bp}}
{\pgfqpoint{200bp}{22bp}}
\pgfpathcurveto{\pgfqpoint{150bp}{0bp}}
{\pgfqpoint{50bp}{0bp}}
{\pgfqpoint{0bp}{1bp}}
\pgfpathlineto{\pgfqpoint{0bp}{0bp}}
\pgfusepath{fill,stroke}}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\makeatletter
\pgfkeys{
/obj/.cd,
scale/.code     =  {\def\pgfogjscale{#1}},
width/.code     =  {\def\pgfogjwidth{#1}},
anchor/.code    =  {\def\pgfobjanchor{#1}},
}
\tikzset{
obj/.cd,
anchor/.code    =  {\def\pgfobjnodeanchor{#1}},
pos/.code       =  {\def\pgfobjnodepos{#1}},
anchor = north,
pos = .5
}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\def\pgfobj{\pgfutil@ifnextchar[{\pgf@obj}{\pgf@obj[]}}
\def\pgf@obj[#1]{%
\pgfkeys{%
/obj/.cd,
scale    =  1,
width    =  {},
anchor   = south,
}%
\pgfqkeys{/obj}{#1}%
\begin{tikzpicture}[baseline=(current bounding box.\pgfobjanchor)]
\ifx\pgfogjwidth\empty  \else
\pgfmathsetmacro{\pgfogjscale}{\pgfogjwidth /400 bp}%
\fi
\pgftransformscale{\pgfogjscale}%
\myobject
\end{tikzpicture}%
}%
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\tikzset{%
object/.style={to path={%
\pgfextra{%
\tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
\pgf@xb=\pgf@x
\pgf@yb=\pgf@y
\pgfmathveclen{\pgf@xa}{\pgf@ya}
\global\let\objlen\pgfmathresult
\path (\tikztostart)  -- node [anchor=\pgfobjnodeanchor,pos=\pgfobjnodepos,
sloped,allow upside down,inner sep=0pt]%
{\pgfobj[width=\objlen]} (\tikztotarget) ;
}%end pgfextra
},% end to path
obj/.cd,
}% end style
}
%8<------8<------8<------8<------8<------8<------8<------8<------8<------
\makeatother
\begin{document}
vector ornament with \texttt{scale=.5}: \pgfobj[scale=.5]

vector ornament between 2 nodes :
\begin{tikzpicture}
\node (A) at (0,0) {};  \node (B) at (7,5) {};
\draw [help lines]  (0,0) grid (7,5);
\draw [fill=black]  (A) circle (2pt)
(B) circle (2pt);
\draw [black]       (A) to [object]  (B);

\end{tikzpicture}

vector ornament between 2 nodes :
\begin{tikzpicture}
\node (A) at (0,0) {};  \node (B) at (7,5) {};
\draw [help lines]  (0,0) grid (7,5);
\draw [fill=black]  (A) circle (2pt)
(B) circle (2pt);
\draw [black]       (A) to [object,pos=.2,anchor=north]  (B);

\end{tikzpicture}

Ornaments with a pentagon :
\begin{tikzpicture}
\node[regular polygon, regular polygon sides=5,
minimum size=8cm,inner sep=0pt](h)  {};
\foreach \i [count=\next from 2] in {1,...,5}
{%
\draw (h.corner \i) to [object] (h.corner \next);
\pgfmathtruncatemacro{\next}{mod(\next,5)} }
\end{tikzpicture}

\end{document}


Here's the result, but as I say: I'm not sure if it is what you want or not.

-
Yes it's fine. Your answer is interesting because I can analyze how you work with pgfkeys. Sometimes it's not easy, for example, I had never thought of using obj/.cd ! – Alain Matthes Apr 13 '12 at 9:29
Glad it's helpful. I'll be curious to see what the end result is. (I'm no expert on pgfkeys - we need Ryan Reich for that!) – Loop Space Apr 13 '12 at 9:30