问题:如何确保第二张图片的蓝色形状与第一张图片中的环的长度相同?
背景:为了说明直线切割后“展开”环的过程。我计划制作一个动画,其中包含从“圆”到“线”的 3 或 4 个中间步骤。
\documentclass[border=5mm, varwidth]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tabular}{@{}c@{}}
\begin{tikzpicture}
\filldraw [fill=gray!30, draw=black] (0,0) circle[radius=1];
\filldraw [fill=blue!15, draw=black, even odd rule] (0,0) circle[radius=1] circle[radius=2];
\end{tikzpicture}
\vspace{2cm} \\
\begin{tikzpicture}
\filldraw [fill=gray!30, draw=black] (0,0) circle[radius=1];
\filldraw[fill=blue!15, draw=black, shift={(0,2)}] (330:3) arc (330:210:3) -- (210:4) arc (210:330:4) -- cycle;
\end{tikzpicture}
\end{tabular}
\end{document}
由于内圆半径为 1cm,外圆半径为 2cm,因此环的长度约为 pi 的 3 倍。
编辑1
我希望nonlineartransformations
PGF 模块可以完成一些工作。我见过使用极坐标进行变换的例子,也见过使用任意变换的例子。我想我缺少的是将半圆展平为直线的参数方程。也就是说,如果我们忘记环的厚度,考虑一个从 (0,0) 开始、逆时针方向在 (0, 1) 结束的半圆,则变换将保持点 (0,0) 不变,但将 (0,1) 向右拉,最终向下拉到 (1,0) 点。一旦我知道如何对 rhs 半圆进行变换,我就可以将对称变换应用于 lhs 半圆,以完成圆变换。然后对另一对具有不同半径的半圆执行此操作以获得环。
编辑2
在 John Kormylo 的建议下(感谢 John!),我能够编写一个函数来将半圆转换为“扁平”。接下来是将其推广为\filldraw
环形命令。
\documentclass[margin=3mm,varwidth]{standalone}
\usepackage{tikz}
\makeatletter
\pgfmathdeclarefunction{alpha}{1}{%
\begingroup
\pgfmathparse{180/#1-90}%
\pgf@x=\pgfmathresult pt\relax
\pgfmathreturn\pgf@x
\endgroup
}
\makeatother
\def\shape#1#2{
\draw [draw={#1}] (0,0) arc[start angle=-90, end angle={alpha(#2)}, radius={#2}];
}
\begin{document}
\begin{tikzpicture}[scale=3]
\shape{red}{1}
\shape{red!90}{2}
\shape{red!80}{3}
\shape{red!70}{4}
\shape{red!60}{5}
\shape{red!50}{6}
\shape{red!40}{7}
\shape{red!30}{8}
\shape{red!20}{9}
\shape{black}{100}
\end{tikzpicture}
\end{document}
左侧紧随对称性。将它们放在一起会产生一个有点笨拙的函数,它有 6 个参数,包括颜色、中心、半径和角度。这仍然不是我最初问题的答案,所以我将它包括在这里,而不是将其作为答案发布。此外,我很确定代码可以清理。
\documentclass[margin=3mm,varwidth]{standalone}
\usepackage{tikz}
% alpha takes 2 arguments:
% #1: angle of arc, for semi-circle either -180 or 180
% #2: radius of arcs
% #3: rotation of angle
\makeatletter
\pgfmathdeclarefunction{alpha}{3}{%
\begingroup
\pgfmathparse{#1/#2+#3}%
\pgf@x=\pgfmathresult pt\relax
\pgfmathreturn\pgf@x
\endgroup
}
\makeatother
% \shape takes 5 arguments:
% #1: draw color, e.g. red
% #2: center, e.g. (0,0)
% #3: radius
% #4: start angle, e.g. 0 for starting at (1,0), -90 for (0,-1)
% #5: angle of arc, for semi-circle either -180 or 180
% #6: rotation of end angle, e.g. -90 to go from (1,0) to (0,-1)
\def\shape#1#2#3#4#5#6{
\draw [draw={#1}] {#2} arc[radius={#3}, start angle={#4}, end angle={alpha(#6,#3,#5)}];
}
\begin{document}
\begin{tikzpicture}[scale=1.8]
\shape{blue!100}{(0,0)}{1}{-90}{-90}{180}
\shape{blue!100}{(0,0)}{1}{-90}{-90}{-180}
\shape{blue!80}{(0,0)}{2}{-90}{-90}{180}
\shape{blue!80}{(0,0)}{2}{-90}{-90}{-180}
\shape{blue!60}{(0,0)}{6}{-90}{-90}{180}
\shape{blue!60}{(0,0)}{6}{-90}{-90}{-180}
\shape{blue!50}{(0,0)}{150}{-90}{-90}{180}
\shape{blue!50}{(0,0)}{150}{-90}{-90}{-180}
\end{tikzpicture}
\end{document}
答案1
我提出两种结构(答案):
假设环面是分布在内部和外部边界圆之间的一组同心圆。该族中的每个圆在压扁过程中都会变形,最终变成一个线段。在第一种构造中,这些曲线的长度在整个过程中是恒定的。特别是,表示变形环面的平面区域具有恒定的面积。在第二种构造中,这些曲线的长度不断增加,但对应于外部圆的曲线的长度不变。
在给出代码之前,我们先来解释一下。我们考虑一个环面, 年代和否外圆上两个直径相对的点 C.我们表示为时间切线C在年代.我们沿着穿过的射线切割环否并希望将其展平,这样,最后,与外圆相对应的曲线成为切线中包含的线段时间和年代 它的中点。
我将简要解释一下第一个构造,例如,它出现在 Cavalieri 关于不可分方法的著作中;参见https://fr.wikipedia.org/wiki/M%C3%A9thode_des_indivisibles#:~:text=spirale%20d'Archim%C3%A8de.-,Aire%20du%20disque,varie%20de%200%20%C3%A0%20R它基于以下想法:为了展平外圆,我们将其想象为一根导线,其端点位于否,绕在与时间。如果圆盘半径增加,但圆盘保持与时间,线的演变给出了圆所需的扁平化过程。
建筑是围绕这个限制过程建造的;有一组圆圈C_k 半径增加,描述了外圆的扁平化过程(见上图)。内圆被迫跟随外圆,因为其扁平化过程由与相应内圆同心的圆定义C_k 圈并保持与固定点相切 S'。
为了完成构造,我们计算定义所有这些弧的角度,每个值钾(通过变量\q在下面的代码中)。
第一个构造的代码
\documentclass[margin=10pt]{standalone}
\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{math, calc}
\xdefinecolor{O}{RGB}{255, 102, 17}
\xdefinecolor{R}{RGB}{238, 34, 34}
\xdefinecolor{B}{RGB}{17, 87, 221}
\begin{document}
\tikzmath{%
real \r, \R, \h, \q;
\r = 1.5;
\R = 2.75;
\h = \R-\r;
}
\begin{tikzpicture}[every node/.style={scale=0.8}, rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\path
(\R, 0) coordinate (S)
(-\R, 0) coordinate (N);
\draw[B, fill=B!30, fill opacity=.5, even odd rule]
(0, 0) circle (\r)
(0, 0) circle (\R);
% \foreach \k [evaluate=\k as \q using \r/(\k*\R-\h)]
% in {1.03, 1.1, 1.2, 1.32, 1.5, 1.7, 2, 2.4, 3, 3.8, 5.1, 8, 17}{%
\foreach \k [evaluate=\k as \q using \r/(\k*\R-\h)]
in {1.03, 1.2, 1.5, 2, 3, 5, 8, 17}{%
\path
($({(1-\k)*\R}, 0) + (-{180*\q}: {\k*\R-\h})$) coordinate (A)
($({(1-\k)*\R}, 0) + ({180*\q}: {\k*\R-\h})$) coordinate (B)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R})$) coordinate (C)
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R})$) coordinate (D);
\draw[B, fill=B!30, fill opacity=.5]
(D) -- (A) arc ({-180*\q}: {180*\q}: {\k*\R-\h}) --
(B) -- (C) arc ({180/\k}: {-180/\k}: {\k*\R}) -- cycle;
}
\draw[B, fill=B!30, fill opacity=.5] (\r, -{3.142*\r}) -- (\r, {3.142*\r})
-- (\R, {3.142*\R}) -- (\R, -{3.142*\R}) -- cycle;
\end{tikzpicture}
在第二个构造的代码中,对应于\foreach命令,最后两个将被后面的内容替换。
\foreach \k in {1.03, 1.2, 1.5, 2, 3, 5, 8, 17}{%
\path
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R-\h})$) coordinate (A)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R-\h})$) coordinate (B)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R})$) coordinate (C)
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R})$) coordinate (D);
\draw[B, fill=B!30, fill opacity=.5]
(D) -- (A) arc ({-180/\k}: {180/\k}: {\k*\R-\h}) --
(B) -- (C) arc ({180/\k}: {-180/\k}: {\k*\R}) -- cycle;
}
\draw[B, fill=B!30, fill opacity=.5]
(\r, -{3.142*\R}) rectangle (\R, {3.142*\R});
评论。由于命令中出现的角度弧是相对于牛轴(TikZ 坐标系),我垂直绘制所有图形,然后旋转图像。
例如,这是产生组成第一个动画的图像的代码。
\documentclass[multi=page, margin=10pt]{standalone}
\usepackage[rgb]{xcolor}
\usepackage{tikz}
\usetikzlibrary{math, calc}
\xdefinecolor{R}{RGB}{238, 34, 34}
\xdefinecolor{B}{RGB}{17, 87, 221}
\begin{document}
\tikzmath{%
real \r, \R, \h, \q;
\r = 1.5;
\R = 2.75;
\h = \R-\r;
}
\begin{page}
\begin{tikzpicture}[rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\draw[B, fill=B!50, even odd rule]
(0, 0) circle (\r)
(0, 0) circle (\R);
\end{tikzpicture}
\end{page}
\foreach \k [evaluate=\k as \q using \r/(\k*\R-\h)]
in {1.03, 1.1, 1.2, 1.32, 1.5, 1.7, 2, 2.4, 3, 3.8, 5.1, 8, 17}{%
\begin{page}
\begin{tikzpicture}[rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\path
($({(1-\k)*\R}, 0) + (-{180*\q}: {\k*\R-\h})$) coordinate (A)
($({(1-\k)*\R}, 0) + ({180*\q}: {\k*\R-\h})$) coordinate (B)
($({(1-\k)*\R}, 0) + ({180/\k}: {\k*\R})$) coordinate (C)
($({(1-\k)*\R}, 0) + (-{180/\k}: {\k*\R})$) coordinate (D);
\draw[B, fill=B!50]
(D) -- (A) arc ({-180*\q}: {180*\q}: {\k*\R-\h}) --
(B) -- (C) arc ({180/\k}: {-180/\k}: {\k*\R}) -- cycle;
\draw[R, thick] (A) -- (D) (B) -- (C);
\end{tikzpicture}
\end{page}
}
\foreach \k in {1, 2, 3, 4}{% the last image lasts longer
\begin{page}
\begin{tikzpicture}[rotate=-90]
\path[clip] (-\R-2, -10) rectangle (\R+1, 10);
\draw[B, fill=B!50] (\r, -{3.142*\r}) -- (\r, {3.142*\r})
-- (\R, {3.142*\R}) -- (\R, -{3.142*\R}) -- cycle;
\draw[R, thick]
(\r, -{3.142*\r}) -- (\R, -{3.142*\R})
(\r, {3.142*\r}) -- (\R, {3.142*\R});
\end{tikzpicture}
\end{page}
}
\end{document}
答案2
这只是部分答案,但我觉得将我的代码放在这里比反复编辑我的问题更合适。回顾一下:我最初的问题是(创造一个术语)如何解开环形物?我的目的是画一个“模拟”图,切割顶部的环并弯曲两部分直到它们水平放置(参见我原始问题中的第一个图)。
第 1 部分:切割和弯曲圆弧
首先,这是“展开弧”的代码。结果与我在编辑问题时呈现的结果类似,只是现在我有一种更可靠的方法来计算“固定点”(在示例中,位于中心南位置的点)和“切点”(在示例中,从中心北位置开始并逐渐向左/向右拉动直到其位于等于半径的水平距离处的点)的位置。
我修改了arc
命令,使用圆心作为输入,而不是圆周上的点(如命令所预期的那样arc
)。这里是我了解了如何做到这一点的地方。我对通常的语法做了一个小改动,因为我希望能够以这种方式调用:(center)(radius)(start angle:end angle)
。那是因为我打算用以下方式调用环:(center)(inner radius:outer radius)(start angle:end angle)
。我希望能够输入环的中心,而不是圆周上的一个点,因为这对我来说似乎更自然。
然后我介绍了一个扩张因子,即增加圆弧半径以产生展开效果的因子。半径从“固定点”向中心增加。为了保持圆弧长度固定,圆弧命令中使用的“结束角度”必须根据膨胀值进行更改。
\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\usepackage[EULERGREEK]{sansmath}
\usetikzlibrary{calc}
\usetikzlibrary{shapes}
\usetikzlibrary{shapes.misc}% "cross out" shape
\usepackage{amssymb}% symbols
\pgfdeclarelayer{bg}
\pgfdeclarelayer{fg}
\pgfsetlayers{bg,main,fg}
% \arcus(center)(radius)(start angle:end angle)
\newcommand\arcus{}
\def\arcus(#1)(#2)(#3:#4){%
($(#1)+({#2*cos(#3)},{#2*sin(#3)})$)arc(#3:#4:#2)}
% \cutarcus(center)(radius)(fixpoint:cutpoint)(dilation)
\newcommand\cutarcus{}
\def\cutarcus(#1)(#2)(#3:#4)(#5){%
($(#1)+({#2*cos(#3)},{#2*sin(#3)})$)arc(#3:#3+(#4-#3)/#5:#2*#5)}
% mark the cutpoint (depends on dilation factor)
\def\cutpoint[#1,(#2)](#3)(#4)(#5:#6)(#7){%
\path\cutarcus(#3)(#4)(#5:#6)(#7)node[#1,pos=1,font=\tiny]{#2};}
% mark the fixpoint (independent of dilation factor)
\def\fixpoint[#1,(#2)](#3)(#4)(#5:#6)(#7){%
\path\cutarcus(#3)(#4)(#5:#6)(#7)node[#1,pos=0,font=\tiny]{#2};}
\tikzset{%
center/.style={circle, fill, fill=white, draw=black, minimum size=2pt, inner sep=0pt, outer sep=0pt},
fixpoint/.style={diamond, fill, fill=black, draw=black, minimum size=2pt, inner sep=0pt, outer sep=0pt},
cutpoint/.style={circle, fill, fill=black, draw=black, minimum size=2pt, inner sep=0pt, outer sep=0pt},}
\begin{document}
\begin{tikzpicture}[font=\sffamily\tiny,scale=1]
% background layer
\begin{pgfonlayer}{bg}
% define grid lines
\draw[help lines, color=gray!30, dashed, line width=0.5pt]%
(-3.5,-1.5) grid (3.5,1.5);
\end{pgfonlayer}
% foreground layer
\clip (-1.5,-1.5) rectangle + (3,4.5);
\begin{pgfonlayer}{fg}
\foreach \m in {1,2,4,8,16,32,64}
%\foreach \m in {1,1.1,...,100}
{%
\draw[red]\cutarcus(0,0)(1)(270:90)(\m);
\draw[blue]\cutarcus(0,0)(1)(-90:90)(\m);
% label the cutpoints
\cutpoint[blue,($\bullet$)](0,0)(1)(-90:90)(\m);
\cutpoint[red,($\bullet$)](0,0)(1)(270:90)(\m);
}%
% label the center
\node at (0,0) [font=\tiny] {$\circ$};
% label the fixed point
\fixpoint[black,($\mathbin{\blacklozenge}$)](0,0)(1)(-90:90)(1);
% make a legend
\matrix [draw,below left] at (3,3) {
\node [center,label=right:center] {}; \\
\node [fixpoint,label=right:fixed point] {}; \\
\node [cutpoint,label=right:cut point] {}; \\
};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
颜色只是表明我将问题分为两部分(这里是左图和右图)的一种方式。如果仔细查看代码,您会发现我的图例是通过创建tikz
样式生成的,而图中的标签则依赖于其他代码。那是因为我事后才制作了图例,我无法快速看到如何使图例与使用的符号一致(反之亦然),因此决定继续。
第 2 部分:切割和弯曲环形件 [未完成]
现在开始“切割环”。代码似乎产生了正确的线条,但遗憾的是颜色填充没有正确应用。也许有人可以帮助我解决这个问题。或者提供更好的解决方案。
\documentclass[margin=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
% \cutarcus(center)(radius)(fixpoint:cutpoint)(dilation)
\newcommand\cutarcus{}
\def\cutarcus(#1)(#2)(#3:#4)(#5){%
($(#1)+({#2*cos(#3)},{#2*sin(#3)})$)arc(#3:#3+(#4-#3)/#5:#2*#5)}
% \cutannulus(center)(inner radius:outer radius)(fixpoint:cutpoint)(dilation)
\newcommand\cutannulus{}
\def\cutannulus[#1](#2)(#3:#4)(#5:#6)(#7){%
\filldraw[fill opacity=0.5,#1,even odd rule]\cutarcus(#2)(#3)(#5:#6)(#7)\cutarcus(#2)(#4)(#5:#6)(#7)}
\begin{document}
\begin{tikzpicture}
\filldraw[fill=gray!50]\arcus(0,0)(1)(-180:180);
\cutannulus[fill=blue!50](0,0)(1:2)(270:90)(1);
\cutannulus[fill=blue!50](0,0)(1:2)(-90:90)(1);
\begin{scope}[yshift=-5cm,on grid]
\filldraw[fill=gray!50]\arcus(0,0)(1)(-180:180);
\cutannulus[fill=blue!50](0,0)(1:2)(270:90)(1.5);
\cutannulus[fill=blue!50](0,0)(1:2)(-90:90)(1.5);
\end{scope}
\end{tikzpicture}
\end{document}
填充颜色未正确应用:
由于我创建tikz
命令的经验有限,它们对空格非常敏感。参数之间不能有空格(当然,必须遵守括号格式)。