Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing clock face in Mathematica (looking for a better solution)

I am trying to find a general solution for drawing clock face like graphical objects in Mathematica. I've already implemented a version of my own, but I think a much better solution must exist. A neater version with less code or clearer thought process would be appreciated.

My version:

radius = 1;
elementList = 
  Join[Table[i, {i, 3, 1, -1}], Table[i, {i, 12, 4, -1}]];
elementNumber = Length[elementList];
thetaList = Table[i, {i, 0, 2 Pi, 2 Pi/elementNumber}][[1 ;; 12]];
coordinateList = Map[{radius*Cos[#], radius*Sin[#]} &, thetaList];
objectList = 
  Map[Style[#, FontFamily -> "Georgia", FontSize -> 30] &, 
   elementList];
Graphics[
 Join[
  MapThread[Text[#1, #2] &, {objectList, coordinateList}],
  {Circle[{0, 0}, 1.2*radius]}
  ]
 ]

enter image description here

like image 605
Ning Avatar asked Nov 18 '11 18:11

Ning


2 Answers

Here is one way to make a clock:

clockFace = Import["http://i.imgur.com/ufanv.jpg"];
{hour, minute, second} = Take[Date[], -3];
hour = Mod[hour, 12] + minute/60.; 
Graphics3D[
{
 {Texture[clockFace], 
      Polygon[{{-1, -1, 0}, {1, -1, 0}, {1, 1, 0}, {-1, 1, 0}},
         VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}
      ]
 }, 
 {Black, AbsoluteThickness[8], 
      Line[{{0, 0, 0}, 
       .55 {Cos[Pi/2 - 2 Pi hour/12], Sin[Pi/2 - 2 Pi hour/12], 0}}
      ]
 },
 {Black, AbsoluteThickness[5], 
      Line[{{0, 0, 0}, 
       .8 {Cos[Pi/2 - 2 Pi minute/60], Sin[Pi/2 - 2 Pi minute/60], 0}}
      ]
 }
}, 
Boxed -> False, Lighting -> "Neutral"]

a clock with a nice face generated by Mathematica

Addition

Here is a rotating, spinning 3D clock for your amusement:

clockFace = Import["http://i.imgur.com/ufanv.jpg"];
vtc = VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
hand[thickness_, radius_, time_] := {AbsoluteThickness[thickness],
   Line[{{0, 0, -1}, {radius Cos[Pi/2 + 2 Pi time],
      radius Sin[Pi/2 + 2 Pi time], -1}}],
   Line[{{0, 0, 1}, {radius Cos[Pi/2 - 2 Pi time],
      radius Sin[Pi/2 - 2 Pi time], 1}}],
   Line[{{0, -1, 0}, {radius Cos[Pi/2 - 2 Pi time], -1,
      radius Sin[Pi/2 - 2 Pi time]}}],
   Line[{{0, 1, 0}, {radius Cos[Pi/2 + 2 Pi time], 1,
      radius Sin[Pi/2 + 2 Pi time]}}],
   Line[{{-1, 0, 0}, {-1, radius Cos[Pi/2 + 2 Pi time],
      radius Sin[Pi/2 + 2 Pi time]}}],
   Line[{{1, 0, 0}, {1, radius Cos[Pi/2 - 2 Pi time],
      radius Sin[Pi/2 - 2 Pi time]}}]};
Dynamic[
  {hour, minute, second} = Take[Date[], -3];
  hour = Mod[hour, 12] + minute/60.;
  Graphics3D[{
    {Texture[clockFace],
     Polygon[{{1, -1, -1}, {-1, -1, -1}, {-1, 1, -1}, {1, 1, -1}},
      vtc],
     Polygon[{{-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1}}, vtc],
     Polygon[{{-1, 1, -1}, {-1, -1, -1}, {-1, -1, 1}, {-1, 1, 1}},
      vtc], Polygon[{{1, -1, -1}, {1, 1, -1}, {1, 1, 1}, {1, -1, 1}},
      vtc], Polygon[{{-1, -1, -1}, {1, -1, -1}, {1, -1, 1}, {-1, -1,
        1}}, vtc],
     Polygon[{{1, 1, -1}, {-1, 1, -1}, {-1, 1, 1}, {1, 1, 1}}, vtc]
     }, {Black,
     hand[8, .55, hour/12],
     hand[5, .8, minute/60],
     hand[3, .8, second/60]
     }
    },
   Boxed -> False, Lighting -> "Neutral",
   ViewPoint ->
    5 {Cos[2 Pi second/60], Sin[2 Pi second/60],
      Sin[2 Pi second/30]}, SphericalRegion -> True,
Background -> Black, ImageSize -> Full]] // Deploy

3D clock

like image 50
Arnoud Buzing Avatar answered Oct 14 '22 15:10

Arnoud Buzing


Here's a version of a function that generalizes the generation of clock face to allow you to easily change the style of the numbers, the number of "hours", and the radius of the face:

Options[clockFace] = {FontFamily -> "Georgia", FontSize -> 30};
clockFace[hours_Integer, radius_?NumericQ, opts : OptionsPattern[]] /;
   hours > 0 && Im[radius] == 0 && radius > 0 :=
 With[{range = Range[12]},
  With[{objects = 
        Style[#, 
          FilterRules[{opts}, Options[Style]] ~Join~ Options[clockFace]] & /@ range,
       thetas = Pi/2 - 2 Pi*range/hours},
  Graphics[Append[
     MapThread[Text[#1, {Cos[#2], Sin[#2]}] &, {objects, thetas}],
     Circle[radius*1.2]]]]]

Some things are just Mathematica style issues; for instance,

FilterRules[{opts}, Options[Style]] ~Join~ Options[clockFace]

is just the way to pass the relevant optional arguments to Style while making sure that clockFace's default values are used where relevant, because Mathematica will use the first applicable rule that it finds in a list of rules (and function options are just lists of rules). I also used With to name things, which is why there's that nesting; other people might prefer to use a single Module. Either way, it's always best to make things local variables whenever possible.

The biggest change, though, was generating the list of numbers in order, using Range, and then adjusting the definition of thetas so everything winds up in the right place. I think it's much easier to see what's going on, because the minus sign means you're moving around clockwise and offsetting by Pi/2 makes it clear you're starting at the top of the clock.

like image 6
Pillsy Avatar answered Oct 14 '22 15:10

Pillsy