在三次 B 样条曲线细化中使用 \foreach 循环

在三次 B 样条曲线细化中使用 \foreach 循环

这个问题仅与 TikZ (/PGF) 实现有关。这是我想要询问的 MWE:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}[scale=2]
\coordinate (p1) at (1,.5);
\coordinate (p2) at (1,1);
\coordinate (p3) at (0,1);
\coordinate (p4) at (0,0);
\coordinate (p5) at (1,0);
\coordinate (p6) at (1,-1);
\coordinate (p7) at (0,-1);
\coordinate (p8) at (0,-.5);
\draw[line width=1pt,blue] (p1) \foreach \p in {p2,p3,p4,p5,p6,p7,p8} {
-- (\p)};

%% For odd points the rule is $n_{2i-1} = .5*p_{i} + .5*p_{i+1}$
%% For even points the rule is $n_{2i} = .125*p_{i-1} + .75*p_{i} + .125*p_{i+1}$

\coordinate (n1) at ($.5*(p1) + .5*(p2)$);
\coordinate (n2) at ($.125*(p1) + .75*(p2) + .125*(p3)$);
\coordinate (n3) at ($.5*(p2) + .5*(p3)$);
\coordinate (n4) at ($.125*(p2) + .75*(p3) + .125*(p4)$);
\coordinate (n5) at ($.5*(p3) + .5*(p4)$);
\coordinate (n6) at ($.125*(p3) + .75*(p4) + .125*(p5)$);
\coordinate (n7) at ($.5*(p4) + .5*(p5)$);
\coordinate (n8) at ($.125*(p4) + .75*(p5) + .125*(p6)$);
\coordinate (n9) at ($.5*(p5) + .5*(p6)$);
\coordinate (n10) at ($.125*(p5) + .75*(p6) + .125*(p7)$);
\coordinate (n11) at ($.5*(p6) + .5*(p7)$);
\coordinate (n12) at ($.125*(p6) + .75*(p7) + .125*(p8)$);
\coordinate (n13) at ($.5*(p7) + .5*(p8)$);
\draw[line width=3pt] (n1) \foreach \n in {n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13} {
-- (\n)};
\end{tikzpicture}

\end{document}

重点是,我想使用指令计算三次 B 样条曲线细化中考虑到初始点 p1,...,p8 找到的所有 n1,...,n13 坐标,\foreach而不是像图中所示那样手动计算,但我不知道如何\foreach在同一次迭代中使用列表中的多个点。如果您还可以将新点生成为列表或数组,那就太好了。

请以更通用的方式进行操作,考虑尽可能多的初始点(不仅仅是 8 个)以及在同一次迭代中使用多个点的可能性。我认为对我来说这个问题只是冰山一角!

答案1

这里混合了第一个答案和我过去barycentric cs避免的calc。我过去常常foreach创建第一个点。

我使用 \pgfmathtruncatemacro而不是evaluate像打击乐那样,因为我不知道哪种形式最有效。

\documentclass{article}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[scale=2]
\foreach \x/\y [count=\i] in {1/.5,1/1,0/1,0/0,1/0,1/-1,0/-1,0/-.5,0/0}{%
      \coordinate (p\i) at (\x,\y);}
\draw[line width=1pt,blue] (p1) \foreach \p in {2,...,8} {-- (p\p)};

\foreach \i  in {1,...,7} {%
    \pgfmathtruncatemacro{\j}{\i+1}%
    \pgfmathtruncatemacro{\k}{\i+2}%
    \pgfmathtruncatemacro{\ind}{2*\i-1}%
    \pgfmathtruncatemacro{\next}{2*\i}%
    \coordinate (n\ind) at (barycentric cs:p\i=0.5,p\j=0.5);
    \coordinate (n\next) at (barycentric cs:p\i=0.125,p\j=0.75,p\k=0.125);
    }

\draw[line width=2pt,red] (n1)\foreach \i in {2,...,13}{-- (n\i)};   
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

这里有一点,但我想我没有理解你的问题。你的公式不适用于复杂的指标,例如检查偶数公式。你可能会发现把留i在左边,把指标写在右边会很有帮助i

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

\begin{tikzpicture}[scale=2]
\coordinate (p1) at (1,.5);
\coordinate (p2) at (1,1);
\coordinate (p3) at (0,1);
\coordinate (p4) at (0,0);
\coordinate (p5) at (1,0);
\coordinate (p6) at (1,-1);
\coordinate (p7) at (0,-1);
\coordinate (p8) at (0,-.5);
\draw[line width=1pt,blue] (p1) \foreach \x in {2,...,8} {-- (p\x)};

%% For odd points the rule is $n_{2i-1} = .5*p_{i} + .5*p_{i+1}$
%% For even points the rule is $n_{2i} = .125*p_{i-1} + .75*p_{i} + .125*p_{i+1}$
\foreach \x[evaluate=\x as \evxx using int(\x/2),
            evaluate=\x as \odxxi using int((\x+1)/2),
            evaluate=\x as \evxxi using int((\x/2)+1),
            evaluate=\x as \odxxii using int((\x+3)/2),
            evaluate=\x as \evxxii using int((\x/2)+2)] in {1,...,13}{
\ifodd\x
\coordinate (n\x) at ($.5*(p\odxxi) + .5*(p\odxxii)$);
\else
\coordinate (n\x) at ($.125*(p\evxx) + .75*(p\evxxi) + .125*(p\evxxii)$);
\fi
}
\draw[line width=3pt] (n1) \foreach \x in {2,...,13}{-- (n\x)};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

我将您的循环拆分为 2 个。我为可变数量的点准备了设计。您只需添加\point{ }一个新点即可。

结果

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}

\newcounter{cnt}

\newcommand{\point}[1]{
    \stepcounter{cnt}
    \coordinate (p\thecnt) at (#1);
}

\begin{document}

    \begin{tikzpicture}[scale=2]
        \point{1,.5};
        \point{1,1};
        \point{0,1};
        \point{0,0};
        \point{1,0};
        \point{1,-1};
        \point{0,-1};
        \point{0,-.5};
        \draw[line width=1pt,blue] (p1) \foreach \p in {2, ..., \thecnt} { -- (p\p)};

        %% For odd points the rule is $n_{2i-1} = .5*p_{i} + .5*p_{i+1}$
        %% For even points the rule is $n_{2i} = .125*p_{i-1} + .75*p_{i} + .125*p_{i+1}$

        \pgfmathtruncatemacro{\max}{\thecnt -1}
        \foreach \k in {1, ..., \max} {
            \pgfmathtruncatemacro{\i}{2 * \k - 1)}
            \pgfmathtruncatemacro{\l}{\k+1)}
            \coordinate (n\i) at ($(p\k)!0.5!(p\l)$);
            \xdef\t{\i}
        }

        \foreach \l in {2, ..., \max} {
            \pgfmathtruncatemacro{\i}{2 * \l - 2)}
            \pgfmathtruncatemacro{\k}{\l - 1)}
            \pgfmathtruncatemacro{\m}{\l + 1)}
            \coordinate (n\i) at ($0.125*(p\k) + 0.75*(p\l) + 0.125*(p\m)$);
        }

        \draw[line width=3pt] (n1) \foreach \k in {2, ..., \t} { -- (n\k)};

    \end{tikzpicture}
\end{document}

相关内容