如何使用 pgfkeys 和“to path”

如何使用 pgfkeys 和“to path”

我不确定标题是否正确,但我会尝试正确解释我的问题。

我一直在研究 pgfvectorian 包,并尝试添加一些有用的宏。其中一个宏是在两个节点之间放置一个矢量装饰。

下一个代码为您提供了一个名为的矢量对象,\myobject我定义了一个宏\pgfobj来绘制该对象。在这个例子中,我添加了 3 个选项:scalewidthanchorwidth用于绘制具有预定义宽度的对象,并anchor用于放置对象。

我还定义了一种样式object,以便轻松地将对象放置在两点之间。我计算两点之间的距离,然后使用sloped和放置对象pos

我的问题:我想扩展样式object。例如,我想更改的值pos和的值,anchor但我找不到解决方案。

我想要一个类似的语法\draw [black] (A) to [object,pos=.2,anchor=north] (B);,但应用这些值node [anchor=south,pos=.5,sloped,allow upside down,inner sep=0pt]

抱歉,代码太长了,但我认为有必要理解这个问题:

\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} 

在此处输入图片描述

备注 1)我可以使用另一个代码来绘制对象,如下:

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

2)事实上我也使用了几个对象,语法如下:

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

3)也许我走错了路,如果你有更好的想法,我会听的!

答案1

(这确实是一条很长的评论,但我想发布一张图片。你还对这个问题感兴趣吗?)

我不确定你想用这个实现什么效果。下面是对你的代码的一个小改动,我添加了一些键,这些键会传递给绘图代码,但我脑子里没有你想要的输出是什么样子的图片。我定义了几个新的键,/tikz/obj/anchor/tikz/obj/pos,它们设置了宏,然后在构造中使用。为了让[object,pos=.2,anchor=south]工作照原样然后我使用object样式偷偷更改目录到,/tikz/obj以便/tikz/obj/anchor/tikz/obj/pos用于posanchor。为了正确执行此操作,我应该放入一个.unknown处理程序以确保任何其他键都传递给/tikz/。或者可以明确使用obj/pos和而obj/anchor无需偷偷更改目录。

代码如下:

\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} 

这是结果,但正如我所说:我不确定这是否是你想要的。

带选项的向量

相关内容