4

How to make the center of a rotation in tikz evolve in a for loop, given a trigonometrical formula (that I reckon should be quite simple: l*cos and l*sin)?

I am trying to make a scheme of the arm extending, and two joints move. Rotating around the shoulder goes fine, but around the elbow I do not manage to update the center of rotation so that the arm stays coherent:

enter image description here

As you can see the forearm is completely shifted...

The initial rotation center that I set for the elbow does allow me to rotate around the elbow, I only run into trouble when I try to have both.

Under is my code, there's a little preamble in which I define the bones one by one, then there is the quite short document.

\documentclass{standalone}
\usepackage{tikz}    
\usetikzlibrary{calc}

\makeatother

\def\humerusS#1#2#3#4{
    \begin{scope}[shift={#1}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (.81, 6.53) -- (.91, 6.63) -- (1.1, 6.65) -- 
    (1.25, 6.55) -- (1.25, 5.72) -- (1.02,4.6) -- 
    (1.04, 4.14) -- (1.13, 4.2) -- (1.14, 3.92) -- 
    (1.05, 3.84) -- (0.95, 3.84) -- (.83, 3.94) -- 
    (.83, 4.17) -- (.88, 4.52) -- (.90, 4.85) -- 
    (1, 5.37) -- (1.04, 5.66) -- (1.03, 6.05) -- 
    (.85, 6.47) -- (.81, 6.53);
    \end{scope}
}   
\def\claviculaS#1#2#3{
    \begin{scope}[shift={#1}, rotate=#2, scale={#3}, draw opacity=1]        
        \draw (1.02, 6.79) -- (1.19, 6.79) -- (1.33, 6.71) -- 
    (1.7, 6.35) -- (1.62, 6.22) -- (1.52, 6.26) -- 
    (1.52, 6.32) -- (1.4, 6.5) -- (1.24, 6.66) -- 
    (1.16, 6.71) -- (1.02, 6.71) -- (1.02, 6.79);
    \end{scope}
}   
\def\scapulaS#1#2#3{
    \begin{scope}[shift={#1}, rotate=#2, scale={#3}, draw opacity=1]        
        \draw (.02, 5.41) -- (0, 5.5) -- (.08, 6.06) -- 
    (.21, 6.3) -- (.35, 6.43) -- (.46, 6.5) -- 
    (.69, 6.61)--(.83, 6.74)--(.92, 6.76)--(.96, 6.73)--
    (.91, 6.68)--(.8, 6.56)--(.8, 6.48)--(.9, 6.25)--
    (.6, 6.03)--(.41, 5.79)--(.3, 5.6)--(.11, 5.41)--(.02, 5.41);
    \end{scope}
}   
\def\ulnaS#1#2#3#4{
    \begin{scope}[shift={#1}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (.78, 4.19)--(.86, 3.86)--(1.06, 3.3)--(1.21, 2.88)--
    (1.56, 2.12)--(1.83, 1.62)--(1.99, 1.45)--(1.98, 1.38)--
    (1.94, 1.32)--(1.96, 1.24)--(1.9, 1.2)--(1.8, 1.32)--
    (1.75, 1.51)--(1.57, 1.84)--(1.06, 2.8)--(.82, 3.37)--
    (.7, 3.63)--(.6, 4.05)--(.62, 4.16)--(.78, 4.19);
    \end{scope}
}   
\def\radiusS#1#2#3#4{
    \begin{scope}[shift={#1}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (.89, 3.8)--(1.09, 3.82)--(1.13, 3.57)--(1.39, 3.22)--
    (1.68, 2.77)--(1.85,2.44)--(2.08, 1.79)--(2.24, 1.45)--(2.24, 1.36)--
    (1.98, 1.38)--(1.93, 1.55)--(1.86, 1.91)--(1.79, 2.12)--(1.53, 2.72)--
    (1.19, 3.26)--(1.04, 3.41)--(.97, 3.62)--(.89, 3.8);
    \end{scope}
}   
\def\handS#1#2#3#4{
    \begin{scope}[shift={#1}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (1.98, 1.35)--(2.21, 1.36)--(2.32, 1.28)--(2.34, 1.19)--
    (2.66, .77)--(2.67, .73)--(2.62, .75)--(2.32, 1.14)--(2.33, 1.04)--
    (2.72, .24)--(2.72, .19)--(2.68, .22)--(2.3, 1.04)--(2.24, 1.05)--
    (2.25, .97)--(2.6, .05)--(2.6, 0)--(2.56, .03)--(2.21, .99)--
    (2.17, 1.05)--(2.16, .98)--(2.4, .18)--(2.39, .14)--(2.36, .18)--
    (2.11, 1.03)--(2.12, .74)--(2.25, .32)--(2.25, .27)--(2.22, .31)--
    (2.06, .82)--(2.03, 1.21)--(1.97, 1.32)--(1.98, 1.35);
    \end{scope}
}   

\def\repereXY#1#2#3{
    \begin{scope}[shift={#1}, rotate=#2, scale={#3}, draw opacity=1]        
        \draw[->] (0,0) -- (1,0) node[above] {$x$};
        \draw[->] (0,0) -- (0,1) node[above] {$y$};        
    \end{scope}
} 

\begin{document}
\begin{tikzpicture}     
    \node (elbow_flex_0) at (1, 3.97) {};        
    \coordinate (shoulder_flex) at (1.05, 6.5);        

    %do not rotate
    \scapulaS{(0,0)}{0}{1}        
    \claviculaS{(0,0)}{0}{1}        

    \foreach \sf in {0,1,...,30} {
        \humerusS{(0,0)}{\sf}{(shoulder_flex)}{1}        

        %\node (elbow_flex) at ([rotate around={\sf:(shoulder_flex)}]elbow_flex_0) {};        
        \path (elbow_flex_0) ++({3.56*sin(\sf)}:{-3.56*cos(\sf)}) node (elbow_flex) {}; 

        \def\ef{50}
        %\foreach \ef in {55,56,...,69} {
            \radiusS{(elbow_flex)}{\ef}{(elbow_flex)}{1}        
            \ulnaS{(elbow_flex)}{\ef}{(elbow_flex)}{1}        
            \handS{(elbow_flex)}{\ef}{(elbow_flex)}{1}     
        %}   
    }

    %reference frame
    \repereXY{(4,5.5)}{0}{.5}      

\end{tikzpicture}
\end{document}
6

Your problem is I think that in the definition of \radiusS/\ulnaS/\handS, the coordinate (0,0) is far away from the pivot point of the lower arm.

What I mean is, that when you do shift=(elbow_flex) in the options to a scope, the effect is that the vector (elbow_flex) is added to every point in the scope, so it is the coordinate (0,0) in the scope that ends up at elbow_flex.

But, in for example \radiusS, the upper end of the bone is at coordinates around (0.9,3.8), so after shifting it ends up far away.

I'll leave it up to you to figure out the correct coordinates, but as an example, if you modify the three macros for the lower arm, so that the shifting looks like

shift={($#1+(-0.89,-3.8)$)}

and remove the \path that (re)defines elbow_flex, the output becomes this:

output of code

\documentclass{standalone}
\usepackage{tikz}    
\usetikzlibrary{calc}

\makeatother

\def\humerusS#1#2#3#4{
    \begin{scope}[shift={#1}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (.81, 6.53) -- (.91, 6.63) -- (1.1, 6.65) -- 
    (1.25, 6.55) -- (1.25, 5.72) -- (1.02,4.6) -- 
    (1.04, 4.14) -- (1.13, 4.2) -- (1.14, 3.92) -- 
    (1.05, 3.84) -- (0.95, 3.84) -- (.83, 3.94) -- 
    (.83, 4.17) -- (.88, 4.52) -- (.90, 4.85) -- 
    (1, 5.37) -- (1.04, 5.66) -- (1.03, 6.05) -- 
    (.85, 6.47) -- (.81, 6.53);
    \end{scope}
}   
\def\claviculaS#1#2#3{
    \begin{scope}[shift={#1}, rotate=#2, scale={#3}, draw opacity=1]        
        \draw (1.02, 6.79) -- (1.19, 6.79) -- (1.33, 6.71) -- 
    (1.7, 6.35) -- (1.62, 6.22) -- (1.52, 6.26) -- 
    (1.52, 6.32) -- (1.4, 6.5) -- (1.24, 6.66) -- 
    (1.16, 6.71) -- (1.02, 6.71) -- (1.02, 6.79);
    \end{scope}
}   
\def\scapulaS#1#2#3{
    \begin{scope}[shift={#1}, rotate=#2, scale={#3}, draw opacity=1]        
        \draw (.02, 5.41) -- (0, 5.5) -- (.08, 6.06) -- 
    (.21, 6.3) -- (.35, 6.43) -- (.46, 6.5) -- 
    (.69, 6.61)--(.83, 6.74)--(.92, 6.76)--(.96, 6.73)--
    (.91, 6.68)--(.8, 6.56)--(.8, 6.48)--(.9, 6.25)--
    (.6, 6.03)--(.41, 5.79)--(.3, 5.6)--(.11, 5.41)--(.02, 5.41);
    \end{scope}
}   
\def\ulnaS#1#2#3#4{
    \begin{scope}[shift={($#1+(-0.89,-3.8)$)}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (.78, 4.19)--(.86, 3.86)--(1.06, 3.3)--(1.21, 2.88)--
    (1.56, 2.12)--(1.83, 1.62)--(1.99, 1.45)--(1.98, 1.38)--
    (1.94, 1.32)--(1.96, 1.24)--(1.9, 1.2)--(1.8, 1.32)--
    (1.75, 1.51)--(1.57, 1.84)--(1.06, 2.8)--(.82, 3.37)--
    (.7, 3.63)--(.6, 4.05)--(.62, 4.16)--(.78, 4.19);
    \end{scope}
}   
\def\radiusS#1#2#3#4{
    \begin{scope}[shift={($#1+(-0.89,-3.8)$)}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (.89, 3.8)--(1.09, 3.82)--(1.13, 3.57)--(1.39, 3.22)--
    (1.68, 2.77)--(1.85,2.44)--(2.08, 1.79)--(2.24, 1.45)--(2.24, 1.36)--
    (1.98, 1.38)--(1.93, 1.55)--(1.86, 1.91)--(1.79, 2.12)--(1.53, 2.72)--
    (1.19, 3.26)--(1.04, 3.41)--(.97, 3.62)--(.89, 3.8);
    \end{scope}
}   
\def\handS#1#2#3#4{
    \begin{scope}[shift={($#1+(-0.89,-3.8)$)}, rotate around={#2:#3}, scale={#4}, draw opacity=1]        
        \draw[fill=white] (1.98, 1.35)--(2.21, 1.36)--(2.32, 1.28)--(2.34, 1.19)--
    (2.66, .77)--(2.67, .73)--(2.62, .75)--(2.32, 1.14)--(2.33, 1.04)--
    (2.72, .24)--(2.72, .19)--(2.68, .22)--(2.3, 1.04)--(2.24, 1.05)--
    (2.25, .97)--(2.6, .05)--(2.6, 0)--(2.56, .03)--(2.21, .99)--
    (2.17, 1.05)--(2.16, .98)--(2.4, .18)--(2.39, .14)--(2.36, .18)--
    (2.11, 1.03)--(2.12, .74)--(2.25, .32)--(2.25, .27)--(2.22, .31)--
    (2.06, .82)--(2.03, 1.21)--(1.97, 1.32)--(1.98, 1.35);
    \end{scope}
}   

\def\repereXY#1#2#3{
    \begin{scope}[shift={#1}, rotate=#2, scale={#3}, draw opacity=1]        
        \draw[->] (0,0) -- (1,0) node[above] {$x$};
        \draw[->] (0,0) -- (0,1) node[above] {$y$};        
    \end{scope}
} 

\begin{document}
\begin{tikzpicture}     
    \node (elbow_flex_0) at (1, 3.97) {};        
    \coordinate (shoulder_flex) at (1.05, 6.5);        

    %do not rotate
    \scapulaS{(0,0)}{0}{1}        
    \claviculaS{(0,0)}{0}{1}        

    \foreach \sf in {0,1,...,30} {
        \humerusS{(0,0)}{\sf}{(shoulder_flex)}{1}        

        \node(elbow_flex) at ([rotate around={\sf:(shoulder_flex)}]elbow_flex_0) {};        
%        \path (elbow_flex_0) ++({3.56*sin(\sf)}:{-3.56*cos(\sf)}) node (elbow_flex) {}; 

        \def\ef{50}
        %\foreach \ef in {55,56,...,69} {
            \radiusS{(elbow_flex)}{\ef}{(elbow_flex)}{1}        
            \ulnaS{(elbow_flex)}{\ef}{(elbow_flex)}{1}        
            \handS{(elbow_flex)}{\ef}{(elbow_flex)}{1}     
%        %}   
    }

    %reference frame
    \repereXY{(4,5.5)}{0}{.5}      

\end{tikzpicture}
\end{document}
  • Ah ok, thank you very much. I do not fully understanding the scopes yet, they're convenient but at the same time I find myself hard coding a lot of stuff empirically. Also it's weird to nest them. Anyhow, thank you again for your solution! – Pierre Dec 22 '17 at 9:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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