# Why are the lines off, when tikzpicture is rotated?

OK, I have some rather long code. I tried to reduce it as much as I could, but it's heavily tangled and I'm still not good in the usage of pgfkeys or xparse.

The problem: If the tikzpicture is rotated by any non-multiple of 90° the lines are off. If the tikzpicture is rotated by any multiple of 90° the lines are fine.

Why is that and how can i prevent it?

%%%%%%%%%%%%%% Common file
\documentclass{standalone}
\usepackage{etoolbox}

%Declare Macros for each floor to be defined by the building files. They are of the form: \ESKFPfloorEG, \ESKFPernEG, \ESKFPlabelsEG
\newcommand{\ESKFPcreatefloor}[1]{%
\expandafter\def\csname ESKFPfloor#1\endcsname{nothing defined}
}
\ESKFPcreatefloor{EG}

% Define Macros for the current floor to be used by the room files.
\newcommand{\ESKFPcurrentfloorcommand}{none}
\newcommand{\ESKFPsetfloor}[1]{%
\renewcommand{\ESKFPcurrentfloorcommand}{\csname ESKFPfloor#1\endcsname}
}

\newcommand{\ESKFPcurrentroom}{0}
\newcommand{\ESKFPsetroom}[1]{
\renewcommand{\ESKFPcurrentroom}{#1}
}

\newcommand{\ESKFPdoorata}{0}
\newcommand{\ESKFPdooratb}{0}
\newcommand{\ESKFPdooratc}{0}
\newcommand{\ESKFPdooratd}{0}
\newcommand{\ESKFPdoorapos}{\ifnumequal{\ESKFPdoorata}{1}{0.75}{0.25}}
\newcommand{\ESKFPdoorbpos}{\ifnumequal{\ESKFPdooratb}{1}{0.75}{0.25}}
\newcommand{\ESKFPdoorcpos}{\ifnumequal{\ESKFPdooratc}{1}{0.75}{0.25}}
\newcommand{\ESKFPdoordpos}{\ifnumequal{\ESKFPdooratd}{1}{0.75}{0.25}}
\newcommand{\ESKFPmisceins}{1}
\newcommand{\ESKFPmisczwei}{2}
\newcommand{\ESKFPmiscnull}{0}
\newcommand{\ESKFPcurrentexitdoorat}{0}

\newcounter{ESKFPcurrentdoor}
\setcounter{ESKFPcurrentdoor}{0}

\makeatletter
\long\def\ESKFPifnodedefined#1#2#3{%
\@ifundefined{pgf@sh@ns@#1}{#3}{#2}%
}
\makeatother

\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes.geometric}

\tikzset{%
every node/.style={outer sep=0pt},
ESKFPdoorcommonstyle/.style={%
transform shape,
text width=,
circular sector,
sloped,
allow upside down,
anchor=sector center,
circular sector angle=90,
draw,
minimum size=200pt,
},
ESKFPdoorstyle1/.style={%
pos=#1,
fill=yellow,
ESKFPdoorcommonstyle,
yscale=-1,
rotate=45,
},ESKFPdoorstyle1/.default=0.75,
ESKFPdoorstyle2/.style={%
pos=#1,
fill=blue,
ESKFPdoorcommonstyle,
%  xscale=-1,
rotate=225
},ESKFPdoorstyle2/.default=0.25,
door1/.style={ESKFPdoorstyle1},
door2/.style={ESKFPdoorstyle2},
ESKFPnothighlightedstyle/.style={fill=white},
ESKFPhighlightedstyle/.style={fill=red},
ESKFPexitdoorstyle/.style={%
alias=ESKFPcurrentexitdoor
},
exitdoor/.style={ESKFPexitdoorstyle},
ESKFProomstyle/.style={ultra thick,fill=white,ESKFPcommonroomstyle},
ESKFPemptyroomstyle/.style={fill=none,ESKFPcommonroomstyle},
ESKFPcommonroomstyle/.style={draw},
ESKFPelsestyle/.style={ESKFPcommonroomstyle},
ESKFProomtextstyle/.style={inner sep=0pt,outer sep=0pt,font={\bfseries}},
ESKFPbackgroundstyle/.style={fill=green!50!white},
set door at 1/.code={\renewcommand{\ESKFPdoorata}{#1}},
set door at 2/.code={\renewcommand{\ESKFPdooratb}{#1}},
set door at 3/.code={\renewcommand{\ESKFPdooratc}{#1}},
set door at 4/.code={\renewcommand{\ESKFPdooratd}{#1}},
set door at 1/.default=1,
set door at 2/.default=1,
set door at 3/.default=1,
set door at 4/.default=1,
set exit door/.code={\renewcommand{\ESKFPcurrentexitdoorat}{#1}},
set exit door/.default=0,
set door 1 pos/.code={\renewcommand{\ESKFPdoorapos}{#1}},
set door 2 pos/.code={\renewcommand{\ESKFPdoorbpos}{#1}},
set door 3 pos/.code={\renewcommand{\ESKFPdoorcpos}{#1}},
set door 4 pos/.code={\renewcommand{\ESKFPdoordpos}{#1}},
set door 1 pos/.default=0.5,
set door 2 pos/.default=0.5,
set door 3 pos/.default=0.5,
set door 4 pos/.default=0.5,
}
%Layers of the Graphic
\pgfdeclarelayer{background}
\pgfdeclarelayer{rooms}
\pgfdeclarelayer{text}
\pgfdeclarelayer{test}
\pgfsetlayers{background,main,rooms,text,test}

%Highlightingstyle
\newcommand{\ESKFPdoifhighlighted}{%
\tikzset{ESKFPcurrentroomstyle/.style={ESKFPhighlightedstyle}}
}
\newcommand{\ESKFPdoifnothighlighted}{%
\tikzset{ESKFPcurrentroomstyle/.style={ESKFPnothighlightedstyle}}
}

\newcommand{\ESKFPcreateroom}[5][]{%#1=local tikz options,#2=name,#3=room number,#4=path with doors,#5=text coordinate
%The path has to be defined counter clockwise. Otherwise, the doors would be outside the room.
%To force the doors to be outside the room, use the option "shape border rotate=90" or "shape border rotate=270"
%If #5 is empty, than it is assumed, that the room has corners at the coordinates ESKFPc#2lu,ESKFPc#2ru, ESKFPc#2lo and ESKFPc#2ro and the text will be positioned at the barycentre of these 4 points.

%Find out, if room has to be highlighted or not
\ifdefmacro{#2}%
{\ifdefstrequal{\ESKFPcurrentroom}{#2}{\ESKFPdoifhighlighted}{\ESKFPdoifnothighlighted}}
{\ifdefstring{\ESKFPcurrentroom}{#2}{\ESKFPdoifhighlighted}{\ESKFPdoifnothighlighted}}
%Apply given options in a local scope
\begin{scope}[#1]
\ifstrempty{#4}
{%
\setcounter{ESKFPcurrentdoor}{0}
\draw[ESKFProomstyle,ESKFPcurrentroomstyle,%
to path=%
{% the following adds the doors, if specified. This definition resides in the macros \ESKFPdoorata, \ESKFPdooratb, \ESKFPdooratc, \ESKFPdooratd and can have the values 1,2 or anything else
\pgfextra{\stepcounter{ESKFPcurrentdoor}}
\ifcsequal{ESKFPdoorat\alph{ESKFPcurrentdoor}}{ESKFPmisceins}
{--node(ESKFProom#2door\the\value{ESKFPcurrentdoor})[door1,pos=\csname ESKFPdoor\alph{ESKFPcurrentdoor}pos\endcsname]{}(\tikztotarget)\tikztonodes}
{%
\ifcsequal{ESKFPdoorat\alph{ESKFPcurrentdoor}}{ESKFPmisczwei}
{--node(ESKFProom#2door\the\value{ESKFPcurrentdoor})[door2,pos=\csname ESKFPdoor\alph{ESKFPcurrentdoor}pos\endcsname]{}(\tikztotarget)\tikztonodes}
{--(\tikztotarget)\tikztonodes}
}
}
]%
(ESKFPc#2lu)to(ESKFPc#2ru)to(ESKFPc#2ro)to(ESKFPc#2lo)to(ESKFPc#2lu)--cycle;
\ifnumgreater{\ESKFPcurrentexitdoorat}{0}
{\coordinate(ESKFProom#2exitdoor) at ($(ESKFProom#2door\ESKFPcurrentexitdoorat.sector center)!0.5!(ESKFProom#2door\ESKFPcurrentexitdoorat.arc start)$);}%Exit door is defined, that door will be used. It is assumed, that this door is indeed defined.
{%
\ESKFPifnodedefined{ESKFProom#2door1}{\coordinate(ESKFProom#2exitdoor) at ($(ESKFProom#2door1.sector center)!0.5!(ESKFProom#2door1.arc start)$);}
{
\ESKFPifnodedefined{ESKFProom#2door2}{\coordinate(ESKFProom#2exitdoor) at ($(ESKFProom#2door2.sector center)!0.5!(ESKFProom#2door2.arc start)$);}
{
\ESKFPifnodedefined{ESKFProom#2door3}{\coordinate(ESKFProom#2exitdoor) at ($(ESKFProom#2door3.sector center)!0.5!(ESKFProom#2door3.arc start)$);}
{
\ESKFPifnodedefined{ESKFProom#2door4}{\coordinate(ESKFProom#2exitdoor) at ($(ESKFProom#2door4.sector center)!0.5!(ESKFProom#2door4.arc start)$);}
{
\coordinate(ESKFProom#2exitdoor) at ($(ESKFPc#2lu)!0.5!(ESKFPc#2ro)$);
}
}
}
}
}
}
{%Path is supplied, especially a door with the style ESKFPexitdoorstyle must be given
%Also the coordinates ESKFPc[ROOMNAME]lu, ESKFPc[ROOMNAME]ru, ESKFPc[ROOMNAME]lo and ESKFPc[ROOMNAME]ro should be defined
\draw[ESKFProomstyle,ESKFPcurrentroomstyle]{#4}--cycle;
\coordinate(ESKFProom#2exitdoor) at (ESKFPcurrentexitdoor);
}

\ifstrempty{#5}
{\coordinate(ESKFProom#2textcenter) at ($0.25*(ESKFPc#2lu)+0.25*(ESKFPc#2ru)+0.25*(ESKFPc#2lo)+0.25*(ESKFPc#2ro)$);}
{\coordinate(ESKFProom#2textcenter) at #5;}

%Text (room number is set), the coordinate ESKFProom[ROOMNAME]textcenter is calculated before. This is #5 or is calculated from ESKFPc[ROOMNAME]lu, ESKFPc[ROOMNAME]ru, ESKFPc[ROOMNAME]lo and ESKFPc[ROOMNAME]ro if not given
\begin{pgfonlayer}{text}
\end{pgfonlayer}
\end{scope}
}

\newcommand{\ESKFPcreateelse}[5][]{%#1=local tikz options,#2=name,#3=room number,#4=path with doors,#5=text coordinate
%The path has to be defined counter clockwise. Otherwise, the doors would be outside the room.
%To force the doors to be outside the room, use the option "shape border rotate=90" or "shape border rotate=270"
%If #5 is empty, than it is assumed, that the room has corners at the coordinates ESKFPc#2lu,ESKFPc#2ru, ESKFPc#2lo and ESKFPc#2ro and the text will be positioned at the barycentre of these 4 points.

%Apply given options in a local scope
\begin{scope}[#1]
%Test if path is given
\ifstrempty{#4}
{%If Path is NOT given
\setcounter{ESKFPcurrentdoor}{0}
\draw[ESKFPelsestyle,%
to path=%
{% the following adds the doors, if specified. This definition resides in the macros \ESKFPdoorata, \ESKFPdooratb, \ESKFPdooratc, \ESKFPdooratd and can have the values 1,2 or anything else
\pgfextra{\stepcounter{ESKFPcurrentdoor}}
\ifcsequal{ESKFPdoorat\alph{ESKFPcurrentdoor}}{ESKFPmisceins}
{--node(ESKFPstairs#2door\the\value{ESKFPcurrentdoor})[door1,pos=\csname ESKFPdoor\alph{ESKFPcurrentdoor}pos\endcsname]{}(\tikztotarget)\tikztonodes}
{%
\ifcsequal{ESKFPdoorat\alph{ESKFPcurrentdoor}}{ESKFPmisczwei}
{--node(ESKFPstairs#2door\the\value{ESKFPcurrentdoor})[door2,pos=\csname ESKFPdoor\alph{ESKFPcurrentdoor}pos\endcsname]{}(\tikztotarget)\tikztonodes}
{--(\tikztotarget)\tikztonodes}
}
}
]%
(ESKFPc#2lu)to(ESKFPc#2ru)to(ESKFPc#2ro)to(ESKFPc#2lo)to(ESKFPc#2lu)--cycle;
}
{%If Path IS given. A door with the style ESKFPexitdoorstyle must be given
%Also the coordinates ESKFPc[ROOMNAME]lu, ESKFPc[ROOMNAME]ru, ESKFPc[ROOMNAME]lo and ESKFPc[ROOMNAME]ro should be defined
\draw[ESKFPelsestyle]{#4}--cycle;
}

\ifstrempty{#5}%Test if coordinate for Text is given
{\coordinate(ESKFPstairs#2textcenter) at ($0.25*(ESKFPc#2lu)+0.25*(ESKFPc#2ru)+0.25*(ESKFPc#2lo)+0.25*(ESKFPc#2ro)$);}%If textcoordinate is NOT given
{\coordinate(ESKFPstairs#2textcenter) at #5;}%If textcoordinate is given
%Text (room number is set), the coordinate ESKFProom[ROOMNAME]textcenter is calculated before. This is #5 or is calculated from ESKFPc[ROOMNAME]lu, ESKFPc[ROOMNAME]ru, ESKFPc[ROOMNAME]lo and ESKFPc[ROOMNAME]ro if not given
\begin{pgfonlayer}{text}
\end{pgfonlayer}
\end{scope}
}

%%%%%% Floor file

\newcommand{\ESKFPfloorGSEG}{%
\begin{scope}[scale=0.1]
%A101
\coordinate(ESKFPcA101lu) at (0,0);
\coordinate(ESKFPcA101ru) at (136,0);
\coordinate(ESKFPcA101ro) at (136,127);
\coordinate(ESKFPcA101lo) at (0,127);
%A102
\coordinate(ESKFPcA102lu) at (ESKFPcA101lo);
\coordinate(ESKFPcA102ru) at (ESKFPcA101ro);
\coordinate(ESKFPcA102lo) at ($(ESKFPcA101lo)+(0,90)$);
\coordinate(ESKFPcA102ro) at ($(ESKFPcA101ro)+(0,90)$);
%A103
\coordinate(ESKFPcA103lu) at (ESKFPcA102lo);
\coordinate(ESKFPcA103ru) at (ESKFPcA102ro);
\coordinate(ESKFPcA103lo) at ($(ESKFPcA102lo)+(0,90)$);
\coordinate(ESKFPcA103ro) at ($(ESKFPcA102ro)+(0,90)$);
%A104
\coordinate(ESKFPcA104lu) at (ESKFPcA103lo);
\coordinate(ESKFPcA104ru) at (ESKFPcA103ro);
\coordinate(ESKFPcA104lo) at ($(ESKFPcA103lo)+(0,120)$);
\coordinate(ESKFPcA104ro) at ($(ESKFPcA103ro)+(0,120)$);
%STA2CAFE
\coordinate(ESKFPcSTA2CAFElu) at ($(ESKFPcA104ro)+(0,-30)$);
\coordinate(ESKFPcSTA2CAFElo) at ($(ESKFPcA104ro)+(0,30)$);
\coordinate(ESKFPcSTA2CAFEru) at ($(ESKFPcSTA2CAFElu)+(120,0)$);
\coordinate(ESKFPcSTA2CAFEro) at ($(ESKFPcSTA2CAFElo)+(120,0)$);

%Rooms
\begin{pgfonlayer}{rooms}
%Left side
\ESKFPcreateroom[set door at 2,set exit door=2]{A101}{A101}{}{}
\ESKFPcreateroom[set door at 1,set door at 2=2,set exit door=2]{A102}{A102}{}{}
\ESKFPcreateroom[set door at 1,set door at 2,set exit door=2]{A103}{A103}{}{}
\ESKFPcreateroom[set door at 1,set door at 2=2,set exit door=2]{A104}{A104}{}{}
%Top side
\ESKFPcreateelse[stairs]{STA2CAFE}{To Cafeteria}{}{}
%
\ESKFPcreateelse{EMPTYA2CAFE}{}{(ESKFPcSTA2CAFElu)coordinate(ESKFPcEMPTYA2CAFElo)--++(0,-30)coordinate(ESKFPcEMPTYA2CAFElu)--node(ESKFPdoorEMPTYA2CAFEleft)[door2]{}node(ESKFPdoorEMPTYA2CAFEright)[door1]{}++(120,0)coordinate(ESKFPcEMPTYA2CAFEru)--++(0,30)coordinate(ESKFPcEMPTYA2CAFEro)}{(0,0)}%No Text to be set
%
\ESKFPcreateelse[stairs]{STAEG2AOGINEARCAFE}{Stairs}{($(ESKFPcSTA2CAFEro)+(0,-30)$)coordinate(ESKFPcSTAEG2AOGINEARCAFElo)--++(0,-120)coordinate(ESKFPcSTAEG2AOGINEARCAFElu)--node(ESKFPdoorSTAEG2AOGINEARCAFEleft)[door2]{}node(ESKFPdoorSTAEG2AOGINEARCAFEright)[door1]{}++(80,0)coordinate(ESKFPcSTAEG2AOGINEARCAFEru)--++(0,120)coordinate(ESKFPcSTAEG2AOGINEARCAFEro)--node(ESKFPdoorSTAEG2AOGINEARCAFEout)[door1,pos=0.25,rotate=180]{}(ESKFPcSTAEG2AOGINEARCAFElo)}{}
\end{pgfonlayer}
\end{scope}

%Backgroundlayer
\begin{pgfonlayer}{background}
\fill[ESKFPbackgroundstyle](ESKFPcA101lu)rectangle(ESKFPcSTAEG2AOGINEARCAFEro);
\end{pgfonlayer}
}
\let\ESKFPfloorEG\ESKFPfloorGSEG

%%%%%%%%%%%Actual Room file

\ESKFPsetfloor{EG}
\ESKFPsetroom{A102}

\begin{document}
\begin{tikzpicture}[mystyle/.style={ESKFPcurrentfloorstyle},rotate=45]
\ESKFPcurrentfloorcommand
\begin{pgfonlayer}{test}
\draw[red](ESKFProomA101exitdoor)to[in=0,out=0](ESKFProomA102exitdoor);
\end{pgfonlayer}
\end{tikzpicture}
\end{document}

-
Which lines are off? – Jake Jun 28 '13 at 20:45
All the lines. If one compiles the file without rotate=45 in the tikzpicture, then there are no gaps between lines that should be equal. But if one compiles the file with rotate=45, then there are these gaps. – Toscho Jun 29 '13 at 8:50

The problem seems to be floating point rounding when performing the calculations --- if one instead rotates the entire picture as a unit, rather than each individually, things seem to line up fine. Change line 294 to something like:

\rotatebox{13}{\begin{tikzpicture}[mystyle/.style={ESKFPcurrentfloorstyle}]


and close the group at the end of line 299:

\end{tikzpicture}}


and you'll be able to arbitrarily rotate it and still have things line up.

-
OK, I also guessed, that it was about the rounding. I just didn't guess, that it would be clearly visible. The problem of your solution is, that the text rotates as well. This should not happen. – Toscho Jul 3 '13 at 15:23
Okay, in that case, you'll need to apply the negative of the rotation to all the text elements in the tikz image (obviously) --- that's left as an exercise for the reader. – WillAdams Jul 3 '13 at 15:38