8

I'm trying to create TikZ diagram to represent the HDD platter. On the platter the track, sector and blocks should be highlighted. I moved from the simple by-the-hand calculated render more onto the systematic approach using variables and calculations and it almost works. The problem I have is with the matching of the lines drawn before the "highlighter" takes action (as shown in the picture bellow). Fumbling with the values little bit I found comibination which is usabe for my usecase, I still wonder and cannot figure out, where does the misalignment comes from.

PS.: I'm using Overleaf to write and render TeX files.

TikZ HDD schematic:

% Hard disk drive platter
% Author: Tomáš Michalek
%
% This diagram attempts to create HDD platter with the selectable track,
% sector and block highlighting.
%
% Current version is quite fragile and any improvements are welcome
%
\documentclass[tikz,margin=10pt]{standalone}
\usepackage{tikz}
\usepackage{comment}


\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   CUSTOMISATIONS
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\numTracks{8}      
\def\numSectors{12}

\def\selectedTrack{6}  % Track to highlight, negative values disable the selection
\def\selectedSector{0} % Sector to highlight, negative values disable the selection

\definecolor{baseColor}{RGB}{18, 54, 69}        % Basic lines and borders
\definecolor{accentColor}{RGB}{1, 103, 143}     % Selection
\definecolor{highlightColor}{RGB}{221, 109, 16} % Crossover of two selections


\pgfmathsetmacro\firstTrack{10cm}
\pgfmathsetmacro\lastTrack{2cm}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   CALCULATIONS
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfmathtruncatemacro{\trackStepRange}{\firstTrack-\lastTrack}
\pgfmathsetmacro\trackStep{\trackStepRange/\numTracks}
\pgfmathsetmacro\sectorStep{360/\numSectors}

\pgfmathtruncatemacro{\selectedSectorStart}{-\sectorStep*\selectedSector} % natural rotation
\pgfmathtruncatemacro{\selectedBlockStart}{\firstTrack-\selectedTrack*\trackStep}
\pgfmathtruncatemacro{\selectedBlockEnd}{\selectedBlockStart-\trackStep}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   DRAWING
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Draw track lines
\foreach \track in {0,...,\numTracks} {
    \draw [baseColor!20] (0,0) circle (\firstTrack-\track*\trackStep);
}

% Draw sector lines
\foreach \i in {0, \sectorStep, ..., 359}
    \draw [baseColor!20] (\i:\firstTrack) -- (\i:\lastTrack);

\foreach \sector in {0, \sectorStep, ..., 359} {
    \pgfmathparse{mod(\sector, \sectorStep*2)}
    \pgfmathtruncatemacro{\remainder}{\pgfmathresult}
    
    \ifnum\remainder=0
        \pgfmathtruncatemacro{\sectorTint}{50};
    \else
        \pgfmathtruncatemacro{\sectorTint}{50}; %25
    \fi

    % If the `track` is selected, highlight it
    \ifnum\selectedTrack>-1
        \fill[accentColor!\sectorTint] (\sector:\selectedBlockStart) arc (\sector:\sector+\sectorStep:\selectedBlockStart) -- (\sector+\sectorStep:\selectedBlockEnd) arc (\sector+\sectorStep:\sector:\selectedBlockEnd) -- cycle;
    \fi
}

% If the `sector` is selected, highlight it
\ifnum\selectedSector>-1
    \fill[accentColor!30, rotate=\selectedSectorStart] (0:\firstTrack) arc (0:\sectorStep:\firstTrack) -- (\sectorStep:\lastTrack) arc (\sectorStep:0:\lastTrack) -- cycle;
\fi

% If both `sector` and `track` are selected, highlight `block`
\ifnum\selectedSector>-1
    \ifnum\selectedTrack>-1
        \fill[highlightColor!80, rotate=\selectedSectorStart] (0:\selectedBlockStart) arc (0:\sectorStep:\selectedBlockStart) -- (\sectorStep:\selectedBlockEnd) arc (\sectorStep:0:\selectedBlockEnd) -- cycle;
    \fi
\fi

\end{tikzpicture}
\end{document}

Aligment issue

0

1 Answer 1

4

If you remove the units cm from your macros \firstTrack and \lastTrack your diagram will be drawn more correct. The size is different now but that can be adjusted again by scaling the diagram or changing the xyz vectors.

