고정 소수점 연산을 사용하는 TikZ의 계산 정확도

고정 소수점 연산을 사용하는 TikZ의 계산 정확도

다음을 만족하는 트리를 만들고 싶습니다.

  1. 오른쪽으로 자랍니다.
  2. 첫 번째 자식은 0도에서 성장합니다(다음 자식은 시계 방향으로 성장).
  3. 모든 하위 노드는 동일한 수직에 있고 연속된 노드 사이의 거리는 항상 동일합니다.

전체적으로 제가 달성하고 싶은 것은 다음과 같습니다.

여기에 이미지 설명을 입력하세요

실제로 코드를 작성하는 쉬운 방법은 다음과 같습니다.

\documentclass{article}
\usepackage{tikz}
\tikzset{bcir/.style={circle,fill=black,
 minimum size=4pt,inner sep=0},every node/.style={bcir}}
\begin{document}
\begin{tikzpicture}[x=3cm,y=2mm]
\node (A) {};
\foreach \i in {0,...,8} \node at (1,-\i) {} edge (A);
\end{tikzpicture}
\end{document}

그러나 나는 동일한 결과를 얻을 것으로 기대했던 다른 접근 방식을 시도했습니다.

\documentclass{article}
\usepackage{tikz}
\usepackage{fp}
\usetikzlibrary{fixedpointarithmetic}
\tikzset{bcir/.style={circle,fill=black,
minimum size=4pt,inner sep=0},every node/.style={bcir}}

\begin{document}
\begin{tikzpicture}[fixed point arithmetic]  
\node {}
  child[grow=\g,level distance=\l cm] 
  foreach \i [evaluate={
     \k=tan(5)*\i;
     \g=-atan(\k);
     \l=3/cos(\g);
  }] in {0,...,13} {node {}};
\end{tikzpicture}  
\end{document}

위의 코드에서는 1) 첫 번째(수평) 자식의 레벨 거리가 3cm이고 2) 두 번째 자식이 -5도 성장한다고 가정했습니다. 이 두 가지 조건과 일부 기본 삼각법을 사용하면 먼저 연속 노드 사이의 형제 거리를 계산한 다음 모든 하위 노드에 대한 각도 g및 레벨 거리를 계산할 수 있습니다.l

나는 내 매개변수화가 정확하다고 믿습니다. 그러나 일부 형제 각도/레벨 거리가 약간 벗어났습니다.

여기에 이미지 설명을 입력하세요

(다른 답변에 따라) 정확도를 향상시키기 위해 고정 소수점 산술 엔진을 사용했지만. 삼각함수를 Taylor 급수의 첫 번째 항으로 대체하더라도,

\begin{tikzpicture}[fixed point arithmetic]  
\node {}
  child[grow=\g,level distance=\l cm] 
  foreach \i [evaluate={
     \k=tan(5)*\i;
     \grad=\k-\k^3/3+\k^5/5-\k^7/7+\k^9/9;
     \g=-deg(\grad);
     \l=3/(1-\grad^2/2!+\grad^4/4!-\grad^6/6!);
  }] in {0,...,8} {node {}};
\end{tikzpicture}

동일한 문제가 존재합니다(여기서는 시리즈가 수렴되도록 보장하기 위해 노드 수를 선택했습니다 atan).

여기에 이미지 설명을 입력하세요

이러한 부정확성 문제를 극복하기 위해 내가 할 수 있는 일이 있습니까? 아니면 피할 수 없는 본질적인 TikZ 문제입니까? (내 접근 방식에 결함이 없다고 가정할 때 그렇습니다.)

답변1

이 경우 수학이 실패하는 이유는 잘 모르겠지만(그래야 한다고 생각하지만) TikZ/PGF가 수학을 수행하는 방식에는 문제가 없는 것 같습니다. 트리가 구성되는 방식과 관련이 있는 것 같습니다. .

안타깝게도 문제가 정확히 무엇인지는 알 수 없었지만 문제가 있다는 사실은~ 아니다수학적 계산 자체의 정확성은 트리 외부에서 동일한 계산을 사용하여 입증할 수 있습니다.

\documentclass[tikz, border=5]{standalone}
\tikzset{bcir/.style={circle,fill=black,
  minimum size=4pt,inner sep=0}, every node/.style={bcir}}

