2

I am trying to draw a cannon with a superposition of a triangle, circle and rectangle. I need it rotated, so I realized that when I draw a rotated shape, it doesn't read the old coordinate system, but a new rotated one instead.

I thought that a simple math would keep track on the desired coordinate. So I defined \rotx and \roty functions to help in the transformations. When I do \rot{0}, everything is fine. But when I do \rot{30} or any other angle, the shape assumes undesired form.

My question is: how to handle rotated coordinates in Tikz?

My code as example:

\begin{tikzpicture}
%-> USEFUL DEFINITIONS
\def\fs{0.1} %... fence width and height
\def\th{2} %... tower height
\def\wh{1} %... wall height
\def\cp{4.5} %... canon position
\def\cr{0.2} %... canon radius
%-> x-rotation (#1=x, #2=y, $3=angle)$
\def\rotx#1#2#3{#1*cos(#3)+#2*sin(#3)}
\def\roty#1#2#3{-#1*sin(#3)+#2*cos(#3)}
\def\rot{30}

%----------> END DEFINITIONS <----------%


%-> DRAW THE FLOOR
\fill[gray!50]
    (-5,-\fs) rectangle(2,0)
    ;

%-> DRAW THE CANNON
\fill[gray!50]
    (-\cp-\cr,0)--
        (-\cp+\cr,0)--
        (-\cp,\cr)--cycle
    (-\cp-\cr/2,3*\cr/2) circle(\cr)
    ;
\fill[gray!50,rotate=\rot]
    ({\rotx{-4.5}{0.2}{\rot}},{\roty{-4.5}{0.2}{\rot}})
        rectangle({\rotx{-4}{0.6}{\rot}},{\roty{-4}{0.6}{\rot}})
%    ({\rotx{-\cp}{3*\cr/2}{0}},
%        {\roty{-\cp}{3*\cr/2}{0}})
%            rectangle({\rotx{-\cp+3*\cr}{5*\cr/2}{0}},
%                {\roty{-\cp+3*\cr}{5*\cr/2}{0}})
    ;

%-> DRAW THE CASTLE
\fill[gray!50]
%... tower
    (0,0) rectangle(5*\fs,\th)
    ;
\foreach \x in {0,0.2,...,0.4}
    \fill[gray!50]
        (\x,\th) rectangle(\x+\fs,\th+\fs)
        ;
%... wall
\fill[gray!50]
    (5*\fs,0) rectangle(20*\fs,\wh)
    ;
\foreach \x in {0.6,0.8,...,1.8}
    \fill[gray!50]
        (\x,\wh) rectangle(\x+\fs,\wh+\fs)
        ;
\end{tikzpicture}
  • I guess you only need transform shape and nest the transformations in scopes (or, if you are confident enough, add them successively). – user121799 Oct 16 '18 at 0:00
  • Hi, @marmot. Thank you for the response. But I still have no idea on how to do this. – Brasil Oct 16 '18 at 0:05
  • My problem is that I do not precisely what the problem is. As far as I can see, \rotx and \roty are just coordinates of a given angle at an elliptic arc. This can be done much easier. Could you perhaps try to explain more precisely what you want? (And sorry, I will decouple soon but get back in 2h.) BTW, nice castle, +1 for that. ;-) – user121799 Oct 16 '18 at 0:08
  • @marmot, I want to rotate the cannon as if it were firing into the castle. I find easy to draw it in the horizontal or vertical, but not at any other angle because coordinates change with rotation. – Brasil Oct 16 '18 at 0:17
  • @marmot in other way, I would like to draw a rotated shape (in this case the rectangle) at a desired position (at the cannon) and with desired width/height. The problem I face here is that I only know how to rotate the shape [argument of ´\fill´] before entering the coordinates, which causes the coordinates I previously knew become unknown. – Brasil Oct 16 '18 at 0:28
3

I probably miss something basic but how about just drawing a line of a certain width from the center of the cannon circle in a given direction? And I would use a pic for that, which prevents you from adding the horizontal position to all coordinates.

