8

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 
            \advance\pgf@xa by-\pgf@xb 
            \advance\pgf@ya by-\pgf@yb  
         \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} 

enter image description here

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 !

1 Answer 1

7

(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 
            \advance\pgf@xa by-\pgf@xb 
            \advance\pgf@ya by-\pgf@yb  
         \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.

vectorian with options

2
  • 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 ! Apr 13, 2012 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!) Apr 13, 2012 at 9:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .