\documentclass{article}
\ExpandArgs{c}\NewDocumentCommand{cmd_1_a}{m O{}}{123 #1 #2}
\def\?#1 {\csname#1\endcsname}
\begin{document}
\?cmd_1_a {4}[6]
\end{document}
命令名完成后加上一个空格。还有不加空格的方法(使用 \peek_analysis_map_inline:n
,不可展)。
\documentclass{article}
\ExpandArgs{c}\NewDocumentCommand{cmd_1_a}{m O{}}{123 #1 #2}
\def\?#1 {\csname#1\endcsname}
\begin{document}
\?cmd_1_a {4}[6]
\end{document}
命令名完成后加上一个空格。还有不加空格的方法(使用 \peek_analysis_map_inline:n
,不可展)。
\begingroup
\ctexset{section/afterskip=5cm}
\tableofcontents
\endgroup
应该用 \computegrad
的结果提取对应分量,你这个的模长不一样。
\documentclass[svgnames]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\begin{document}
\makeatletter
\newcommand\computegrad[4][0.00025]{% [delta], function, x, y
\begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\def\@tempdelta{#1}%
\pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
\pgfmathparse{#2(#3+\@tempdelta,#4)}\let\@temppxa\pgfmathresult
\pgfmathparse{#2(#3-\@tempdelta,#4)}\let\@temppxb\pgfmathresult
\edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
\pgfmathparse{#2(#3,#4+\@tempdelta)}\let\@temppya\pgfmathresult
\pgfmathparse{#2(#3,#4-\@tempdelta)}\let\@temppyb\pgfmathresult
\edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
\edef\@tempu{\fpeval{(\@temppx,\@temppy,-1)/sqrt(\@temppx^2+\@temppy^2+1)}}%
\edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
\def\noexpand\pgfmathresulta{\fpeval{1*(#3,#4,\@tempz)-\@tempu}}}%
\?}
\def\gradcomponent#1#2#3{%
\edef\pgfmathresult{\fpeval{#2+\expanded{\noexpand\gradcomponent@#1}{#3}}}}
\def\gradcomponent@(#1,#2,#3)#4{\ifcase
\if#4x 1 \else\if#4y 2 \else\if#4z 3 \else 4 \fi\fi\fi
\or (0,#2,#3)\or (#1,0,#3)\or (#1,#2,0)\else(#1,#2,#3)\fi}
%%%%%%%%%%%%%%%%%green
\newcommand\computegraf[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}}
%%%%%%%%%%%%%%%%%yellow
\newcommand\computegrag[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}%
\let\pgfmathresultb\pgfmathresult
\gradcomponent\pgfmathresult\pgfmathresulta{y}%
\let\pgfmathresulta\pgfmathresult \let\pgfmathresult\pgfmathresultb}
%%%%%%%%%%%%%%%%%red
\newcommand\computegrah[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}%
\let\pgfmathresultb\pgfmathresult
\gradcomponent\pgfmathresult\pgfmathresulta{x}%
\let\pgfmathresulta\pgfmathresult \let\pgfmathresult\pgfmathresultb}
%%%%%%%%%%%%%%%%%blue
\newcommand\computegral[4][0.00025]{\computegrad[#1]{#2}{#3}{#4}%
\let\pgfmathresultb\pgfmathresult
\gradcomponent\pgfmathresult\pgfmathresulta{z}%
\let\pgfmathresulta\pgfmathresult \let\pgfmathresult\pgfmathresultb}
\makeatother
\begin{tikzpicture}
[declare function={f(\x,\y)=0.6*sin(deg(\x))*cos(deg(\y);}]
\begin{axis}[scale=2,axis equal,view={0}{0},axis lines=center,axis on top,zmax=4.5,zmin=-1,samples=30,xlabel={$X$},ylabel={$Y$},zlabel={$F(x,y)$}]%ticks=none,
\addplot3[surf,color=DarkBlue,opacity=0.5,domain=0:2*pi, y domain=0:3,faceted color=black] {f(x,y)};
%%define P
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({0.7},{0.25},{f(x,y)})};
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({2.8},{0.5},{f(x,y)})};
%space vector
\draw[->,green,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegraf{f}{0.7}{0.25}} --\pgfmathresulta;
%y vector
\draw[->,yellow,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegrag{f}{0.7}{0.25}} --\pgfmathresulta;
%x vector
\draw[->,red,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegrah{f}{0.7}{0.25}} --\pgfmathresulta;
%z vector
\draw[->,blue,shorten <=0cm]({0.7},{0.25},{f(0.7,0.25)})\pgfextra{\computegral{f}{0.7}{0.25}} --\pgfmathresulta;
%%%
%space vector
\draw[->,green,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegraf{f}{2.8}{0.5}} --\pgfmathresulta;
%y vector
\draw[->,yellow,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegrag{f}{2.8}{0.5}} --\pgfmathresulta;
%x vector
\draw[->,red,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegrah{f}{2.8}{0.5}} --\pgfmathresulta;
%z vector
\draw[->,blue,shorten <=0cm]({2.8},{0.5},{f(2.8,0.5)})\pgfextra{\computegral{f}{2.8}{0.5}} --\pgfmathresulta;
\end{axis}
\end{tikzpicture}
\end{document}
需要自己计算在该点的法向量,但是 pgf 的计算精度不是很高,而且比较准确的数值算法会很慢。
\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usetikzlibrary{calc}
\usepgfplotslibrary{colormaps,fillbetween}
\makeatletter
\newcommand\computegrad[4][0.00025]{% [delta], function, x, y
\begingroup\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\def\@tempdelta{#1}%
\pgfmathparse{#2(#3,#4)}\let\@tempz\pgfmathresult
\pgfmathparse{#2(#3+\@tempdelta,#4)}\let\@temppxa\pgfmathresult
\pgfmathparse{#2(#3-\@tempdelta,#4)}\let\@temppxb\pgfmathresult
\edef\@temppx{\fpeval{(\@temppxa-\@temppxb)/(2*\@tempdelta)}}%
\pgfmathparse{#2(#3,#4+\@tempdelta)}\let\@temppya\pgfmathresult
\pgfmathparse{#2(#3,#4-\@tempdelta)}\let\@temppyb\pgfmathresult
\edef\@temppy{\fpeval{(\@temppya-\@temppyb)/(2*\@tempdelta)}}%
\edef\@tempu{\fpeval{(\@temppx,\@temppy,-1)/sqrt(\@temppx^2+\@temppy^2+1)}}%
\edef\?{\endgroup\def\noexpand\pgfmathresult{\@tempu}%
\def\noexpand\pgfmathresulta{\fpeval{(#3,#4,\@tempz)+\@tempu}}}%
\?}
\makeatother
\begin{document}
\begin{tikzpicture}[declare function={f(\x,\y)=0.8*sin(deg(\x))+1.2*ln(\y);}]
\begin{axis}[axis equal image,view={-45}{15},
domain=-2:5,y domain=0:5,samples=20,axis lines=center,axis on top,
xmax=6,ymax=8,zmax=4,xmin=-2,ymin=-1,zmin=-2.5,
xlabel=\tiny $X$,ylabel=\tiny $Y$,zlabel=\tiny $Z$]
\addplot3[colormap/bone,surf,z buffer=sort,] (x,y,{f(x,y)});
%%define P
\addplot3+ [mark=ball,mark size=2pt,scatter src=rand,ball color=yellow!80!black!60]
coordinates {({0.25*pi},{3},{f(x,y)})};
\draw[->,shorten <=-1cm] ({0.25*pi},{3},{f(0.25*pi,3)})
\pgfextra{\computegrad{f}{0.25*pi}{3}} -- \pgfmathresulta;
\draw[red,->,shorten <=-1cm] (0.785398, 3., 1.88402)--(1.35108, 3.4, 0.88402);
\end{axis}
\end{tikzpicture}
\end{document}
看看你的电脑上是否有这个文件夹:
c:\texlive\2024\texmf-dist\xindy\modules
可以保存切点和向量终点的坐标,然后利用 perpendicular 坐标系统即可画出。
\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{decorations.markings}
\makeatletter
\def\my@tangentparse#1{\in@{ at}{#1}%
\ifin@\my@tangentparse@#1\@nil\else\my@tangentparse@ last at#1\@nil\fi}
\def\my@tangentparse@#1 at#2\@nil{\pgfkeysalso{postaction=decorate,
decoration = { % 对path进行装饰(decorate)
markings, % 启用marking
mark = at position #2 % 在指定位置#1添加marking
with{ % marking的具体内容
% 定义(0, 0)为tangent point xxx,即切点
\coordinate (tangent point #1) at (0, 0);
% 定义(1, 0)为tangent unit vector xxx,即单位切向量
\coordinate (tangent unit vector #1) at (1, 0);
% 定义(0, 1)为tangent orthogonal unit vector xxx,即单位法向量
\coordinate (tangent orthogonal unit vector #1) at (0, 1);
}
},
}}
\tikzset{
tangent/.code = \my@tangentparse{#1},
use tangent/.style = { % 定义use tangent样式,参数#1是切点的序号
shift = (tangent point #1), % 以tangent point-xxx为原点
x = (tangent unit vector #1), % 以tangent unit vector-xxx为x轴单位向量
y = (tangent orthogonal unit vector #1)% 以tangent orthogonal unit vector-xxx为y轴单位向量
},
use tangent/.default = last,
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw[->] (-1,0) -- (3,0) node[anchor=south east]{$x$};
\draw[->] (0,-1) -- (0,2) node[anchor=south west]{$y$};
\draw[tangent=A at 0.65,tangent=B at 0.8] (0, 0) .. controls (1, 0) and (1, 1) .. (2, 0.5);
\fill[use tangent=A] circle(1pt) node[below=1] {$p$};
\draw[black!20,use tangent=A] (-1.5, 0) -- (1.5, 0);%切线
\draw[->, use tangent=A] (0, 0) -- (0, 1) coordinate(L) node[scale=0.4,above=2] {$vector$}; %法线
\draw[dotted,black!10, shorten <=-1cm] (L) -- (0,0 |- L); %辅助线
\draw[dotted,black!10] (L) -- (0,0 -| L); %辅助线
\draw[red,->] (tangent point A) -- (L |- tangent point A);
\draw[red,->] (tangent point A) -- (L -| tangent point A);
\draw[->, use tangent=B] (0, 0) -- (0, 1) coordinate(L);
\draw[red,->] (tangent point B) -- (L |- tangent point B);
\draw[red,->] (tangent point B) -- (L -| tangent point B);
\end{tikzpicture}
\end{document}
在导言区加上 \usefonttheme{professionalfonts}
。可以放在 \usepackage{mtpro2}
前一行。
如果没有递增计数器,\ref
显示为空,hyperref
不会为空的文本创建超链接。
只能使用 \hyperref[<label>]{<text>}
或 \pageref
。
也可以在写入 \label
时就指定需要显示的文字:
\documentclass{article}
\usepackage{tcolorbox}
\usepackage{hyperref}
\tcbuselibrary{skins,minted}
%% 重定义minted环境前的行号样式
\renewcommand{\theFancyVerbLine}
{%
\ttfamily\textcolor[rgb]{0.5,0.5,1.0}
{%
\footnotesize\arabic{FancyVerbLine}
}
}
\makeatletter
\protected\def\setnextlabeltext#1{\AddToHookNext{label}{\protected@edef\@currentlabel{#1}%
\edef\@currentlabel{\detokenize\expandafter{\@currentlabel}}}}
\makeatother
\newcounter{myexample}
\NewTCBListing{myjava}{O{} O{}}{%
listing engine = minted,
minted style = colorful,
minted language = java,
%minted label =#1
minted options={%
fontsize = \small,
breaklines,
autogobble,
linenos,
numbersep = -1.5mm,
%numbersep = 3pt,
keywordcase = lower, % 关键字小写, upper为大写, capitalize为首字母大写, 默认为lower
mathescape = true, % 在注释中可以书写并渲染数学公式
showspaces = false,
tabsize = 4,
texcomments = false,
%framerule = 1pt,
%breaklines = true,
fontfamily = tt,
},
%colback = blue!5!white,
%colframe = blue!75!black,
colback = white,
colframe = black,
colbacktitle=white,
coltitle=black,
listing only,
left = 5mm,
enhanced,
overlay = {\begin{tcbclipinterior}\fill[red!20!blue!20!white] (frame.south west)
rectangle ([xshift = 5mm]frame.north west);\end{tcbclipinterior}},
attach boxed title to top center = {yshift =-3mm},
center title,
%IfValueTF = {#1}{title=#1}{step=myexample, title=code:\themyexample},
IfEmptyTF = {#1}{% 第一个没有值
step=myexample, title=code:\themyexample,
IfEmptyTF={#2}{label=code:\themyexample}{label={#2}}
}{% 第一个有值
title={#1}, IfEmptyTF={#2}{}{phantom=\setnextlabeltext{#1},phantomlabel={#2}}
},
fonttitle = \ttfamily\large,
boxrule=0.75pt,
boxed title style={
boxrule=0pt,
colframe=white,
size = fbox,
},
%frame hidden
%boxed title style={arc=0pt,outer arc=0pt,boxrule=0pt},
}
\begin{document}
\begin{myjava}[test][aaa]
public class HelloWorld {
// A `Hello World' in Java
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
\end{myjava}
\begin{myjava}
public class HelloWorld {
// A `Hello World' in Java
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
\end{myjava}
a\hyperref[aaa]{text}.\pageref{aaa}.\ref{aaa}.\ref{code:1}.
\end{document}
这个 \setnextlabeltext
也可以在递增计数器之后,\label
之前使用。
microtype
的多数功能只是对 primitive 的封装,XeTeX 缺少对应的 primitive,很多功能没法实现。
某些功能有替代办法,比如 \textls
可以通过设置 fontspec
的选项 WordSpace
、LetterSpace
为合适的值来替代。
\documentclass{..}
\usepackage{morewrites}
...
或
\RequirePackage{morewrites}
\documentclass{..}
morewrites
要放在很前面才能有效。
这是右边页码宽度增加了,但是 logo 和页码的距离不变,所以 logo 往左移了一点。
如果使用 fancyhdr
,titleps
等,应该对左、中、右的页眉分别设置,而不是设置一个固定长度。
封面和目录应当设置 nomarginpar
。\fancyhfoffset
只有 fancyhdr
定义的 pagestyle 才有用,必须用 \fancypagestyle
重新定义 plain 样式。
每次修改 geometry 都要重新设置 \fancyheadoffset
和 \fancyfootoffset
,否则页眉页脚的位置可能不对。
使用 positioning
库可以以相对位置排布 node,容易排出第二行。之后使用使用第二行的宽度与第三行单个 node 的宽度可以计算出第三行 node 之间的间距,然后用和第二行一样的方法即可。
字体为 霞鹜文楷:https://github.com/lxgw/LxgwWenKai 。
\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{positioning,decorations.pathreplacing,shapes.misc,arrows.meta}
\usepackage{ctex}
\setCJKmainfont{LXGW WenKai} % https://github.com/lxgw/LxgwWenKai
\begin{document}
\definecolor{col1}{HTML}{4faabc}
\definecolor{col2}{HTML}{e26a6f}
\definecolor{col3}{HTML}{4eab93}
\definecolor{col4}{HTML}{b85f84}
\makeatletter
\newcommand\tvtext[2]{\pgfmathparse{#1}\vbox to\pgfmathresult\p@{\vss\hsize=1em#2\vss}}
\newcommand\getsepoffixedwidth[5]{%
\begingroup
\pgf@process{\path#1;}\pgf@xa=\pgf@x
\pgf@process{\path#2;}\pgf@xb=\pgf@x
\pgf@process{\path#3;}\pgf@xc=\pgf@x
\pgfmathparse{(\pgf@xb-\pgf@xa-(#4)*2*(\pgf@xc-\pgf@xa))/(#4-1)}%
\edef\x{\endgroup\def\noexpand#5{\pgfmathresult pt}}\x}
\makeatother
\begin{tikzpicture}[
l0style/.style={draw=#1,thick,rectangle,rounded corners=3pt},
l1style/.style={l0style=#1,text width=76pt,align=center},
l2style/.style={l0style=#1,text width=76pt,align=center},
l3style/.style={l0style=#1,text height=76pt,inner xsep=5pt},
llstyle/.style={draw=#1,thick,-Latex},
]
% level 1
\node(l1) [l1style=col1] at (0,0) {电磁学};
% level 2 node 2
\node(l2-2) [below left=7pt and 3pt of l1.south, l2style=col2] {基础:实验定律};
\node(l2-1) [left=6pt of l2-2.west, l2style=col1] {方法:归纳法};
\node(l2-3) [right=6pt of l2-2.east, l2style=col3] {核心:四大定理};
\node(l2-4) [right=6pt of l2-3.east, l2style=col4] {线索:相互作用};
\def\TV#1{\tvtext{76pt}{\linespread{1}\selectfont \noindent#1}}
\node(l3-1) [below right=15pt and 0pt of l2-1.south west, l3style=col1]{\TV{现象到本质}};
\getsepoffixedwidth{(l2-1.west)}{(l2-4.east)}{(l3-1.center)}{13}{\sep}
\node(l3-2) [right=\sep of l3-1, l3style=col1]{\TV{特殊到一般}};
\node(l3-3) [right=\sep of l3-2, l3style=col2]{\TV{库伦定律}};
\node(l3-4) [right=\sep of l3-3, l3style=col2]{\TV{安培定律}};
\node(l3-5) [right=\sep of l3-4, l3style=col2]{\TV{电磁感应定律}};
\node(l3-6) [right=\sep of l3-5, l3style=col3]{\TV{电场高斯定理}};
\node(l3-7) [right=\sep of l3-6, l3style=col3]{\TV{电场环路定理}};
\node(l3-8) [right=\sep of l3-7, l3style=col3]{\TV{磁场高斯定理}};
\node(l3-9) [right=\sep of l3-8, l3style=col3]{\TV{磁场环路定理}};
\node(l3-10) [right=\sep of l3-9, l3style=col4]{\TV{物质与电场}};
\node(l3-11) [right=\sep of l3-10, l3style=col4]{\TV{物质与磁场}};
\node(l3-12) [right=\sep of l3-11, l3style=col4]{\TV{电场与磁场}};
\node(l3-13) [right=\sep of l3-12, l3style=col4]{\TV{磁场与电场}};
\path[decorate,decoration={brace,amplitude=7pt},draw=col1,thick] (l2-1.north) -- (l2-4.north);
\begin{scope}[shorten >=-.4pt]
\foreach \i in {1,2} \path[llstyle=col1](l2-1.south)--(l3-\i.north);
\foreach \i in {3,...,5} \path[llstyle=col2](l2-2.south)--(l3-\i.north);
\foreach \i in {6,...,9} \path[llstyle=col3](l2-3.south)--(l3-\i.north);
\foreach \i in {10,...,13} \path[llstyle=col4](l2-4.south)--(l3-\i.north);
\end{scope}
\end{tikzpicture}
\end{document}
\foo 1 2 {}
得到的是 *1, 2 *
,而不是 *1,2*
。
TeX 宏的参数有两种,一种是没有分隔符的参数(或定界符,undelimited parameter),另一种是有分隔符的参数(delimited parameter)。参数的分隔符就是两个参数之间的记号,是标记参数结束的一些符号。
TeX 在开始读取 undelimited parameter 时,会忽略空格,之后如果发现第一个记号是 begin-group character,则认为这个参数是由一对括号包裹(可以认为 {
标记参数的开始位置,}
标记结束位置,它们不会在最终的参数里出现),否则这个参数就是遇到的第一个非空格记号。
读取 delimited parameter 时,不会忽略空格,这个参数由指定的定界符来标记结束的位置(定界符必须与定义时的完全匹配),并且 {}
需要正确嵌套,并且如果结果是一对正确嵌套的组,则最外层的括号不会出现在实参中。在这两种情况中,{
可以是任意 catcode 为 1 的字符(即 begin-group character),}
可以是任意 catcode 为 2 的字符(即 end-group character)。
macro parameter(catcode=6 的字符或被 let 为这些字符的控制序列,一般是 #
) + begin-group character 可以看成是一个特殊的定界符,只能放在最末尾。在匹配时,begin-group character 必须和定义时使用的字符完全一致。
如假定 [
和 {
的 catcode 都为 1,则 \def\foo#1#[...}
在使用时也必须是 \foo aaa[...
,不能是 \foo aaa{...
。
了解这些之后,答案就很清楚了。\def\foo#1#2#{...}
,第一个参数是 undelimited parameter,第二个参数由 {
定界,#1
是 1
,#2
分别是 2
和空。
需要注意的是,TeX 在读取一个控制词(如 \a
、\foo
是控制词,\;
是控制符,它们都是控制序列)会忽略它后面的空格,所以 \foo␣␣
等于 \foo␣
等于 \foo
。如前所述,macro parameter 可以是字符,也可以是控制序列,如
\let\pp#
\def\foo#1\pp2{\pp1,#2}
\def\foo#1#2{#1,#2}
两种完全一致。
空格只比较 catcode,不比较 charcode,TeX 在读取输入文本时,所有的 catcode=10 的字符都会变成 charcode=32, catcode=10 的记号。
更详细的内容可以参考 The TeXBook 第 20 章。
l3draw
相当于 pgf
中最基本的部分。tikz
的作用是把绘图代码转换为 pgf
宏。本问题相当于是说重新实现 tikz
。
pgf 的一个 node 有形状、锚点、文字,还可以被保存。这些代码是很多的。
如果只要实现文字旋转和指定到某一位置,用 l3draw
提供的几个 transform 命令即可,文字使用 box 或 coffin 皆可。要指定锚点则需要自己计算文字的尺寸,然后再根据它来计算平移变换需要设置的向量。
\documentclass{article}
\usepackage{l3draw}
\usepackage{tikz}
\begin{document}
\ExplSyntaxOn
\draw_begin:
\draw_path_moveto:n { 0cm , 0cm }
\draw_path_use_clear:n { }
\group_begin:
\draw_transform_rotate:n { 30 }
\draw_transform_shift:n { 1cm , 3cm }
\hbox_set:Nn \l_tmpa_box { A }
\draw_box_use:N \l_tmpa_box
\group_end:
\draw_end:
\ExplSyntaxOff
\tikz{
\path (0,0);
\node[rotate=30,inner sep=0pt,outer sep=0pt,anchor=south west] at (1,3) {A};
}
\end{document}
可以参考 pgfmanual
或者相关笔记:https://ask.latexstudio.net/ask/article/175.html ,pgf 的 node 在该笔记的第二十五章。
问 如何使用 LaTeX3自定义一个命名中包含特殊字符的命令