\documentclass[tikz,border=3.14mm]{standalone}
\begin{document}
\begin{tikzpicture}
%-> USEFUL DEFINITIONS
\def\fs{0.1} %... fence width and height
\def\th{2} %... tower height
\def\wh{1} %... wall height
\def\cp{4.5} %... canon position
\def\cr{0.2} %... canon radius
%-> x-rotation (#1=x, #2=y, $3=angle)$
\tikzset{pics/cannon/.style={code={
\fill[gray!50]
    (-\cr,0)--
        (+\cr,0)--
        (0,\cr)--cycle
    (-\cr/2,3*\cr/2) circle(\cr)
    ;
\draw[gray!50,line width=1mm](-\cr/2,3*\cr/2) -- ++(#1:1);  
}}}


%----------> END DEFINITIONS <----------%


%-> DRAW THE FLOOR
\fill[gray!50]
    (-5,-\fs) rectangle(2,0)
    ;

\pic at (-\cp,0) {cannon=30};

%-> DRAW THE CASTLE
\fill[gray!50]
%... tower
    (0,0) rectangle(5*\fs,\th)
    ;
\foreach \x in {0,0.2,...,0.4}
    \fill[gray!50]
        (\x,\th) rectangle(\x+\fs,\th+\fs)
        ;
%... wall
\fill[gray!50]
    (5*\fs,0) rectangle(20*\fs,\wh)
    ;
\foreach \x in {0.6,0.8,...,1.8}
    \fill[gray!50]
        (\x,\wh) rectangle(\x+\fs,\wh+\fs)
        ;
\end{tikzpicture}
\end{document}

enter image description here

  • Wow! A really great and simpler idea! I will try it and see how it works. Then I can check your answer as the solution to this problem! Thank you! – Brasil Oct 16 '18 at 13:45
  • Ah! Could you please explain the role of \tikzset? I am just starting to tikz, so I still don't know a looot of things. Thank you again! – Brasil Oct 16 '18 at 13:48
  • @Brasil \tikzset is a shortcut for a pgfkeys command. What it does is to allow you to define a style or code. In this example, it is used to define the pic. You can define the style of nodes in a similar fashion etc. – user121799 Oct 16 '18 at 13:59
0

I present here a work around of the problem. As the drawing is the aim, it can be considered as a solution. Instead of trying to get the rotated coordinates of the rectangle, I simply used closed paths generating the desired rectangle of the canon.

I even used the very same idea to rotate the starburst and the velocity vector.

\begin{tikzpicture}
%-> USEFUL DEFINITIONS
\def\fs{0.1} %... fence width and height
\def\th{2} %... tower height
\def\wh{1} %... wall height
\def\cp{4.5} %... canon position
\def\cr{0.1} %... canon radius
\def\cl{0.3} %... canon length
\def\rot{45}

%----------> END DEFINITIONS <----------%


%-> DRAW THE FLOOR
\fill[gray!50]
    (-5,-\fs) rectangle(2,0)
    ;

%-> DRAW THE CANNON
\fill[gray!50]
    (-\cp-\cr,0)--
        (-\cp+\cr,0)--
        (-\cp,\cr)--cycle
    (-\cp-\cr/2,3*\cr/2) circle(\cr)
    ;
\fill[gray!50]
    (-\cp-\cr/2,3*\cr/2)--++
        ({\rot-90}:\cr)--++
        (\rot:\cl)--++
        ({\rot+90}:2*\cr)--++
        ({\rot+180}:\cl)--cycle
    ;

\begin{scope}
\clip
    ({-\cp-\cr/2+\cl*cos(\rot)},{3*\cr/2+\cl*sin(\rot)})--++
        ({\rot-90}:5*\cr)--++
        (\rot:5*\cr)--++
        ({\rot+90}:11*\cr)--++
        ({\rot+180}:5*\cr)--cycle
    ;
\node[starburst, draw, minimum width=\cr mm, minimum height=\cr mm, white, fill=gray!50] at ({-\cp-\cr/2+\cl*cos(\rot)},{3*\cr/2+\cl*sin(\rot)}) {};
\end{scope}

%... the vectors
\draw[->, very thick, gray!50]
    ({-\cp-\cr/2+\cl*cos(\rot)},{3*\cr/2+\cl*sin(\rot)})--
        ({-\cp-\cr/2+3*\cl*cos(\rot)},{3*\cr/2+3*\cl*sin(\rot)})
        node[above left]{$v_0$}
    ;
\draw[<->, gray!50]
    (-0.2,0)--
        (-0.2,\th) node[midway, fill=white]{$h$}
    ;
\draw[<->, gray!50]
    (-\cp,-0.4)--
        (0,-0.4) node[midway, fill=white]{$d$}
    ;


%-> DRAW THE CASTLE
\fill[gray!50]
%... tower
    (0,0) rectangle(5*\fs,\th)
    ;
\foreach \x in {0,0.2,...,0.4}
    \fill[gray!50]
        (\x,\th) rectangle(\x+\fs,\th+\fs)
        ;
%... wall
\fill[gray!50]
    (5*\fs,0) rectangle(20*\fs,\wh)
    ;
\foreach \x in {0.6,0.8,...,1.8}
    \fill[gray!50]
        (\x,\wh) rectangle(\x+\fs,\wh+\fs)
        ;

%-> DRAW THE BRICKS
\foreach \y in {0,0.2,...,\th}
    \foreach \x in {0,0.2,...,2}
        \draw[white]
            (\x,\y) rectangle(\x+2*\fs,\y+\fs)
            ;
\foreach \y in {0.1,0.3,...,\th}
    \foreach \x in {0.1,0.3,...,2}
        \draw[white]
            (\x,\y) rectangle(\x+2*\fs,\y+\fs)
            ;
\end{tikzpicture}

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.