Моделирование случайно сгенерированных вписанных треугольников

Моделирование случайно сгенерированных вписанных треугольников

Проблема, которую я моделирую: На окружности случайно выбраны три точки. Какова вероятность того, что треугольник, образованный этими тремя точками, содержит центр окружности?

Концептуальное понимание: Предположим, мы фиксируем две из трех точек, назовем их A и B. Для того чтобы треугольник содержал центр, третья точка C должна лежать внутри дуги A'B', где A' и B' являются изображениями точек A и B соответственно при повороте на 180 градусов.

Что я хочу, чтобы произошло: Случайно сгенерированный вписанный треугольник, который будет заполнен зеленым, если он содержит центр, и красным, если он не содержит центра. Я также хотел бы вести подсчет количества успехов и неудач для вычисления экспериментальной вероятности.

введите описание изображения здесь

Несколько ключевых вещей: У меня есть доступ к координатам x и y каждой точки с помощью \pgfextractxи \pgfextracty. Мой метод состоял в том, чтобы проверить, находится ли точка C между координатами x и y точек A и B, с помощью \xintifboolexpr, однако, это некорректно.

Минимальный рабочий пример:

\documentclass{article}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=1cm]{geometry}
\usepackage{amsmath,amsfonts,tikz,xintexpr,calc}

\newcommand\circletest{
\begin{tikzpicture}[scale=0.6]

    \newdimen{\tempxa}
    \newdimen{\tempya}
    \newdimen{\tempxb}
    \newdimen{\tempyb}
    \newdimen{\tempxc}
    \newdimen{\tempyc}

    \def\radius{2}
    \draw (0,0) coordinate (O);
    \draw (O) circle[radius=\radius];
    \draw (rnd*360:\radius) coordinate (A);
        \pgfextractx\tempxa{\pgfpointanchor{A}{center}}
        \pgfextracty\tempya{\pgfpointanchor{A}{center}}
    \draw (rnd*360:\radius) coordinate (B);
        \pgfextractx\tempxb{\pgfpointanchor{B}{center}}
        \pgfextracty\tempyb{\pgfpointanchor{B}{center}}
    \draw (rnd*360:\radius) coordinate (C);
        \pgfextractx\tempxc{\pgfpointanchor{C}{center}}
        \pgfextracty\tempyc{\pgfpointanchor{C}{center}}

    \xintifboolexpr { (((\tempxc > -\tempxa) && (\tempxc < -\tempxb)) || ((\tempxc > -\tempxb) && (\tempxc < -\tempxa))) && (((\tempyc > -\tempya) && (\tempyc < -\tempyb)) || ((\tempyc > -\tempyb) && (\tempyc < -\tempya)))} %%I know this is grotesque 
     {\filldraw[color=green!80!black!100, fill=green!15] (A) -- (B) -- (C) -- cycle;} %true
      {\filldraw[color=red!80!black!100, fill=red!15] (A) -- (B) -- (C) -- cycle;} %false

    \fill[black] (A) circle[radius=2pt];
    \fill[black] (B) circle[radius=2pt];
    \fill[black] (C) circle[radius=2pt];
    \fill[black] (O) circle[radius=2pt];

    \draw (A) node[below]{A};
    \draw (B) node[below]{B};
    \draw (C) node[below]{C};
\end{tikzpicture}}

\begin{document}

\foreach \x in {0,1,...,11}{
    \circletest
}


\end{document}

Проблема, с которой я столкнулся: Очевидно, что проблема в моем операторе сравнения \xintifboolexprвместе с моим гротескным кодом, следующим за ним. Я ищу более простой метод, чтобы узнать, находится ли точка C на дуге окружности между (-\tempax,-\tempay)и (-\tempbx,-\tempby).

РЕДАКТИРОВАТЬ: Правильное решение, предложенное Сэнди Г.

\documentclass{article}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=1cm]{geometry}
\usepackage{amsmath,amsfonts,tikz,xintexpr,calc}
\usepackage{xfp}

