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.

I want to create a \rating command that draws a partly filled circle, according to a numeric parameter between 0 and 100:

sequence of 10 circular rating symbols

Question: How can I modify the expression for determining the angles in arc, so that the filling rises more steadily over the whole value range? Right now, ratings from 0 to 20 look empty, 80 to 100 look completely filled and only in between there is a steady rise.

Clarification: Rather than a mathematically rigoros expression, I am looking for the simplest expression that looks right, i.e. that \rating{25}, \rating{50} and \rating{75} visually look like 1/4, 2/4 and 3/4.

\documentclass{minimal}
\usepackage{tikz}

\newcommand{\rating}[1]{
\begin{tikzpicture}
\fill[lightgray] ({270-1.8*#1}:1ex) arc ({270-1.8*#1}:{270+1.8*#1}:1ex) -- cycle;
\draw[black, thin, radius=1ex] (0,0) circle;
\end{tikzpicture}}

\begin{document}
This really should scale\dots
\rating{0} \rating{10} \rating{20} \rating{30} \rating{40} \rating{50}
\rating{50} \rating{60} \rating{70} \rating{80} \rating{90} \rating{100}
\dots linearly.
\end{document}
share|improve this question
    
This is a maths question rather than a TeX one. –  Jubobs Aug 5 at 15:17
    
Possible duplicate: tex.stackexchange.com/a/108622/19356 –  Who is crazy first Aug 5 at 15:18
    
@Jubobs: Partly agreed: I'm more interested in a working (in the TeX environment) solution than a mathematically correct one. –  ojdo Aug 5 at 15:19
    
@ojdo If a simple mathematical solution exists, why not use it? –  Jubobs Aug 5 at 23:13
    
@Jubobs: I accepteded the clip answer because it would work even for other shapes without the need for asin etc. Frankly, I am overwhelmed by the number of options I was offered. I will probably adapt the optional parameter idea of your answer. –  ojdo Aug 5 at 23:15

5 Answers 5

up vote 6 down vote accepted

As an aside, please see Why should the minimal class be avoided?

Here is a solution using a clipped path in TikZ. Note that the clip path cannot have extra options added, so I've drawn the circle with your specifications separately, outside the scope of the \clip path.

\documentclass{article}
\usepackage{tikz}

\newcommand{\rating}[1]{%
  \begin{tikzpicture}[x=1ex,y=1ex]
    \begin{scope}
      \clip (0,1) circle (1);
      \fill[lightgray] (-1,0) rectangle (1,#1/50);
    \end{scope}
    \draw[black, thin, radius=1] (0,1) circle;
  \end{tikzpicture}%
}

\begin{document}
This really should scale\dots
\foreach \h in {0,5,...,100} {\rating{\h}}
\dots linearly.
\end{document}

enter image description here

share|improve this answer
1  
Aside noted, elegance of the clip path solution appreciated :-) –  ojdo Aug 5 at 15:51

Another way with TikZ but without explicit clipping:

\documentclass[border=5]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\tikzset{circle mark/.pic={
  \draw [path picture={%
    \fill (path picture bounding box.south west) |-  
      ($(path picture bounding box.south east)!#1/100!(path picture bounding box.north east)$) 
      |- cycle;}] circle [radius=1ex];
}}
\begin{document}
\foreach \i in {0,10,...,100}
  \tikz\path pic{circle mark=\i};
\end{document}

enter image description here

share|improve this answer

Just for fun with PSTricks.

\documentclass[preview,border=12pt,varwidth]{standalone}
\usepackage{pstricks}


\newcommand\rating[2][.25pt]{%
\psset{unit=#1,runit=#1}
\pspicture(100,100)
\psclip{\pscircle[linestyle=none,linewidth=0](50,50){50}}
    \psframe*[linecolor=gray](100,#2)
\endpsclip
\pscircle[dimen=m](50,50){50}
\endpspicture}

\begin{document}
Linearly filled circles:\\
\foreach \i in {0,10,...,100}{\rating{\i}}
\end{document}

enter image description here

share|improve this answer

Run with xelatex

\documentclass{article}
\usepackage{pstricks}

\def\rateColor{black!40}
\newcommand\rating[2][]{%
  \ifx\relax#1\relax\else\gdef\rateColor{#1}\fi
  \psset{unit=1ex}%
  \pspicture[dimen=inner](-1.2,-1.2)(1.2,1.2)
    \psclip{\pscircle{1}}
      \psframe*[linecolor=\rateColor](-1,-1)(!1 #2 100 div 2 mul 1 sub)
    \endpsclip\pscircle{1}
  \endpspicture}

\begin{document}
This really should scale \dots

\tiny
\multido{\iA=0+10}{21}{\ifnum\iA>100\expandafter\rating\expandafter{\the\numexpr200-\iA}\else\rating{\iA}\fi} \par
\normalsize
\rating[red]{0} 
\multido{\iA=10+10}{20}{\ifnum\iA>100\expandafter\rating\expandafter{\the\numexpr200-\iA}\else\rating{\iA}\fi} \par
\Large
\rating[blue]{0} 
\multido{\iA=10+10}{20}{\ifnum\iA>100\expandafter\rating\expandafter{\the\numexpr200-\iA}\else\rating{\iA}\fi} \par
\end{document}

enter image description here

share|improve this answer

All you need is a different parameterisation of the angle; see below for details.

enter image description here

Additionally,

  1. since you seem to use \rating "inline", you may want to simply use \tikz instead of a tikzpicture environment;
  2. avoid spurious spaces in the definition of \rating (instead, insert a space between calls to \rating, wherever one is needed);
  3. instead of hardcoding 1ex as the radius, make it an optional argument, for more flexibility;
  4. as already pointed out by Paul in his answer, avoid the minimal class when using tikz.

\documentclass{article}
\usepackage{tikz}
\usepackage{amsmath}

\newcommand{\rating}[2][1ex]{%
  \pgfmathsetmacro\th{asin(#2/50-1)}% (theta angle of polar coordinates)
    \tikz{%
      \fill[lightgray] (\th:#1) arc (\th:-180-\th:#1) -- cycle;
      \draw[black, thin, radius=#1] (0,0) circle;
    }%
}

\begin{document}
This really should scale\dots
\foreach \h in {0,10,...,100} {\rating{\h} }
\dots linearly.

\section*{Parameterisation explained}

Let~\(R\) be the disk radius. In polar coordinates,
%
\[
  y = R \sin \theta \,.
\]
%
Therefore,
%
\[
  \theta = \arcsin \frac{y}{R}  \,.
\]
%
Because the quantity~\(y/R\) varies over~\([-1,1]\)
but you want a parameter~\(u\) that varies over~\([0,100]\),
the right affine transformation will get you there:
%
\[
  \frac{y}{R} = \frac{u}{50} - 1 \,.
\]
%
\end{document}
share|improve this answer

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.