diff options
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-bbox/README.txt | 24 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual-en-library-bbox.tex | 181 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.pdf | bin | 0 -> 234562 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.tex | 26 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/tikz-bbox/pgflibrarybbox.code.tex | 120 |
5 files changed, 351 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/tikz-bbox/README.txt b/Master/texmf-dist/doc/latex/tikz-bbox/README.txt new file mode 100644 index 00000000000..077f3aabab0 --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-bbox/README.txt @@ -0,0 +1,24 @@ +tikz-bbox +========= + +Copyright 2021 by marmotghost. +v0.1 + +This file may be distributed and/or modified under the +LaTeX project public license (LPPL), version 1.3c +see +https://www.latex-project.org/lppl/lppl-1-3c/ + + +The built-in determination of the bounding box in TikZ is not entirely accurate. +This is because, for Bezier curves, it is the smallest box that contains all +control points, which is in general larger than the box that just contains the +curve. This library determines the exact bounding box of the curve. + +In order to load this library in a LaTeX document, you need to add + +\usetikzlibrary{bbox} + +to the preamble after loading the tikz package. While this library might +possibly work with TeX or ConTeXt, this has never been tested. This library +loads and uses the fpu library. diff --git a/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual-en-library-bbox.tex b/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual-en-library-bbox.tex new file mode 100644 index 00000000000..9d42ae0dd51 --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual-en-library-bbox.tex @@ -0,0 +1,181 @@ +% Copyright 2021 by marmotghost +% v0.1 +% +% This file may be distributed and/or modified under the +% LaTeX project public license (LPPL), version 1.3c +% see +% https://www.latex-project.org/lppl/lppl-1-3c/ +% +% It has been claimed that the license of this library had been changed so that this +% library is no longer part of pgf. This claim is a lie. There was no license change +% at all. Now, in 2021, the license got changed to LaTeX project public license +% (LPPL), version 1.3c. + +\section{Bounding Boxes for B\'ezier Curves} + + +\begin{pgflibrary}{bbox} + This library provides methods to determine tight bounding boxes for + B\'ezier curves. This library loads and uses the + |fpu| library. While this library might + possibly work with |TeX| or |ConTeXt|, this has never been tested. +\end{pgflibrary} + +\subsection{Bounding box without the library} + +\tikzname\ determines the bounding box of (cubic) Bezier curves by establishing the +smallest rectangle that contains the end point and the two control points of the +curve. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[% + bullet/.style={circle,fill, + inner sep=1pt}] + \draw (0,0) .. controls (-1,1) + and (1,2) .. (2,0); + \draw (current bounding box.south west) + rectangle + (current bounding box.north east); + \draw[red,dashed] + (0,0) -- (-1,1) + node[bullet,label=above:{$(x_a,y_a)$}]{} + (2,0) -- (1,2) + node[bullet,label=above:{$(x_b,y_b)$}]{}; + \path (0,0) + node[bullet,label=below:{$(x_0,y_0)$}]{} + (2,0) + node[bullet,label=below:{$(x_1,y_1)$}]{}; +\end{tikzpicture} +\end{codeexample} + +As one can see from this illustration, this may lead to drastic overestimates of +the bounding box. + +\subsection{Computing the bounding box} + +Establishing the precise bounding box has been discussed in various places, the +following discussion uses in part the results from +\url{https://pomax.github.io/bezierinfo/}. What is a cubic B\'ezier curve? A +cubic B\'ezier curve running from $(x_0,y_0)$ to $(x_1,y_1)$ with control points +$(x_a,y_a)$ and $(x_b,y_b)$ can be parametrized by +\begin{equation} + \gamma(t)~=~ + \begin{pmatrix} x(t)\\ y(t) \end{pmatrix}~=~ + \begin{pmatrix}t^3 x_{1}+3 t^2 (1-t) x_{b}+(1-t)^3 + x_{0}+3 t (1-t)^2 x_{a}\\ + t^3 y_{1}+3 + t^2 (1-t) y_{b}+(1-t)^3 y_{0}+3 t (1-t)^2 + y_{a}\end{pmatrix}\;,\label{eq:gammaBezier} +\end{equation} +where $t$ runs from $0$ to $1$ (and $\gamma(0)=(x_0,y_0)$ and +$\gamma(1)=(x_1,y_1)$). Surely, the bounding box has to contain +$(x_0,y_0)$ and $(x_1,y_1)$. If the functions $x(t)$ and $y(t)$ have extrema in +the interval $[0,1]$, then the bounding box will in general be larger than that. +In order to determine the extrema of the curve, all +we need to find the extrema of the functions $x(t)$ and $y(t)$ for $0\le t\le +1$. That is, we need to find the solutions of the quadratic equations +\begin{equation} + \frac{\mathrm{d}x}{\mathrm{d}t}(t)~=~0\quad\text{and}\quad + \frac{\mathrm{d}y}{\mathrm{d}t}(t)~=~0\;. +\end{equation} +% (*parametrization of x:*) +% myx = x0 (1 - t)^3 + 3 xa (1 - t)^2 t + 3 xb (1 - t) t^2 + x1 t^3 +% (*d1\ne0 condition for t1 and t2 to exist*) +% === (*case d1\ne0*) == +% d1 = x0 - x1 - 3 xa + 3 xb +% (*square root, d2=0 \[Rule] only one solution,d2<0 \[Rule] no solution*) +% d2 = x0*x1 - x1*xa + xa*xa - x0*xb - xa xb + xb*xb +% (*first t*) +% t1 = (x0 - 2*xa + xb - sqrt(d2))/(x0 - x1 - 3*xa + 3*xb) +% = (x0 - 2*xa + xb - sqrt(d2))/d1 +% (*second t*) +% t2 = (x0 - 2*xa + xb + sqrt(d2))/(x0 - x1 - 3*xa + 3*xb) +% = (x0 - 2*xa + xb + sqrt(d2))/d1 +% === (*case d1=0*) == +% (*2nd condition for extra condition: d3\ne0*) +% d3 = x1 + xa - 2 xb +% (*third t*) +% t3 = (x1 + 2*xa - 3*xb)/(2*d3)% d3 = x1 + 3 xa - 3 xb - x0 +Let's discuss $x$ first. If the discriminant +\begin{equation} + d~:=~x_0\,x_1 - x_1\,x_a + x_a\,x_a - x_0\,x_b - x_a x_b + x_b\,x_b +\end{equation} +is greater than 0, there are two solutions +\begin{equation} + t_\pm~=~\frac{x_{0}-2x_{a}+x_{b}\pm\sqrt{d}}{% + x_{0}-x_{1}-3(x_{a}- x_{b})} \;. +\end{equation} +If the denominator $x_{0}-x_{1}-3(x_{a}- x_{b})$ vanishes, one may use the +l'Hospital rule to determine the solutions. +In this case, we need to make sure that the bounding box contains, say +$(x(t_-),y_0)$ and $(x(t_+),y_0)$. If $d\le0$, the bounding box does not need to +be increased in the $x$ direction. On the other hand, if there are solutions, +one needs include the points $\bigl(x(t_\pm),y_0\bigr)$ with $x(t)$ from +\eqref{eq:gammaBezier} in the bounding box. + +The analogous statements apply to $y(t)$. + +\subsection{Using the library} + +\begin{key}{/pgf/bezier bounding box=\meta{boolean} (default true)} + Turn the tight bounding box algorithm on and off. The initial value is + |false|. + + \emph{Caveat:} As can be seen from the derivations, the necessary + computations involve the squaring of lengths and taking ratios of lengths, + which can easily lead to |dimension too large| errors. The library uses + |fpu| to account for that, but errors may still occur. +\end{key} + + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[bezier bounding box,% + bullet/.style={circle,fill, + inner sep=1pt}] + \draw (0,0) .. controls (-1,1) + and (1,2) .. (2,0); + \draw (current bounding box.south west) + rectangle + (current bounding box.north east); + \draw[red,dashed] + (0,0) -- (-1,1) + node[bullet,label=above:{$(x_a,y_a)$}]{} + (2,0) -- (1,2) + node[bullet,label=above:{$(x_b,y_b)$}]{}; + \path (0,0) + node[bullet,label=below:{$(x_0,y_0)$}]{} + (2,0) + node[bullet,label=below:{$(x_1,y_1)$}]{}; +\end{tikzpicture} +\end{codeexample} + +A few comments are in order. +\begin{enumerate} +\item For paths with arrow heads one may need to load the \texttt{bending} + library. This is because otherwise the quick arrow head distorts the path, and + this happens after the bounding box has been computed. Even worse, arrow heads + could get deformed. +\item If you shorten a path by some negative length, the bounding box will not + be accurate either. However, this has nothing to do with curves, it also + applies to straight lines. So this is not specific to the |bbox| library but + something that one may want to keep in mind. +\item Let us also note that the computations can lead to |Dimension too large| + errors. These errors do not come directly from the computations done by the + library, which uses |fpu| for its computations, but from the aftermath. Many of + these problems can be avoided by using the |fpu| library also for computing + reciprocals, which can be achieved using the key + |/pgf/fpu/install only={reciprocal}|. This allows one to fix many + |Dimension too large| errors in other libraries, which are not related to the + present one, and also fixes inaccuracies of (inverse) transformations when the + scale factors are not integer. +\end{enumerate} + +\subsection{Reporting a bug} + +This library is maintained at the GitHub repository +\href{https://github.com/marmotghost/tikz-bbox}{tikz-bbox}, where issues can get +reported. The author is also active on the noncommercial \TeX\ Q\,\&\,A site +\href{https://topanswers.xyz/tex}{topanswers.xyz/tex}, where requests that are not +issues in the strict sense can be discussed. + +\endinput diff --git a/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.pdf b/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.pdf Binary files differnew file mode 100644 index 00000000000..69630c59646 --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.pdf diff --git a/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.tex b/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.tex new file mode 100644 index 00000000000..465bc22beaf --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-bbox/pgfmanual4bbox.tex @@ -0,0 +1,26 @@ +\documentclass[a4paper]{ltxdoc} +\usepackage[version=latest]{pgf} +\usepackage{xkeyval,calc,listings,tikz,fp,amsmath,amssymb} +\usepackage[T1]{fontenc}% +\usepackage{makeidx} +\makeindex +\usepackage{hyperref} +\hypersetup{% + colorlinks=true, + linkcolor=blue, + filecolor=blue, + urlcolor=blue, + citecolor=blue, + pdfborder=0 0 0, +} +\makeatletter % see https://tex.stackexchange.com/q/33946 +\input{pgfmanual.code} % +\makeatother % +\input{pgfmanual-en-macros.tex} % link from +% /usr/local/texlive/2019/texmf-dist/doc/generic/pgf/macros/pgfmanual-en-macros.tex +% or the equivalent on your installation +\def\pgfautoxrefs{1} +\usetikzlibrary{bbox} +\begin{document} +\input{pgfmanual-en-library-bbox.tex} +\end{document} diff --git a/Master/texmf-dist/tex/latex/tikz-bbox/pgflibrarybbox.code.tex b/Master/texmf-dist/tex/latex/tikz-bbox/pgflibrarybbox.code.tex new file mode 100644 index 00000000000..a9e887f809e --- /dev/null +++ b/Master/texmf-dist/tex/latex/tikz-bbox/pgflibrarybbox.code.tex @@ -0,0 +1,120 @@ +% Copyright 2021 by marmotghost +% v0.1 +% +% This file may be distributed and/or modified under the +% LaTeX project public license (LPPL), version 1.3c +% see +% https://www.latex-project.org/lppl/lppl-1-3c/ + + +\usepgflibrary{fpu} +\global\let\pgf@bbox@lt@curveto@normal\pgf@lt@curveto +\global\let\pgf@bbox@nlt@curveto@normal\pgf@nlt@curveto + +\pgfqkeys{/pgf}{bezier bounding box/.is if=pgf@bbox@switch@} + + +\def\pgf@bbox@switch@false{% + \let\pgf@lt@curveto \pgf@bbox@lt@curveto@normal + \let\pgf@nlt@curveto\pgf@bbox@nlt@curveto@normal +} + +\def\pgf@bbox@switch@true{% + \let\pgf@lt@curveto \pgf@bbox@curveto + \let\pgf@nlt@curveto\pgf@bbox@curveto +} +\def\pgf@bbox@curveto#1#2#3#4#5#6{% +\begingroup +\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}% + % extrema in x + % first discriminant d1, must be \ne 0 + \pgfmathsetmacro{\pgf@temp@a}{(\pgf@path@lastx)-(#5)-3*(#1)+3*(#3)}% + \pgfmathtruncatemacro{\pgf@temp@c}{(abs(\pgf@temp@a)>0.1?1:0)}% + \ifnum\pgf@temp@c=1\relax + % second discriminant d2, must be \ge 0 + \pgfmathsetmacro{\pgf@temp@b}{(\pgf@path@lastx)*(#5)-(#5)*(#1)+(#1)*(#1)-(\pgf@path@lastx)*(#3)-(#1)*(#3)+(#3)*(#3)}% + \pgfmathtruncatemacro{\pgf@temp@c}{sign(\pgf@temp@b)}% + \ifnum\pgf@temp@c<0 + \else + \pgfmathsetmacro{\pgf@temp@b}{sqrt(abs(\pgf@temp@b))}% + \pgfmathsetmacro{\pgf@temp@c}{max(0,min(1,((\pgf@path@lastx)-2*(#1)+(#3)-\pgf@temp@b)/\pgf@temp@a))}% + \pgfmathparse{(\pgf@path@lastx)*pow((1-\pgf@temp@c),3)+3*(#1)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#3)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#5)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgfutil@tempdimb}{\pgf@path@lasty}% + \pgfmathsetmacro{\pgf@temp@c}{max(0,min(1,((\pgf@path@lastx)-2*(#1)+(#3)+\pgf@temp@b)/\pgf@temp@a))}% + \pgfmathparse{(\pgf@path@lastx)*pow((1-\pgf@temp@c),3)+3*(#1)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#3)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#5)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgfutil@tempdimb}{\pgf@path@lasty}% + \fi + \else + % third discriminant d3, must be \ne 0 + \pgfmathsetmacro{\pgf@temp@b}{abs((#5)+(#1)-2*(#3))}% + \pgfmathtruncatemacro{\pgf@temp@c}{(abs(\pgf@temp@b)>0.1?1:0)}% + \ifnum\pgf@temp@c=1\relax + \pgfmathsetmacro{\pgf@temp@c}{((#5)+2*(#1)-3*(#3))/((#5)+(#1)-2*(#3))}% + \pgfmathparse{(\pgf@path@lastx)*pow((1-\pgf@temp@c),3)+3*(#1)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#3)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#5)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgfutil@tempdimb}{\pgf@path@lasty}% + \fi + \fi + % 0/0 + \pgfmathsetmacro{\pgf@temp@a}{(#5)+(#1)-2*(#3)}% + \pgfmathtruncatemacro{\pgf@temp@b}{(abs(\pgf@temp@a)>0.1?1:0)}% + \ifnum\pgf@temp@b=1\relax + \pgfmathsetmacro{\pgf@temp@c}{max(0,min(1,((#5)+2*(#1)-3*(#3))/(2*\pgf@temp@a)))}% + \else + \pgfmathsetmacro{\pgf@temp@c}{0.5}% + \fi + \pgfmathparse{(\pgf@path@lastx)*pow((1-\pgf@temp@c),3)+3*(#1)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#3)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#5)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgfutil@tempdimb}{\pgf@path@lasty}% +% +% y code + % first discriminant d1, must be \ne 0 + \pgfmathsetmacro{\pgf@temp@a}{(\pgf@path@lasty)-(#6)-3*(#2)+3*(#4)}% + \pgfmathtruncatemacro{\pgf@temp@c}{(abs(\pgf@temp@a)>0.1?1:0)}% + \ifnum\pgf@temp@c=1\relax + % second discriminant d2, must be \ge 0 + \pgfmathsetmacro{\pgf@temp@b}{(\pgf@path@lasty)*(#6)-(#6)*(#2)+(#2)*(#2)-(\pgf@path@lasty)*(#4)-(#2)*(#4)+(#4)*(#4)}% + \pgfmathtruncatemacro{\pgf@temp@c}{sign(\pgf@temp@b)}% + \ifnum\pgf@temp@c<0 + \else + \pgfmathsetmacro{\pgf@temp@b}{sqrt(abs(\pgf@temp@b))}% + \pgfmathsetmacro{\pgf@temp@c}{max(0,min(1,((\pgf@path@lasty)-2*(#2)+(#4)-\pgf@temp@b)/\pgf@temp@a))}% + \pgfmathparse{(\pgf@path@lasty)*pow((1-\pgf@temp@c),3)+3*(#2)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#4)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#6)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgf@path@lastx}{\pgfutil@tempdimb}% + \pgfmathsetmacro{\pgf@temp@c}{max(0,min(1,((\pgf@path@lasty)-2*(#2)+(#4)+\pgf@temp@b)/\pgf@temp@a))}% + \pgfmathparse{(\pgf@path@lasty)*pow((1-\pgf@temp@c),3)+3*(#2)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#4)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#6)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgf@path@lastx}{\pgfutil@tempdimb}% + \fi + \else + % third discriminant d3, must be \ne 0 + \pgfmathsetmacro{\pgf@temp@b}{abs((#6)+(#2)-2*(#4))}% + \pgfmathtruncatemacro{\pgf@temp@c}{(abs(\pgf@temp@b)>0.1?1:0)}% + \ifnum\pgf@temp@c=1\relax + \pgfmathsetmacro{\pgf@temp@c}{((#6)+2*(#2)-3*(#4))/((#6)+(#2)-2*(#4))}% + \pgfmathparse{(\pgf@path@lasty)*pow((1-\pgf@temp@c),3)+3*(#2)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#4)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#6)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgf@path@lastx}{\pgfutil@tempdimb}% + \fi + \fi + % 0/0 + \pgfmathsetmacro{\pgf@temp@a}{(#6)+(#2)-2*(#4)}% + \pgfmathtruncatemacro{\pgf@temp@b}{(abs(\pgf@temp@a)>0.1?1:0)}% + \ifnum\pgf@temp@b=1\relax + \pgfmathsetmacro{\pgf@temp@c}{max(0,min(1,((#6)+2*(#2)-3*(#4))/(2*\pgf@temp@a)))}% + \else + \pgfmathsetmacro{\pgf@temp@c}{0.5}% + \fi + \pgfmathparse{(\pgf@path@lasty)*pow((1-\pgf@temp@c),3)+3*(#2)*pow((1-\pgf@temp@c),2)*\pgf@temp@c+3*(#4)*(1-\pgf@temp@c)*\pgf@temp@c*\pgf@temp@c+(#6)*\pgf@temp@c*\pgf@temp@c*\pgf@temp@c}% + \pgfutil@tempdimb=\pgfmathresult pt\relax% + \pgf@protocolsizes{\pgf@path@lastx}{\pgfutil@tempdimb}% +% + \pgf@protocolsizes{\pgf@path@lastx}{\pgf@path@lasty}% + \pgf@protocolsizes{#5}{#6}% + \endgroup + \pgfsyssoftpath@curveto{\the#1}{\the#2}{\the#3}{\the#4}{\the#5}{\the#6}% +} +\endinput |