在 Tikz 中离散化线方向

在 Tikz 中离散化线方向

在印刷电路板 (PCB) 布局中,线条只能水平、垂直和对角线方向。因此,每条线都是水平/垂直部分与对角线部分的组合。

我正在寻找一种在 Tikz 中实现这些知识的方法。这意味着当一个人画一条线时:

\draw (0,0) -- ++(5,2);

应将其绘制为:

\draw (0,0) -- ++(3,0) -- ++(2,2);

水平和垂直方向总是优先于对角线方向。当然,当明确给出坐标时,这很容易实现。但是,当坐标有名称时,我看不出有什么办法可以做到这一点。

从算法上来说,应该这样做:假设两个点是(x1,y1)(x2,y2)

  1. 计算差额(dx,dy)
  2. 如果abs(dx) >= abs(dy)执行以下操作
  3. 移动(x1,y1)一行(x1+sgn(dx)*(abs(dx)-abs(dy)),y1)又一行(x2,y2)

如果abs(dx) < abs(dy)只是将 x 轴与 y 轴交换的话。

如果原始线是完美的对角线,则结果也是对角线(因为水平部分的长度为零)。如果线是完美的水平/垂直,则结果线也是水平/垂直(因为对角线部分的长度等于零)。

答案1

以下示例定义了一个宏\drawcircuitline,该宏接受一个可选参数作为选项,draw以及两个强制参数,即坐标,无论是显式的还是作为节点名称,在两种情况下都没有括号。计算需要似乎缺少的函数sign。因此它通过以下方式定义\pgfmathdeclarefunction

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\pgfmathdeclarefunction{sign}{1}{%
  \begingroup
    \ifdim#1pt>\z@
      \def\pgfmathresult{1}%
    \else
      \ifdim#1pt=\z@
        \def\pgfmathresult{0}%
      \else
        \def\pgfmathresult{-1}%
      \fi
    \fi
    \pgfmath@smuggleone\pgfmathresult
  \endgroup
}
\makeatother

\newcommand*{\drawcircuitline}[3][]{%
  \draw[{#1}]
    let \p1=($(#3)-(#2)$),
        \n2={abs(\x1) - abs(\y1)},
        \n3={(\n2 > 0) * sign(\x1) * \n2},
        \n4={(\n2 < 0) * sign(\y1) * (-\n2)},
        \p{m}=(\n{3}, \n{4})
    in
    (#2) -- ++(\p{m}) -- (#3);
}

\begin{document}
  \begin{tikzpicture}[thick]
    \draw[help lines] (-6,-6) grid (6,6);
    \foreach \x/\y in { 4/0, -4/0, 0/4, 0/-4,
         1/1, -1/1, -1/-1, 1/-1, 5/5, -5/5, -5/-5, 5/-5,
         6/3, 3/6, -3/6, -6/3, -6/-3, -3/-6, 3/-6, 6/-3}
      \fill (\x,\y) circle[radius=3pt];
    \coordinate (a) at (1,1);
    \coordinate (b) at (6,3);
    \drawcircuitline{a}{b}
    \drawcircuitline{a}{5,5}
    \drawcircuitline{a}{3,6}
    \drawcircuitline{-1,1}{-3,6}
    \drawcircuitline{-1,1}{-5,5}
    \drawcircuitline{-1,1}{-6,3}
    \drawcircuitline{-1,-1}{-6,-3}
    \drawcircuitline{-1,-1}{-5,-5}
    \drawcircuitline{-1,-1}{-3,-6}
    \drawcircuitline{1,-1}{3,-6}
    \drawcircuitline{1,-1}{5,-5}
    \drawcircuitline{1,-1}{6,-3}
    \drawcircuitline{-4,0}{4,0}
    \drawcircuitline{0,4}{0,-4}
  \end{tikzpicture}
\end{document}  

结果

答案2

只需一点低级魔法,pcb trace就可以创建一条“到路径”。带星号的版本 ( pcb trace*) 从与无星号版本相反的一端开始路径的对角线部分:

\documentclass[tikz,border=5]{standalone}
\begin{document}
\makeatletter
\tikzset{%
  pcb/.style={
    draw=black,
    ultra thick,
    rounded corners=1ex,
  },
  pcb node/.style={%
    insert path={
      node [shape=circle, fill=white, draw, ultra thick, inner sep=2pt] {}
    }
  },
  pcb trace/.style={%
    to path={%
      \pgfextra{%
        % Get start point
        \tikz@scan@one@point\pgf@process(\tikztostart)%
        \pgf@xc=\pgf@x\pgf@yc=\pgf@y%
        % Get end point
        \tikz@scan@one@point\pgf@process(\tikztotarget)%
        \pgf@xb=\pgf@x\pgf@yb=\pgf@y%
        % Get difference between points
        \advance\pgf@x by-\pgf@xc%
        \advance\pgf@y by-\pgf@yc%
        % Get absolute values
        \pgf@xa=\ifdim0pt>\pgf@x-\fi\pgf@x%
        \pgf@ya=\ifdim0pt>\pgf@y-\fi\pgf@y%
        % For entirely horizontal, vertical and diagonal lines: do nothing.
        \ifdim\pgf@xa=0pt\else%
          \ifdim\pgf@ya=0pt\else%
            \ifdim\pgf@xa=\pgf@ya\else%
              \c@pgf@counta=\ifdim0pt>\pgf@x-\fi1\relax%
              \c@pgf@countb=\ifdim0pt>\pgf@y-\fi1\relax%
              \pgfpathlineto{%
                \ifdim\pgf@xa<\pgf@ya%
                  \ifx#1*%
                    \pgfpoint{\pgf@xb}{\pgf@yc+\c@pgf@countb\pgf@xa}%
                  \else%
                    \pgfpoint{\pgf@xc}{\pgf@yb-\c@pgf@countb\pgf@xa}%
                  \fi%
                \else%
                  \ifx#1*%
                    \pgfpoint{\pgf@xc+\c@pgf@counta\pgf@ya}{\pgf@yb}%
                  \else%
                    \pgfpoint{\pgf@xb-\c@pgf@counta\pgf@ya}{\pgf@yc}%
                  \fi%
                \fi%
              }%
            \fi%
          \fi%
        \fi%
      } 
      -- (\tikztotarget)
    }
  },
  pcb trace*/.style={pcb trace=*}
} 

\begin{tikzpicture}

\foreach \i in {-3,...,3}{
  \path [pcb]  
  (\i*2,7) [pcb node] to [pcb trace*] (\i,0) to [pcb trace] (\i*2,-7) [pcb node];
 \path [pcb]
   (7, \i*2) [pcb node] to [pcb trace*] (0,\i) to [pcb trace] (-7,\i*2) [pcb node];
}

\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容