类Path为一条几何路径,可以通过直线,二次曲线,三次曲线来构成任意路径。Path提供了moveTo, lineTo, curveTo, curveToCubic, closePath方法来构成路径。
下面的例子动态显示一条Bezier曲线。
/**
* The animation thread.
*/
Thread _thread;
bool _drawn;
/**
* The random number generator.
*/
readonly Random _random = new Random();
/**
* The animated path
*/
readonly Path _path = new Path();
/**
* Red brush used to fill the path.
*/
readonly SolidBrush _brush = new SolidBrush(Color.Red);
const int Numpts = 6;
readonly int[] _animpts = new int[Numpts * 2];
readonly int[] _deltas = new int[Numpts * 2];
private void Beziers()
{
Reset(screenWidth, screenHeight);
_thread = new Thread(RunBeziers);
_thread.Start();
}
private void RunBeziers()
{
Thread me = Thread.CurrentThread;
if (!_drawn)
{
lock (this)
{
graphics2D.Clear(Color.White);
graphics2D.Fill(_brush, _path);
_drawn = true;
}
}
while (_thread == me)
{
DrawDemo(screenWidth, screenHeight);
}
}
/**
* Generates new points for the path.
*/
private void Animate(int[] pts, int[] deltas, int i, int limit)
{
int newpt = pts[i] + deltas[i];
if (newpt <= 0)
{
newpt = -newpt;
deltas[i] = (_random.Next() & 0x00000003) + 2;
}
else if (newpt >= limit)
{
newpt = 2 * limit - newpt;
deltas[i] = -((_random.Next() & 0x00000003) + 2);
}
pts[i] = newpt;
}
/**
* Resets the animation data.
*/
private void Reset(int w, int h)
{
for (int i = 0; i < _animpts.Length; i += 2)
{
_animpts[i + 0] = (_random.Next() & 0x00000003) * w / 2;
_animpts[i + 1] = (_random.Next() & 0x00000003) * h / 2;
_deltas[i + 0] = (_random.Next() & 0x00000003) * 6 + 4;
_deltas[i + 1] = (_random.Next() & 0x00000003) * 6 + 4;
if (_animpts[i + 0] > w / 2)
{
_deltas[i + 0] = -_deltas[i + 0];
}
if (_animpts[i + 1] > h / 2)
{
_deltas[i + 1] = -_deltas[i + 1];
}
}
}
/**
* Sets the points of the path and draws and fills the path.
*/
private void DrawDemo(int w, int h)
{
for (int i = 0; i < _animpts.Length; i += 2)
{
Animate(_animpts, _deltas, i + 0, w);
Animate(_animpts, _deltas, i + 1, h);
}
//Generates the new pata data.
_path.Reset();
int[] ctrlpts = _animpts;
int len = ctrlpts.Length;
int prevx = ctrlpts[len - 2];
int prevy = ctrlpts[len - 1];
int curx = ctrlpts[0];
int cury = ctrlpts[1];
int midx = (curx + prevx) / 2;
int midy = (cury + prevy) / 2;
_path.MoveTo(midx, midy);
for (int i = 2; i <= ctrlpts.Length; i += 2)
{
int x1 = (curx + midx) / 2;
int y1 = (cury + midy) / 2;
prevx = curx;
prevy = cury;
if (i < ctrlpts.Length)
{
curx = ctrlpts[i + 0];
cury = ctrlpts[i + 1];
}
else
{
curx = ctrlpts[0];
cury = ctrlpts[1];
}
midx = (curx + prevx) / 2;
midy = (cury + prevy) / 2;
int x2 = (prevx + midx) / 2;
int y2 = (prevy + midy) / 2;
_path.CurveTo(x1, y1, x2, y2, midx, midy);
}
_path.ClosePath();
// clear the clipRect area before production
graphics2D.Clear(Color.White);
graphics2D.Fill(_brush, _path);
RefreshBitmap();
}
其中实时更新图像需要CompositionTarget.Rendering事件来处理。CompositionTarget.Rendering += CompositionTargetRendering;
private void CompositionTargetRendering(object sender, EventArgs e)
{
bmp.Invalidate();
}