Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have a problem with this code :

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\begin{document}

\begin{tikzpicture}[decoration={markings, mark = at position .5 with
 {\draw (-2pt,-2pt) -- (2pt,2pt)  (2pt,-2pt) -- (-2pt,2pt);}}]    

% wrong 
%\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1)--(0,0);
%fine
\draw [postaction={decorate}] (0,0) -- ++(146:1.2) arc (146:157:1.2)--(0,0);
\end{tikzpicture}

\end{document}

The line after % wrong gives an error dimension too large. I think there is a math problem because the arc or the radius is too small or perhaps both. A solution is (another one is to use a scale >1 but for the fine line don't use a scale like .8 :

\documentclass{article}
\usepackage{tikz,fp}
\usetikzlibrary{decorations.markings,fixedpointarithmetic}

\begin{document}

\begin{tikzpicture}[fixed point arithmetic,
                    decoration={markings, mark = at position .5 with
       {\draw (-2pt,-2pt) -- (2pt,2pt)  (2pt,-2pt) -- (-2pt,2pt);}}]     

\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1)--(0,0);
\end{tikzpicture}

\end{document} 

But I can't use it because the time for the compilation is too long.

Is it possible to speed up the last code or perhaps someone knows another way to get the mark without an error ? Perhaps I use decoration in a wrong way!

share|improve this question
1  
Maybe related: tex.stackexchange.com/questions/4404/… (not the question, but the answer). –  Caramdir Jun 15 '11 at 16:11
    
Unfortunately yes I put the solution with fixedpointarithmetic and the problem is similar. The little difference is that I want to put a mark in the middle of the arc. Perhaps I can avoid decoration ? –  Alain Matthes Jun 15 '11 at 16:42
    
The other difference is that an arc seems to be more simple than a zigzag. –  Alain Matthes Jun 15 '11 at 16:48
1  
I have also had this problem with decorating rounded corners at the middle of the curve. My solution was to alter the location by a percent or two; it seems to me that the problem is arithmetically unstable, possibly just a consequence of TeX's built-in arithmetic not being so good. –  Ryan Reich Jun 15 '11 at 17:20
    
That's interesting, both lines work without an error for me, using PGF 2.10. –  Jake Jun 15 '11 at 23:55

2 Answers 2

up vote 8 down vote accepted

The problem is in the implementation of the mathematical function veclen. In short, it doesn't just do (x^2 + y^2)^{1/2} (How could it? Taking square roots isn't even possible theoretically let alone the issues of precision.) but does something more complicated that at some stage involves dividing by one of the components. You can test this by trying a simple:

\pgfmathparse{veclen(0.00006,0.00006)}