When you use units, these lengths will be converted to pts and on which you use \pgfmathtruncatemacro. This will lead to a different result than with \pgfmathsetmacro and since you also don't use \pgfmathsetlengthmacro, the unit will be lost and the value will be interpreted to be in the xyz coordinate system again which scales your diagram beyond the values (2cm, 10cm) you actually want.


In summary:

   input       converted

     2cm      56.9055 pt
    10cm     284.52756pt
10cm-2cm     227.62206pt

but with \pgfmathtruncatemacro the value 227 will be stored in \trackStepRange which will then lead to \trackStep being wrong and then everything else that depends on it as well.


That said, I've rewritten your diagram because it was a bit too much for me to follow. It's the same approach, though, I believe, with the exception that I'm counting the tracks from inside to outside. This makes the math a bit easier.


I have also a draft of another approach where each block is drawn/filled individually and a few styles like track 1 sector 0/.style=hdd sel block are defined and accessed during two nested loops.

If you need to color/tint areas further that solution might be easier to use.

And we can also use the heatmark shape.

Code

\documentclass[tikz, margin=10pt]{standalone}
\definecolor     {baseColor}{RGB}{ 18,  54,  69} % Basic lines and borders
\definecolor   {accentColor}{RGB}{  1, 103, 143} % Selection
\definecolor{highlightColor}{RGB}{221, 109,  16} % Crossover of two selections
\tikzset{
  ring segment/.style n args={4}{insert path={% helpful
       ({#1}:{#4}) arc[start angle={#1}, end angle={#2}, radius={#4}]
    -- ({#2}:{#3}) arc[start angle={#2}, end angle={#1}, radius={#3}] -- cycle}}}
\begin{document}
\begin{tikzpicture}[
  hdd border/.style    ={draw=     baseColor!20},
  hdd sel track/.style ={fill=   accentColor!50},
  hdd sel sector/.style={fill=   accentColor!30},
  hdd sel block/.style ={fill=highlightColor!80},
]
%% independent of selection
\newcommand*\numTracks{8}
\newcommand*\numSectors{12}
\newcommand*\baseR{2}
\newcommand*\stepR{.5}
\pgfmathsetmacro\maxR{\baseR+\numTracks*\stepR}
\pgfmathsetmacro\stepAngle{360/\numSectors}

%% dependent of selection
\newcommand*\selTrack{1}
\newcommand*\selSector{0}
\pgfmathsetmacro\selAngleL{\stepAngle*\selSector}
\pgfmathsetmacro\selAngleU{\selAngleL+\stepAngle}
\pgfmathsetmacro\selRadiusL{\baseR+\stepR*\selTrack}
\pgfmathsetmacro\selRadiusU{\selRadiusL+\stepR}

%% the drawing
\ifnum\selTrack>-1
  \fill[hdd sel track, even odd rule]
    circle [radius=\selRadiusU] circle [radius=\selRadiusL];
\fi
\ifnum\selSector>-1
  \fill[hdd sel sector, ring segment=\selAngleL\selAngleU\baseR\maxR];
\fi
\ifnum\selTrack>-1 \ifnum\selSector>-1
  \fill[hdd sel block,  ring segment=\selAngleL\selAngleU\selRadiusL\selRadiusU];
\fi                \fi

%% borders on top
\foreach \track in {0, ..., \numTracks}
  \draw[hdd border] (0,0) circle[radius=\baseR+\track*\stepR];
\foreach[count=\i from 0] \sectors in {1, ..., \numSectors}
  \draw[hdd border] (\i*\stepAngle:\baseR) -- (\i*\stepAngle:\maxR);
\end{tikzpicture}
\end{document}

Output

enter image description here

4
  • Thank you! I made the circle from the outside in for the purpose of maintaining the "real" behaviour for the disk, but I don't really need it, I can just use it as it is. As the issue with alignment is resolved, I will mark it as solved. I thought that the macros may round the numbers, but I didn't know that they convert it to pt.
    – jr.root.cs
    Sep 27 at 4:37
  • One more small question, why use \newcommand* instead of \def. Does it have any advantages or is it just a choice?
    – jr.root.cs
    Sep 27 at 4:51
  • \def is a TeX primitive which has no security and will let you break something that already exists without warning. \newcommand, when used, verifies if what you try to create already exists, and warns you.
    – SebGlav
    Sep 27 at 5:32
  • Makes sense! Thanks, I will switch to \newcommand in my further endeavours.
    – jr.root.cs
    Sep 27 at 7:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .