在呈现文档时,可以将 tikz 坐标导出到文本文件吗?让文档为:
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\coordinate(vertexA) at (0, 10);
\coordinate(vertexB) at (5, 8);
\coordinate(vertexC) at (2.5, 0);
\end{tikzpicture}
\end{document}
我很高兴有一个文本文件,其中包含 tikz 中每个命名点的页码和绝对坐标。它可能看起来像这样:(表格格式仅用于说明,但并不重要。)
label | page | top | left | unit
--------+------+-----+------+------
vertexA | 1 | 128 | 54 | pt
--------+------+-----+------+------
vertexB | 1 | ... | ... | pt
--------+------+-----+------+------
vertexC | 1 | ... | ... | pt
最后,我想为我的学生创建测试表。他们应该通过填写小圆圈来回答多项选择题。通过了解圆圈的位置,我可以借助计算机程序扫描和检查结果表。(我知道如何进行机器视觉,但不知道如何在 tikz 中导出坐标。)
答案1
这会将缩放点(65536 sp = 1 pt)中的坐标保留在文件中.pos
:
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{calc}
\newwrite\posfile
\immediate\openout\posfile=\jobname .pos
\newcommand\coordpos[1]{%
\node at (#1) {\pdfsavepos\write\posfile{#1: \the\pdflastxpos, \the\pdflastypos}}
}
\begin{document}
\begin{tikzpicture}
\coordinate(vertexA) at (0, 10);
\coordinate(vertexB) at (5, 8);
\coordinate(vertexC) at (2.5, 0);
\coordpos{vertexA};
\coordpos{vertexB};
\coordpos{vertexC};
\end{tikzpicture}
\end{document}
导致
vertexA: 6830544, 49603716
vertexB: 16153939, 45874358
vertexC: 11492241, 30956926
答案2
与 David 的典型机智黑客相比,这是我的超级冗余答案(尽管只有我们努力才能打破他的计划)。但它不使用写入处理程序,而是.txt
通过以下方式更新文件pgfplotstable
我做了什么?
我开始更新 TikZ 图片计数器(虽然\pgfpictureid
也这样做,但我不想碰它)并且我还计算 TikZ 图片中的节点数以供以后使用。
在每个 TikZ 图片的末尾,我都会获取页码、节点原始名称及其顶部和左侧位置,并将其写入临时表。然后我将vertcat
上一个表写入pointlist.txt
。然后我用更新后的表重写该文件。我重置节点计数器并等待下一张图片。
如何使用
您relevant
将要启用录制的 TikZ 图片添加到相关图片中,并将atl
节点和坐标添加到其中。这样会在同一文件夹中生成一个 txt 文件,pointlist.txt
您也可以将其排版到 TeX 文件中,如下所示。
代码
\documentclass{scrartcl}
\usepackage{tikz,lipsum,pgfplotstable}
\usepackage[user]{zref}
\pgfplotsset{compat=1.8}
%======================= Here we go ==============================
\newcounter{mypiccount}\setcounter{mypiccount}{0}
\newcounter{mypointcount}\setcounter{mypointcount}{0}
\makeatletter
\tikzset{
relevant/.prefix style={
remember picture,
execute at begin picture={\zlabel{\pgfpictureid}},
execute at end picture={%
\pgfplotstableset{
create on use/label/.style={create col/assign/.code={
\edef\myentry{\expandafter\csname nnn\themypiccount\number\numexpr\pgfplotstablerow+1\relax\endcsname}
\pgfkeyslet{/pgfplots/table/create col/next content}{\myentry}
}
},
create on use/top/.style={create col/assign/.code={
\pgfpointdiff{\pgfpointanchor{current page}{north west}}%
{\pgfpointanchor{nnn-\themypiccount-\number\numexpr\pgfplotstablerow+1\relax}{center}}
\edef\myentry{\the\pgf@y}
\pgfkeyslet{/pgfplots/table/create col/next content}{\myentry}
}
},
create on use/left/.style={create col/assign/.code={
\pgfpointdiff{\pgfpointanchor{current page}{north west}}%
{\pgfpointanchor{nnn-\themypiccount-\number\numexpr\pgfplotstablerow+1\relax}{center}}
\edef\myentry{\the\pgf@x}
\pgfkeyslet{/pgfplots/table/create col/next content}{\myentry}
}
},
create on use/page/.estyle={create col/set={\zpageref{\pgfpictureid}}},
}%
\pgfplotstablenew[columns={label,page,top,left}]{\themypointcount}{\mytemptable}%
\ifnum\themypiccount>1\pgfplotstablevertcat{\mytemptable}{pointlist.txt}\else\fi%
\pgfplotstablesave[columns={label,page,top,left}]{\mytemptable}{pointlist.txt}
\pgfplotstableclear{\mytemptable}%
\setcounter{mypointcount}{0}%
},
execute at begin picture={%
\stepcounter{mypiccount}\setcounter{mypointcount}{0}%
}
},
atl/.style={/utils/exec={\stepcounter{mypointcount}},
alias={nnn-\themypiccount-\themypointcount},
append after command={\pgfextra{\expandafter\xdef\csname nnn\themypiccount\themypointcount\endcsname{\tikz@last@fig@name}}}
}
}
\makeatother
%======================= That was weird ==============================
\begin{document}
\begin{tikzpicture}[relevant]
\node[atl] (vertexA) at (0, 10) {A};
\node[atl] (vertexB) at (5, 8) {B};
\node (vertexC) at (2.5, 0) {C};
\end{tikzpicture}
\lipsum[1-6]
\begin{tikzpicture}[relevant]
\node[atl] (vertexA) at (0, 10) {A};
\node[atl] (vertexB) at (5, 8) {B};
\node[atl] (vertexD) at (2, 8) {D};
\node (vertexC) at (2.5, 0) {C};
\end{tikzpicture}
\begin{tikzpicture}[relevant]
\node[atl,circle] (vertexA) at (0, 10) {A};
\node[atl] (vertexB) at (5, 8) {B};
\node[atl] (vertexD) at (2, 8) {D};
\node (vertexC) at (2.5, 0) {C};
\end{tikzpicture}
\lipsum[1-3]
\begin{tikzpicture}[relevant]
\node[atl] (vertexB) at (5, 8) {B};
\node (vertexD) at (2, 8) {D};
\node[atl] (vertexC) at (2.5, 0) {C};
\end{tikzpicture}
\pgfplotstabletypeset[string type]{pointlist.txt}
\tikz[overlay,remember picture]{
\draw[thick,red] (current page.north west) -- ++(193.76636pt,-160.42473pt);
\draw[thick,blue] (current page.north west) -- ++(122.63449pt,-388.04668pt);
}
\end{document}
这给出
需要考虑的几点:
- 我已经删除了单位列,因为维度列的条目已经
pt
涉及(很好地尝试让坏事看起来很好:P) - 我做了一些糟糕的事情,比如在宏中使用数字等。但获取节点的原始名称总是无聊而糟糕。这可能是我真正不喜欢 TikZ 的少数事情之一。但这是一种设计选择,允许在节点名称中使用大量非字母字符。
由于某种原因,当我想初始化一个单行表时,它总是产生两行,我不知道为什么。不再相关。\thepage
正如 MWE 中所述,如果 TeX 认为图片太大并将其推到下一页,则有可能欺骗计数器。计数器仍然是 2,但图片在第 3 页。我记得用某个zref
模块修复了它,但我找不到它。- 如果您缩放图片,距离不会更新,因为我没有考虑转换,所以存在一些(更多)脆弱性。
要做的事情
删除包含条目的初始表格行现在可以对表格进行排序。-
。然后可以按页列进行排序。找到那个固定的zref
东西
答案3
这是一个解决方案,它创建了一个表格
<coordinate name> <picture id> <page> <x_pic> <y_pic> <x_cipic> <y_cipic> <x> <y>
在哪里
<coordinate name>
是坐标的名称;<picture id>
是图片的ID(随着每一个\pgfpicture
而增加的值,因此\tikzpicture
);<page>
是页码;<x_pic>
和<y_pic>
分别是图片原点的坐标<picture id>
;<x_cipic>
和<y_cipic>
分别是图片内部坐标的坐标;<x>
和<y>
分别是页面左下角坐标的坐标。
这需要remember picture
您想要保存坐标的图片。
此解决方案可以在任何图片之外使用。
代码
\documentclass{scrartcl}
\usepackage{tikz,etoolbox}
\makeatletter
\patchcmd\pgfpicture{\edef\pgfpictureid{pgfid\the\pgf@picture@serial@count}}{\edef\pgfpictureid{pgfid\the\pgf@picture@serial@count:\the\c@page}}{}{}
\tikzset{
export coordinates/.style 2 args={%
/utils/exec={\begingroup
\pgftransformreset
\immediate\openout\w@pgf@writea=#2\relax},
@export coordinates/.list={#1},
/utils/exec={\immediate\closeout\w@pgf@writea
\endgroup}},
@export coordinates/.code=\tikz@expc@export{#1}%
}
\def\tikz@expc@export#1{%
\expandafter\let\expandafter\pgf@temp\csname pgf@sh@pi@#1\endcsname
\expandafter\tikz@expc@split\pgf@temp\pgf@stop
\pgfsys@getposition{\csname pgf@sh@pi@#1\endcsname}\tikz@expc@original@picture%
\pgfextract@process\tikz@expc@original@picture{\tikz@expc@original@picture}%
\pgfextract@process\tikz@expc@coordinpic{\let\pgf@shape@interpictureshift\pgfutil@gobble\pgfpointanchor{#1}{center}}%
\tikz@expc@original@picture \pgf@xa\pgf@x \pgf@ya\pgf@y
\tikz@expc@coordinpic
\pgf@xb\pgf@x \pgf@yb\pgf@y \pgf@xc\pgf@x \pgf@yc\pgf@y
\advance\pgf@xc\pgf@xa \advance\pgf@yc\pgf@ya
%
\immediate\write\w@pgf@writea{#1 \tikz@expc@pid\space\tikz@expc@page\space
\the\pgf@xa\space\the\pgf@ya\space
\the\pgf@xb\space\the\pgf@yb\space
\the\pgf@xc\space\the\pgf@yc}}%
\def\tikz@expc@split pgfid#1:#2\pgf@stop{%
\def\tikz@expc@pid{#1}%
\def\tikz@expc@page{#2}}
\makeatother
\begin{document}
\begin{tikzpicture}[remember picture]
\coordinate[label=A](vertexA) at (0, 10);
\coordinate[label=B](vertexB) at (5, 8);
\coordinate[label=C](vertexC) at (2.5, 0);
\end{tikzpicture}
\tikzset{export coordinates={vertexA,vertexB,vertexC}{coordsA.dat}}
\pagebreak
\begin{tikzpicture}[remember picture]
\coordinate[label=A](vertexA') at (0, 10);
\coordinate[label=B](vertexB') at (5, 8);
\coordinate[label=C](vertexC') at (2.5, 0);
\end{tikzpicture}
\tikzset{export coordinates={vertexA,vertexB,vertexC,vertexA',vertexB',vertexC'}{coordsB.dat}}
\end{document}
输出coordsB.dat
vertexA 1 1 108.33208pt 461.03311pt 0.0pt 284.52744pt 108.33208pt 745.56055pt
vertexB 1 1 108.33208pt 461.03311pt 142.26372pt 227.62195pt 250.5958pt 688.65506pt
vertexC 1 1 108.33208pt 461.03311pt 71.13185pt 0.0pt 179.46393pt 461.03311pt
vertexA' 2 2 108.33208pt 461.03311pt 0.0pt 284.52744pt 108.33208pt 745.56055pt
vertexB' 2 2 108.33208pt 461.03311pt 142.26372pt 227.62195pt 250.5958pt 688.65506pt
vertexC' 2 2 108.33208pt 461.03311pt 71.13185pt 0.0pt 179.46393pt 461.03311pt
答案4
该方法\pdfsavepos
也已用于自动多项选择项目。也许你可以看看它的网站,并考虑加入该项目?它允许对问题和答案进行打乱,从扫描中获取结果,并生成带注释的完整答题纸。