Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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{\ESKFPcurrentadditionaltext}{}


\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},
ESKFPstairsstyle/.style={ultra thick,fill=green!80!black,ESKFPcommonroomstyle},
ESKFPelsestyle/.style={ESKFPcommonroomstyle},
stairs/.style={ESKFPelsestyle/.style={ESKFPstairsstyle}},
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.
{%
 \renewcommand{\ESKFPcurrentadditionaltext}{Exit door guessed}
 \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)$);
     \renewcommand{\ESKFPcurrentadditionaltext}{No exit door}
    }
   }
  }
 }
}
}
{%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}
\node[ESKFProomtextstyle](ESKFProom#2text) at (ESKFProom#2textcenter) {#3\ESKFPcurrentadditionaltext};
\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}
\node[ESKFProomtextstyle](ESKFPstairs#2text) at (ESKFPstairs#2textcenter) {#3\ESKFPcurrentadditionaltext};
\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}
share|improve this question
2  
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
add comment

1 Answer

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.

zoomed in on an area which was failing to align

share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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