4

What I am trying to accomplish is the calculation of a length in cm, which I need for a TikZ drawing. The calculation itself is not trivial (cubic root, which I turned into math.log and math.exp), thus I have decided to use Lua, which will also allow me to define the number of decimal points through string.format. Out of this calculation, I would like to return a LaTeX length definition in cm. Now I have finally arrived at a half-baked solution, that seems to set the length but for some reason the length dbe is still as zero. As per MWE, I am printing the command to the Log as well, see print(tmp) for debugging and if I Ctrl+C/Ctrl+V this output directly, the length definition works. Where am I going wrong with printing/returning the commands back to LaTeX?

\documentclass{article}
\usepackage{luacode}
\usepackage{tikz}
\usetikzlibrary{fadings,shapes,calc}

% Define a variable as a length
\newcommand{\nvar}[2]{%
    \newlength{#1}
    \setlength{#1}{#2}
}

% Define a few constants for transmission line drawing
\nvar{\rx}{0.33333cm}
\nvar{\diameter}{0.6cm}
\nvar{\db}{2cm}

% calculate some other dimensions (cubic root using ln and e)
\begin{luacode}
rx=0.33333
db=2
dbe= math.exp(math.log(rx*db*db)/3)
tmp = "\\newlength{\\dbe}\\setlength{\\dbe}{" .. string.format("%.2f", dbe) .. "cm}"
print(tmp)
tex.print(tmp)
\end{luacode}


\begin{document}

The \LaTeX lengths:\\
\the\rx\\
\the\diameter\\
\the\db \\
\the\dbe


\begin{tikzpicture}
        \colorlet{left}{black}
        \tikzset{line core/.style={draw=red,ultra thick, circle,fill=orange,minimum height=\dbe,anchor=center},%
       line conductor/.style={shading = axis,circle, left color=left, right color=left!30!white,shading angle=180, anchor=center, minimum height=\dbe}
        }

        % looping through available phases
        \foreach \phase/\centreX/\centreY in{1/0/0,2/4/0,3/2/3}
        {
            \coordinate (centre\phase) at (\centreX,\centreY);
            \node [line core] at (centre\phase) {}; 
            % drawing a phase transmission line - need to add at least three or four conductors
            \foreach \angle in {90,30,150}
            {
                \node [line conductor] at ($ (centre\phase) + (\angle:\diameter)$) {};
                \node [line conductor] at ($ (centre\phase) + (-\angle:\diameter)$) {};
            }
        }
\end{tikzpicture}


\end{document}

The output I get through print(tmp) in the log is:

\newlength{\dbe}\setlength{\dbe}{1.10cm}

edit: using MacTeX/TeXLive 2015 with all the latest packages through tlmgr

  • It's just a constant number it seems you are not doing a calculation based on input from the document, so why use lua at all? – David Carlisle Dec 12 '15 at 16:18
  • @DavidCarlisle yes, that is true. The question here was the first one, a follow up question would have been how I could take input from a given length, say \rx and do the calculation for \dbe. – Nils Bausch Dec 12 '15 at 16:42

1 Answers1

5

Printing a string such as

\newlength{\dbe}\setlength\dbe{...}

is not the same as executing the instructions contained in the string.

Since you've already set up the utility macro \nvar to define a length variable and assign a value to the newly-defined variable, I would take the following tack: Inside the Lua-side group, set up a function called, say, mycalc that performs the cube-root calculations and returns a length string. Then, make use of \nvar to define \dbe as follows:

\nvar{\dbe}{\directlua{mycalc(0.33333,2,"cm")}}

Note that in the code below, I don't employ the string.format function that's in your code -- I don't see the need to limit the precision of the calculation at this point.

enter image description here

\documentclass{article}
\usepackage{luacode}
\usepackage{tikz}
\usetikzlibrary{fadings,shapes,calc}

% Define a variable as a length
\newcommand{\nvar}[2]{\newlength{#1}\setlength{#1}{#2}}

%% Lua-side code
\begin{luacode}
function mycalc ( rx , db , unit )
  return (  tex.sprint ( math.exp(math.log(rx*db*db)/3) .. unit ) )
end
\end{luacode}

% Define a few constants
\nvar{\rx}{0.33333cm}
\nvar{\diameter}{0.6cm}
\nvar{\db}{2cm}
\nvar{\dbe}{\directlua{mycalc(0.33333,2,"cm")}}

\begin{document}
\noindent
The \LaTeX\ lengths:\\
\the\rx\\
\the\diameter\\
\the\db \\
\the\dbe


\begin{tikzpicture}
        \colorlet{left}{black}
        \tikzset{line core/.style={draw=red,ultra thick, circle,fill=orange,minimum height=\dbe,anchor=center},%
       line conductor/.style={shading = axis,circle, left color=left, right color=left!30!white,shading angle=180, anchor=center, minimum height=\dbe}
        }

        % looping through available phases
        \foreach \phase/\centreX/\centreY in{1/0/0,2/4/0,3/2/3}
        {
            \coordinate (centre\phase) at (\centreX,\centreY);
            \node [line core] at (centre\phase) {}; 
            % drawing a phase transmission line - need to add at least three or four conductors
            \foreach \angle in {90,30,150}
            {
                \node [line conductor] at ($ (centre\phase) + (\angle:\diameter)$) {};
                \node [line conductor] at ($ (centre\phase) + (-\angle:\diameter)$) {};
            }
        }
\end{tikzpicture}

\end{document}

Addendum: In the preceding code, the "variables" \rx and \db are hardcoded and their values thus have to be entered again as constants in the \nvar call that sets up \dbe. To streamline the process, one can replace the instructions

\nvar{\rx}{0.33333cm}
\nvar{\diameter}{0.6cm}
\nvar{\db}{2cm}
\nvar{\dbe}{\directlua{mycalc(0.33333,2,"cm")}}

with

\newcommand\rxval{0.33333}
\newcommand\dbval{2}   

\nvar{\rx}{\rxval cm}
\nvar{\diameter}{0.6 cm}
\nvar{\db}{\dbval cm}
\nvar{\dbe}{\directlua{mycalc(\rxval,\dbval,"cm")}}

That way, one only needs to modify \rxval and \dbval in order to modify \rx, \db, and \dbe.

Mico
  • 506,678
  • I had not thought about creating a function, but that works brilliantly. I am also now making use of defining a number first \def\rxVal{0.33333}, which I then use to derive a length from \nvar{\rx}{\rxVal cm} and then finally in \nvar{\dbe}{\directlua{mycalc(\rxVal, \dbVal)}}. The idea was to parameterise these values, so that I can reuse it whilst creating my TikZ drawing. – Nils Bausch Dec 12 '15 at 16:59
  • @aXon - I'm glad my answer works for you. :-) I've posted an addendum that formalizes your idea of defining macros containing (scalar) numers first and then using these macros to automate the definition of the length variables \rx, \db, and \dbe. – Mico Dec 12 '15 at 17:22