
TikZ에서는 한 점에서 (회전 및 이동된) 타원까지 직교 투영을 그리고 싶습니다. 특별한 예로, 그림의 점에서 타원까지 가장 짧은 선을 그리고 바람직하게는 타원에도 점을 표시하고 싶습니다.
나는 원을 사용하여 이 작업을 수행하는 데 성공했습니다(점은 원과 점 자체 및 원의 중심을 통과하는 선과의 교차점에 의해 제공되기 때문입니다). 하지만 타원을 사용하면 TikZ에서 작동하지 않는 것 같습니다.
위 그림의 예제 코드는 다음과 같습니다.
\documentclass{standalone}
\usepackage{tikz,tkz-euclide}
\begin{document}
\newcommand{\boundellipse}[3]% center, xdim, ydim
{(#1) ellipse (#2 and #3)
}
\begin{tikzpicture}
\draw[shift={(-0.875,0)},rotate=25] \boundellipse{0,0}{1}{3};%left
\node at (0,4)[circle,fill,inner sep=1.5pt]{};
\end{tikzpicture}
\end{document}
답변1
TikZ + 경사하강법을 제안합니다
\documentclass[tikz]{standalone}
\usepackage{tikz,tkz-euclide}
\begin{document}
\newcommand{\boundellipse}[3]% center, xdim, ydim
{(#1) ellipse (#2 and #3)}
\makeatletter
\xdef\sx{-0.875} % shift x
\xdef\sy{0} % shift y
\xdef\ra{1} % radius a
\xdef\rb{3} % radius b
\xdef\ro{25} % rotation
\pgfpointxy{0}{4}
\xdef\Px{\the\pgf@x}\xdef\Py{\the\pgf@y}
% let \ang ("angle") be a free variable and run gradient descent
\def\ang{234} % choose your favorite initial value
\foreach\iterationcounter in{1,...,20}{
\begin{tikzpicture}
\draw(-5,-3)rectangle(1,5);
\draw[shift={(-0.875,0)},rotate=25] \boundellipse{0,0}{1}{3};
\node at (0,4)[circle,fill,inner sep=1.5pt]{};
% evaluate Ellipse(\ang)
\pgfpointxy{\sx + \rb*cos(\ang)*sin(\ro) + \ra*sin(\ang)*cos(\ro)}
{\sy - \rb*cos(\ang)*cos(\ro) + \ra*sin(\ang)*sin(\ro)}
\xdef\Qx{\the\pgf@x}\xdef\Qy{\the\pgf@y}
\draw(\Qx,\Qy)circle(.1);
% evaluate diff vector to target point
\xdef\Dx{\the\dimexpr\Px-\Qx}
\xdef\Dy{\the\dimexpr\Py-\Qy}
\draw[red,->](\Qx,\Qy)--+(\Dx,\Dy);
% evaluate tangent line = d Ellipse(\ang) / d\ang
\pgfpointxy{- \rb*sin(\ang)*sin(\ro) + \ra*cos(\ang)*cos(\ro)}
{+ \rb*sin(\ang)*cos(\ro) + \ra*cos(\ang)*sin(\ro)}
\xdef\Tx{\the\pgf@x}
\xdef\Ty{\the\pgf@y}
\draw[blue,->](\Qx,\Qy)--+(\Tx,\Ty);
% inner product
\pgfmathsetmacro\Inn{\Dx*\Tx + \Dy*\Ty}
% rescale inner product
\pgfmathsetmacro\inn{\Inn / sqrt(\Tx*\Tx+\Ty*\Ty)}
\message{^^J thinbold: \inn ^^J}
% update angle
\pgfmathsetmacro\ang{\ang + \inn/10} % /10 is the step length
\xdef\ang{\ang}
\end{tikzpicture}
}
\end{document}
답변2
수학 문제와 알고리즘 접근 방식
@Thruston이 제안한 것처럼 문제를 해결하려면 수학이 필요합니다. 어쨌든 이것은 분석적인 방법으로 풀기 어려운 사소하지 않은(사차) 방정식으로 이어집니다(둘 중 하나를 살펴보겠습니다).비슷한 질문또는점-타원 및 점-타원체 거리 방정식 분석). 그래서 아이디어는 방정식을 수치적으로 해결하는 것입니다. ~에https://wet-robots.ghost.io/simple-method-for-distance-to-ellipse/원점과의 거리를 최소화하여 타원 위의 점(직교 투영)을 찾는 기하학적이고 안정적인 알고리즘을 찾았습니다.
알고리즘
다음 단계와 이미지는 아이디어를 제안합니다.
- 연결하다영형그리고피얻기 위해서A_start(이렇게 하면 타원의 "오른쪽"에서 알고리즘을 실행할 수 있습니다).
- 원(파란색)을 그리고 파란색 원과 타원이 있는 두 교차점의 중간점을 얻습니다.
- 중간점을 사용하여 새로운 작은 원(보라색)을 그리고 프로세스를 반복합니다(예: 빨간색, 주황색, 분홍색 등).
코드
코드에는 패키지 tikz
, tkz-euclide
특히 \usetikzlibrary{intersections}
교차점이 필요합니다. tkz-euclide
명령이 기분이 좋아서 사용합니다 . 어쨌든 순수 tikz에서도 동일한 결과를 얻을 수 있습니다.
\begin{tikzpicture}
% INITIAL DATA %
% the arbitrary point P
\tkzDefPoint(3,2){P}
% the center of the ellipse
\tkzDefPoint(0,0){O}
% use rotate=angle to set the desired orientation
\path[draw,name path=theellipse,rotate=20] (O) ellipse (2cm and 1cm);
\tkzLabelPoints[above right](P)
\tkzLabelPoints[below left](O)
% STARTING POINT OF ALGORITHM %
\path[name path=OP] (O)--(P);
\path[name intersections={of=OP and theellipse,by={Aone}}];
% comment/erase if need next three code lines
\tkzLabelPoint[above left](Aone){$A_{\textrm{start}}$}
\tkzDrawCircle[help lines](P,Aone)
\tkzDrawPoints(Aone)
% ALGORITHM TO FIND THE ORTHOGONAL PROJECTION %
% set up a different number of steps if needed
% (algorithm converges relatively fast)
\foreach \i in {1,...,3}
{
% define a circle with center P through Aone
% (Astart for the first step)
\tkzDefCircle[radius](P,Aone)
\tkzGetLength{dPAone}
\path[name path=circle] (P) circle (\dPAone pt);
% find intersections of circle with ellipse (Aone, Atwo)
\path[name intersections={of=circle and theellipse,by={Atwo,Aone}}];
% find a "proper" midpoint of Aone -- Atwo on the ellipse
\tkzDefMidPoint(Aone,Atwo)\tkzGetPoint{Aone}
\path[name path=PAone] (P)--(Aone);
\path[name intersections={of=PAone and theellipse,by={Aone}}];
}
% GET AND PRINT OUT THE DISTANCE
\tkzDrawPoints(O,P,Aone)
\tkzDrawSegment[red](P,Aone)
\end{tikzpicture}
답변3
비교를 위해 다음과 같이 매우 간단하게 이 작업을 수행할 수 있습니다.메타포스트solve
매크로와 적절한 도우미 기능을 사용합니다 .
\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
path e; pair p; numeric k;
e = fullcircle xscaled 233 yscaled 144 rotated 10;
p = 160 dir 142;
vardef acute(expr t) =
direction t of e dotprod (p - point t of e) > 0
enddef;
k = solve acute(0, 4);
drawarrow p -- point k of e withcolor red;
draw e;
dotlabel.top(btex $p$ etex, p);
endfig;
\end{mplibcode}
\end{document}
이것은 로 포장되어 luamplib
있으므로 lualatex
.
노트
solve
176~177페이지에 설명되어 있습니다.메타폰트 책.아이디어는 또는 와
foo
같은 매크로를 정의한다는 것입니다 . 그런 다음 where 및 is 값이 true이고 false 인지 호출합니다 . 이진 검색을 사용하여 과 사이의 간선 값을 찾습니다 .foo(x)
true
false
solve foo(a, b)
a
b
foo(a)
foo(b)
solve
a
b
이 경우 나는 타원 점의 접선이 타원 점 사이의 선과 예각을 이루는 지 여부를 알려주기 위해 연산자를
acute
사용하는 매크로를 정의했습니다.dotprod
t
p
t
solve
각도가 더 이상 예각이 아닌 지점을 찾습니다. 따라서 이 지점은 에 대한 선이 접선p
에 직교하고 에 가장 가까운 지점입니다p
.의 다양한 위치에 대한 올바른 초기 값을 선택하려면 약간의 기술과 판단이 필요합니다
p
.
보시다시피 내 설명은 코드보다 더 깁니다 ...