Board

专注WPF、SWT、Java、TUIO、lua、电子白板软件研发、多点触摸算法、跟踪算法、视频会议、触摸一体机、红外触控、触摸框架、数字图像处理研究

导航

InkCanvas 自由虚线笔画

Posted on 2011-08-05 23:49  kodos  阅读(2351)  评论(5编辑  收藏  举报

先看效果图:

因为公司是做电子白板软件的所以,对InkCanvas的Stroke进行继承,这样既可省去橡皮擦等的开发.

核心是重写DrawCore函数.

DrawEnd 函数是实现笔尾的三角箭头

DrawHead 函数是实现笔头的三角箭头 

其实原理也简单,就是使用 PathGeometry 然后设置Pen 的DashStyle

再使用LineSegment 绘制stylusPoint既可。

 internal class PathStrokeK : Stroke
    {
        private static double[] dashs = new double[] { 5.0, 3.0 };
        private static Brush EndBrush = Brushes.Red;
        private Geometry endGeometry;
        private static string EndGeometryString = "M 0,0 L {0},{1} L0,{0}z";
        private Size endSize;
        private static Brush HeadBrush = Brushes.Green;
        private Geometry headGeometry;
        private static string HeadGeometryString = "M 0,{1} L {0},0 L{0},{0}z";
        private Size headSize;
        private static double Ratio = 5.0;
        private static double Thickness = 3.0;

        public PathStrokeK(StylusPointCollection spc)
            : base(spc)
        {
            string source = string.Format(HeadGeometryString, Thickness * Ratio, (Thickness * Ratio) / 2.0);
            string str2 = string.Format(EndGeometryString, Thickness * Ratio, (Thickness * Ratio) / 2.0);
            this.headGeometry = Geometry.Parse(source);
            this.endGeometry = Geometry.Parse(str2);
            this.headSize = new Size(Thickness * Ratio, Thickness * Ratio);
            this.endSize = new Size(Thickness * Ratio, Thickness * Ratio);
        }

        public void AddPoints(IEnumerable<StylusPoint> stylusPoints)
        {
            foreach (StylusPoint point in stylusPoints)
            {
                base.StylusPoints.Add(point);
            }
        }

        protected override void DrawCore(DrawingContext dc, DrawingAttributes da)
        {
            Brush brush = new SolidColorBrush(da.Color);
            StylusPointCollection stylusPoints = base.StylusPoints;
            if ((dashs == null) || (dashs.Length == 0))
            {
                base.DrawCore(dc, da);
            }
            else if (stylusPoints.Count > 0)
            {
                Pen pen = new Pen
                {
                    Brush = brush,
                    Thickness = Thickness,
                    DashStyle = new DashStyle(dashs, 0.0),
                    DashCap = PenLineCap.Round,
                    LineJoin = PenLineJoin.Round,
                    MiterLimit = 0.0
                };
                PathGeometry geometry = new PathGeometry();
                PathFigure figure = new PathFigure
                {
                    StartPoint = (Point)stylusPoints[0],
                    IsClosed = false
                };
                for (int i = 1; i < stylusPoints.Count; i++)
                {
                    figure.Segments.Add(new LineSegment((Point)stylusPoints[i], true));
                }
                geometry.Figures.Add(figure);
                dc.DrawGeometry(null, pen, geometry);
                dc.DrawGeometry(brush, null, new EllipseGeometry((Point)stylusPoints[0], Thickness / 2.0, Thickness / 2.0));
                dc.DrawGeometry(brush, null, new EllipseGeometry((Point)stylusPoints[stylusPoints.Count - 1], Thickness / 2.0, Thickness / 2.0));
            }
            if (stylusPoints.Count > 1)
            {
                if (this.headGeometry != null)
                {
                    this.DrawHead(dc, (Point)stylusPoints[0], (Point)stylusPoints[1], HeadBrush);
                }
                if (this.endGeometry != null)
                {
                    this.DrawEnd(dc, (Point)stylusPoints[stylusPoints.Count - 1], (Point)stylusPoints[stylusPoints.Count - 2], EndBrush);
                }
            }
        }

        private void DrawEnd(DrawingContext dc, Point p0, Point p1, Brush b)
        {
            Matrix matrix = new Matrix();
            matrix.Translate(-this.endSize.Width / 2.0, -this.endSize.Height / 2.0);
            Vector vector = new Vector(1.0, 0.0);
            Vector vector2 = Point.Subtract(p0, p1);
            matrix.Rotate(Vector.AngleBetween(vector, vector2));
            matrix.Translate(p0.X, p0.Y);
            Geometry geometry = Geometry.Combine(this.endGeometry, Geometry.Empty, GeometryCombineMode.Union, new MatrixTransform(matrix));
            dc.DrawGeometry(b, null, geometry);
        }

        private void DrawHead(DrawingContext dc, Point p0, Point p1, Brush b)
        {
            Matrix matrix = new Matrix();
            matrix.Translate(-this.headSize.Width / 2.0, -this.headSize.Height / 2.0);
            Vector vector = new Vector(1.0, 0.0);
            Vector vector2 = Point.Subtract(p1, p0);
            matrix.Rotate(Vector.AngleBetween(vector, vector2));
            matrix.Translate(p0.X, p0.Y);
            Geometry geometry = Geometry.Combine(this.headGeometry, Geometry.Empty, GeometryCombineMode.Union, new MatrixTransform(matrix));
            dc.DrawGeometry(b, null, geometry);
        }
    }