\begin{document}
\begin{tikzpicture}[every node/.style={bcir, anchor=center}]
\node {} child [grow=\g, level distance=\l cm] foreach \i [evaluate={%
  \k=tan(5)*\i; \g=-atan(\k); \l=3/cos(\g);}]
  in {0,...,13} { node {} };

\foreach \i [evaluate={%
  \k=tan(5)*\i; \g=-atan(\k); \l=3/cos(\g);}]
  in {0,...,13} { \draw [red] (0,0) -- (\g:\l) node [bcir,fill=red]{}; }
\end{tikzpicture}  
\end{document}

여기에 이미지 설명을 입력하세요

그래서 뭔가 다른 일이 벌어지고 있어야합니다.

어쨌든 나는 당신이 할 수 있는 일을 통해 많은 일을 하고 있다고 생각합니다.많이더 간단하게는 맞춤형 성장 기능을 사용합니다.

grow via three points다음은 라이브러리 의 성장 함수 의 예를 보여줍니다 trees.

\documentclass[tikz, border=5]{standalone}
\usetikzlibrary{trees}
\tikzset{bcir/.style={circle,fill=black,
  minimum size=4pt,inner sep=0}, every node/.style={bcir}}

\begin{document}
\begin{tikzpicture}[grow via three points={%
  one child at (3,0) and two children at (3,0) and (3,-1/4)
}]
\node {} child foreach \i in {0,...,13} { node {} };
\end{tikzpicture}  
\end{document}

여기에 이미지 설명을 입력하세요

답변2

PSTricks 솔루션:

\documentclass{article}

\usepackage{multido}
\usepackage{pstricks}
\usepackage{xfp}

% parameters
\def\NoDots{9}
\def\Hori{4}
\def\Vert{3}

\begin{document}

\begin{pspicture}(\Hori,\Vert)
  \psdot(0,\Vert)
  \multido{\r = \Vert+-\fpeval{\Vert/(\NoDots-1)}}{\NoDots}{%
    \psline(0,\Vert)(\Hori,\r)
    \psdot(\Hori,\r)}
\end{pspicture}

\end{document}

산출

\NoDots매개변수( , \Hori및 ) 의 값을 변경하기만 하면 \Vert그에 따라 도면이 조정됩니다.

답변3

당신의 문제는 나를 궁금하게 만들었습니다. MetaPost는 또한 기본적으로 고정 소수점 산술을 사용합니다. 내부적으로 MetaPost는 2^(-16)최대 . (최근부터 여러 부동 소수점 연산 모드로 전환하는 것이 가능해졌지만 여기서는 사용하지 않겠습니다.)2^122^15

그래서 저는 동일한 기능을 사용하여 두 번째 그래프의 MetaPost 버전을 만들고 정렬을 관찰하기로 결정했습니다. (LuaLaTeX로 처리됩니다.)

\documentclass[border=2mm]{standalone}
\usepackage{luamplib}
  \mplibsetformat{metafun}  
\begin{document}
  \begin{mplibcode}
    u := cm;
    def dot(expr c) = drawdot c withpen pencircle scaled 3bp enddef;
    beginfig(1);
      dot(origin); 
      for i = 0 upto 13:
        k := i*tand5; % or i*sind5/cosd5 with Plain MetaPost
        g := -atan k ; % or -angle(1, k) with Plain MetaPost; 
        l := 3u/cosd g;
        draw origin -- l*dir g;
        dot(l*dir g);
      endfor
    endfig;
  \end{mplibcode}
\end{document}

글쎄, 내가 볼 수 있는 한 그들은 올바르게 정렬된 것 같습니다.

여기에 이미지 설명을 입력하세요

따라서 이 경우에는 고정 소수점 산술 자체에 문제가 있는 것이 아니라 고정 소수점 라이브러리 tikz(숫자를 표현하는 데 두 개의 몇 비트가 사용됩니까?)에 문제가 있는 것 같습니다. 또는 삼각 함수가 정의되는 방식으로.

어쨌든 (LuaTeX를 사용하여) 부동 소수점 연산으로 전환할 수 있다면 tikz정확도가 크게 향상될 것입니다.

관련 정보