% \iffalse meta-comment
%
% File: sunpath.dtx Copyright (C) 2019 Hong-Phuc Bui
%
% It may be distributed and/or modified under the conditions of the
% LaTeX Project Public License (LPPL), either version 1.3c of this
% license or (at your option) any later version.  The latest version
% of this license is in the file
%
%    https://www.latex-project.org/lppl.txt
%
%
% -----------------------------------------------------------------------
%
% The development version of the bundle can be found at
%
%    https://github.com/hpb-htw/sunpath
%
% for those people who are interested.
%
% -----------------------------------------------------------------------
% \fi
%
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[2018/12/01]
%<package>\ProvidesPackage{sunpath}[2024/10/10 v0.1-Alpha Draw Sun Path]
% \fi

% \changes{v0.1-Alpha}
%         {2024/10/10}
%         {Initial implementation}


% \section{Implementation}
%
% \subsection{Package Dependenies}
%
%    \begin{macrocode}
\RequirePackage{expl3}
\RequirePackage{tikz}
%    \end{macrocode}
%
% Load necsessary \texttt{tikz}-libraries.
%    \begin{macrocode}
\usetikzlibrary{calc,math,through}
%    \end{macrocode}




% \subsection{\texttt{tikz}-Options for the new coordinate system}
% Setup  options for tikzpicture environment.
% \DescribeMacro{spradius} The radius of the 0° Altitude circle, default 5.5. 
% This value can be accessed via macro \verb:\spradius:.
%
% \DescribeMacro{altitude projection} 
% How the altitude of the sun is "projected" on the sunpath diagram. 
% Valid values are \texttt{spherical} and \texttt{equidistance}.
% Its default value is \texttt{spherical}.
%
% This value can be accessed via macro \verb:\sprojection:.

% These options can be used like 
% 
% \begin{verbatim}
% \begin{tikzpicture}[spradius=6,altitude projection=equidistance]
% \coordinate (sunrise) at (sunpath cs:azi=105, alt=66.6);
% \end{tikzpicture}
% \end{verbatim}
%
%    \begin{macrocode}
\pgfkeys{/tikz/.cd,
  spradius/.store in=\spradius,
  spradius=5.5,
  altitude projection/.store in = \spprojection,
  altitude projection=spherical
}
%    \end{macrocode}
%


% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \subsection{Define the new coordinate system \texttt{sunpath}}
\makeatletter

% \subsubsection{Azimuth and altitude}
% Define component \texttt{azi} (=Azimuth angle) and \texttt{alt} (=Altidude angle) for the coordinate system \texttt{sunpath}.
%    \begin{macrocode}
\tikzset{
  cs/azi/.store in=\tikz@cs@azi,
  cs/alt/.store in=\tikz@cs@alt,
}
%    \end{macrocode}


% \subsubsection{Projection functions}
% Funtions to map the atitude of the sun to the altitude value on the sun path diagram.
% 
% \DescribeMacro{spherical} 
% maps an altitude angle $\theta$ to the altitude radius on the diagram with the function 
%   \[s (\theta) = r \cos(\theta). \]
%
% \DescribeMacro{equidistance}
% maps an altitude angle $\theta$ to the altitude radius on the diagram with the function
%    \[e (\theta) = r - r\cdot \frac{\theta}{90}. \]
%
% \DescribeMacro{altradius}
% this function is used in the coordinate system \texttt{sunpath} to determinate the altitude 
% radius of an azimuth angle on the sun path chart. 
% It depends on the value of the option \verb:altitude projection:.
% 
%
% \DescribeMacro{aziangle}
% maps the azimuth angle $\Phi$ to the azimuth angle on the diagram with the function
%     \[ a(\Phi) = 90 - \Phi. \]
%    \begin{macrocode}
\tikzset{  
  declare function = {
      spherical(\alt) = \spradius * cos(\alt);
      equidistance(\alt) = \spradius - \spradius*\alt/90;
      altradius(\alt) = \spprojection(\alt); 
      aziangle(\x) = 90 - \x;
  }
} 
%    \end{macrocode}
%


