我有两个想要的节点和焦点,并且我知道距离之和应该是多少(常数乘以焦点节点之间的距离)。
我所知道的绘制椭圆的方法是将中心点以及长轴和短轴作为参数。
我想定义另一个函数(myellipse?),它将两个节点和常数乘数作为参数。
这是我目前绘制它们的方式,手工进行所有计算(示例并不完美):
\draw [rotate around={-15:(1.8,0.5)}] (1.8,0.5) ellipse (2 and 1);
答案1
第三次编辑:没有节点或记忆的更简单的解决方案......结果与第二次编辑相同(见下文) 但没有标签。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, cste
\path[#1] let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
in \pgfextra{
\pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
\pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
\pgfmathsetmacro{\lentotcm}{\focal*2*#4}
\pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
\pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
}
(\p3) ellipse[x radius=\axeone cm,y radius=\axetwo cm, rotate=\angle];
}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (5,3);
\ellipsebyfoci{draw,fill=cyan!50}{a}{b}{1.4}
\begin{scope}
\ellipsebyfoci{clip}{a}{b}{1.4}
\ellipsebyfoci{draw,fill=orange!50,name=ell 2}{0,0}{3,5}{1.05}
\fill[red] (a) circle(2pt);
\fill[red] (b) circle(2pt);
\end{scope}
\end{tikzpicture}
\end{document}
第二次编辑:以下是一个带有裁剪椭圆示例的解决方案(使用我的答案到在 tikz 中绘制缩放多边形的最佳方法只是为了记住椭圆节点的路径)。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric,decorations.pathreplacing}
\makeatletter
% to produce automaticaly homothetic paths
\newcounter{homothetypoints} % number of vertices of path
\tikzset{
% homothety is a family...
homothety/.style={homothety/.cd,#1,/tikz/.cd},
% ...with some keys
homothety={
% parameters
scale/.store in=\homothety@scale,% scale of current homothetic transformation
center/.store in=\homothety@center,% center of current homothetic transformation
name/.store in=\homothety@name,% prefix for named vertices
% default values
scale=1,
center={0,0},
name=homothety,
% initialization
init memoize homothetic path/.code={
\xdef#1{}
\setcounter{homothetypoints}{0}
},
% incrementation
++/.code={\addtocounter{homothetypoints}{1}},
% a style to store an homothetic transformation of current path into #1 macro
store in/.style={
init memoize homothetic path=#1,
/tikz/postaction={
decorate,
decoration={
show path construction,
moveto code={
% apply homothetic transformation to this segment and add result to #1
\xdef#1{#1 ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentfirst)$)}
% name this vertex
\coordinate[homothety/++](\homothety@name-\arabic{homothetypoints})
at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentfirst)$);
},
lineto code={
% apply homothetic transformation to this segment and add result to #1
\xdef#1{#1 -- ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
% name this vertex
\coordinate[homothety/++] (\homothety@name-\arabic{homothetypoints})
at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$);
},
curveto code={
% apply homothetic transformation to this segment and add result to #1
\xdef#1{#1
.. controls ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentsupporta)$)
and ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentsupportb)$)
.. ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
% name this vertex
\coordinate[homothety/++] (\homothety@name-\arabic{homothetypoints})
at ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$);
},
closepath code={
% apply homothetic transformation to this segment and add result to #1
\xdef#1{#1 -- cycle ($(\homothety@center)!\homothety@scale!(\tikzinputsegmentlast)$)}
},
},
},
},
},
}
\makeatother
\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, cste
\path let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
in \pgfextra{
\pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
\pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
\pgfmathsetmacro{\lentotcm}{\focal*2*#4}
\pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
\pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
}
(\p3) node[#1,inner sep=0,rotate=\angle,ellipse,minimum width=2*\axeone cm,minimum height=2*\axetwo cm]{};
}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (5,3);
\ellipsebyfoci{draw,fill=cyan!50,name=ell 1,homothety={store in=\mypath}}{a}{b}{1.4}
\node[fill=white] at (ell 1.south){1.4};
\begin{scope}
\clip \mypath;
\ellipsebyfoci{draw,fill=orange!50,name=ell 2}{0,0}{3,5}{1.05}
\node[fill=white] at (ell 2.south){1.05};
\fill[red] (a) circle(2pt);
\fill[red] (b) circle(2pt);
\end{scope}
\end{tikzpicture}
\end{document}
第一次编辑:这是一个解决方案持续的 乘数按要求 (请参阅下文解释)。
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric}
\begin{document}
\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, cste
\path let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
in \pgfextra{
\pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
\pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
\pgfmathsetmacro{\lentotcm}{\focal*2*#4}
\pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
\pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
}
(\p3) node[#1,inner sep=0,rotate=\angle,ellipse,minimum width=2*\axeone cm,minimum height=2*\axetwo cm]{};
}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (5,3);
\ellipsebyfoci{draw,fill=cyan!50,name=ell 1}{a}{b}{1.4}
\node[fill=white] at (ell 1.south){1.4};
\ellipsebyfoci{draw,fill=orange!50,name=ell 2}{a}{b}{1.05}
\node[fill=white] at (ell 2.south){1.05};
\fill[red] (a) circle(2pt);
\fill[red] (b) circle(2pt);
\end{tikzpicture}
\end{document}
第一个答案:这是一个节点形状为椭圆的解决方案(通过shapes.geometric
库)。
我\ellipsebyfoci
使用四个参数定义宏:
- 椭圆的选项(绘制、填充等),
- 第一焦点点,
- 第二焦点点,
- 焦点和边界之间的距离总和。
所有计算均以厘米为单位以避免溢出(! Dimension too large.
)。
代码:
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric}
\newcommand\ellipsebyfoci[4]{% options, focus pt1, focus pt2, sum
\path let \p1=(#2), \p2=(#3), \p3=($(\p1)!.5!(\p2)$)
in \pgfextra{
\pgfmathsetmacro{\angle}{atan2(\y2-\y1,\x2-\x1)}
\pgfmathsetmacro{\focal}{veclen(\x2-\x1,\y2-\y1)/2/1cm}
\pgfmathsetmacro{\lentotcm}{#4/1cm}
\pgfmathsetmacro{\axeone}{(\lentotcm - 2 * \focal)/2+\focal}
\pgfmathsetmacro{\axetwo}{sqrt((\lentotcm/2)*(\lentotcm/2)-\focal*\focal}
}
(\p3) node[#1,inner sep=0,rotate=\angle,ellipse,minimum width=2*\axeone cm,minimum height=2*\axetwo cm]{};
}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (7,3);
\fill[red] (a) circle(2pt);
\fill[red] (b) circle(2pt);
\ellipsebyfoci{draw,fill=orange,fill opacity=.1}{a}{b}{8cm}
\end{tikzpicture}
\end{document}
答案2
我得到了我想要的东西!但不确定是否有更好的方法……
\makeatletter
\newcommand*{\myellipse}[3]{
% Bigger axis: #3
% Smaller axis: sqrt([#3]ˆ2 - |uv|ˆ2)
\coordinate (midpoint) at ($(#1)!0.5!(#2)$) {};
% Calculate angle
\pgfmathanglebetweenpoints{\pgfpointanchor{#1}{center}}
{\pgfpointanchor{#2}{center}}
\let\angle\pgfmathresult % save result in \angle
% calculate distance
\pgfpointdiff{\pgfpointanchor{#1}{center}}
{\pgfpointanchor{#2}{center}}
\pgf@xa=\pgf@x % no need to use a new dimen
\pgf@ya=\pgf@y
\pgfmathparse{veclen(\pgf@xa,\pgf@ya)/28.45274} % to convert from % pt to cm
\let\uv\pgfmathresult % save the result in \uv
\draw [rotate around={\angle:(midpoint)}]
(midpoint) ellipse ({#3} and {sqrt((#3)*(#3) - (\uv)*(\uv))});
}
\makeatother
答案3
这个例子不是一个完整的答案,而只是 Tikz 工具对椭圆逐点计算的概述,这当然不是最佳的
\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\begin{scope}[rotate=15]
\def\entraxe{200}
\draw (0,0)coordinate(A) -- (\entraxe/100,0)coordinate(B);
\foreach \rr in {101,102,103,...,299}{
\path[red,name path =circleA] (A) circle (\rr/100);
\path[blue,name path =circleB] (B) circle ({(400-\rr)/100});
\path[dashed,name intersections={of=circleA and circleB}];
\draw (intersection-1) circle (0.01cm);
\draw (intersection-2) circle (0.01cm);
}
\end{scope}
\end{tikzpicture}
\end{document}