\newcommand\circletest{
\begin{tikzpicture}[scale=0.6]

    \pgfmathsetmacro{\rndA}{rnd*360}
    \pgfmathsetmacro{\rndB}{rnd*360}
    \pgfmathsetmacro{\rndC}{rnd*360}

    %defining x and y coordinates of each point

    \def\radius{2}
    \def\xa{\fpeval{\radius*cosd(\rndA)}}
    \def\ya{\fpeval{\radius*sind(\rndA)}}
    \def\xb{\fpeval{\radius*cosd(\rndB)}}
    \def\yb{\fpeval{\radius*sind(\rndB)}}
    \def\xc{\fpeval{\radius*cosd(\rndC)}}
    \def\yc{\fpeval{\radius*sind(\rndC)}}

   %calculating side lengths of triangle
   \def\A{\fpeval{sqrt((\xb-\xc)^2 + (\yb-\yc)^2)}}
   \def\B{\fpeval{sqrt((\xa-\xc)^2 + (\ya-\yc)^2)}}
   \def\C{\fpeval{sqrt((\xa-\xb)^2 + (\ya-\yb)^2)}}

   %calculating angles of triangle
   \def\angleA{\fpeval{acosd((\B^2 + \C^2 -\A^2)/(2*\B*\C))}}
   \def\angleB{\fpeval{acosd((\C^2 + \A^2 -\B^2)/(2*\C*\A))}}
   \def\angleC{\fpeval{acosd((\A^2 + \B^2 -\C^2)/(2*\A*\B))}}

   %defining some coordinates
    \draw (0,0) coordinate (O);
    \draw (O) circle[radius=\radius];
    \draw (\xa,\ya) coordinate (A);
    \draw (\xb,\yb) coordinate (B);
    \draw (\xc,\yc) coordinate (C);

   %test if center is in circle
    \xintifboolexpr{((\angleA < 90) && (\angleB < 90)) && (\angleC < 90)}
     {\filldraw[color=green!80!black!100, fill=green!15] (A) -- (B) -- (C) -- cycle;} %true
     {\filldraw[color=red!80!black!100, fill=red!15] (A) -- (B) -- (C) -- cycle;} %false

   %Drawing points on top of line
    \draw[fill=black] (\xa,\ya) circle(1.5pt);
    \draw[fill=black] (\xb,\yb) circle(1.5pt);
    \draw[fill=black] (\xc,\yc) circle(1.5pt);
    \draw[fill=black] (O) circle(1.5pt);

\end{tikzpicture}}

\begin{document}

\foreach \x in {0,1,...,30}{
    \circletest
}

\end{document}

решение1

Можно воспользоваться calcбиблиотекой иэтот рецепт, который очень похож на ваш, но, возможно, немного короче. Использование calcбиблиотеки также позволяет нам избегать введения новых измерений. Определение a picимеет то преимущество, что вы можете использовать TiкZ, чтобы расположить рисунки в любом удобном для вас порядке.

\documentclass{article}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=1cm]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
What is the probability for the triangle containing the origin? Without loss of
generality we can take the angle of $A$ to be 0 (because one can rotate the
setup without changing the probability). Then the angle of $B$, $\beta$ can be
chosen to be between $0$ and $\pi$ (because one can reflect the setup at the
$x$--axis without changing the probability). Then the angle of $C$, 
 $\gamma$, needs to satisfy
