
Я хотел бы нарисовать цепочку шестеренок, вот так:
Я использую макрос, предоставленный Аленом Маттесом вСоздание шестеренок в TikZдля рисования одной шестерни с некоторыми изменениями для получения эффекта «двойной шестерни» (т.е. внутренней/внешней шестерни).
Мой реальный код такой:
\documentclass{standalone}
\usepackage{tikz}
\newcommand{\gear}[5]{%
\foreach \i in {1,...,#1} {%
[rotate=(\i-1)*360/#1] (0:#2) arc (0:#4:#2) {[rounded corners=1.5pt]
-- (#4+#5:#3) arc (#4+#5:360/#1-#5:#3)} -- (360/#1:#2)
}}
\begin{document}
\begin{tikzpicture}
\matrix[column sep=-0.1cm,draw=none,fill=none,ampersand replacement=\&] {
%%%%%%%%%%%%%%
% First gear %
%%%%%%%%%%%%%%
\node[circle,minimum size=40mm,fill=gray,shade] at (0,0){};
\node[circle,minimum size=30mm,fill=white] at (0,0){};
\draw[thick,rotate=10,fill=gray,shade] \gear{18}{2}{2.2}{10}{2};
\draw[thick,rotate=22,fill=white] \gear{18}{1.5}{1.7}{6}{1};\&
%%%%%%%%%%%%%%%
% Second gear %
%%%%%%%%%%%%%%%
\node[circle,minimum size=40mm,fill=gray,shade] at (0,0){};
\node[circle,minimum size=30mm,fill=white] at (0,0){};
\draw[thick,rotate=10,fill=gray,shade] \gear{18}{2}{2.2}{10}{2};
\draw[thick,rotate=22,fill=white] \gear{18}{1.5}{1.7}{6}{1};\\
};
\end{tikzpicture}
\end{document}
который производит:
для перемещения второй шестерни влево/вправо я поместил шестерни в так, \matrix
что мне просто нужно скопировать код из первой шестерни во вторую ячейку матрицы и указать column sep
так, чтобы шестерни находились на нужном расстоянии. Однако этот метод больше не работает, когда вы добавляете третью шестерню, для которой нужен другой column sep
.
чтобы переместить вторую шестеренку вверх/вниз и получить эффект первого изображения, я пробовал использовать параметры xshift
и (именно так я получил первое изображение), но это требует большой работы и множества перекомпиляций.yshift
\draw
Итак, мой вопрос:
есть ли лучший способ переместить шестеренку (где шестеренка состоит из двух \draw
и двух \node
команд, как показано в коде) влево-вправо-вверх-вниз относительно другой, без необходимости вручную позиционировать ее с помощью xshift
и yshift
?
Более общий подход
Чтобы сделать вопрос более общим, давайте рассмотрим случай, когда каждая шестеренка состоит только из одной шестеренки, без внутренней шестерни, фона и т. д. tikzpicture
В приведенном выше коде это будет выглядеть так:
\begin{tikzpicture}
\matrix[column sep=-0.1cm,draw=none,fill=none,ampersand replacement=\&] {
%%%%%%%%%%%%%%
% First gear %
%%%%%%%%%%%%%%
\draw[thick] \gear{18}{2}{2.2}{10}{2};\&
%%%%%%%%%%%%%%%
% Second gear %
%%%%%%%%%%%%%%%
\draw[thick] \gear{18}{2}{2.2}{10}{2};\\
};
\end{tikzpicture}
Как соединить две или более передач, изменив их положение, как на первом изображении?
решение1
Вот отправная точка и всего лишь одна из многих идей, каквходданные.
Аргументы этого next gear
стиля имеют форму
[<opt>:<text>]<abs angle>:<next gear’s radius>
где
:<text>
и[<opt>:<text>]
являются необязательными,<abs angle>
обозначает абсолютный угол/направление следующей передачи и<next gear’s radius>
определяет радиус следующей шестерни.
Библиотека turtle
используется только для своего forward
стиля и \tikz@lib@turtle@dir
макроса. Честно говоря, это можно было бы закодировать и без библиотеки, ну да ладно…
Обновлять
Ну, слушайте, это новая передача ( \ngear[<options>](<point>)
) и попробуйте на выходе.
Комбинация шестерен требует немного математики, поскольку количество зубьев, ширина этих зубьев и вращение зависят от предыдущей шестерни и ее вращения.
Вы можете перехватить управление \qrr@tikz@do@nextgear@
и самостоятельно вставить необходимые расчеты для следующей передачи.
(Вы даже можете переопределить его так, \ngear
чтобы он действовал как интерфейс для одного из уже определенных \gear
макросов в TeX.sx.)
Код
\documentclass[tikz,convert=false]{standalone}
\usepackage{tikz}
\usetikzlibrary{backgrounds,turtle}
\makeatletter
\newcommand*{\gearset}{\pgfqkeys{/gear}}
\newcommand*{\geargetvalue}[1]{\pgfkeysgetvalue{/gear/#1}}
\gearset{
outer radius/.initial=1cm,
outer height/.initial=5cm,
outer width/.initial=.5cm,
outer number/.initial=10,
outer rotate/.initial=0,
inner radius/.initial=,
inner rotate/.initial=0,
inner height/.initial=.2cm,
inner width/.initial=.2cm,
inner number/.initial=18,
height/.style={/gear/outer height={#1},/gear/inner height={#1}},
width/.style={outer width={#1},inner width={#1}},
% outer outer radius=.4pt, rounded corners?
% inner outer radius=.2pt,
% outer inner radius=.4pt,
% inner inner radius=.2pt,
/tikz/every gear/.style={draw,fill=none,even odd rule,rounded corners=.5pt},
% /tikz/every outer gear/.style={top color=blue, bottom color=green},
% /tikz/every inner gear/.style={draw=blue,fill=white},
}
\newcommand*{\ngear}[1][]{\begingroup\gearset{#1}\ngear@}
\def\ngear@(#1){%
\geargetvalue{outer radius}\qrr@gear@outerR
\geargetvalue{inner radius}\qrr@gear@innerR
\geargetvalue{outer number}\qrr@gear@outerN
\geargetvalue{inner number}\qrr@gear@innerN
\geargetvalue{outer height}\qrr@gear@outerH
\geargetvalue{inner height}\qrr@gear@innerH
\geargetvalue{outer width}\qrr@gear@outerW
\geargetvalue{inner width}\qrr@gear@innerW
\geargetvalue{outer rotate}\qrr@gear@outerRot
\geargetvalue{inner rotate}\qrr@gear@innerRot
\pgfmathsetmacro\qrr@gear@ooArc{(\qrr@gear@outerW)/(\qrr@gear@outerR+\qrr@gear@outerH)/pi*180}%
\pgfmathsetmacro\qrr@gear@ioArc{180/(\qrr@gear@outerN) - \qrr@gear@ooArc}%
\pgfmathsetmacro\qrr@gear@oiArc{(\qrr@gear@innerW)/(\qrr@gear@innerR+\qrr@gear@innerH)/pi*180}%
\pgfmathsetmacro\qrr@gear@iiArc{180/(\qrr@gear@innerN) - \qrr@gear@oiArc}%
\pgfmathtruncatemacro\qrr@gear@outerN{\qrr@gear@outerN-1}%
\pgfmathtruncatemacro\qrr@gear@innerN{\qrr@gear@innerN-1}%
\scope[shift={(#1)}]%
\path[every gear/.try, every outer gear/.try] ({\qrr@gear@outerRot}:{\qrr@gear@outerR+\qrr@gear@outerH})
\foreach \@tooth in {0,...,\qrr@gear@outerN} {
\pgfextra
\pgfmathsetmacro\qrr@gear@sa{\qrr@gear@outerRot+2*\@tooth*(\qrr@gear@ooArc+\qrr@gear@ioArc)}%
\endpgfextra
arc[radius={\qrr@gear@outerR+\qrr@gear@outerH}, start angle=\qrr@gear@sa, delta angle=\qrr@gear@ooArc]
-- (\qrr@gear@sa+\qrr@gear@ooArc:{\qrr@gear@outerR})
arc[radius={\qrr@gear@outerR}, start angle=\qrr@gear@sa+\qrr@gear@ooArc, delta angle=2*\qrr@gear@ioArc]
-- (\qrr@gear@sa+\qrr@gear@ooArc+2*\qrr@gear@ioArc:{\qrr@gear@outerR+\qrr@gear@outerH})
arc[radius={\qrr@gear@outerR+\qrr@gear@outerH}, start angle=\qrr@gear@sa+\qrr@gear@ooArc+2*\qrr@gear@ioArc, delta angle=\qrr@gear@ooArc]
}
\ifx\qrr@gear@innerR\pgfutil@empty\else
% ; % un-comment this and the next line to have two paths
% \path[every gear/.try, every inner gear]
(0:{\qrr@gear@innerR-\qrr@gear@innerH})
\foreach \@tooth in {0,...,\qrr@gear@innerN} {
\pgfextra
\pgfmathsetmacro\qrr@gear@sa{\qrr@gear@innerRot+2*\@tooth*(\qrr@gear@oiArc+\qrr@gear@iiArc)}%
\endpgfextra
arc[radius={\qrr@gear@innerR-\qrr@gear@innerH}, start angle=\qrr@gear@sa, delta angle=\qrr@gear@oiArc]
-- (\qrr@gear@sa+\qrr@gear@oiArc:{\qrr@gear@innerR})
arc[radius={\qrr@gear@innerR}, start angle=\qrr@gear@sa+\qrr@gear@oiArc, delta angle=2*\qrr@gear@iiArc]
-- (\qrr@gear@sa+\qrr@gear@oiArc+2*\qrr@gear@iiArc:{\qrr@gear@innerR-\qrr@gear@innerH})
arc[radius={\qrr@gear@innerR-\qrr@gear@innerH}, start angle=\qrr@gear@sa+\qrr@gear@oiArc+2*\qrr@gear@iiArc, delta angle=\qrr@gear@oiArc]
}
\fi
;
\endscope
\endgroup
}
\def\qrr@tikz@gear@current@radius{0pt}
\def\qrr@tikz@do@nextgear{\pgfutil@ifnextchar[\qrr@tikz@do@nextgear@{\qrr@tikz@do@nextgear@[]}}
\def\qrr@tikz@do@nextgear@[#1]#2:#3\@qrr@tikz@do@nextgear{%
\pgfmathsetmacro\qrr@tikz@gear@distance{\qrr@tikz@gear@current@radius+(#3)+\pgfkeysvalueof{/gear/outer height}}%
\pgfmathsetmacro\qrr@tikz@gear@current@radius{abs(#3)}%
\gdef\tikz@lib@turtle@dir{#2}%
\pgfkeysalso{/tikz/turtle/forward/.expanded=\qrr@tikz@gear@distance pt}
\pgfgetlastxy\pgf@gear@@x\pgf@gear@@y
\pgfkeysalso{/tikz/gear={#1, outer radius=\qrr@tikz@gear@current@radius pt}{\pgf@gear@@x,\pgf@gear@@y}}
}
\tikzset{
gear/.style 2 args={/tikz/insert path={\pgfextra{\ngear[#1](#2)}}},
turtle/next gear/.code=\qrr@tikz@do@nextgear#1\@qrr@tikz@do@nextgear
}
\begin{document}
\begin{tikzpicture}[show background grid,/gear/height=.3cm,every gear/.append style=thick]
\draw[dash pattern={on \pgflinewidth off 2\pgflinewidth},thin] (0,0) [turtle={
next gear/.list={
0:2cm,
{[outer rotate=-90,outer width=.18cm,outer number=10]90:2cm},
{[outer width=.49cm,outer number=14,outer rotate=0]30:3cm},
{[outer width=.2cm,outer rotate=18]120:2cm}
}}];
\end{tikzpicture}
\end{document}