4

I would like to use pythontex for some repetitive calculations.


edit

instead of having a solution with the first code I posted below (it's a bit complicated and there is a simple way to do it with tikz ... thanks to Marmot), if someone can show me how to retrieve variables which are calculate with python. May be with a simple example like calculation of the coordinates of the middle of a segment.

\begin{pycode}
def Middle(XA,YA,XB,YB):
    XK=(XA+XB)/2
    YK=(YA+YB)/2
\end{pycode}

And I would like to know how to retrieve XK and YK individually.


First post :

I have this part of code (the entire one is below, with a figure to illustrate the output) :

\pgfmathsetmacro{\XofA}{\XA*\OI+\YA*\OJ*cos(\angle)}
\pgfmathsetmacro{\YofA}{\YA*\OJ*sin(\angle)}
\pgfmathsetmacro{\XofAprojOI}{\XA*\OI}
\pgfmathsetmacro{\YofAprojOI}{0}
\pgfmathsetmacro{\XofAprojOJ}{\YA*\OJ*cos(\angle)}
\pgfmathsetmacro{\YofAprojOJ}{\YA*\OJ*sin(\angle)}

with XA and YA, I want to retrieve XofA, YofA, XofAprojOI, YofAprojOI, XofAprojOJ and YofAprojOJ, but with an another point, say B for example, I want to retrieve XofB, YofB, XofBprojOI, YofBprojOI, XofBprojOJ and YofBprojOJ.

In order to avoid the repetition of this code (for all the points I have to define), I would like to have a pythontex function which return all these variables. Something like (all I tried failed, so I just can give an idea of what I want) :

\begin{pycode}
def coordTransformations(XA,YA):
    XofA=XA*OI+YA*OJ*cos(angle)
    YofA=YA*OJ*sin(angle)
    etc.
\end{pycode}

and use the results in my latex code.

The entire code is :

\documentclass[10pt,a4paper]{article}
\usepackage[latin1]{inputenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{pythontex}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{scopes}
\usetikzlibrary{arrows.meta}

\begin{document}


\def\angle{75}
\def\OI{1.2}
\def\OJ{0.7}
\def\Xmin{-1}
\def\Xmax{6}
\def\Ymin{-1}
\def\Ymax{8}
\def\XA{2}
\def\YA{3}
\def\XB{4}
\def\YB{7}
\def\XH{\XB}
\def\YH{\YA}
\begin{tikzpicture}[x=1.0cm,y=1.0cm,scale=1,every node/.style={scale=1}]    
    \pgfmathsetmacro{\XofA}{\XA*\OI+\YA*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofA}{\YA*\OJ*sin(\angle)}
    \pgfmathsetmacro{\XofAprojOI}{\XA*\OI}
    \pgfmathsetmacro{\YofAprojOI}{0}
    \pgfmathsetmacro{\XofAprojOJ}{\YA*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofAprojOJ}{\YA*\OJ*sin(\angle)}

    \pgfmathsetmacro{\XofB}{\XB*\OI+\YB*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofB}{\YB*\OJ*sin(\angle)}
    \pgfmathsetmacro{\XofBprojOI}{\XB*\OI}
    \pgfmathsetmacro{\YofBprojOI}{0}
    \pgfmathsetmacro{\XofBprojOJ}{\YB*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofBprojOJ}{\YB*\OJ*sin(\angle)}

    \pgfmathsetmacro{\XK}{0.5*(\XA+\XB)}
    \pgfmathsetmacro{\YK}{0.5*(\YA+\YB)}

    \pgfmathsetmacro{\XofH}{\XH*\OI+\YH*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofH}{\YH*\OJ*sin(\angle)}
    \pgfmathsetmacro{\XofHprojOI}{\XH*\OI}
    \pgfmathsetmacro{\YofHprojOI}{0}
    \pgfmathsetmacro{\XofHprojOJ}{\YH*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofHprojOJ}{\YH*\OJ*sin(\angle)}

    \pgfmathsetmacro{\XofK}{\XK*\OI+\YK*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofK}{\YK*\OJ*sin(\angle)}
    \pgfmathsetmacro{\XofKprojOI}{\XK*\OI}
    \pgfmathsetmacro{\YofKprojOI}{0}
    \pgfmathsetmacro{\XofKprojOJ}{\YK*\OJ*cos(\angle)}
    \pgfmathsetmacro{\YofKprojOJ}{\YK*\OJ*sin(\angle)}


    \coordinate (A) at (\XofA,\YofA);
    \coordinate (B) at (\XofB,\YofB);
    \coordinate (K) at (\XofK,\YofK);
    \coordinate (H) at (\XofH,\YofH);


    % grille :
    % ~~~~~~~~
    \foreach \n in {\Ymin,...,\Ymax}
        \draw  [color=black!20,shift={(\angle:{\n*\OJ})}] (0:\Xmin*\OI) -- (0:{\Xmax*\OI}); % parallèles (Ox)
    \foreach \n in {\Xmin,...,\Xmax}
        \draw  [color=black!20,shift={(0:{\n*\OI})}] ({\angle}:\Ymin*\OJ) -- (\angle:{\Ymax*\OJ}); % parallèles (Oy)    

    % axes :
    % ~~~~~~
    \pgfmathsetmacro{\Xmaxminus}{\Xmax-1}
    \pgfmathsetmacro{\Ymaxminus}{\Ymax-1}

        %   axe (Ox) :
        %   ~~~~~~~~~~
    \draw [arrows={-Stealth[inset=2pt, angle=30:7pt]}] (0:\Xmin*\OI) -- (0:\Xmax*\OI) node [shift={(0:2ex)}] {$x$}; % axe (Ox)
    \foreach \n in {\Xmin,...,\Xmaxminus}%
        \draw [xshift=\n*\OI cm](\angle:3pt) -- ({180+\angle}:3pt);

        %   axe (Oy) :
        %   ~~~~~~~~~~
    \begin{scope}[rotate=\angle]
        \draw [arrows={-Stealth[inset=2pt, angle=30:7pt]}] (0:\Ymin*\OJ) -- (0:\Ymax*\OJ) node [shift={(\angle:2ex)}] {$y$}; % axe (Oy)
        \foreach \n in {\Ymin,...,\Ymaxminus}%
            \draw [xshift=\n*\OJ cm]({180-\angle}:3pt) -- (-\angle:3pt);
    \end{scope}

    % points du repère :
    % ~~~~~~~~~~~~~~~~~~
    \draw ({180+\angle/2}:2ex) node [font=\small,fill=white,inner sep=0ex] {$O$};

    \begin{scope}[shift={(0:\OI)}]
        \draw (\angle:-2ex) node [font=\small,fill=white,inner sep=0ex] {$I$};
    \end{scope}

    \begin{scope}[shift={(\angle:\OJ)}]
        \draw (0:-2ex) node [font=\small,fill=white,inner sep=0ex] {$J$};
    \end{scope}

    % points dans le plan :
    % ~~~~~~~~~~~~~~~~~~~~~

    \draw [densely dashed,draw=] (\XofAprojOJ,\YofAprojOJ) node [font=\small,fill=white,inner sep=0ex,shift={(180:2ex)}] {$\YA$} %
        -- (A) node [fill, circle, inner sep=1.5pt] {} node [fill=white, inner sep =0.5pt,shift={({\angle/2}:-2ex)}] {$A$}%
        -- (\XofAprojOI,\YofAprojOI) node [font=\small,fill=white,inner sep=0ex,shift={(\angle:-2ex)}] {$\XA$};

    \draw [densely dashed,draw=] (\XofBprojOJ,\YofBprojOJ) node [font=\small,fill=white,inner sep=0ex,shift={(180:2ex)}] {$\YB$} %
        -- (B) node [fill, circle, inner sep=1.5pt] {} node [fill=white, inner sep =0.5pt,shift={({\angle/2}:2ex)}] {$B$}%
        -- (\XofBprojOI,\YofBprojOI) node [font=\small,fill=white,inner sep=0ex,shift={(\angle:-2ex)}] {$\XB$};

    \draw [densely dashed,draw=] (\XofKprojOJ,\YofKprojOJ) node [font=\small,fill=white,inner sep=0ex,shift={(180:2ex)}] {$\pgfmathprintnumber{\YK}$} %
        -- (K) node [fill, circle, inner sep=1.5pt] {} node [fill=white, inner sep =0.5pt,shift={({\angle/2+90}:2ex)}] {$K$}%
        -- (\XofKprojOI,\YofKprojOI) node [font=\small,fill=white,inner sep=0ex,shift={(\angle:-2ex)}] {$\pgfmathprintnumber{\XK}$};

    \draw [fill=orange!30,opacity=0.3] (A) -- (B) %
        -- (H) node [fill=black,opacity=1, circle, inner sep=1.5pt] {} node [right=5pt,opacity=1,text=black,inner sep=1pt,fill=white] {$H$} %
        -- cycle;
\end{tikzpicture}

\end{document}

and the picture is :

enter image description here

Thanks.

Stan
  • 173

2 Answers2

2

This is not an answer to your question (as a marmot, I am very scared of snakes;-) but to tell you that you do not need python for this.

\documentclass[10pt,a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{scopes}
\usetikzlibrary{arrows.meta}

\begin{document}

\begin{tikzpicture}[xscale=1.2,yscale=0.7]
\pgftransformxslant{.15}
    \draw[help lines] (-1,-1) grid (6,8);
    \draw[thick,-latex] (0,0) -- (6,0) node[right] {$x$};
    \draw[thick,-latex] (0,0) -- (0,8) node[above] {$y$};
    \coordinate (O) at (0,0); 
    \coordinate (A) at (2,3); 
    \coordinate (B) at (4,7);
    \coordinate (H) at (4,3);
    \coordinate (K) at (3,5);
    \node[draw,fill, circle, inner sep=1.5pt,label=below:$A$] at (A) {};
    \node[draw,fill, circle, inner sep=1.5pt,label=right:$B$] at (B) {};
    \node[draw,fill, circle, inner sep=1.5pt,label=below:$H$] at (H) {};
    \node[draw,fill, circle, inner sep=1.5pt,label=left:$K$] at (K) {};
    \filldraw[-,fill=orange!30,opacity=0.3] (A) -- (H) -- (B) -- (K) -- (A);
    \foreach \coor in {A,B,K}
    {\draw[densely dashed] (O |- \coor) -- (\coor) -- (O -| \coor);}
\end{tikzpicture}
\end{document}

enter image description here

I just focused on some key elements of your picture, the others can be added. The message is that TikZ has all sorts of transformations already built in and one does not have to reinvent the wheel.

  • Well, I was pretty sure there was a very simple solution with tikz. I didn't know this \pgftransformxslant command ... this is a great solution, and I'll keep it in my tex file, but ... If possible I would like to know how to do that with pythontex, because I begin to learn python (for my students), and I would like to use it with latex. An example like calculate coordinates of the middle of a segment would be great. In fact, my problem is how to use one by one multiple variables that have been calculate under python. – Stan Feb 06 '18 at 00:02
  • @Stan Fair enough. However, I'm not 100% sure if this is then the right forum for your question. You seem to be mainly stuck at the task of finding the correct python code. It might thus be worthwhile to get a working code from another forum, and if you then have problems making things work with LaTeX come back here. –  Feb 06 '18 at 00:30
  • In fact I know how to do that with python : input variables, then xk=... and yk=..., and finally print(xk,yk). I know how to retrieve a unique result from python to use it in latex (I found examples in the web), but I don't know how to retrieve multiple results separatly (like xk and yk here). May be I have to do an other post with a more simple and explicit example. By the way, I learnt something very intersting with your answer (pgftransformxslant command). – Stan Feb 06 '18 at 10:03
  • @Stan Very good. How about writing this in the question? People may not find it here. BTW, on p. 57 of the pythontex manual there are examples of that kind. –  Feb 06 '18 at 14:40
  • I wrote an other post in fact : https://tex.stackexchange.com/questions/413912/how-to-retrieve-multiples-variables-separatly-with-pythontex. I tried with \pysub command, but not working. – Stan Feb 06 '18 at 14:46
2

To calculate and print the values of (from your example) XK and YK is simple. Return both values as members of a list

\documentclass{article}
\usepackage{pythontex}
\usepackage{tikz}
\begin{document}
    \begin{pycode}
def Middle(XA,YA,XB,YB):
    XK=(XA+XB)/2
    YK=(YA+YB)/2
    return([XK,YK])
    \end{pycode}
\pyc{XK,YK=Middle(0,0,12,10)}
\py{XK}

\py{YK}

\py{XK+YK}
\end{document}

If you want to use the values of XK and YK inside of a Tikz draw statement, you will need to use the \pys{....} inline command to generate the whole text line (the s indicates a substitution string operation). This is pretty easy because the \pys returns a string, but allows you to substitute python generated values using a !{....} envelope inside the \pys{...} wrapper.

Try inserting the following code before the \end{document} statement.

\pys{XK + YK looks like !{XK}+!{YK}}

\pys{The value of YK is !{YK}}

\begin{tikzpicture}
\pys{\draw(!{XK},!{YK}) circle(1em);}
\draw(0,0)rectangle(12,10);
\end{tikzpicture}
Bill N
  • 652
  • 6
  • 16
  • Thank you for this solution. I read some things with !{...}, but it didn't work because I didn't realise I had to embedded this with \pys{...} inside a tikz environment. Now it works. Thanks a lot. – Stan Jul 16 '18 at 08:56