【问题标题】:Drawing clock face in Mathematica (looking for a better solution)在 Mathematica 中绘制钟面(寻找更好的解决方案)
【发布时间】:2011-11-18 18:38:24
【问题描述】:

我正在尝试为在 Mathematica 中绘制像图形对象一样的钟面寻找通用解决方案。我已经实现了自己的版本,但我认为必须存在更好的解决方案。更简洁的版本,更少的代码或更清晰的思维过程将不胜感激。

我的版本:

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]}
  ]
 ]

【问题讨论】:

  • 也许这是一个很好的起点:blog.wolfram.com/2007/07/09/…
  • 我认为@BrettChampion 的建议完美地回答了这个问题。问这个问题我感到有点羞耻(我应该先问谷歌和文档,然后再在这里问问题,我只问了后者)。我应该保留这篇文章还是删除它,哪个选择对社区更好?
  • 我会保留你的帖子。有很多有趣的方法可以构建时钟(和钟面)。
  • @Ning 恕我直言,作为一个学习 Mathematica 并每天使用它的人,我说坚持下去。下面的两个答案很有趣,我喜欢从其他人如何处理这类问题中学习(即两个非常不同的答案)。

标签: graphics wolfram-mathematica drawing clock


【解决方案1】:

这是制作时钟的一种方法:

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"]

加法

这是一个旋转的 3D 时钟供您娱乐:

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

【讨论】:

  • 也许你可以使用 Polygon[#, vtc] & /@(PolyhedronData["Cube", "VertexCoordinates"][[#]] & /@ PolyhedronData["Cube", "FaceIndices"])] 之类的东西来获取人脸坐标
  • @belisarius,这是一个很好的提示,但我必须单独调整多边形以使侧面的多边形直立。
  • 是的。我想知道是否可以通过排列来解决。我没有很努力,但找不到明显的方法。
【解决方案2】:

这是一个泛化钟面生成的函数的一个版本,让您可以轻松更改数字的样式、“小时”数和钟面的半径:

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]]]]]

有些东西只是 Mathematica 风格的问题;例如,

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

只是将相关的可选参数传递给Style 的方法,同时确保在相关的地方使用clockFace 的默认值,因为 Mathematica 将使用它在规则列表中找到的第一个适用规则 (和功能选项只是规则列表)。我还使用With 来命名事物,这就是嵌套的原因;其他人可能更喜欢使用单个 Module。无论哪种方式,最好尽可能使事物成为局部变量。

不过,最大的变化是使用Range 按顺序生成数字列表,然后调整thetas 的定义,以便一切都在正确的位置结束。我认为更容易看到正在发生的事情,因为减号表示您正在顺时针移动并偏移Pi/2,这清楚地表明您从时钟的顶部开始。

【讨论】:

    【解决方案3】:

    以下是一个工作 3D 时钟,通过轻松结合 @Arnoud 的答案与 Christopher's blog entry 制作:

    makeHand[fl_, bl_, fw_, bw_] :=
        Polygon[{{-bw, -bl, 0.1}, {bw, -bl, 0.1}, {fw, fl, 0.1}, 
                 {0, fl + 8 fw, 0.1}, {-fw, fl, 0.1}}/9];
    
    hourHand = makeHand[5, 5/3, .1, .3];
    minuteHand = makeHand[7, 7/3, .1, .3];
    secondHand = {Red, EdgeForm[Black], makeHand[7, 7/3, .1/2, .3/2]};
    clockFace = Import["http://i.imgur.com/ufanv.jpg"];
    
    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}}]},
    
        Rotate[hourHand, Dynamic[Refresh[-30 Mod[AbsoluteTime[]/3600, 60] \[Degree], 
         UpdateInterval -> 60]], {0, 0, 1}],
        Rotate[minuteHand, Dynamic[Refresh[-6 Mod[AbsoluteTime[]/60, 60] \[Degree], 
         UpdateInterval -> 1]], {0, 0, 1}],
        Rotate[secondHand, Dynamic[Refresh[-6 Mod[AbsoluteTime[], 60] \[Degree], 
         UpdateInterval -> 1/20]], {0, 0, 1}]}, Boxed -> False]
    

    编辑

    动画是在计划任务中使用 Rasterize[] 捕获的!

    a = Graphics3D[(* etc etc*)];
    b = {};
    t = CreateScheduledTask[AppendTo[b, Rasterize@a], {2, 30}];
    StartScheduledTask[t];
    While[MatchQ[ScheduledTasks[], {ScheduledTaskObject[_, _, _, _,True]}],Pause[1]];
    RemoveScheduledTask[ScheduledTasks[]];
    Export["c:\\test.gif", b, "DisplayDurations" -> 1]
    

    【讨论】:

    • +1,好的。那是错误的。我什至下载了 v8,所以我可以运行它。
    • @rcollyer 恐怕我不明白。有什么问题?
    • 对不起,俗语。城市词典中的third definition 最接近我这里的用法。具体来说,我在评论使用非常强大的工具来创建准确的时钟动画具有讽刺意味。
    • @rcollyer 您是否注意到在上次编辑中使用了ScheduledTask?我以前从来没有这样用过!
    • 不,我没有。哇,我认为第一次使用很荒谬。这个更糟糕,也更有趣。
    【解决方案4】:

    Mathematica 内置了一个叫做ClockGauge 的东西。从文档中可以看出,钟面造型的可能性是无穷无尽的。准系统版本如下所示:

    ClockGauge[]
    

    【讨论】:

    • 请看一下问题中的时间戳:)
    • @belisarius 哦,好吧,这里也有这个解决方案不会有什么坏处。
    • 我想这个网站上几乎所有关于 Mma 的问题都可以重写,因为它们大多来自 v7 和 v8 :D
    【解决方案5】:

    你的方法很好。只是有点乱。这是我的解释:

    hours = 12;
    radius = 1;
    thetaList = Rest@Range[2 Pi, 0, -2 Pi/hours] + Pi/2;
    coordinateList = radius {Cos@#, Sin@#} & /@ thetaList;
    Graphics[{
      FontFamily -> "Georgia",
      FontSize -> 30,
      Text ~MapThread~ {Range@hours, coordinateList},
      Circle[{0, 0}, 1.2 radius]
    }]
    

    【讨论】:

      猜你喜欢
      • 2014-07-20
      • 1970-01-01
      • 2013-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      • 2012-06-04
      • 2012-01-12
      相关资源
      最近更新 更多