tikz-pgf 路径的长度、表面和坐标

tikz-pgf 路径的长度、表面和坐标

我需要对属于 tikz-pgf 路径的点进行计算。更具体地说,我想知道有多少个点的 y 坐标超过给定值,并且我想用数字计算路径下方区域的表面(积分)。

或者(或另外):有没有办法评估路径和封闭表面的长度?

答案1

这是一个概念验证集成宏。结果以 pt² 为单位(除以 806.56 可得到 cm²)。

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

\makeatletter
\def\integrate#1{{
    % Use the facilities in the decoration library to break the path into
    % simple chunks.
    \pgf@decorate@parsesoftpath#1\parsedpath
    \gdef\area{0}
    \xdef\length{\pgf@decorate@totalpathlength}

    \let\pgf@decorate@inputsegmentobject@moveto\relax
    \let\pgf@decorate@inputsegmentobject@lineto\tsx@integrate@lineto
    \let\pgf@decorate@inputsegmentobject@curveto\tsx@integrate@curveto

    \parsedpath
}}

\def\tsx@integrate@lineto#1#2#3{
    #2
    \pgf@xa\pgf@x
    \pgf@ya\pgf@y
    #3
    \pgf@xb\pgf@x
    \pgf@yb\pgf@y
    \pgfmathparse{\area + (\the\pgf@xb-\the\pgf@xa)*0.5*(\the\pgf@ya + \the\pgf@yb)}
    \xdef\area{\pgfmathresult}
}

\def\tsx@integrate@curveto#1#2#3#4#5{
    #2
    \pgf@xa\pgf@x
    \pgf@ya\pgf@y
    #3
    \pgf@xb\pgf@x
    \pgf@yb\pgf@y
    #4
    \pgf@xc\pgf@x
    \pgf@yc\pgf@y
    #5

    % Use Green's theorem to calculate the area: ∫_D dA = -∫_{∂D} y dx.
    % This probably does not work in all cases.
    % Also this has the problem that there are larger numbers in between. 
    % Probably should use Lua for that.
    \pgfmathparse{\area + 
        % integral over the curve
        %(3 Subscript[x, 3] (Subscript[y, 1] + Subscript[y, 2] - 2 Subscript[y, 4]) - 3 Subscript[x, 2] (-2 Subscript[y, 1] + Subscript[y, 3] + Subscript[y, 4]) - Subscript[x, 1] (10 Subscript[y, 1] + 6 Subscript[y, 2] + 3 Subscript[y, 3] + Subscript[y, 4]) + Subscript[x, 4] (Subscript[y, 1] + 3 Subscript[y, 2] + 6 Subscript[y, 3] + 10 Subscript[y, 4]))/20
        +(3*\pgf@xc*(\pgf@ya + \pgf@yb -2*\pgf@y)                                   - 3*\pgf@xb*(-2*\pgf@ya + \pgf@yc + \pgf@y)                                  - \pgf@xa*(10*\pgf@ya + 6*\pgf@yb + 3*\pgf@yc + \pgf@y)                                          + \pgf@x*(\pgf@ya + 3*\pgf@yb + 6*\pgf@yc + 10*\pgf@y))/20
        % integral over the line between the endpoints
        -(\pgf@y*(\pgf@xa - \pgf@x) + 0.5*(\pgf@x-\pgf@xa)*(\pgf@y-\pgf@ya))
        % area between that line and the x-axis
        -(\pgf@x-\pgf@xa)*0.5*(\pgf@ya + \pgf@y)
        }
    \xdef\area{\pgfmathresult}
}

\makeatother
\begin{document}

\begin{tikzpicture}
    \draw[save path=\mypath] plot[domain=0:1,smooth] (\x,{\x*\x});
    \integrate{\mypath}
    \show\area
    \show\length
\end{tikzpicture}
\end{document}

curvto 积分计算存在方向问题(例如圆的面积为 -r²π;我选择负号来使图上的积分起作用)和较大的中间值(将上述示例积分为 1.1 已经太多了)。

答案2

好的,下面是一些类似于答案的内容。我正在将其中的一些内容作为 TeX-SX 书法包的一部分来实现,该包涉及操纵软路径,并且我已经开始将软路径操纵分离到其自己的包文件中。这里似乎是记录这一点的最佳地点!

相关文件spath.dtx可从TeX-SX 包项目。该文件也很有用,spath_test.tex因为我还没有写任何文档!要生成样式文件,请运行tex spath.dtx(如果有任何文档,您可以从中获取pdflatex spath.dtx)。

这是一种面向对象的方法,使用与 PGF 捆绑在一起的 Till Tantau 的 OO 实现(因此您可能需要最新版本的 PGF 才能使其工作)。以下是一些示例代码:

\documentclass{article}
\usepackage{tikz}
\usepackage{spath}

\begin{document}
\begin{tikzpicture}
\path[save path=\tmppath] (0,0) -- (1,1) (2,1) .. controls (3,1) and (4,2) .. (5,2);
\show\tmppath
\pgfoonew \mypath =new spath(\tmppath)
\mypath.show(path)
\mypath.length()
\mypath.initial point()
\mypath.show(initial point)
\mypath.final point()
\mypath.show(final point)
\mypath.show(length)
\mypath.translate path(\trpath,1cm,1cm)
\mypath.show(path)
\trpath.show(path)
\mypath.concatenate(\catpath,\trpath)
\catpath.show(path)
\mypath.weld(,\trpath)
\mypath.show(path)
\mypath.use path with tikz(draw,red,line width=.5cm)
\mypath.use path(stroke)
\end{tikzpicture}
\end{document}

我们首先使用常规 TikZ 命令定义一条路径并将其保存为\tmppath。然后我们定义该类的新实例spath并用 对其进行初始化\tmppath。在最终使用它之前,我们对它进行各种操作,并找出一些有关它的事实。最后两个,\mypath.use path with tikz(options)\mypath.use path,是实际的渲染命令。第一个使用与 TikZ 相同的方法来渲染路径,因此可以采用任何 TikZ 选项(我不能 100% 保证它们都能正常工作,但它们应该可以)。第二个使用底层 PGF 系统,因此采用基本选项之一:strokefill

这实际上不能作为您问题的答案,因为您要求的任何事情都没有实现(请注意,这length是指软路径中的命令数量,而不是路径长度)。但将两个已经给出的答案中的任何一个适应此设置并不难。它不过,请回答评论中有关重复使用路径的问题。

答案3

作为我自己的问题的部分答案,这里有一个简单的宏,允许人们使用路径名机制对先前保存的路径上的点执行给定的操作。

\makeatletter
\def\everypathpoint#1#2{%
  \begingroup
    \expandafter\let\expandafter\pgfsyssoftpath@movetotoken\csname #2\endcsname
    \expandafter\let\expandafter\pgfsyssoftpath@linetotoken\csname #2\endcsname
    \expandafter\show\csname #2\endcsname
    \@nameuse{tikz@intersect@path@name@#1}%
  \endgroup
}%
\makeatother 

例如,此宏可以与代码一起使用

  \newcount\mycount
  \mycount=0
  \def\myaction#1#2{\ifdim #2>0.5cm\global\advance\mycount by 1\fi}%

  \draw[thick, name path=f] plot (\x, \y{\x});
  \everypathpoint{f}{myaction}%

此代码仅计算路径中给定值以上的点数,但允许任何其他操作(包括面积计算)。路径可以包含的元素数量还有待观察(我敢打赌,比我在这里考虑的最小元素 moveto 和 lineto 要多)。

相关内容