(the number was chosen as that happens to be the number that TeX barfs on when trying Altermundus' example. Multiply by 10 and it all works again.)

Looking at the implementation of veclen I noticed that it did some initial scaling to take into account large numbers. So I added some lines to test also for small numbers as well. And that appears to solve the problem.

(Unfortunately, I couldn't get \pgfmathredeclarefunction to work properly. Rather than debug that, I just \let the old function to \relax and overwrote it.)

Code:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\makeatletter
\let\pgfmath@function@veclen\relax
\pgfmathdeclarefunction{veclen}{2}{%
  \begingroup%
  \pgfmath@x#1pt\relax%
  \pgfmath@y#2pt\relax%
  \ifdim\pgfmath@x<0pt\relax%
  \pgfmath@x-\pgfmath@x%
  \fi%
  \ifdim\pgfmath@y<0pt\relax%
  \pgfmath@y-\pgfmath@y%
  \fi%
  \ifdim\pgfmath@x=0pt\relax%
  \pgfmath@x\pgfmath@y%
  \else%
  \ifdim\pgfmath@y=0pt\relax%
  \else%
  \ifdim\pgfmath@x>\pgfmath@y%
  \pgfmath@xa\pgfmath@x%
  \pgfmath@x\pgfmath@y%
  \pgfmath@y\pgfmath@xa%
  \fi%
  % We use a scaling factor to reduce errors.
  % First, see if we should scale down
  \let\pgfmath@tmp@scale=\divide
  \let\pgfmath@tmp@restore=\multipy
  \ifdim\pgfmath@y>10000pt\relax%
  \c@pgfmath@counta1500\relax%
  \else%
  \ifdim\pgfmath@y>1000pt\relax%
  \c@pgfmath@counta150\relax%
  \else%
  \ifdim\pgfmath@y>100pt\relax%
  \c@pgfmath@counta50\relax%
  \else%
  % Not scaling down, should we scale up?
  \let\pgfmath@tmp@scale=\multiply
  \let\pgfmath@tmp@restore=\divide
  \ifdim\pgfmath@y<0.00001pt\relax%
  \c@pgfmath@counta1500\relax%
  \else%
  \ifdim\pgfmath@y<0.0001pt\relax%
  \c@pgfmath@counta150\relax%
  \else%
  \ifdim\pgfmath@y<0.001pt\relax%
  \c@pgfmath@counta50\relax%
  \else
  \c@pgfmath@counta1\relax%
  \fi%
  \fi%
  \fi%
  \fi%
  \fi%
  \fi%
  \pgfmath@tmp@scale\pgfmath@x\c@pgfmath@counta\relax%
  \pgfmath@tmp@scale\pgfmath@y\c@pgfmath@counta\relax%
  \pgfmathreciprocal@{\pgfmath@tonumber{\pgfmath@y}}%
  \pgfmath@x\pgfmathresult\pgfmath@x%
  \pgfmath@xa\pgfmath@tonumber{\pgfmath@x}\pgfmath@x%
  \edef\pgfmath@temp{\pgfmath@tonumber{\pgfmath@xa}}%
  %
  % Use A+x^2*(B+x^2*(C+x^2*(D+E*x^2))) 
  % where
  % A = +1.000012594
  % B = +0.4993615349 
  % C = -0.1195159052
  % D = +0.04453994279
  % E = -0.01019210944
  %
  \pgfmath@x-0.01019210944\pgfmath@xa%
  \advance\pgfmath@x0.04453994279pt\relax%
  \pgfmath@x\pgfmath@temp\pgfmath@x%
  \advance\pgfmath@x-0.1195159052pt\relax%
  \pgfmath@x\pgfmath@temp\pgfmath@x%
  \advance\pgfmath@x0.4993615349pt\relax%
  \pgfmath@x\pgfmath@temp\pgfmath@x%
  \advance\pgfmath@x1.000012594pt\relax%
  \ifdim\pgfmath@y<0pt\relax%
  \pgfmath@y-\pgfmath@y%
  \fi%
  \pgfmath@x\pgfmath@tonumber{\pgfmath@y}\pgfmath@x%
  % Invert the scaling factor.
  \pgfmath@tmp@restore\pgfmath@x\c@pgfmath@counta\relax%
  \fi%
  \fi%
  \pgfmath@returnone\pgfmath@x%
  \endgroup%
}

\makeatother

\begin{document}

\pgfmathparse{veclen(0.00006,0.00005)}
Vector length is: \pgfmathresult

\begin{tikzpicture}[decoration={markings, mark = at position .5 with
 {\draw (-2pt,-2pt) -- (2pt,2pt)  (2pt,-2pt) -- (-2pt,2pt);}}]    

% wrong 
\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1) -- (0,0);
%fine
\draw [postaction={decorate}] (2,0) -- ++(146:1.2) arc (146:157:1.2) -- (2,0);
\end{tikzpicture}

\end{document}

Result:

decorated curve

As can be seen, the accuracy is not great! However, at that level of precision then it's probably not all that important. Perhaps a better implementation would be to test if the components of the vector are less than some small number and then simply return the maximum of the two: at that level, the difference between the sup norm and the l^2 norm is not a lot! (A slightly more sophisticated version would have a switch that returned the sup norm or the l^1 norm depending on whether it was acceptable to underestimate or overestimate.)

share|improve this answer
    
Interesting to know that the problem cab be solved with a new implementation of the mathematical function veclen. In my package tkz-euclide` I use a macro called \tkzveclen. I made this macro with fp perhaps a solution for me is to make a temporary implementation. The problem is the time of compilation and to be sure there are no bad effects. –  Alain Matthes Jun 16 '11 at 8:37
    
@Altermundus: I would guess that there are many such edge cases that weren't considered in designing the functions. Clearly some where (such as that the vector might be too long) but I would guess it is impossible to test for everything! Knowing exactly what to do here would require more knowledge of what actually matters than I have. For so small a vector, I would be surprised if anyone could tell the difference between the actual length and an approximation so simply adding an escape would seem the simplest implementation. –  Loop Space Jun 16 '11 at 10:04
    
@Andrew You can avoid \let\pgfmath@function@veclen\relax with \pgfmathdeclarefunction*{veclen}{2}. The next macro is strange \def\pgfmathredeclarefunction#1#2{% ... has only two arguments and makes only \pgfmath@namedef{pgfmath#1@}{#2}. –  Alain Matthes Jun 16 '11 at 12:13
    
@Altermundus: maybe I'm reading the manual incorrectly, but I thought that \pgfmathredeclarefunction was a way of replacing an existing function with new code but the same number of arguments. But it didn't work so I just hacked it and didn't go looking for an alternative. Now I look at the code, I can see that you are right. –  Loop Space Jun 16 '11 at 12:18
    
@Andrew Perhaps the macro is not very well described in the pgfmanual or perhaps it's a bug in its definition. –  Alain Matthes Jun 16 '11 at 12:24

I answer to my question because perhaps it will be useful for someone. It's my first macro with lualatex so perhaps I made something very bad. I don't know exactly how to get the result from luaveclen,perhaps tostring is not necessary. The time of compilation is correct !

%!TEX TS-program =  lualatex
\documentclass[11pt]{article}
\usepackage{fontspec}
\usepackage{luatextra}   
\usepackage{tikz}
\usetikzlibrary{decorations.markings}   

\begin{document}

\makeatletter     

\def\luaveclen#1#2{
    \directlua{
        x = #1;
        y = #2;
       r=(x*x+y*y)^0.5
       tex.print(tostring(r))}
}  

\pgfmathdeclarefunction*{veclen}{2}{%
\begingroup 
  \edef\pgfmath@tmp{\luaveclen{#1}{#2}}
  \pgfmath@returnone\pgfmath@tmp pt
\endgroup    
}
\makeatother  

\pgfmathparse{veclen(0.00003,0.00004)}
 Vector length is: \pgfmathresult    

\begin{tikzpicture}[decoration={markings, mark = at position .5 with
 {\draw (-2pt,-2pt) -- (2pt,2pt)  (2pt,-2pt) -- (-2pt,2pt);}}]    

\draw [postaction={decorate}] (0,0) -- ++(146:1) arc (146:157:1) -- (0,0);
\end{tikzpicture} 

\end{document} 

enter image description here

share|improve this answer
1  
This sounds like an excellent use of lualatex. Maybe one could write an alternative to \pgfmathparse: maybe \luamathparse. –  Loop Space Jun 16 '11 at 16:09
    
A french guy works on this : pgfluamath.parser.lua,v 1.5 2011/06/07 08:58:58 cjorssen. You can find the file in pgf CVS in the directory luamath of the librairies. Christophe writes in good TeX my macros that you can find in pgfmathfunctions.integerarithmetics.code.tex. My codes are not always fine :( –  Alain Matthes Jun 16 '11 at 16:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.