Month
- Error linked to active characters?by Bibi on November 13, 2025 at 5:46 pm
This MWE gives an error that disappears if line #3 or line #4 are commented. I would say that this has probably something to do with active characters, but I am not able to understand what goes wrong here. Any help? \documentclass[9pt, professionalfont]{beamer} \usepackage{pgfplots} \usepackage[french]{babel} % No error if this line (or the next one) is commented \usetikzlibrary{babel} \begin{document} \begin{frame} \begin{overlayarea}{\textwidth}{5cm} \only<1>{ \begin{center} \begin{tikzpicture} \begin{axis} \addplot {x^2+4}; \end{axis} \end{tikzpicture} \end{center} } \end{overlayarea} \end{frame} \end{document}
- How to avoid \big having more space than \left?by allo on November 13, 2025 at 4:03 pm
When using \big instead of \left \right I get some unwanted extra space. Example: \documentclass{article} \usepackage{amsmath} \usepackage{stix} \begin{document} \begin{align*} \big\langle \star \hat A \big\rangle \\ % Bad \left\langle \star \hat A \right\rangle % Good \end{align*} \end{document} I want to use \big, because in my more complicated equation \left \right would cause larger angles to be used that look worse than using \big for my equation.
- How come when filling in TikZ, there is a visible gap between adjacent fills?by Jasper on November 12, 2025 at 1:00 am
How come when filling in TikZ, there is a visible gap between adjacent fills? \documentclass[tikz,border=1cm]{standalone} \begin{document} \begin{tikzpicture} \fill (0,0) -- (1,1) -- (1,0) -- cycle; \fill (0,0) -- (1,1) -- (0,1) -- cycle; \end{tikzpicture} \end{document}
- How to distribute TikZ pics along entire path consisting of multiple subpaths?by dsacre on November 11, 2025 at 7:25 pm
Assume the following: One wants to distribute (ideally: equally by length) TikZ pics along a path consisting of multiple subpaths. MWE \documentclass[border=5pt]{standalone} \usepackage{tikz} % DESCRIPTION: Definition of picture for positioning along the path \tikzset{ mypic/.pic={ \path[fill=cyan](0,0)circle(5pt); } } \begin{document} \begin{tikzpicture} \path[draw=black] (0,0)--++(0,2.5) arc(0:180:5) --++(0,-2.5) arc(180:360:5) % DESCRIPTION: Distributes pictures only on last part of path foreach \t in {0, 0.125, ..., 1}{ pic[pos=\t]{mypic} } ; \end{tikzpicture} \end{document} Result Goals Distribute pics along complete path (without copy pasting the foreach construct to each subpath) Achieve equal distribution by length over the whole path Question Is there a way to achieve this with plain TikZ or a TikZ library? Ideally, the solution should be as programmatically as possible, since it is intended to be used in an animation later on.
- Why does activating tagging in a footnote-heavy document increase the PDF file size much more with lualatex than with pdflatex?by Senex on November 11, 2025 at 11:32 am
The file below generates a 70 page "lorem ipsum" file with ~5–10 footnotes per page. Activating tagging (just changing tagging=off to tagging=on) produces a much larger increase in PDF file size when compiling with lualatex compared with pdflatex, although the output of show-pdf-tags seems to indicate that the tagging structure is actually smaller for lualatex. pdflatex lualatex tagging=off PDF size 297kB 270kB tagging=on PDF size 529kB 870kB relative size of PDFs 1.78 3.22 show-pdf-tags output size 929kB 810kB If I remove the \footnote command, so that everything appears as body text, the difference is much smaller: Engine pdflatex lualatex tagging=off PDF size 206kB 231kB tagging=on PDF size 326kB 397kB relative size of PDFs 1.58 1.71 show-pdf-tags output size 357kB 359kB These results are from an up-to-date TeX Live 2025. So: (1) What is going on? (2) Is it possible to reduce the file size produced by lualatex? (Is there some setting I should have applied?) (I understand that tagging is under active development and this might be a transient issue. I noticed this when converting a private book style to be tagging-compatible.) Code for the document: \DocumentMetadata{ pdfversion=2.0, pdfstandard=UA-2, lang=la, tagging=off, } \documentclass{book} \ExplSyntaxOn \cs_new:Npn\generatecomplexfile { \int_zero:N\l_tmpa_int \int_do_until:nNnn{\l_tmpa_int}>{500}{ \int_incr:N\l_tmpa_int \group_begin: \int_set:Nn\l_tmpa_int{\int_mod:nn{\l_tmpa_int}{100}+1} \int_set:Nn\l_tmpb_int{\int_mod:nn{\l_tmpa_int}{19}+1} \lipsum_aux:ee{\int_use:N\l_tmpa_int}{\int_use:N\l_tmpb_int} \footnote{\lipsum_aux:ee{\int_use:N\l_tmpa_int}{1}}~ \par \group_end: } } \cs_new:Npn\lipsum_aux:nn #1#2 { \lipsum[#1][1-#2] } \cs_generate_variant:Nn\lipsum_aux:nn{ ee } \ExplSyntaxOff \usepackage{lipsum} \begin{document} \generatecomplexfile \end{document}
- How can I use a counter with a dynamically-created name in Latex Expl3?by Jean-Louis Brabant on November 10, 2025 at 6:55 am
I am new to Expl3 and would like to be able to use a counter by retrieving its name dynamically, performing this operation within a user command for other stuff. I am unable to display the counter value. I may be making a beginner's mistake, but I don't know where it might be... Here is the minimal example I am working on : \documentclass{article} \ExplSyntaxOn % declare counter \int_new:N \g_strxdiv_leveliv_division_count_int % initialize counter \int_gset:Nn \g_strxdiv_leveliv_division_count_int { 1 } % Construct the counter name dynamically \cs_new:Npn \__strxgen_construct_counter_name:nn #1% first variable part #2% second variable part { g_strx#1_#2_count_int % used as-is, \__strxgen_construct_counter_name:nn { div } { leveliv } gives the correct name ('g_strxdiv_leveliv_count_int') } % For user purposes \NewDocumentCommand\Test { m m } { \int_use:c { \__strxgen_construct_counter_name:nn { #1 } { #2 } } % <other stuff should be placed here using the counter once "reconstructed"> } \ExplSyntaxOff \begin{document} \Test{div}{leviv} % displays the error messg 'You can't use '\relax' after the. (...)' ) % Thinking it was an expansion issue with \int_use:c, I've tried with \exp_args:... without more success. \end{document} Thank you so much for your help.
- Simplified space-separated vector macro not workingby Hugh on November 9, 2025 at 4:03 pm
I'm trying to write a macro that allows me to turn something like this: \vec{12 12 12} ...into something like this: \begin{bmatrix}12 \\ 12 \\ 12\end{bmatrix} Here is the code I wrote for it: \renewcommand{\vec}[1]{\begin{bmatrix}{\vecHelper#1}\end{bmatrix}} \newcommand{\vecHelper}[1]{#1\@ifnextchar\@sptoken{\\\vecHelper}{\@ifnextchar\egroup{}{\vecHelper}}} The idea is to keep parsing characters one at a time, adding \\ upon seeing a space and terminating the recursion upon the end of the input (in this case, seeing an \egroup). When I then try writing: $$\vec{12 12 12}$$ it actually displays correctly: However, I get the following error messages (I use Overleaf): I suspect the issue has something to do with the ending brace not being there at some point when it is supposed to, but I'm not sure when or why and I'm not sure how to fix it. In case it's of any use, I tried adding debugging characters to my macro to see if it was functioning correctly, and I didn't see any issues: \renewcommand{\vec}[1]{\begin{bmatrix}{\vecHelper#1}\end{bmatrix}} \newcommand{\vecHelper}[1]{#1\@ifnextchar\@sptoken{a\\\vecHelper}{b\@ifnextchar\egroup{c}{d\vecHelper}}} $$\vec{12 12 12}$$ This also gives the same errors as above. Thank you all for your time.
- beautification of a block matrixby RIPAN DAS on November 9, 2025 at 3:21 pm
I am looking for suggestions on how to improve the visual presentation of a block matrix I created in LaTeX. I'm hoping to "beautify" it and make it easier to read. Here is the code: \documentclass{article} \usepackage{amsmath} \newcommand{\bigzero}{\mbox{\normalfont\Large\bfseries 0}} \newcommand{\rvline}{\hspace*{-\arraycolsep}\vline\hspace*{-\arraycolsep}} \begin{document} \[ \begin{bmatrix} \begin{matrix} \dfrac{\partial \tilde{x}_1}{\partial x_1}(x) &\cdots & \dfrac{\partial \tilde{x}_1}{\partial x_n}(x)\\ \vdots &\ddots &\vdots \\ \dfrac{\partial \tilde{x}_1}{\partial x_1}(x) &\cdots & \dfrac{\partial \tilde{x}_1}{\partial x_n}(x) \end{matrix} & \rvline & \bigzero \\ \hline \bigzero & \rvline & \begin{matrix} \dfrac{\partial \tilde{x}_1}{\partial x_1}(x) &\cdots & \dfrac{\partial \tilde{x}_1}{\partial x_n}(x)\\ \vdots &\ddots &\vdots \\ \dfrac{\partial \tilde{x}_1}{\partial x_1}(x) &\cdots & \dfrac{\partial \tilde{x}_1}{\partial x_n}(x) \end{matrix} \end{bmatrix} \] \end{document} as you can see, there is no gap between the horizontal line and the rows just above and below it. i want to make it better and look beautiful and if possible some more beautification.
- Bracket covers sum limits using mathclap environmentby mlg on November 9, 2025 at 12:09 pm
I have the following code: \documentclass{article} \usepackage{mathtools} \begin{document} \[S_1 = \frac{1}{2} \left(\sum_{\mathclap{i = n + 1}}^{n + m} a_i t_i \right)\] \end{document} And it produces this output: As you can see, the bracket partially covers the lower sum limit. How can I avoid this?
- TikZ: How to draw a 3D shape by defining its 2D cross-section and 3D path?by Diaa on November 8, 2025 at 12:24 pm
For the following, I would like to draw a 3D shape by sweeping the cross-section (i.e., rectangle or circle) along the 3D path from its start to end coordinates, while having, if possible, the option to draw the hidden edges as dashed lines based on the 3d view view angles control the smoothness of connectivity at vertices (getting right-angled bends or curved ones). \documentclass[tikz,border=10pt]{standalone} \usepackage{tikz} \usetikzlibrary{3d,calc,perspective} \begin{document} \begin{tikzpicture}[3d view={140}{40}] \begin{scope}[->, black, thin] \draw (0,0,0)-- (3,0,0) node[anchor=north east]{$x$}; \draw (0,0,0) -- (0,3,0) node[anchor=north west]{$y$}; \draw (0,0,0) -- (0,0,3) node[anchor=south]{$z$}; \end{scope} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \coordinate (start1) at (3,1,2); \coordinate (end1) at (3,1,-2); \draw[canvas is xy plane at z=2, fill=blue!10] ($(start1) - (0.25,0.5)$) rectangle ($(start1) + (0.25,0.5)$); \coordinate (v1) at ($(start1)+(0,0,1)$); \coordinate (v2) at ($(v1)+(-2,0,0)$); \coordinate (v3) at ($(v2)+(0,0,-6)$); \coordinate (v4) at ($(v3)+(2,0,0)$); \draw[blue] (start1) -- (v1) -- (v2) -- (v3) -- (v4) -- (end1); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \coordinate (start2) at (-3,1,2); \coordinate (end2) at (-3,1,-2); \draw[canvas is xy plane at z=2, fill=red!10] (start2) circle (0.25); \coordinate (v11) at ($(start2)+(0,0,1)$); \coordinate (v22) at ($(v11)+(2,0,0)$); \coordinate (v33) at ($(v22)+(0,0,-6)$); \coordinate (v44) at ($(v33)+(-2,0,0)$); \draw[red] (start2) -- (v11) -- (v22) -- (v33) -- (v44) -- (end2); \end{tikzpicture} \end{document}
- How can I get \enumerate to use Chinese numerals instead of Arabic ones?by neruneru on November 7, 2025 at 5:22 pm
I'm trying to set up \enumerate to use Chinese numerals (一,二,三,四……) using the zhnumber package. The effect I'm trying to achieve is this: Desired Output: The package zhnumber provides a macro to convert counters into Chinese numerals, \zhnum, and I tried using it with the enumi counter and the label option in the enumitem package. However, it looks like what happens is the label computes once when the counter is 0 instead of with every new instance of \item. This is the MWE and output: Code: \documentclass{ltjtarticle} \usepackage{zhnumber} \usepackage{enumitem} \begin{document} \begin{enumerate}[label=(\zhnum{enumi})] \item 道可道,非常道。 \item 名可名,非常名。 \item 無名天地之始。 \item 有名萬物之母。 \item 故常無欲,以觀其妙。 \item 常有欲,以觀其繳。 \end{enumerate} \end{document} Actual Output: Here, 零 is the Chinese numeral for 0. This is not the case, for instance, if you use label=\arabic{enumi}, which works as expected: I am using the ltjtarticle document class which calls the luatex-jp package (and compiles with LuaLaTeX), since I need this to typeset other things in my document. If anyone has any idea how I can fix this problem please let me know! I'm willing to use packages that aren't zhnumber but they need to be compatible with luatex-jp and ltjtarticle (ctex doesn't seem to work, for example). PS: Incidentally, is there a way to use fullwidth Arabic numerals with enumitem? In this vertical document, the fullwidth Arabic numerals would not rotate like the halfwidth ones.
- Book design with TikZby Francesco Sieni on November 7, 2025 at 10:25 am
there's a way to desgin a book cover like this one? MWE The only thing i managed to do were the frames \documentclass{book} \usepackage[paperwidth=115mm, paperheight=195mm]{geometry} \usepackage{tikz} \usepackage{tikzpagenodes} \usetikzlibrary{calc} \begin{document} \thispagestyle{empty} %external frame \tikz[overlay,remember picture]\draw($(current page.north east)+(-1.0cm,-1.0cm)$)--($(current page.north west)+(1.0cm,-1.0cm)$)--($(current page.south west)+(1.0cm,1.0cm)$)--($(current page.south east)+(-1.0cm,1.0cm)$)--cycle; %inside \tikz[overlay,remember picture]\draw($(current page.north east)+(-1.1cm,-1.1cm)$)--($(current page.north west)+(1.1cm,-1.1cm)$)--($(current page.south west)+(1.1cm,1.1cm)$)--($(current page.south east)+(-1.1cm,1.1cm)$)--cycle; \end{document} It doesn't matter if the color of the page (in this case black) because then I would like to invert it (i.e. white page and black frames,) Can you help me? Thank you very much!
- Is excludeonly still working? (TeXlive 2025)by Markus Nißl on November 7, 2025 at 8:38 am
I came across excludeonly with this question: Is there an \exclude option? Is excludeonly still working? I'm using 2003/03/14 v1.0 with TeXlive 2025. This next minimal example has file b.tex in the generated output. I only want files a.tex and c.tex in the output. \documentclass{article} \usepackage{excludeonly} \excludeonly{b} \begin{document} \include{a} \include{b} \include{c} \end{document} What am I doing wrong? Or what am I misunderstanding?
- "Hanging" corners on Tikz diagramby pwesterbaan on November 6, 2025 at 7:23 pm
I'm creating a diagram of an open box using Tikz: \documentclass[margin=5pt, convert={density=1000, size=10000}]{standalone} \usepackage{tikz} \usetikzlibrary{calc} \pagecolor[RGB]{255,255,255} \begin{document} % H-------G % /| /| % / | / | % / E----/--F % / / / / % D-------C / % | / | / % |/ |/ % A-------B \begin{tikzpicture}[ declare function={ wdth=4.35; hgt=2; x_offset=2.75; y_offset=2.75;} ] \coordinate (A) at (0,0); \coordinate (B) at (wdth,0); \coordinate (C) at (wdth,hgt); \coordinate (D) at (0,hgt); \coordinate (E) at ($(A)+(x_offset, y_offset)$); \coordinate (F) at ($(B)+(x_offset, y_offset)$); \coordinate (G) at ($(C)+(x_offset, y_offset)$); \coordinate (H) at ($(D)+(x_offset, y_offset)$); \draw[fill=black!15, line width=1pt] (A) -- (B) -- (F) -- (E) -- cycle; \draw[line width=1pt] (E) -- (F) -- (G) -- (H) -- cycle; \draw[fill=white, line width=1pt] (A) -- (E) -- (H) -- (D) -- cycle; \draw[fill=white, line width=1pt] (B) -- (F) -- (G) -- (C) -- cycle; \draw[fill=white, line width=1pt] (A) -- (B) -- (C) -- (D) -- cycle; \draw[dotted] (A) -- (E) -- (F); \end{tikzpicture} \end{document} The problem I'm having is that the lines protrude where the corners meet (likely because my line width=1pt). How do I draw this diagram without the "hanging" bits at the corners?
- Want to use LaTeX for Studentsby GowriSaro on November 6, 2025 at 6:03 am
The students don’t have knowledge of TeX but they want to use it. I heard that BakomaTeX has a facility to use LaTeX even the user doesn’t have knowledge of TeX, but I wasn’t able to use it. (The actual problem is that I’m not able to get much information regarding BakomaTeX.) Please refer me to any free LaTeX tool which is more user friendly, so that it’s more likely that the students are going to use it. I can train the students to the basic level of TeX, but what I’m looking for is something based on the WYSIWYG principle, like BakomaTeX.
- Iterated plot with TikZ, PGFPlots and foreach loopby Dominique on November 5, 2025 at 4:31 pm
I'm trying to plot an illustration of the fixed point method in which a function is evaluated repeatedly in a loop. The result should be a staircase or spiral plot on top of the plot of the function itself. I've read here about the use of \edef inside a foreach loop. The following MWE should show what I'm trying to do, but it seems to only perform a single iteration. Notes: the loop variable isn't used inside the loop. perhaps it's an illusion that only single iteration is performed and the real issue is that \xprev and \xnext aren not updated at each pass through the loop. I tried placing the updates inside the \edef, but that gives an undefined control sequence error. I also tried \pgfplotsinvokeforeach instead of \foreach, but only obtained other errors. \documentclass{standalone} \usepackage{tikz} \usepackage{pgfplots} \pgfplotsset{compat=1.18} \begin{document} \pgfmathdeclarefunction{g}{1}{\pgfmathparse{#1^2 - 2}} \begin{tikzpicture} \begin{axis} [ xmin = -2.5, xmax = 2.5, ymin = -3, ymax = 3, axis x line = center, axis y line = center, domain=-2.5:2.5, samples=300, ] \addplot[ultra thick] {g(x)}; % graph of g \addplot[thin] {x}; % diagonal \def\xstart{-0.75} \pgfmathsetmacro{\xprev}{\xstart}; \pgfmathsetmacro{\xnext}{g(\xprev)}; \draw[thick, blue] (\xstart, 0) -- (\xstart, \xnext) -- (\xnext, \xnext); \foreach \i in {1, 2, 3}{ \pgfmathsetmacro{\xprev}{\xnext} \pgfmathsetmacro{\xnext}{g(\xprev)} % x <- g(x) \edef\plotoneiter{% \noexpand% \draw[thick, blue] ({\xprev}, {\xprev}) -- ({\xprev}, {\xnext}) -- ({\xnext}, {\xnext}); }\plotoneiter% } \end{axis} \end{tikzpicture} \end{document} Thanks in advance for any hints! EDIT: Here is a quick sketch of what I'm trying to achieve:
- Number sign/hash (#) not allowed in environment defined with listingsby Zeping Lee on November 3, 2025 at 8:31 am
The number sign ("#") raises an error in an environment defined with \lstnewenvironment of listings package. This is possibly related to the recent changes in LaTeX2e kernel ( 2025-11-01) because the CI of my citeproc-lua package breaks without any modifications. LaTeX2e <2025-11-01> L3 programming layer <2025-10-24> Package: listings 2024/09/23 1.10c (Carsten Heinz) \documentclass{article} \usepackage{listings} \lstnewenvironment{bash}{% \lstset{language = bash}% }{} \begin{document} \begin{lstlisting}[language=bash] make install # This works \end{lstlisting} \begin{bash} make install # This doesn't work \end{bash} \end{document} Error: ./tmp.tex:13: You can't use `macro parameter character #' in horizontal mode. l.13 make install # This doesn't work
- I want a command which can take two arbitrary ellipses, and shade the region between them, bounded by their mutual tangentsby Jasper on November 2, 2025 at 9:31 pm
I want a command which can take two arbitrary ellipses, and shade the region between them, bounded by their mutual tangents. \documentclass[tikz,border=1cm]{standalone} \begin{document} \begin{tikzpicture} \fill (-5,0) ellipse[x radius = 1, y radius = pi]; \fill ({sqrt(2)},e) ellipse[x radius = {sqrt(pi)}, y radius = {sqrt(e^sqrt(pi))}]; \end{tikzpicture} \end{document}
- TikZ arrow difference in different PDF-viewer(PDF-XChange-Editor v10.5.2)?by Explorer on November 1, 2025 at 6:03 pm
I have the following mwe: \documentclass[tikz,border=5pt]{standalone} \usetikzlibrary{arrows.meta} \begin{document} \begin{tikzpicture}[% foo/.tip={Latex[width=0pt 5, length=5pt]}, line cap=round,line join=round,scale=1.3 ] \begin{scope} \coordinate (A) at (-1,0); \coordinate (B) at (1,0); \coordinate (C) at (0,{sqrt(3)}); \draw[foo-foo] (A) -- (B); \draw[foo-foo] (A) -- (C); \draw[foo-foo] (B) -- (C); \end{scope} \end{tikzpicture} \end{document} Then the output's arrow differs in different PDF-viewers: case1: PDF.js in LaTeXWorkshop case2: Edge browser case3: PDF-Xchange-Editor The abnormal arrow tip only shown with PDF-Xchange-Editor. Is this the PDF-viewer to be blamed, what caused this difference? Edit to mizimizhi Z's comments(@muzimuzhiZ): The test code: \documentclass[tikz,border=5pt]{standalone} \usetikzlibrary{arrows.meta} \begin{document} \tikz \draw[line join=round, {-Latex}] (0,0) -- (1,0); \begin{tikzpicture}[ line width=5pt, line join=round ] \draw (0,0) -- (1,1) -- (1,0); \draw[line join=miter, xshift=2cm] (0,0) -- (1,1) -- (1,0); \end{tikzpicture} \end{document} While in contrast, I compared it with another PDF-viewer: foxit-PDF-editor-pro, it gives the correct result:
- With the Roboto Flex font, siunitx \micro not displayed with an upright muby Denis Bitouzé on October 31, 2025 at 11:35 am
The following MCE displays \unit{\micro\gram} as expected, that is with the (upright mu) Micro Sign character: \documentclass{article} \usepackage{fontspec} \usepackage{siunitx} \setmainfont{TeX Gyre Schola} % \setmainfont{RobotoFlex-VariableFont.ttf} \begin{document} \begin{itemize} \item Greek Small Letter Mu/Unicode char 03BC: μ/\char"03BC \item Micro Sign/Unicode char 00B5: µ/\char"00B5 \item \verb|\unit{\micro\gram}|: \unit{\micro\gram} \end{itemize} \end{document} However, if the TeX Gyre Schola font is replaced with the Roboto Flex font, \unit{\micro\gram} is displayed with a slanted mu, so not with a Micro Sign: I assume this is a bug in the Roboto Flex font, but is there anything that can be done on the (Lua)LaTeX side to resolve the issue?
- Error with `\DocumentMetadata` and nicematrixby Keks Dose on October 29, 2025 at 12:00 pm
TexLive 2025, up to date MWE: \DocumentMetadata{pdfstandard=A-2b, lang=de-DE, pdfversion=1.7} \documentclass{article} \usepackage{nicematrix, array} \begin{document} \begin{NiceTabular}{p{4em}p{4em}p{4em}} \multicolumn{3}{p{8em}}{Überschrift}\\ $\downarrow$ & zwei & drei \\ \end{NiceTabular} \end{document} % Local Variables: % TeX-engine: luatex % End: Works, if I comment out the first line. Throws errors otherwise, first one: ./251029-lua-dev-nicematrix.tex:9: Use of \@@array doesn't match its definition. \@ifnextchar ...\reserved@d = #1\def \reserved@a { #2}\def \reserved@b {#3}\f... It took me hours to boil my file down to this mwe. The \downarrow line threw errors with the developer version of LuaLaTeX, I had to replace it with \(\downarrow\). And for whatever reason another error isn't visible, but there was another error with the dev version. I added here the tag "tagged-pdf", because neither "documentmetadata", nor PDF-management were predefined. Feel free to change to better fitting tag of this question.
- Segmented cake symbolby Sebastiano on October 26, 2025 at 9:50 pm
Let's take as an example an old request of mine, where I asked to create small symbols (eyes) to indicate the difficulty of an exercise. TikZ or symbol eyes for difficulty of examples/exercises Since I can't find a symbol, among those available in the symbol manual, that represents 1/4 of a cake to indicate time (and that can be associated with 1/2, 3/4, and 4/4), I wonder if it's possible to adapt the Marsupilam code to use a symbol that can be found in an Italian national newspaper. I think that is an image and not a symbol. \documentclass[12pt]{standalone} \usepackage{tikz} \newcommand\straightEye[1][1.2ex] {% \begin{tikzpicture}[scale=#1/1cm] \draw (0,0) circle (.5); \fill (0,0) circle (.25); \end{tikzpicture}% } \newcommand\downwardsEye[1][1.2ex] {% \begin{tikzpicture}[scale=#1/1cm] \draw (0,0) circle (.5); \fill (0,-.25) circle (.25); \end{tikzpicture}% } \newcommand\rightEye[1][1.2ex] {% \begin{tikzpicture}[scale=#1/1cm] \draw (0,0) circle (.5); \fill (.25,0) circle (.25); \end{tikzpicture}% } \begin{document} \straightEye \downwardsEye \ look at me \rightEye\rightEye \end{document}
- Why does \marginpar break wrapstuff?by Sammy on October 22, 2025 at 6:25 pm
I'm creating worksheets that require text-wrapped graphics and margin notes. For wrapping, I use the wrapstuff package, which handles lists and other content well. For margin notes, I use \marginpar, sometimes together with \leavevmode to align the note with the surrounding text. However, when I combine wrapstuff and \marginpar, the text stops wrapping properly after the margin note. If I use \leavevmode, it even causes an error. I need both wrapped figures and margin notes inside a custom environment, but the issue can be reproduced with the following minimal (not) working example: \documentclass{article} \usepackage{wrapstuff} \usepackage{tikz} \usepackage{lipsum} \begin{document} \begin{wrapstuff} \tikz{\draw (0,0) rectangle (5,3);} \end{wrapstuff} \lipsum[1][1-3] \begin{enumerate} \item \marginpar{Test} \lipsum[1][1-3] \end{enumerate} \end{document} Why does \marginpar break wrapstuff and is there a workaround that allows both margin notes and wrapped content to work reliably in such cases?
- \textfrak and German umlautsby Reinhard Neuwirth on October 22, 2025 at 8:16 am
Fraktur font in text mode is fine for German umlauts in lower case but reports a "corrupted NFSS tables" error for upper case, although it compiles and produces a flawless .pdf file. \documentclass{article} % RN. 22/10/2025 %======================= \usepackage{yfonts} \begin{document} \textfrak{\"a\"o\"u} \textfrak{\"A\"O\"U} \end{document}
- Direct alternative to \bm, but with unicode-math supportby t1m013y on October 21, 2025 at 5:05 pm
When I used LaTeX without unicode-math, I used \bm to make bold the entire equation or large part of it. Now I need to use \usepackage{unicode-math} for Cyrillic characters in math, and \bf doesn't work with unicode math. I need a direct alternative for \bm that takes existing styles into account and also affects all operators. For example: \bm{a + \mathrm{b}} will produce: {bold italic a} {bold +} {bold non-italic b}. Is there such unicode-compatible command in LaTeX or in some LaTeX package?
- Using macros to define optional arguments for environmentsby user419944 on October 21, 2025 at 12:24 am
I am trying to use a macro to define the optional arguments to a tcbraster environment. Here is a simple example: \documentclass{article} \usepackage{tcolorbox} \tcbuselibrary{raster} \def\myoptions{raster columns=2} \begin{document} \begin{tcbraster}[\myoptions] \end{tcbraster} \end{document} This fails with Error: I do not know the key '/tcb/raster columns=2'. What I want is for TeX to see [\myoptions] as [raster columns=2]. This must be easy, but I have been going around in circles for hours trying to solve it. My end goal is to write a macro using, e.g., \clist_map_inline that will allow me to dynamically set options to tcbraster, so that I can write, e.g.,: \begin{tcbraster}[\myoptions{3,4}] and have it interpreted as: \begin{tcbraster}[raster columns=2,raster force size=false,raster column 1/.style={width=3cm},raster column 2/.style={width=4cm}] Any advice very gratefully accepted! Michael Thanks for the rapid and helpful replies below! It would probably help if I tried to explain what I'm trying to do here. Basically, I want to reduce the amount of effort required to produce arbitrarily deep nests of tcbrasters, with specified column widths. I'm thinking of a macro, e.g., \COLS, that has two arguments: (1) a clist of column widths (in units of \textwidth), and (2) a bunch of tcolorboxes, and it returns a tcolorbox that contains a tcbraster containing the tcolorboxes. One or more of the tcolorboxes in the 2nd argument to \COLS can in turn be another \COLS. E.g., suppose \A, \B, \C are tcolorboxes, then I can do something like \COLS{0.3,0.2,0.5}{\A\B\COLS{0.4,0.6}{\C\COLS{1.0}{\A\B}}} to produce: A B C A B This particular example is pretty silly, but the general idea is to make beamer slides that can easily contain boxes of configurable width for text, tcboxfit, images, etc, and to be able to create these very quickly and flexibly. For example, suppose I want a beamer slide with two images in the left 30% of the slide, aligned on top of each other, followed to the right by a tcboxfit of width 40% containing text, with an image below it, and the remaining column on the right containing a few more tcolorboxes. Handcoding all of this would involve a page of bespoke TeX. I may have a hundred or more slides, each one of which I would like to be able to quickly create. In principle all I should need are the column widths, the contents of the boxes, and a simple way of describing the layout. Update Following all the helpful comments, I have something that works. E.g., my definition of \COLSthree for three columns is as follows: \def\COLSthree#1#2{% \begin{tcolorbox}[blankest] \expandafter\tcbraster\expandafter[\mythree{#1}] #2 \endtcbraster \end{tcolorbox} } Where \mythree is cfr's \myoptions with 3 widths, each given as a fraction of \textwidth. E.g., \COLSthree{0.3,0.3,0.4}{} creates a tcolorbox which contains a tcbraster with three columns with the indicated widths. I also define \COLSone, \COLStwo, etc. The output of any of these \COLS can be used as a tcolorbox in the argument list of another \COLS, to arbitrary depth. I use \tcbraster rather than \begin{tcbraster} since the former does what I want with respect to \linewidth and nested rasters. The end result is a very compact way of specifying any slide layout I want, freeing me up to concentrate on the content. Now I can get back to writing my physics lectures! The final enhancement would be to replace the separate \COLS with a single macro that makes decisions based on the number of column widths. Penultimate update OK, after much wrangling I've got a solution using \begin{tcbraster} etc. I've defined three macros: \A to handle a single column tcbraster, \B for two columns, and \C for three. Also, I have a macro \BOX which is needed to embed some of the tcbrasters inside a tcolorbox to get around problems with \textwidth changing mysteriously (e.g., if you have a single column raster that contains a two column raster - \textwidth changes before and after the \tcbset line if you don't use \BOX). \def\A#1#2{% \tcbset{ my options/.style args={##1}{ raster columns=1, raster force size=false, raster column 1/.style={width=##1\textwidth}, raster row skip=0pt, }, } \begin{tcbraster}[my options={#1},blankest] #2 \end{tcbraster} } \def\B#1#2{% \tcbset{ my options/.style args={##1,##2}{ raster columns=2, raster force size=false, raster column 1/.style={width=##1\textwidth}, raster column 2/.style={width=##2\textwidth}, raster row skip=0pt, }, } \begin{tcbraster}[my options={#1},blankest] #2 \end{tcbraster} } \def\C#1#2{% \tcbset{ my options/.style args={##1,##2,##3}{ raster columns=3, raster force size=false, raster column 1/.style={width=##1\textwidth}, raster column 2/.style={width=##2\textwidth}, raster column 3/.style={width=##3\textwidth}, raster row skip=0pt, }, } \begin{tcbraster}[my options={#1},blankest] #2 \end{tcbraster} } \def\BOX#1{% \begin{tcolorbox}[blankest] #1 \end{tcolorbox} } This works very nicely, apart from the need to have a separate macro for each number of columns. Final update So, finally, I've got it going with a single macro \COLS that takes a comma-delimited set of column widths. Getting this to work was a challenge. \documentclass{beamer} \usepackage{tcolorbox} \usepackage{calc} \tcbuselibrary{raster} \long\def\COLS#1#2{\begin{tcolorbox}% % % This macro takes comma-delimited arguments in #1 and sets options % for \tcbraster giving the number of columns and their widths in % units of \textwidth. % % #2 is the material to put in the raster (normally \tcolorboxes). % % Usage, e.g., \COLS{0.3,0.2,0.5} % % Begin by setting options in common to all numbers of columns. % \tcbset{my options/.style={ raster force size=false, raster row skip=0pt, }, } % % \appendOptions is a macro used to build up the list of new options % to append using \pgfkeys. % \def\appendOptions{} % % \nArgs counts the comma-delimited arguments in #1 % \newcount\nArgs\nArgs 0\relax % % Process the comma-delimited arguments in #1. % \extractArgs #1,\end, % % Append the final option needed, listing the total number of % columns in the raster. % \edef\appendOptions{\appendOptions raster columns=\the\nArgs} % % Prepare for calling \pgfkeys with the new options. % \def\argForPGF{/tcb/my options/.append style={\appendOptions}} % % Make the call to \pgfkeys. % \edef\temp{\noexpand\pgfkeys{\argForPGF}}\temp% % % Finally, use tcbraster. % \begin{tcbraster}[my options] #2 \end{tcbraster} \end{tcolorbox}} \def\extractArgs#1#2,{% % % \extractArgs calls itself iteratively to find comma-delimited % arguments, and updates \appendOptions appropriately. % It returns when it has found all the arguments. % \ifx\end#1% % % Increment the number of arguments found. % \else\advance\nArgs 1\relax% % % Append the options for the column just found. Note that we % have to use the calc package to multiply by \textwidth for % some reason. #1#2\textwidth doesn't work here. % \edef\appendOptions{\appendOptions raster column \the\nArgs/.style={width=\the\dimexpr#1#2\textwidth},}% % % Continue until there are no arguments left. % \expandafter \extractArgs\fi} % Here is an example of the usage. \def\A{\begin{tcolorbox}A \end{tcolorbox}} \begin{document} \COLS{0.2,0.8}{\A \COLS{1}{% \A \COLS{0.5,0.5}{\A \COLS{0.5,0.5}{% \A\A}}}} \end{document} The above code should work as is. It produces a bunch of embedded boxes with "A" in them. Normally I would use [blankest] to remove the box outlines, but I left them in so you can see the box sizes. Thanks for everyone's help along the way.
- The nature of the \sup operatorby Sebastiano on October 20, 2025 at 9:00 pm
I am writing some notes for a very time-consuming job. I was wondering what kind of operator \sup is, or what its nature is, considering that it does not leave any space between itself and the curly bracket. Why does it not have a small space by default? \documentclass{article} \usepackage{amsmath,amssymb} \begin{document} \begin{equation} M_n\equiv \sup \{|f_n(x) - f(x)| : x\in D\} < \varepsilon, \quad \forall n > \nu_{\varepsilon}. \end{equation} \end{document}
- A logistical way to recursively subdivide triangles (into 6 sub-triangles), such that all detail is captured and no triangles are wastedby Jasper on October 19, 2025 at 4:33 pm
I have a surface composed of triangles. I want to recursively subdivide these triangles into 6 sub-triangles, which are then themselves further subdivided into 6 more and so on. I want for this subdivision to carry on only until enough detail is captured, and no more after that. I do not know what the heck I should measure for this. I tried using the laplacian, but it didn't seem to work. Maybe there is a better measurement, or perhaps either my laplaican function could be wrong. There are two functions called append_surface in the MWE. swap their order to see each's effect. In particular, I've included the current function, along with my experimental function which I made in an attempt to solve this question. The current function produces: The experimental function produces: mwe.tex \documentclass[ tikz ,border = 1cm ]{standalone} \makeatletter \tikzset{ /lua-tikz3dtools/.is family % abbreviated "td" ,/lua-tikz3dtools/.cd ,/lua-tikz3dtools/parametric/.cd % appreviated "p" ,/lua-tikz3dtools/parametric/matrix/.cd % abbreviated "m" ,object/.code = {\protected@edef\luatikztdtools@p@m@transformation{#1}} ,object = {identity_matrix()} ,name/.code = {\protected@edef\luatikztdtools@p@m@name{#1}} ,name = {Change me!} ,/lua-tikz3dtools/parametric/surface/.cd % abbreviated "s" ,ustart/.estore in = \luatikztdtools@p@s@ustart ,ustop/.estore in = \luatikztdtools@p@s@ustop ,usamples/.estore in = \luatikztdtools@p@s@usamples ,vstart/.estore in = \luatikztdtools@p@s@vstart ,vstop/.estore in = \luatikztdtools@p@s@vstop ,vsamples/.estore in = \luatikztdtools@p@s@vsamples ,x/.code = {\protected@edef\luatikztdtools@p@s@x{#1}} ,y/.code = {\protected@edef\luatikztdtools@p@s@y{#1}} ,z/.code = {\protected@edef\luatikztdtools@p@s@z{#1}} ,transformation/.code = {\protected@edef\luatikztdtools@p@s@transformation{#1}} ,fill options/.code = {\protected@edef\luatikztdtools@p@s@filloptions{#1}} ,ustart = {0} ,ustop = {1} ,usamples = {10} ,vstart = {0} ,vstop = {1} ,vsamples = {10} ,x = {sphere(tau*u, pi*v)[1][1]} ,y = {sphere(tau*u, pi*v)[1][2]} ,z = {sphere(tau*u, pi*v)[1][3]} ,transformation = {identity_matrix()} ,fill options = {fill, fill opacity = 0.3} } \ExplSyntaxOn \lua_load_module:n { mwe-lua } \NewDocumentCommand { \appendsurface } {o} { \group_begin: \tikzset{ /lua-tikz3dtools/parametric/surface/.search~also = {/tikz} ,/lua-tikz3dtools/parametric/surface/.cd ,#1 } \__lua_tikztdtools_appendsurface: \group_end: } \NewDocumentCommand { \displaysegments } {} { \group_begin: \__lua_tikztdtools_displaysegments: \group_end: } \NewDocumentCommand { \setobject } {o} { \group_begin: \tikzset{ /lua-tikz3dtools/parametric/matrix/.search~also = {/tikz} ,/lua-tikz3dtools/parametric/matrix/.cd ,#1 } \__lua_tikztdtools_setobject: \group_end: } \ExplSyntaxOff \makeatother \begin{document} \begin{tikzpicture} \setobject[ name = {T} ,object = { matrix_multiply( euler(pi/2,pi/3,5*pi/6) ,translate(0,0,-15) ) } ] \appendsurface[ ustart = {-7} ,ustop = {7} ,usamples = {7} ,vstart = {-7} ,vstop = {7} ,vsamples = {7} ,transformation = {T} ,x = {u} ,y = {v} ,z = { 3 / ((u)^2+(v)^2+1/2) } ,fill options = { preaction = { fill = red!70!black ,fill opacity = 1 } ,postaction = { draw = black ,ultra thin ,line join = round ,line cap = round } } ] \displaysegments \end{tikzpicture} \end{document} mwe-lua.lua local eps = 0.0000001 --- scalar multiplication --- @param a number the scalar coefficient --- @param v table<table<number>> the vector --- @return table<table<number>> the scaled vector local function scalar_multiplication(a, v) local tmp = v[1] return { {a*tmp[1], a*tmp[2], a*tmp[3], 1} } end --- vector subtraction --- @param u table<table<number>> the first vector --- @param v table<table<number>> the second vector --- @return table<table<number>> their difference local function vector_subtraction(u, v) local U = u[1] local V = v[1] return { {U[1]-V[1], U[2]-V[2], U[3]-V[3], 1} } end --- vector addition --- @param u table<table<number>> the first vector --- @param v table<table<number>> the second vector --- @return table<table<number>> their sum local function vector_addition(u, v) local U = u[1] local V = v[1] return { {U[1]+V[1], U[2]+V[2], U[3]+V[3], 1} } end --- length of a vector --- @param u table<table<number>> the vector to be measured --- @return number the vectors length local function length(u) local result = math.sqrt((u[1][1])^2 + (u[1][2])^2 + (u[1][3])^2) return result end --- distance between two points --- @param P1 table<table<number>> a point --- @param P2 table<table<number>> another point --- @return number their distance local function distance(P1, P2) local A = P1[1] local B = P2[1] return math.sqrt( (A[1]-B[1])^2 + (A[2]-B[2])^2 + (A[3]-B[3])^2 ) end -- https://tex.stackexchange.com/a/747040 --- Creates a TeX command that evaluates a Lua function --- --- @param name string The name of the `\csname` to define --- @param func function --- @param args table<string> The TeX types of the function arguments --- @param protected boolean|nil Define the command as `\protected` --- @return nil local function register_tex_cmd(name, func, args, protected) -- The extended version of this function uses `N` and `w` where appropriate, -- but only using `n` is good enough for exposition purposes. name = "__lua_tikztdtools_" .. name .. ":" .. ("n"):rep(#args) -- Push the appropriate scanner functions onto the scanning stack. local scanners = {} for _, arg in ipairs(args) do scanners[#scanners+1] = token['scan_' .. arg] end -- An intermediate function that properly "scans" for its arguments -- in the TeX side. local scanning_func = function() local values = {} for _, scanner in ipairs(scanners) do values[#values+1] = scanner() end func(table.unpack(values)) end local index = luatexbase.new_luafunction(name) lua.get_functions_table()[index] = scanning_func if protected then token.set_lua(name, index, "protected") else token.set_lua(name, index) end end local segments = {} local mm = {} mm.tau = 2*math.pi local pi = math.pi local cos, sin = math.cos, math.sin --- matrix multiplication --- --- @param A table<table<number>> left matrix --- @param B table<table<number>> right matrix --- @return table<table<number>> the product function mm.matrix_multiply(A, B) local rows_A = #A local columns_A = #A[1] local rows_B = #B local columns_B = #B[1] assert( columns_A == rows_B, string.format( [[ Wrong size matrices for multiplication. Size A: %d,%d Size B: %d,%d ]], rows_A, columns_A, rows_B, columns_B ) ) local product = {} for row = 1, rows_A do product[row] = {} for column = 1, columns_B do product[row][column] = 0 for dot_product_step = 1, columns_A do local a = A[row][dot_product_step] local b = B[dot_product_step][column] assert(type(a) == "number", string.format("Expected number but got %s in A[%d][%d]", type(a), row, dot_product_step)) assert(type(b) == "number", string.format("Expected number but got %s in B[%d][%d]", type(b), dot_product_step, column)) product[row][column] = product[row][column] + a * b end end end return product end function mm.yrotation(angle) local c = cos(angle) local s = sin(angle) return { {c,0,-s,0} ,{0,1,0,0} ,{s,0,c,0} ,{0,0,0,1} } end function mm.translate(x,y,z) return { {1,0,0,0} ,{0,1,0,0} ,{0,0,1,0} ,{x,y,z,1} } end function mm.zrotation(angle) local c = cos(angle) local s = sin(angle) return { {c,s,0,0} ,{-s,c,0,0} ,{0,0,1,0} ,{0,0,0,1} } end function mm.euler(alpha,beta,gamma) return mm.matrix_multiply( mm.zrotation(gamma) ,mm.matrix_multiply( mm.yrotation(beta) ,mm.zrotation(alpha) ) ) end function mm.midpoint(triangle) local P,Q,R = table.unpack(triangle) local x = (P[1]+Q[1]+R[1])/3 local y = (P[2]+Q[2]+R[2])/3 local z = (P[3]+Q[3]+R[3])/3 return {{x,y,z,1}} end local lua_tikz3dtools_parametric = {} lua_tikz3dtools_parametric.math = {} for k, v in pairs(_G) do lua_tikz3dtools_parametric.math[k] = v end for k, v in pairs(mm) do lua_tikz3dtools_parametric.math[k] = v end for k, v in pairs(math) do lua_tikz3dtools_parametric.math[k] = v end local function single_string_expression(str) return load(("return %s"):format(str), "expression", "t", lua_tikz3dtools_parametric.math)() end local function double_string_function(str) return load(("return function(u,v) return %s end"):format(str), "expression", "t", lua_tikz3dtools_parametric.math)() end local function append_surface(hash) local ustart = hash.ustart local ustop = hash.ustop local usamples = hash.usamples local vstart = hash.vstart local vstop = hash.vstop local vsamples = hash.vsamples local x = hash.x local y = hash.y local z = hash.z local drawoptions = hash.drawoptions local filloptions = hash.filloptions local transformation = hash.transformation x = double_string_function(x) y = double_string_function(y) z = double_string_function(z) ustart = single_string_expression(ustart) ustop = single_string_expression(ustop) usamples = single_string_expression(usamples) vstart = single_string_expression(vstart) vstop = single_string_expression(vstop) vsamples = single_string_expression(vsamples) transformation = single_string_expression(transformation) local ustep = (ustop - ustart) / (usamples - 1) local vstep = (vstop - vstart) / (vsamples - 1) local function parametric_surface(u, v) return { x(u,v), y(u,v), z(u,v), 1 } end local function distance(P1, P2) return math.sqrt( (P1[1]-P2[1])^2 + (P1[2]-P2[2])^2 + (P1[3]-P2[3])^2 ) end local eps = 0.0000001 for i = 0, usamples - 2 do local u = ustart + i * ustep for j = 0, vsamples - 2 do local v = vstart + j * vstep local A = parametric_surface(u, v) local B = parametric_surface(u + ustep, v) local C = parametric_surface(u, v + vstep) local D = parametric_surface(u + ustep, v + vstep) local the_segment1 = mm.matrix_multiply({ A, B, D },transformation) local the_segment2 = mm.matrix_multiply({ A, C, D },transformation) if not ( distance(A, B) < eps or distance(B, D) < eps or distance(A, D) < eps ) then table.insert( segments, { segment = the_segment1, filloptions = filloptions, type = "triangle" } ) end if not ( distance(A, C) < eps or distance(C, D) < eps or distance(A, D) < eps ) then table.insert( segments, { segment = the_segment2, filloptions = filloptions, type = "triangle" } ) end end end end local function append_surface(hash) local ustart = hash.ustart local ustop = hash.ustop local vstart = hash.vstart local vstop = hash.vstop local x = hash.x local y = hash.y local z = hash.z local filloptions = hash.filloptions local transformation = hash.transformation x = double_string_function(x) y = double_string_function(y) z = double_string_function(z) ustart = single_string_expression(ustart) ustop = single_string_expression(ustop) vstart = single_string_expression(vstart) vstop = single_string_expression(vstop) transformation = single_string_expression(transformation) --- parametric definition of our surface This function maps --- a point from the 2D domain onto the 3D codomain. --- @param u number the first coordinate component --- @param v number the second coordinate component --- @return table<number> the map of the given coordinates onto R3 local function parametric_surface(u, v) return { { x(u,v), y(u,v), z(u,v), 1 } } end --- distance between two DOMAIN points --- @param A table<table<number>> the first point in the DOMAIN --- @param B table<table<number>> the second point in the DOMAIN --- @return number their Euclidean distance in the DOMAIN local function dist2(A,B) local Ax, Ay = A[1], A[2] local Bx, By = B[1], B[2] return math.sqrt((Ax-Bx)^2+(Ay-By)^2) end --- gives the incentre of a triangle on the 2D domain --- @param T table<table<number>> --- @return table<number> the incentre (u,v) local function incentre2(T) local A,B,C = T[1],T[2],T[3] local DAB = dist2(A,B) local DBC = dist2(B,C) local DCA = dist2(C,A) local S = DAB + DBC + DCA if S == 0 then -- degenerate triangle, return centroid as fallback return { (A[1]+B[1]+C[1]) / 3, (A[2]+B[2]+C[2]) / 3 } end -- weighted average: (a*A + b*B + c*C) / (a+b+c) local dotx = (A[1]*DAB + B[1]*DBC + C[1]*DCA) / S local doty = (A[2]*DAB + B[2]*DBC + C[2]*DCA) / S return { dotx, doty } end --- partial derivatives of f(x,y) at the point (x=a,y=b) local function first_partial_derivatives(a,b) local eps = 1e-6 local dfdu = scalar_multiplication( 1/eps ,vector_subtraction( parametric_surface(a+eps, b) ,parametric_surface(a,b) ) ) local dfdv = scalar_multiplication( 1/eps ,vector_subtraction( parametric_surface(a, b+eps) ,parametric_surface(a,b) ) ) return {dfdu, dfdv} end --- second partial derivatives --- @param a number the first coordinate component --- @param b number the second coordinate component --- @return table<nnumber> the second partial derivates local function second_partial_derivatives(a, b) local eps = 1e-6 local FPD1, FPD2 = first_partial_derivatives(a, b)[1], first_partial_derivatives(a, b)[2] local FPD1h = first_partial_derivatives(a+eps, b)[1] local FPD2h = first_partial_derivatives(a, b+eps)[2] local d2fdu2 = scalar_multiplication( 1/eps ,vector_subtraction( FPD1h ,FPD1 ) ) local d2fdv2 = scalar_multiplication( 1/eps ,vector_subtraction( FPD2h ,FPD2 ) ) return {d2fdu2, d2fdv2} end local function laplacian(a,b) local P, Q = second_partial_derivatives(a, b)[1], second_partial_derivatives(a, b)[2] return scalar_multiplication(1/2,vector_addition(P, Q)) end -- local LL = parametric_surface(ustart, vstart) -- local LR = parametric_surface(ustop, vstart) -- local UL = parametric_surface(ustart, vstop) -- local UR = parametric_surface(ustop, vstop) local TRI1 = {{ustart, vstart}, {ustop, vstart}, {ustart, vstop}} local TRI2 = {{ustop, vstop}, {ustop, vstart}, {ustart, vstop}} local tris = {TRI1, TRI2} local max_depth = 4 -- you can tune this local iteration = 0 local min_DT = 0.05 local max_DT = 0.5 local tiny = 1e-12 while iteration < max_depth do local newtris = {} local refined = false for _, tri in ipairs(tris) do local v1, v2, v3 = tri[1], tri[2], tri[3] local P = incentre2(tri) -- Adaptive threshold based on Laplacian local PL = laplacian(P[1], P[2]) local px, py, pz = PL[1][1], PL[1][2], PL[1][3] local Lmag = math.sqrt(px*px + py*py + pz*pz) local invL = 1 / (Lmag + tiny) local DT = math.max(min_DT, math.min(invL, max_DT)) -- Distances to control refinement local D1 = dist2(P, v1) local D2 = dist2(P, v2) local D3 = dist2(P, v3) if (D1 < DT) or (D2 < DT) or (D3 < DT) then table.insert(newtris, tri) else -- Midpoints of edges (not P→vertex midpoints) local e12 = { (v1[1] + v2[1]) * 0.5, (v1[2] + v2[2]) * 0.5 } local e23 = { (v2[1] + v3[1]) * 0.5, (v2[2] + v3[2]) * 0.5 } local e31 = { (v3[1] + v1[1]) * 0.5, (v3[2] + v1[2]) * 0.5 } -- Six subtriangles around P that fill the parent: local t1 = { P, v1, e12 } local t2 = { P, e12, v2 } local t3 = { P, v2, e23 } local t4 = { P, e23, v3 } local t5 = { P, v3, e31 } local t6 = { P, e31, v1 } table.insert(newtris, t1) table.insert(newtris, t2) table.insert(newtris, t3) table.insert(newtris, t4) table.insert(newtris, t5) table.insert(newtris, t6) refined = true end end tris = newtris iteration = iteration + 1 if not refined then break end end for _, tri in ipairs(tris) do -- map UV to 3D local A = parametric_surface(tri[1][1], tri[1][2])[1] local B = parametric_surface(tri[2][1], tri[2][2])[1] local C = parametric_surface(tri[3][1], tri[3][2])[1] -- matrix-multiply by transformation local the_segment = mm.matrix_multiply({A, B, C}, transformation) if not ( distance({A}, {B}) < eps or distance({B}, {C}) < eps or distance({A}, {C}) < eps ) then table.insert( segments, { segment = the_segment, filloptions = filloptions, type = "triangle" } ) end end end register_tex_cmd( "appendsurface", function() append_surface{ ustart = token.get_macro("luatikztdtools@p@s@ustart"), ustop = token.get_macro("luatikztdtools@p@s@ustop"), usamples = token.get_macro("luatikztdtools@p@s@usamples"), vstart = token.get_macro("luatikztdtools@p@s@vstart"), vstop = token.get_macro("luatikztdtools@p@s@vstop"), vsamples = token.get_macro("luatikztdtools@p@s@vsamples"), x = token.get_macro("luatikztdtools@p@s@x"), y = token.get_macro("luatikztdtools@p@s@y"), z = token.get_macro("luatikztdtools@p@s@z"), transformation = token.get_macro("luatikztdtools@p@s@transformation"), filloptions = token.get_macro("luatikztdtools@p@s@filloptions"), } end, { } ) local function make_object(name, tbl) local obj = {} obj[name] = tbl return obj end local function set_matrix(hash) local transformation = single_string_expression(hash.transformation) local name = hash.name local tbl = make_object(name, transformation) for k, v in pairs(tbl) do lua_tikz3dtools_parametric.math[k] = v end end register_tex_cmd( "setobject", function() set_matrix{ name = token.get_macro("luatikztdtools@p@m@name"), transformation = token.get_macro("luatikztdtools@p@m@transformation"), } end, { } ) local function display_segments() local function comparator(a,b) return mm.midpoint(a.segment)[1][3] < mm.midpoint(b.segment)[1][3] end -- Perform sorting after filtering out skipped segments table.sort(segments, comparator) -- Iterate through the sorted segments for rendering for _, segment in ipairs(segments) do -- Handle triangle segments if segment.type == "triangle" then local P, Q, R = segment.segment[1], segment.segment[2], segment.segment[3] tex.sprint(string.format( "\\path[%s] (%f,%f) -- (%f,%f) -- (%f,%f) -- cycle;", segment.filloptions, P[1], P[2], Q[1], Q[2], R[1], R[2] )) end end -- Clear the segments array after processing segments = {} end register_tex_cmd("displaysegments", function() display_segments() end, { })
- Use of key-value pairs in \NewDocumentCommandsby Reinhard Neuwirth on October 18, 2025 at 9:31 am
I have a number of \NewDocumentCommands each defined with several big O optional arguments. Their ease of use would greatly benefit from defining the arguments as key-value pairs. One quick look at Chapter 28: The l3keys module. Key-value interfaces has convinced me that The Latex3 Interfaces document will be a valuable resource later, but for me is no way to start. Next I attempted to find whatever @egreg had produced in his answers on that subject in the past. I am sure it would make some serious reading, but the TeX Exchange was not helpful in identifying it. Code that works would get me started. The following is a flawed example supplied by Microsoft Bing AI. Would someone please identify what is missing, the reference to { mymodule } seems to be sitting there somewhat isolated. \documentclass{article} % RN. 18/10/2025 %======================= \usepackage{xparse} \usepackage{expl3} % Step 1: Define the key-value interface \ExplSyntaxOn \keys_define:nn { mymodule } { color .tl_set:N = \l_mymodule_color_tl, size .tl_set:N = \l_mymodule_size_tl, style .tl_set:N = \l_mymodule_style_tl, color .initial:n = black, % Default value size .initial:n = 12pt, % Default value style .initial:n = normal % Default value } % Step 2: Define the command using the keys \NewDocumentCommand{\customtext}{O{} m} { % Parse the optional argument as key-value pairs \keys_set:nn { mymodule } { #1 } % Use the parsed values to format the output \textcolor{\l_mymodule_color_tl}{% \fontsize{\l_mymodule_size_tl}{\l_mymodule_size_tl}\selectfont \textbf{\l_mymodule_style_tl:~#2}% } } \ExplSyntaxOff \begin{document} % Example usage \customtext{Default settings text.} \customtext[color=red,size=18pt,style=italic]{Customized text.} \customtext[color=blue]{Partially customized text.} \end{document}```
- `\mapsto` as a subscriptby Mariano Suárez-Álvarez on October 18, 2025 at 2:50 am
The code \documentclass{article} \begin{document} $x_\mapsto$ \end{document} results in the following: Changing x_\mapsto to x_{\mapsto} does what one would probably hope, but I wonder: is this the expected behavior?