\[ \pi<\gamma<\pi+\beta \] 
for the center to be inside the triangle, see Figure~\ref{fig:derivation}.
As $\beta$ scans the domain $[0,\pi]$, the probability for a triangle with
corners at random positions of the circle enclosing the center of the circle is
$1/4$. 
\begin{figure}[ht]
\centering
\begin{tikzpicture}[dot/.style={circle,inner sep=1pt,fill},
    declare function={rr=2.5;}]
 \begin{scope}
  \draw (0,0) circle[radius=rr] (0,0) -- (rr,0) node[dot,label=right:$A$]{};
  \pgfmathsetmacro{\rndB}{rnd*90}
  \draw (1,0) arc[start angle=0,end angle=\rndB,radius=1] 
    node[midway,anchor=180+\rndB/2,circle]{$\beta$}
  (0,0) -- (\rndB:rr) node[dot,label={[anchor=\rndB+180]:$B$}]{};
  \draw[dashed] (180+\rndB:rr) -- (0,0) -- (180:rr);
  \draw[blue,thick] (180:rr) arc[start angle=180,end angle=180+\rndB,radius=rr]
  node[midway,anchor=\rndB/2,circle,align=right]{allowed\\ positions\\ for $C$};
 \end{scope}
 %
 \begin{scope}[xshift=2.8*rr*1cm]
  \draw (0,0) circle[radius=rr] (0,0) -- (rr,0) node[dot,label=right:$A$]{};
  \pgfmathsetmacro{\rndB}{90+rnd*90}
  \draw  (1,0) arc[start angle=0,end angle=\rndB,radius=1] 
    node[midway,anchor=180+\rndB/2,circle]{$\beta$}
    (0,0) -- (\rndB:rr) node[dot,label={[anchor=\rndB+180]:$B$}]{};
  \draw[dashed] (180+\rndB:rr) -- (0,0) -- (180:rr);
  \draw[blue,thick] (180:rr) arc[start angle=180,end angle=180+\rndB,radius=rr]
  node[midway,anchor=\rndB/2,circle,align=right]{allowed\\ positions\\ for $C$};
 \end{scope}
\end{tikzpicture}
\label{fig:derivation}
\end{figure}

