WPF点连成曲线,贝塞尔曲线两种画法
先看效果图:
黑色是需要经过的点;
黄色为控制点;
绿色为两点之间的中点。
方式一:
方式二:
<Canvas x:Name="canvas2"/>
方法一代码,【这是别人的代码,时间久了忘记原出处了】:
Path path; public void UpdateRoad(List<Point> list) { double x = this.canvas2.ActualWidth; double y = this.canvas2.ActualHeight; PathFigure pf = new PathFigure(); pf.StartPoint = list[0]; List<Point> controls = new List<Point>(); for (int i = 0; i < list.Count; i++) { controls.AddRange(Control1(list, i)); } for (int i = 1; i < list.Count; i++) { BezierSegment bs = new BezierSegment(controls[i * 2 - 1], controls[i * 2], list[i], true); bs.IsSmoothJoin = true; pf.Segments.Add(bs); } PathFigureCollection pfc = new PathFigureCollection(); pfc.Add(pf); PathGeometry pg = new PathGeometry(pfc); path = new Path(); path.Stroke = Brushes.Black; path.Data = pg; canvas2.Children.Add(path); } public List<Point> Control1(List<Point> list, int n) { List<Point> point = new List<Point>(); point.Add(new Point()); point.Add(new Point()); if (n == 0) { point[0] = list[0]; } else { point[0] = Average(list[n - 1], list[n]); } if (n == list.Count - 1) { point[1] = list[list.Count - 1]; } else { point[1] = Average(list[n], list[n + 1]); } Point footPoint = Average(point[0], point[1]); Point sh = Sub(list[n], footPoint); point[0] = Mul(Add(point[0], sh), list[n]); point[1] = Mul(Add(point[1], sh), list[n]); AddPoint(point[0]); AddPoint(point[1]); return point; } public Point Average(Point x, Point y) { return new Point((x.X + y.X) / 2, (x.Y + y.Y) / 2); } public Point Add(Point x, Point y) { return new Point(x.X + y.X, x.Y + y.Y); } public Point Sub(Point x, Point y) { return new Point(x.X - y.X, x.Y - y.Y); } public Point Mul(Point x, Point y, double d = 0.6) { Point temp = Sub(x, y); temp = new Point(temp.X * d, temp.Y * d); temp = Add(y, temp); return temp; }
方式二代码:
Path path2 = null; private void PaintLine(List<Point> points) { StringBuilder data = new StringBuilder("M"); data.AppendFormat("{0},{1} C", points[0].X, points[0].Y);for (int i = 1; i < points.Count; i++) { Point pre = new Point((points[i - 1].X + points[i].X) / 2, points[i - 1].Y); //控制点 Point next = new Point((points[i - 1].X + points[i].X) / 2, points[i].Y); //控制点 data.AppendFormat(" {0},{1} {2},{3} {4},{5}", pre.X, pre.Y, next.X, next.Y, points[i].X, points[i].Y); } path2 = new Path { Stroke = Brushes.DodgerBlue, StrokeThickness = 1, Data = Geometry.Parse(data.ToString()) }; this.canvas2.Children.Add(path2); }
方法二逻辑简单得多,代码量也特别少,控制点为两点之间的中点,然后第一个控制点与第一个点水平,第二个控制点与第二个点水平。