绘制中心未被某些路径剪切的完整节点

绘制中心未被某些路径剪切的完整节点

目标

我想绘制中心不被某些路径剪裁的完整节点。

该解决方案如何可能发挥作用?

为了更好地理解,我将分两个步骤来描述:

  • 绘制前裁剪——“修剪”每个中心超出范围的节点,
  • 绘制完整节点(其中心不被路径剪切),即没有任何剪切。

这可能吗?

问题的底部有两页文档,第一页是正常剪辑,第二页是我想要实现的(但需要手动剪辑 - 在这种情况下很容易,但通常并不简单,所以显示的代码显然不是我想要的)。

分解

值得补充的是,该问题可以分解为:

这里的关键是能够迭代路径中的点和曲线。我在手册中寻找它,但没有找到多少运气(或者,像往常一样,我搜索错了)。

例子

\documentclass{minimal}
\usepackage[utf8]{inputenc}
\usepackage[paperwidth=6.25cm,paperheight=6.25cm,margin=0pt]{geometry}
\usepackage{ifthen}
\usepackage{tikz}
\begin{document}
\parindent=0pt
\pagestyle{empty}
\begin{tikzpicture}[remember picture,overlay]
\node at (current page.center) {%
\begin{tikzpicture}[overlay]
    \clip[draw] (0.35,0) circle (3.45);
    \foreach \y in {-3,-2,...,3}
        \foreach \x in {-3,-2,...,3} {
            \node[draw] at (\x,\y) {};
            \draw[fill] (\x,\y) circle (0.1pt);
        }
\end{tikzpicture}
};
\end{tikzpicture}
\newpage
\begin{tikzpicture}[remember picture,overlay]
\node at (current page.center) {%
\begin{tikzpicture}[overlay]
    \draw (0.35,0) circle (3.45);
    \foreach \y in {-3,-2,...,3}
        \foreach \x in {-3,-2,...,3} {
            \pgfmathsetmacro{\radiusc}{3.45^2 - (\x - 0.35)^2 - (\y - 0)^2}
            \ifthenelse{\lengthtest{\radiusc pt>0pt}\OR\lengthtest{\radiusc pt=0pt}}{
            \node[draw] at (\x,\y) {};
            \draw[fill] (\x,\y) circle (0.1pt);
            }{}
        }
\end{tikzpicture}
};
\end{tikzpicture}
\end{document}

正常剪裁 智能剪辑

答案1

这是一个原型。困难在于(据我所知)裁剪根本不由 TeX 处理,而是由最终的文档格式完成的(因此实际上由文档查看器完成)。因此,如果通过通常的方式进行裁剪,TeX 不知道哪些会被裁剪,哪些不会被裁剪,因此无法使用该信息。这意味着我们必须模拟裁剪。为此,我使用了库。intersections这个想法是,如果我们有一条封闭的路径,那么如果一条射线从该点开始并以“无穷大”结束,与该路径相交的次数为奇数,则该点位于该路径内。这并非 100% 准确:切线是有问题的,就像“无穷大”一样。因此,我们希望“无穷大”是“很远很远”的,并且我们希望通过某种方式选择射线以避免切线。我将“很远很远”设置为 10 厘米(尽管这很容易修改),对于射线,我已将其设置为您(用户)选择某个“中心点”,然后如果继续沿正确的方向前进,所有射线都会通过该点。通过改变该点,应该可以找到一个(对于有限数量的节点)避免所有切线的点。

最后一个问题是如何实现是否应该绘制节点的决定。这很困难,因为如果我们已经在处理节点,那么转过身说“实际上,忘掉它”就有点棘手了。设置了太多不同的组和事物,我很难弄清楚如何取消和关闭它们。相反,我放置了一个命令,它\ifinside看起来好像需要两个参数。第一个是要考虑的坐标,第二个是如果坐标在剪切路径内(也可以很容易地有一个\ifoutside)要包含的代码。作为奖励,坐标保留为“当前坐标”,因此不必在参数中重新指定它。(这也可以修改,而且我认为考虑的坐标是最后提到的坐标的变体会很有用。)

综合以上内容,我们得到以下代码:

\documentclass{article}
%\url{}
\usepackage{tikz}
\usetikzlibrary{intersections,calc}

\makeatletter
\newdimen\clipper@sx
\newdimen\clipper@sy
\newdimen\clipper@ex
\newdimen\clipper@ey
\newdimen\clipper@len

\def\ifinside#1{%
  \pgfextra{%
    \tikz@scan@one@point\pgfutil@firstofone#1
    \clipper@sx=\pgf@x\relax
    \clipper@sy=\pgf@y\relax
    \pgfmathsetlength{\clipper@ex}{(\clipper@sx -  \pgfkeysvalueof{/tikz/clipper/centre point x})}%
    \pgfmathsetlength{\clipper@ey}{(\clipper@sy -  \pgfkeysvalueof{/tikz/clipper/centre point y})}%
    \pgfmathsetlength{\clipper@len}{veclen(\clipper@ex,\clipper@ey)}%
    \pgfmathsetlength{\clipper@ex}{\clipper@sx + 10cm / \clipper@len *  \clipper@ex}%
    \pgfmathsetlength{\clipper@ey}{\clipper@sy + 10cm / \clipper@len *  \clipper@ey}%
    \edef\tikz@intersect@path@name@radius{\noexpand\pgfsyssoftpath@movetotoken{\the\clipper@sx}{\the\clipper@sy}\noexpand\pgfsyssoftpath@linetotoken{\the\clipper@ex}{\the\clipper@ey}}%
    \tikzset{name intersections={of=clipper@path and radius, total=\clipper@total}}%
    \ifodd\clipper@total
    \let\clipper@next=\pgfutil@firstofone
    \else
    \let\clipper@next=\pgfutil@gobble
    \fi
    \tikz@lastx=\clipper@sx
    \tikz@lasty=\clipper@sy
  }\clipper@next%
}

\tikzset{
  clipper/.style={
    name path=clipper@path,
    set clipper centre={#1},
  },
  clipper/centre point x/.initial={0.1},
  clipper/centre point y/.initial={0.1},
  set clipper centre/.code={%
    \def\clipper@temp{#1}%
    \ifx\clipper@temp\pgfutil@empty
    \else
    \tikz@scan@one@point\pgfutil@firstofone#1%
    \edef\tikz@marshal{\noexpand\tikzset{%
      clipper/centre point x=\the\pgf@x,
      clipper/centre point y=\the\pgf@y,
    }}%
    \tikz@marshal
    \fi
  }
}

\makeatother

\begin{document}
\begin{tikzpicture}
\draw[red,thick,clipper={(0.1,0.1)}] (0,0) circle[radius=3cm];
\foreach \nx in {-4,-3.5,...,4} {
  \foreach \ny in {-4,-3.5,...,4} {
    \fill[green] (\nx,\ny) circle[radius=1pt];
    \path \ifinside{(\nx,\ny)}{node[draw] {a}};
  }
}
\end{tikzpicture}
\end{document}

结果:

根据中心裁剪的节点

我没有严格测试过,但这个理论没有错!而且,慢的。但接下来必须以合理的准确度来完成这一任务。

相关内容