Silverlight 引路蜂二维图形库示例:动画Beziers曲线

jerry Silverligth 2015年11月26日 收藏

类Path为一条几何路径,可以通过直线,二次曲线,三次曲线来构成任意路径。Path提供了moveTo, lineTo, curveTo, curveToCubic, closePath方法来构成路径。

下面的例子动态显示一条Bezier曲线。

  1. /**
  2. * The animation thread.
  3. */
  4. Thread _thread;
  5. bool _drawn;
  6. /**
  7.  * The random number generator.
  8.  */
  9. readonly Random _random = new Random();
  10. /**
  11.  * The animated path
  12.  */
  13. readonly Path _path = new Path();
  14. /**
  15.  * Red brush used to fill the path.
  16.  */
  17. readonly SolidBrush _brush = new SolidBrush(Color.Red);
  18. const int Numpts = 6;
  19. readonly int[] _animpts = new int[Numpts * 2];
  20. readonly int[] _deltas = new int[Numpts * 2];
  21.  
  22. private void Beziers()
  23. {
  24.  Reset(screenWidth, screenHeight);
  25.  _thread = new Thread(RunBeziers);
  26.  _thread.Start();
  27. }
  28.  
  29. private void RunBeziers()
  30. {
  31.  
  32.  Thread me = Thread.CurrentThread;
  33.  
  34.  if (!_drawn)
  35.  {
  36.   lock (this)
  37.   {
  38.    graphics2D.Clear(Color.White);
  39.    graphics2D.Fill(_brush, _path);
  40.    _drawn = true;
  41.   }
  42.  }
  43.  while (_thread == me)
  44.  {
  45.   DrawDemo(screenWidth, screenHeight);
  46.  }
  47. }
  48.  
  49. /**
  50. * Generates new points for the path.
  51. */
  52. private void Animate(int[] pts, int[] deltas, int i, int limit)
  53. {
  54.  int newpt = pts[i] + deltas[i];
  55.  if (newpt <= 0)
  56.  {
  57.   newpt = -newpt;
  58.   deltas[i] = (_random.Next() & 0x00000003) + 2;
  59.  }
  60.  else if (newpt >= limit)
  61.  {
  62.   newpt = 2 * limit - newpt;
  63.   deltas[i] = -((_random.Next() & 0x00000003) + 2);
  64.  }
  65.  pts[i] = newpt;
  66. }
  67.  
  68. /**
  69. * Resets the animation data.
  70. */
  71. private void Reset(int w, int h)
  72. {
  73.  for (int i = 0; i < _animpts.Length; i += 2)
  74.  {
  75.   _animpts[i + 0] = (_random.Next() & 0x00000003) * w / 2;
  76.   _animpts[i + 1] = (_random.Next() & 0x00000003) * h / 2;
  77.   _deltas[i + 0] = (_random.Next() & 0x00000003) * 6 + 4;
  78.   _deltas[i + 1] = (_random.Next() & 0x00000003) * 6 + 4;
  79.   if (_animpts[i + 0] > w / 2)
  80.   {
  81.    _deltas[i + 0] = -_deltas[i + 0];
  82.   }
  83.   if (_animpts[i + 1] > h / 2)
  84.   {
  85.    _deltas[i + 1] = -_deltas[i + 1];
  86.   }
  87.  }
  88. }
  89.  
  90. /**
  91.  * Sets the points of the path and draws and fills the path.
  92.  */
  93. private void DrawDemo(int w, int h)
  94. {
  95.  for (int i = 0; i < _animpts.Length; i += 2)
  96.  {
  97.   Animate(_animpts, _deltas, i + 0, w);
  98.   Animate(_animpts, _deltas, i + 1, h);
  99.  }
  100.  //Generates the new pata data.
  101.  _path.Reset();
  102.  int[] ctrlpts = _animpts;
  103.  int len = ctrlpts.Length;
  104.  int prevx = ctrlpts[len - 2];
  105.  int prevy = ctrlpts[len - 1];
  106.  int curx = ctrlpts[0];
  107.  int cury = ctrlpts[1];
  108.  int midx = (curx + prevx) / 2;
  109.  int midy = (cury + prevy) / 2;
  110.  _path.MoveTo(midx, midy);
  111.  for (int i = 2; i <= ctrlpts.Length; i += 2)
  112.  {
  113.   int x1 = (curx + midx) / 2;
  114.   int y1 = (cury + midy) / 2;
  115.   prevx = curx;
  116.   prevy = cury;
  117.   if (i < ctrlpts.Length)
  118.   {
  119.    curx = ctrlpts[i + 0];
  120.    cury = ctrlpts[i + 1];
  121.   }
  122.   else
  123.   {
  124.    curx = ctrlpts[0];
  125.    cury = ctrlpts[1];
  126.   }
  127.   midx = (curx + prevx) / 2;
  128.   midy = (cury + prevy) / 2;
  129.   int x2 = (prevx + midx) / 2;
  130.   int y2 = (prevy + midy) / 2;
  131.   _path.CurveTo(x1, y1, x2, y2, midx, midy);
  132.  }
  133.  _path.ClosePath();
  134.  // clear the clipRect area before production
  135.  
  136.  graphics2D.Clear(Color.White);
  137.  graphics2D.Fill(_brush, _path);
  138.  
  139.  RefreshBitmap();
  140.  
  141. }

其中实时更新图像需要CompositionTarget.Rendering事件来处理。CompositionTarget.Rendering += CompositionTargetRendering;

  1. private void CompositionTargetRendering(object sender, EventArgs e)
  2. {
  3.  bmp.Invalidate();
  4. }