% \subsubsection{Coordinate system \texttt{sunpath}}
%    \begin{macrocode}
\tikzdeclarecoordinatesystem{sunpath}%
{
    \tikzset{cs/.cd,azi=0,alt=0,#1}
    \tikzmath{      
      \r = altradius(\tikz@cs@alt);
      \angle = aziangle(\tikz@cs@azi);
    }
    \pgfpointadd{\pgfpointxy{0}{0}}{%
        \pgfpointpolarxy{\angle}{\r}
    }
}
%    \end{macrocode}
\makeatother 



% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \subsection{Setup optical options for sunpath diagram}
%    \begin{macrocode}
\tikzset{
  sunpath grid/.style={help lines,color=blue!45!white!80},
  sunpath tick/.style={draw,thick,color=blue!90!white!80},
  sunpath minor tick/.style={draw,thin,color=blue!90!white!80},
  altitude label/.style={
      font=\footnotesize\sffamily,
      fill=white,minimum width={width("90")+2pt},
      inner sep=0.5pt
  },
  azimuth label/.style={
      font=\footnotesize\sffamily,
      minimum width={width("360")+2pt},
      inner sep=0.5pt
  },
}
%    \end{macrocode}
%
%
% \subsection{Expose some commands for end-user}
%    \begin{macrocode}
\NewDocumentCommand\drawcrosshair{}{
    \draw[sunpath grid] (-\spradius,0) -- (\spradius,0);
    \draw[sunpath grid] (0,-\spradius) -- (0,\spradius);
}
%    \end{macrocode}
%
%    \begin{macrocode}
\NewDocumentCommand\drawgeodirection{}{
  \foreach \dname / \dgrad in {N/0, E/90, S/180, W/270}{
      \tikzmath{
        \polarangle = aziangle(\dgrad);
      }
      \coordinate (D) at (\polarangle:\spradius cm + 22pt);
      \node[anchor=270-\dgrad] at (D) {\dname};
  };
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
\NewDocumentCommand\drawaltitudecircle{m}{
  \foreach \altitude in #1 {
    \coordinate (A) at (sunpath cs:azi=0,alt=\altitude) ;  
    \path[draw,sunpath grid] (0,0) circle[radius=altradius(\altitude)];
  }
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
\NewDocumentCommand\drawaltitudelabel{O{135}m}{
  \foreach \altitude in #2 {
      \coordinate (A) at (sunpath cs:azi=#1,alt=\altitude) ;      
      \node [anchor=east,altitude label] at (A) {\altitude};  
    }
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
\NewDocumentCommand\drawazimuthlabel{m}{
  \foreach \azimuth in #1 {
      \tikzmath{
        \polarangle = aziangle(\azimuth);
      }
      \coordinate (D) at (\polarangle:\spradius cm + 13pt);
      \node[azimuth label] at (D) {\azimuth};
  }
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
\NewDocumentCommand\drawazimuthline{m m m}{
  \foreach \azimuth in #1{
      \draw[sunpath grid] (sunpath cs:azi=\azimuth,alt={#2}) -- (sunpath cs:azi=\azimuth,alt={#3});
  }
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
\NewDocumentCommand\drawazimuthtick{}{
  \foreach \azimuth in {10,20,...,360}{
    \tikzmath{      
        \pa = aziangle(\azimuth);
    }
    \path[sunpath tick] (\pa:\spradius) -- (\pa:{\spradius cm+6pt});
  }
  
  \foreach \azimuth in {1,2,...,360}{
    \tikzmath{      
        \pa = aziangle(\azimuth);
    }
    \path[sunpath minor tick] (\pa:\spradius) -- (\pa:{\spradius cm+2.5pt});
  }
  
  \foreach \azimuth in {15,30,...,360}{
      \tikzmath{      
          \pa = aziangle(\azimuth);
      }
      \path[sunpath minor tick] (\pa:\spradius) -- (\pa:{\spradius cm+5pt});
    }  
}
%    \end{macrocode}
%
%
%%%%%%%%%%%%%%
\endinput
%%%%%%%%%%%%%%


