给出以下具有不规则形状多边形的 TikZ 图片:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\path[draw=blue] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
\node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (3.5,0.4) {};
\node [circle,draw=none,fill=green,inner sep=0pt,minimum size=0.3cm] at (1.03,1.3) {};
\node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (3.3,2) {};
\node [circle,draw=none,fill=red,inner sep=0pt,minimum size=0.3cm] at (0.7,1.8) {};
\end{tikzpicture}
\end{document}
图片中的两个绿色圆圈完全位于多边形内,而红色圆圈部分或全部位于多边形外。有没有办法在 TikZ 中自动执行“所有权”测试?我知道存在用于此类测试的算法,但 TikZ 是否已经提供了此功能或类似功能(例如单点测试)?
答案1
这是一个使用的解决方案射线投射法。该c
点是多边形外部的任意点。结果的质量取决于交点计算的准确性。
注意:要删除帮助行,您可以注释该\draw[help lines,...
行并取消注释该\path[name path...
行。
\documentclass[tikz]{standalone}
\usetikzlibrary{intersections}
\def\mycircles{
{c1/red/3.5,0.4},{c2/blue/1.03,1.3},
{c3/violet/3.3,2},{c4/lime/0.7,1.8},
{c5/orange/2,0.55}%
}
\begin{document}
\begin{tikzpicture}
\path[draw=blue,name path=polygon] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
\foreach \cname/\ccolor/\ccoord in \mycircles {
\node [circle,name path global=\cname,draw=none,fill=\ccolor,minimum size=3mm] (\cname) at (\ccoord) {};
}
\begin{scope}[overlay]
\coordinate (c) at (-100,300);
\foreach \cname/\ccolor/\ccoord in \mycircles {
\draw[help lines,dashed,name path global=line-\cname] (\cname.center) -- (c);
%\path[name path global=line-\mypath] (\mypath.center) -- (c);
}
\end{scope}
\coordinate (text) at (0,0);
\foreach \cname/\ccolor/\ccoord in \mycircles {
\path[%
name intersections={of=polygon and \cname,total=\npc},
name intersections={of=polygon and line-\cname,total=\nplc},
]
\pgfextra{
\node[align=flush left,at=(text),anchor=north west,node font=\scriptsize,inner sep=.1em] (desc) {
\pgfmathsetmacro\mypartial{int((\npc != 0)}
\pgfmathsetmacro\myin{int(mod(\nplc,2)!=0)}
\pgfmathsetmacro\mytexti{\mypartial==1?"intersects":(\myin==1?"is in":"is out")}
\pgfmathsetmacro\mytextii{\myin==1?"center is in":"center is out")}
\ccolor{} circle \mytexti{} (\mytextii)
};
\coordinate (text) at (desc.south west);
};
}
\end{tikzpicture}
\end{document}
答案2
以下是 Paul Gaborit 的漂亮答案的替代方案,该答案专门针对您类型的多边形(或更一般的形状)。您的形状称为“星形”因为存在(至少)一个点,其优点是形状中的任何点都可以通过不与边界相交的直线连接到该点。给定此点,测试所有权很简单:如果
- 其中心与星点的连线不与边界相交,并且
- 圆与边界不相交。
在下面的 MWE 中,我手工挑选了一个星点(并画出来)并执行所有权测试。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{intersections}
\makeatletter % https://tex.stackexchange.com/a/38995/121799
\tikzset{
use path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\makeatother
\begin{document}
\begin{tikzpicture}[broadcast/.code n args={2}{\xdef#2{#1}}]
\path[draw=blue,name path=poly] (0,3) -- (5,4) -- (3,2) -- (4,0) -- (1,1) -- cycle;
\coordinate (star) at (2,2);
\fill[blue] (star) circle (1pt);
\foreach \X [count=\Y] in {(3.5,0.4),(1.03,1.3),(3.3,2),(0.7,1.8)}
{\path[name path=aux] \X coordinate (X) to[bend left=0] (star);
\path[name intersections={of=poly and aux,total=\t},broadcast={\t}{\intT}];
\node [circle,draw=none,inner sep=0pt,minimum size=0.3cm,name
path=circ,save path=\pathC] (c-\Y) at (X) {};
\path[name intersections={of=poly and circ,total=\t},broadcast={\t}{\intS}];
\pgfmathtruncatemacro{\itest}{\intS+\intT}
\ifnum\itest=0
\fill[green,use path=\pathC];
\else
\fill[red,use path=\pathC];
\fi}
\end{tikzpicture}
\end{document}
该方法仅限于星形边界。然而,它不会遇到测试路径碰到拐角时出现的问题Paul Gaborit 的回答非常好。