当计算一条线与另一条双线路径之间的交点时,TikZ 通常会返回双线路径中间的交点。这里的问题是如何获得与路径外线的交点。我相信,我们可以将点移动一个值.5\pgflinewidth + .5\pgfinnerlinewidth
,但我在宏中使用它,它应该首先检查路径是否是双线,然后它可以进行校正。代码目前是这样的:
\documentclass[tikz,border=1mm]{standalone}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\node (rect) [name path=rect,draw,double,ultra thick,double distance=3pt, rounded corners,minimum size=1cm]{};
\draw[name path=line] (rect.center)--(.7,.7);
\path[name intersections={of= rect and line}];
\node at (intersection-1) [circle,fill=blue,inner sep=.5pt]{};
\end{tikzpicture}
\end{document}
我很感激你的建议。
评论@Augustin 的回答:
这应该是一条评论,但发布图片需要在这里编辑。Augustin 的答案仅适用于直线斜率为 45 度的情况,这种情况很少见。例如,尝试
...
\draw[name path=line,draw] (rect.center)--(.7,.1);
..
您将获得以下结果:
我很感谢你的尝试,但我需要一个通用的解决方案。更重要的是,我在问题中提到我可以转移点。我需要完成的是如何检查路径是否是双重的以及如何获取其innerlinewidth
、总计linewidth
等的键(您拥有的所有信息都是路径本身),以便能够进行正确的转移。
答案1
您可以使用calc
TikZ 包来完成这项工作:
\documentclass[tikz,border=1mm]{standalone}
\usetikzlibrary{intersections,calc}
\begin{document}
\begin{tikzpicture}
\def \borderSep {3pt} % Define the border separation as a constant
\node (rect) [name path=rect,draw,double,ultra thick,double distance=\borderSep, rounded corners,minimum size=1cm]{};
\draw[name path=line,draw] (rect.center)--(.7,.7);
\path[name intersections = {of=rect and line, by={a}}];
% Offset the nodes by sqrt(2) * separation
\node at ($(a) + 1/1.41*(\borderSep,\borderSep)$) [circle,fill=blue,inner sep=.5pt]{};
\node at ($(a) - 1/1.41*(\borderSep,\borderSep)$) [circle,fill=blue,inner sep=.5pt]{};
\end{tikzpicture}
\end{document}
您将获得以下内容:
编辑:更通用的解决方案:
\documentclass[tikz,border=1mm]{standalone}
\usetikzlibrary{intersections,calc}
\begin{document}
\begin{tikzpicture}
% If the rect has single border, set borderSep and borderThickness to 0pt
\def \borderSep {3pt}
\def \borderThickness {1.5pt}
\node (rect) [name path=rect,draw,double,ultra thick,double distance=\borderSep,rounded corners,minimum size=1cm]{};
\draw[name path=line,draw] (rect.center)--(.7,.1);
% Construct invisible rectangles at the positions of the borders
\node (rect) [name path=rectIn, rounded corners=6pt, minimum size=1cm+\borderSep+\borderThickness]{};
\node (rect) [name path=rectOut, rounded corners=2pt, minimum size=1cm-\borderSep-\borderThickness]{};
\path[name intersections = {of=rectIn and line, by={intIn}}];
\path[name intersections = {of=rectOut and line, by={intOut}}];
\node at (intIn) [circle,fill=blue,inner sep=.5pt]{};
\node at (intOut) [circle,fill=blue,inner sep=.5pt]{};
\end{tikzpicture}
\end{document}
现在,这在一般情况下也有效。请注意,如果您想要更精细的控制,则需要编辑(例如使用全局变量)rectIn 和 rectOut 圆角的半径。
答案2
这是一种数学方法,\dimexpr
在需要与单位无关的地方使用(适用于 pt、cm 或其他单位)。
它仅适用于线(使用\myline
命令添加,但它可以像真正的 tikz 线一样接受参数)。线可以从任何点开始并终止于任何其他点,但必须与双路径相交。
双路径部分的距离也必须定义为\DoubleDist
变量中定义。我认为代码可以更通用,并适用于超厚(但尚未包含此类参数,我不知道是否可以在不定义新参数的情况下添加)。
最后,交叉点的形状(圆形)最好由用户选择,但我也厌倦了这样做。(我想任何能理解代码的人都可以自己做)。
代码:
\documentclass[tikz,border=1mm]{standalone}
\usetikzlibrary{intersections}
\usetikzlibrary{calc}
\begin{document}
\def\DoubleDist{4.1 pt}
%\Usage \myline(x1,y1)(x2,y2)[parameters]=\draw[parameters] (x1,y1)--(x2,y2); +keep needed numbers
\makeatletter
\def\myline{\@ifnextchar({\readFirstOPoint}{\node at (0,0){Error in line 1};}}
\def\readFirstOPoint(#1,#2){
\gdef\lineXStart{#1}
\gdef\lineYStart{#2}
\@ifnextchar(
{\readSecondPoint}
{\node at (0,0){Error in line 2};}
}
\def\readSecondPoint(#1,#2){
\gdef\lineXStop{#1}
\gdef\lineYStop{#2}
\readParametersAndDraw
}
\def\readParametersAndDraw
{\@ifnextchar[{\Storeparam}{\gdef\LineParam{\empty}\ExecuteLine}}
\def\Storeparam[#1]
{
\gdef\LineParam{[#1]}
\ExecuteLine
}
\def\ExecuteLine
{
\draw\LineParam (\lineXStart,\lineYStart)--(\lineXStop,\lineYStop);
}
\makeatother
% Will be used to shift the point
\newlength{\xsh}
\newlength{\ysh}
% Finding double path intersections. Usage \FindIndersections(path)
\makeatletter
\def\FindIndersections{
\@ifnextchar({\ReadIndersection}{\node at (0,0){Error in readind indersection}}
}
\def\ReadIndersection(#1){
\pgfmathsetmacro\XShiftFactor{(\lineXStop-\lineXStart)/sqrt((\lineXStart-\lineXStop)^2+(\lineYStart-\lineYStop)^2)}
\pgfmathsetmacro\YShiftFactor{(\lineYStop-\lineYStart)/sqrt((\lineXStart-\lineXStop)^2+(\lineYStart-\lineYStop)^2)}
\setlength{\xsh}{\dimexpr\XShiftFactor\dimexpr\dimexpr\DoubleDist/2\relax+\pgflinewidth\relax\relax}
\setlength{\ysh}{\dimexpr\YShiftFactor\dimexpr\dimexpr\DoubleDist/2\relax+\pgflinewidth\relax\relax}
\draw[fill=blue] ($(#1)-(\the\xsh ,\the\ysh)$) circle (1pt);
\draw[fill=blue] ($(#1)+(\the\xsh, \the\ysh)$) circle (1pt);
}
\makeatother
\begin{tikzpicture}
\node (rect) [name path=rect,draw,double,double distance=\DoubleDist, rounded corners,minimum size=30 pt]{};
\myline(0.2,0)(0.8,0.3)[brown,name path=line]
\path[name intersections={of= rect and line}];
\FindIndersections(intersection-1)
\end{tikzpicture}
\end{document}
输出:
对于像云一样的一些复杂形状,交点无法找到真正的中间,所以我的方法也失败了:
代码:
\begin{tikzpicture}
\node (rect) [name path=rect,draw,draw, cloud,,double,double distance=\DoubleDist,minimum size=1.3 cm]{};
\myline(0.2,0)(-0.7,-0.4)[brown,name path=line]
\path[name intersections={of= rect and line}];
\draw[fill=red] (intersection-1) circle (1pt);
\FindIndersections(intersection-1)
\end{tikzpicture}
(使用 tikzlibrary 形状)。
结果:
答案3
\documentclass[tikz,border=1mm]{standalone}
\usetikzlibrary{intersections,fit}
\begin{document}
\begin{tikzpicture}
\node (rect) [name path=rect,draw,double,ultra thick,double distance=3pt, rounded corners,minimum size=1cm]{};
\draw[name path=line] (rect.center)--(.7,.7);
\path[name intersections={of= rect and line}];
\node at (intersection-1) [circle,fill=blue,inner sep=.5pt]{};
\end{tikzpicture}
\begin{tikzpicture}
\node (inner-rect) [name path=inner-rect,draw,ultra thick,
minimum size=1cm-4.5pt,inner sep=0pt,rounded corners=1.5pt]{};
\node (outer-rect) [name path=outer-rect,draw,ultra thick,
minimum size=1cm+4.5pt,inner sep=0pt,rounded corners=4.5pt]{};
\foreach \X [count=\Y] in {45,90,210,-45}
{\draw[name path=line-\Y] (inner-rect.center)--(\X:0.8);
\path[name intersections={of=inner-rect and line-\Y}]
node at (intersection-1) [circle,fill=blue,inner sep=.5pt]{};
\path[name intersections={of=outer-rect and line-\Y}]
node at (intersection-1) [circle,fill=red,inner sep=.5pt]{};}
\end{tikzpicture}
\end{document}