保持长度固定,使圆弧变平

保持长度固定,使圆弧变平

问题:如何确保第二张图片的蓝色形状与第一张图片中的环的长度相同?

背景:为了说明直线切割后“展开”环的过程。我计划制作一个动画,其中包含从“圆”到“线”的 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

我希望nonlineartransformationsPGF 模块可以完成一些工作。我见过使用极坐标进行变换的例子,也见过使用任意变换的例子。我想我缺少的是将半圆展平为直线的参数方程。也就是说,如果我们忘记环的厚度,考虑一个从 (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

我提出两种结构(答案):

  1. 压平环 在此处输入图片描述

  2. 压平并拉伸环。 在此处输入图片描述

假设环面是分布在内部和外部边界圆之间的一组同心圆。该族中的每个圆在压扁过程中都会变形,最终变成一个线段。在第一种构造中,这些曲线的长度在整个过程中是恒定的。特别是,表示变形环面的平面区域具有恒定的面积。在第二种构造中,这些曲线的长度不断增加,但对应于外部圆的曲线的长度不变。

在给出代码之前,我们先来解释一下。我们考虑一个环面, 年代外圆上两个直径相对的点 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命令的经验有限,它们对空格非常敏感。参数之间不能有空格(当然,必须遵守括号格式)。

相关内容