![В математике](https://rvso.com/image/328834/%D0%92%20%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B5.png)
Должен отметить, что я уже знаком с TikZ и ищу технические ответы, как будто TikZ недостаточно техничен.
Этот вопрос перекликается со следующим вопросом: в чем разница между этими вещами:
\def\pointA{\pgfpoint{0cm}{0cm}}
\coordinate (A) at (current page.north east);
\coordinate (A) at (1,1);
(current page.north east)
\node [anchor=east] {}
<-- якорь? :-p(просто демонстрируя совпадение терминов)\pgfpointanchor
<-- но это действительно должен быть якорь, или это точка? :-p
Я думаю, что мое понимание недостаточно, и это мешает моим попыткам, показанным ниже.
В математике
Аточкаопределяется как:
Точка — это точное положение или местоположение на плоской поверхности. Важно понимать, что точка — это не вещь, а место.
Акоординатаопределяется как:
Координаты — это упорядоченный набор чисел, определяющих положение точки.
Якорь — это:
Я хотел бы пояснить это на практических примерах.
Определим координату:
\coordinate (rightmid) at ($ (current page.north east) + (0,-18cm) $); % use tikz calc library
Существует множество неявных координат (следует ли их называть координатами, точками, якорями или как-то еще?), например:
- (текущая страница.северо-запад)
- (текущая страница.север)
- (текущая страница.северо-восток)
- (текущая страница.восток)
- (текущая страница.юго-восток)
- (текущая страница.юг)
- (текущая страница.юго-запад)
- (текущая страница.центр)
Допустим, я хочу вычислить вертикальное расстояние между двумя объектами (я намеренно выбрал слово «объекты») И сохранить эту переменную для использования за пределами текущей области действия.
например, две вещи — (текущая страница.северо-восток) и (справа посередине)
Если заняться арифметикой, то мне известны следующие варианты (это все?):
Я мог бы использовать
\pgfmathparse
для оценки арифметикиЯ мог бы использовать
\path let \p1=
синтаксис.
Используя опцию 1, я могу задать \pgfxa
, \pgfya
для \pgfx
и \pgfy
для вычислений и получить результат с помощью \pgfmathresult
.
Затем я могу определить уникальную длину (глобальную), например \setlength{\mylength}{2cm}
. Затем я могу использовать \mylength
для ее извлечения. Это не позволит мне записать все в самодостаточном макросе, поскольку \setlength
может быть определено только один раз. Альтернативой является использование \global\let\mylength{2cm}
, что, как мне кажется, лучше подходит для этой работы (поправьте меня, если я ошибаюсь. Имеет ли это последствия для значения+единицы/измерения)?
Собираем все вместе
- Можно ли использовать ширину одного узла TikZ для расчета ширины другого?
- Как преобразовать координату в pgfpoint и наоборот?
- Координаты A, B: вычислить |BA| и угол между +x и (BA)
- макрос pgf, возвращающий узел
Вот эксперимент, которыйне компилируетсяна основе нескольких ответов:
\documentclass{article}
\usepackage{fontspec}
\usepackage{tikz}
\usetikzlibrary{calc}
% A4 Paper
\pdfpagewidth=210mm \pdfpageheight=297mm % for PDF output
\paperwidth=210mm \paperheight=297mm % for TikZ
\newcommand{\getdistance}[3]{
\makeatletter
% Syntax: <length variable/macro> <coordinate1> <coordinate2>
\pgfpointdiff{\pgfpointanchor{#2}{center}} % https://tex.stackexchange.com/a/39325/13552
{\pgfpointanchor{#3}{center}} % https://tex.stackexchange.com/a/39325/13552
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\pgfmathparse{veclen(\pgf@xa,\pgf@ya)}
\global\let#1\pgfmathresult % <-- I want the pgfmathresult to be a dimension like 510 pt
\makeatother
}
\begin{document}
\begin{tikzpicture}[overlay]
\coordinate (rightmidtest) at ($ (current page.north east) + (0,-10cm) $); % use tikz calc library
\coordinate (rightmid) at ($ (current page.north east) + (0,-18cm) $); % use tikz calc library
\end{tikzpicture}
\getdistance{\globalresult}{rightmidtest}{rightmid}
\getdistance{\globalresult}{current page.north east}{rightmid}
\getdistance % <-- Should expand to last distance measured
\end{document}
Обновленный код 2016-02-25Работающий
После анализа и нового понимания ответа Перкусса я придумал кое-что еще.
Помнить:
(current page)
подразумевается- Якорь .center подразумевается в TikZ, но не в PGF
\pgfpointanchor{<ref>}{<anchor e.g. center>}
Я использовал xparse
синтаксис для макроса, потому что его легче читать.
\documentclass{article}
\usepackage{fontspec}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{xparse}
\makeatletter
\NewDocumentCommand{\getdistance}{ m m O{center} m O{center} }{%
%Syntax: {\<macro>} {<ref1>} [<anchor>] {<ref2>} [<anchor>]
\pgfpointdiff{\pgfpointanchor{#2}{#3}}% https://tex.stackexchange.com/a/39325/13552
{\pgfpointanchor{#4}{#5}}% https://tex.stackexchange.com/a/39325/13552
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\pgfmathparse{veclen(\pgf@xa,\pgf@ya)} % result as number (floating point)
%\pgfmathveclen{\pgf@xa}{\pgf@ya} % alternate syntax to pgfmathparse: result as number (floating point)
%\global\let#1\pgfmathresult pt % does not recognize pt.
\global\edef#1{\pgfmathresult\ pt}
%\pgfmathprintnumber{\pgfmathresult}%
}
\makeatother
\begin{document}
\begin{tikzpicture}[remember picture,overlay]
% (current page) is implicit
% .center is implicit in TikZ but not in PGF \pgfpointanchor{<ref>}{<anchor e.g. center>}
\coordinate (referral1) at ($ (current page.north east) + (0,-18cm) $); % use tikz calc library
\node [minimum height=2cm] (referral2) {};
\end{tikzpicture}
\begin{tikzpicture}[remember picture,overlay]
\getdistance{\globalresultA}{current page}{referral1}
\getdistance{\globalresultB}{current page}[north east]{referral1}
\getdistance{\globalresultC}{current page}[north east]{referral2}[north]
\getdistance{\globalresultD}{current page}[north east]{referral2}[south]
\end{tikzpicture}
\globalresultA
\globalresultB
\globalresultC
\globalresultD
\end{document}
решение1
Я думаю, путаница возникает из-за того, что TikZ работает с рефералами, а не с объектами. Когда a
упоминается определенное имя узла. Обычно предполагается, что пользователь, вероятно, имеет в виду его центральную координату. Или в случае рисования вещей между двумя вещами, если одна из них является узлом, то она вычисляет точку на его границе магическим образом, так что пользователь не замечает.
Но все это делается внутри. И ничего не связано с узлами или чем-то еще. Узел имеет имя, на которое можно ссылаться, и предопределенные места, где он понимает.
Ни один из них не сохраняется. Они просто проверяются на наличие или просто выполняются. Другими словами, если вы пишете shape=duck
, то он не перебирает все возможные имена форм, он просто делает проверку существования (я использую бессмысленные имена для настоящих макросов)
\pgfutil@ifdefined\pgf@Shape@#1@...{<if it exists use>}{<if not err>}
С якорями все то же самое: если вы говорите anchor=heel
, он запрашивает это имя через some \pgf@sh@#1@anchor@#2
и так далее.
А откуда они берутся? Они определяются в объявлении формы через \savedanchor
и \anchor
и так далее.
Итак, они там и тщательно организованы так, что когда вы ссылаетесь на них, все, от ширины и высоты текстового поля до пути формы, мучительно кодируется вручную. Вот почему это очень утомительная работа — определять новые формы. И когда вы ссылаетесь на них, они организованы таким образом, что позиция привязки записывается (глобально!) внутри регистров длины\pgf@<x,y>
Короче говоря, когда речь идет об узле-якоре, на самом деле существует довольно сложная процедура получения из него координат.
Кроме того, существует разница между координатой, которая является , \pgf@<x,y>
и узлом типа координаты, который является \coordinate
.
Наконец, когда вы ссылаетесь на узел, TikZ пытается помочь вам, предполагая, что вы имеете в виду его центральный якорь, чтобы вы могли сэкономить несколько нажатий клавиш, но иногда вам нужно выполнить более тонкую операцию, например, измерить расстояние.
Вы не можете обойтись без реферальных имен. Вам нужны фактические координаты (опять же, не \coordinate
s). Как прокомментировал Марк Виброу, вам нужно каким-то образом понять контекст, и это делается с помощью \pgf@process
ответа на такие вопросы: является ли это буквальной координатой (1,1)
, является ли это именем узла, является ли это якорем узла и т. д. Затем вы можете использовать полученные \pgf@<x,y>
регистры.
Затем вы можете делать с ними все, что захотите. Ваш пример let
синтаксиса также делает потрясающую работу по упрощению этого, но он все еще делает то, что вы описали. На самом деле ваш вопрос в основном в том, почему TikZ существует поверх PGF. Это очень хорошо спроектированный фронтенд для очень многословного, но мощного синтаксиса PGF.
решение2
\def\pointA{\pgfpoint{0cm}{0cm}}
Используйте это только в том случае, если вы знакомы с PGF (основа TiкZ). В любом случае, не важно, что \pgfpoint
делает TeX; эта команда никогда не существует сама по себе. Обычно она является частью синтаксиса, например
\coordinate (A) at (current page.north east);
дает точке имя. Неважно, каковы фактические x- и y-координаты. Мы знаем, где (A)
находится, и это все, что нам нужно знать.
\coordinate (A) at (1,1);
Аналогично предыдущему. Обычно мы называем точки, чтобы (A) сократить длину/сложность кода и (B) улучшить читаемость. Например
(current page.north east)
С круглыми скобками он выдаетдвигаться вдействие. Это похоже на то, как если бы вы держали ручку, переместили бы руку в следующее место, где вы хотите что-то нарисовать. Например
Этот код делает TiкZ перемещает перо по всему холсту и объявляет узлы/координаты.
\node [anchor=east] {}
поместите узел "рядом" с текущим положением ручки. Под "рядом" я подразумеваю, что якорь, который вы даете, должен совпадать с положением ручки. Это очень похоже на то, как вы на лодке можете бросить якорь туда, куда хотите, и этот якорь затем зафиксирует лодку.
практическая часть
- тебе нужно
\makeatletter
. - Вы, вероятно, захотите
\pgfmathsetlength
вместо\pgfmathsetmacros
или\pgfmathparse
.- но помните, все размеры должны быть указаны до их использования.
- будьте осторожны при использовании узла
(current page)
. Обычно вам нужно[overlay]
. - вам нужно находиться внутри
tikzpicture
среды, чтобы получить что-либо, созданное вами вtikzpicture
среде.- если вы не выполняете работу в той же
tikzpicture
среде, вам нужно[remember picture]
.
- если вы не выполняете работу в той же
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\newcommand{\getdistance}[3]{
% Syntax: <length variable/macro> <coordinate1> <coordinate2>
\pgfpointdiff{\pgfpointanchor{#2}{center}} % http://tex.stackexchange.com/a/39325/13552
{\pgfpointanchor{#3}{center}} % http://tex.stackexchange.com/a/39325/13552
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\pgfmathparse{veclen(\pgf@xa,\pgf@ya)}
\global\let#1\pgfmathresult % <-- I want the pgfmathresult to be a dimension like 510 pt
}
\begin{document}
\begin{tikzpicture}[remember picture,overlay]
\coordinate (rightmidtest) at ($ (current page.north east) + (0,-10cm) $); % use tikz calc library
\coordinate (rightmid) at ($ (current page.north east) + (0,-18cm) $); % use tikz calc library
\end{tikzpicture}
\tikz[remember picture,overlay]{
\getdistance{\globalresulta}{rightmidtest}{rightmid}
\getdistance{\globalresultb}{current page}{rightmid}
}
\globalresulta
\globalresultb
\end{document}
решение3
\def\pointA{\pgfpoint{0cm}{0cm}}
Это в принципе то же самое, что и
\coordinate (A) at (0,0);
\coordinate (A) at (current page.north east);
Здесь вы просто называете верхний правый угол страницы как
A
. Это бессмысленно в том смысле, что местоположение уже названо, но может быть полезно, так как не нужно вводить все это вручную, а просто написатьA
.\coordinate (A) at (1,1);
Координаты в TikZ в основном являются узлами с
coordinate
формой, им не требуется заголовок и, что особенно важно, они не имеютsep
. Так что это точка. Тем не менее, запись\node[coordinate] (a) at (0,0) {};
равна\coordinate (a) at (0,0);
Смотрите такжеTikZ: разница между \node и \coordinate?
(current page.north east)
Это указывает на верхний правый угол текущей "страницы". Обычно это страница формата А4, но может быть любого размера. В данном случае страница не обязательно подразумевает обычный лист бумаги, но это может быть любая обозначенная область.
\node [anchor=east] {}
<-- якорь?Нет, это не якорь. Это узел, позиционирование которого определяется размещением спроектированного якоря в координате. Так же
\node [anchor=east] at (4,0) {};
разместим узел, имеющийeast
якорь, совпадающий с координатой(4,0)
.
решение4
Я не знаю, как редактировать свой старый ответ. Я просто напишу новый.
В ТикZ существует множество способов указания точек
Укажите числовые координаты.
Например(1,2)
,(3mm,4in,5pt)
,(6:7)
, ,(axis cs:x=8)
.Дайте предопределенное имя узла и имя якоря.
Например(current page.south east)
,(current bounding box.north west)
.Дайте предопределенное имя узла.
Например(current page)
. Это эквивалентно(current page.center)
Дайте предопределенный
coordinate
.
Например\coordinate(X)at(1,2);\path(X);
. Acoordinate
на самом деле является узлом, якоря которого «исчезают»:(X)
,(X.center)
,(X.south)
, и(X.34)
все дают один и тот же результат.
Их аналоги PGF - это
\pgfpointxy
,\pgfpointxyz
,\pgfpointpolar
, и так далее\pgfpointanchor{#1}{#2}
\pgfpointanchor{#1}{center}
\pgfpointanchor{#1}{center}
Теперь вы видите, что в определении \getdistance
можно заполнить только имя узла, а якорь center
выбран обязательно. Поэтому
\getdistance{\globalresultb}{current page.north east}{rightmid}
не компилируется, так как current page.north east
больше не является узлом. Но
\coordinate (A) at (current page.north east);
\getdistance{\globalresultb}{A}{rightmid}
компилируется, потому что (A)
это имя узла.
Какой тип вклада вы внесете, решать вам.\getdistance
вы можете обработать. Например, в TiкZ, \tikz@parse@node
может обрабатывать (X)
и (Y.Z)
. но не (1,2)
. В более общем смысле \tikz@@scan@@no@calculator
и обрабатывает (X)
, (Y.Z)
, и (1,2)
. Еще в более общем смысле \tikz@@@scan@@absolute
может обрабатывать ($ (current page.north east) + (0,-10cm) $)
. Вам нужно выбрать один.