\begin{figure}[ht]
\centering
\begin{tikzpicture}[pics/circletest/.style={code={
        \tikzset{circletest/.cd,#1}%
        \def\pv##1{\pgfkeysvalueof{/tikz/circletest/##1}}%
        \draw (0,0) coordinate (O) circle[radius=\pv{r}];
        \pgfmathsetmacro{\rndA}{rnd*360}
        \pgfmathsetmacro{\rndB}{rnd*360}
        \pgfmathsetmacro{\rndC}{rnd*360}
        \path (\rndA:\pv{r}) coordinate[label={[anchor=\rndA+180]:$A$}] (A)
         (\rndB:\pv{r}) coordinate[label={[anchor=\rndB+180]:$B$}] (B) 
         (\rndC:\pv{r}) coordinate[label={[anchor=\rndC+180]:$C$}] (C);
        \draw let \p1=(A),\p2=(B),\p3=(C),\p0=(O),
         \n1={(\x0-\x2)*(\y1-\y2)-(\x1-\x2)*(\y0-\y2)},
         \n2={(\x0-\x3)*(\y2-\y3)-(\x2-\x3)*(\y0-\y3)},
         \n3={(\x0-\x1)*(\y3-\y1)-(\x3-\x1)*(\y0-\y1)}
         in \pgfextra{\pgfmathtruncatemacro\itest{%
            ((\n1 < 0) || (\n2 < 0) || (\n3 < 0)) &&
            ((\n1 > 0) || (\n2 > 0) || (\n3 > 0))}}
         \ifnum\itest=0
          [color=green!80!black!100, fill=green!15] (A) -- (B) -- (C) -- cycle
         \else
          [color=red!80!black!100, fill=red!15]  (A) -- (B) -- (C) -- cycle
         \fi;
        \fill (O) circle[radius=1pt] node[below]{$O$}; 
    }},circletest/.cd,r/.initial=1]
 \path foreach \X in {1,...,5}
 {  foreach \Y in {1,...,5} {(3*\X,3*\Y) pic{circletest}}}; 
\end{tikzpicture}
\end{figure}

\end{document}

введите описание изображения здесь

Альтернативное предложение, основанное на пересечениях. Постройте луч, который выходит из круга из его центра. Если число пересечений с треугольником четное, центр находится снаружи треугольника, в противном случае — внутри.

\documentclass{article}
\usepackage[left=2cm, right=2cm, top=2cm, bottom=1cm]{geometry}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}[pics/circletest/.style={code={
        \tikzset{circletest/.cd,#1}%
        \def\pv##1{\pgfkeysvalueof{/tikz/circletest/##1}}%
        \draw (0,0) coordinate (O) circle[radius=\pv{r}];
        \pgfmathsetmacro{\rndA}{rnd*360}
        \pgfmathsetmacro{\rndB}{rnd*360}
        \pgfmathsetmacro{\rndC}{rnd*360}
        \path (\rndA:\pv{r}) coordinate[label={[anchor=\rndA+180]:$A$}] (A)
         (\rndB:\pv{r}) coordinate[label={[anchor=\rndB+180]:$B$}] (B) 
         (\rndC:\pv{r}) coordinate[label={[anchor=\rndC+180]:$C$}] (C);
        \path[name path=triangle] (A) -- (B) -- (C) -- cycle;
        \path[name path=ray,overlay] (O) -- ({180+(\rndA+\rndB+\rndC)/3}:1.5*\pv{r});
        \draw[name intersections={of=triangle and ray,total=\t}]
         \ifodd\t
          [color=green!80!black!100, fill=green!15] (A) -- (B) -- (C) -- cycle
         \else
          [color=red!80!black!100, fill=red!15]  (A) -- (B) -- (C) -- cycle
         \fi;
    }},circletest/.cd,r/.initial=1]
 \path foreach \X in {1,...,5}
 {  foreach \Y in {1,...,5} {(3*\X,3*\Y) pic{circletest}}}; 
\end{tikzpicture}
\end{document}

введите описание изображения здесь

Этот подход ограничен точностью пересечений и может оказаться неудачным, если треугольник слишком тонкий, т.е. по сути представляет собой линию.

P.S. Эти распределения соответствуют реальной вероятности.

введите описание изображения здесь

решение2

Чтобы удовлетворить свое любопытство относительно экспериментальной вероятности, я сделал это в metapost. Кажется, требуется около 100 000 треугольников, чтобы последовательно получить теоретическую вероятность (т. е. 1/4) с точностью до 3 знаков после запятой. Если вы прокомментируете команды рисования, чтобы просто вывести результат, то 1 000 000 запусков займут всего несколько секунд. Часть вывода для 20 000 вписанных треугольников в окружности диаметром 1 мм:

введите описание изображения здесь Бежать с lualatex:

\documentclass{article}
\usepackage{luamplib}
\usepackage{geometry}
\mplibnumbersystem{double}
\mplibtextextlabel{enable}
\mplibcodeinherit{enable}
\begin{document}
\begin{mplibcode}
    vardef triarray(expr r,n)=
        save x,tmp,width;
        width:=\mpdim{\linewidth} div r;
        count:=0;
        tot:=n;
        for j=0 upto n:
            % for the grid
            drawoptions(withpen pencircle scaled .1bp shifted ((r+.1)*(j mod width),-(r+.1)*(j div width)));
            for i=1 upto 3: x[i]:=uniformdeviate(8); endfor;
            % sort vals, probably didn't need to, but made things tidier.
            if x1>x2: 
                tmp:=x1; x1:=x2; x2:=tmp; 
            fi;
            if x2>x3:
                tmp:=x2; x2:=x3; x3:=tmp;
                if x1>x2:
                    tmp:=x1; x1:=x2; x2:=tmp; 
                fi;
            fi;
            % end sort
            % points on a circle in mp are mapped to the interval [0,8] with 0->0 and 8->360
            % reflected points rather than rotating arc
            if ((x1+4) mod 8>x2) and ((x1+4) mod 8<x3) and ((x3+4) mod 8>x1) and ((x3+4) mod 8<x2):
                fill fullcircle scaled r withcolor .2[white,green];
                count:=count+1;
            else:
                fill fullcircle scaled r withcolor .2[white,red];
            fi;
            % uncomment below for the triangles
            draw for i=1 upto 3: point x[i] of (fullcircle scaled r)-- endfor cycle; 
        endfor;
    enddef;
    beginfig(0);

    triarray(1mm,20000);

    endfig;
\end{mplibcode}
\begin{mplibcode}
beginfig(1);
        picture p; string s;
        s="$\frac{"&decimal(count)&"}{"&decimal(tot)&"}="&decimal(count/tot)&"$";
        p= s infont defaultfont scaled defaultscale;
        draw p;
endfig;
\end{mplibcode}
\end{document} 

Связанный контент