中小企业网站制作方法,北京市网页设计,网页是网站吗,秦皇岛微信推广平台WPF Canvas 平滑笔迹控件名#xff1a;CanvasHandWriting作者#xff1a;小封#xff08;邝攀升#xff09;原文链接#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers编辑#xff1a;驚鏵完整的思路如下收集路径点集。平均采样路径点集。将路径点集转为… WPF Canvas 平滑笔迹控件名CanvasHandWriting作者小封邝攀升原文链接 https://github.com/WPFDevelopersOrg/WPFDevelopers编辑驚鏵完整的思路如下收集路径点集。平均采样路径点集。将路径点集转为 LineB。把 LineB 数据传给 Path。1Vector2D.cs 代码如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace WPFDevelopers.Samples.ExampleViews.CanvasHandWriting
{public class Vector2D{public double X { get; set; } 0;public double Y { get; set; } 0;/// summary/// 向量的模/// /summarypublic double Mold{get{//自身各分量平方运算.double X this.X * this.X;double Y this.Y * this.Y;return Math.Sqrt(X Y);//开根号,最终返回向量的长度/模/大小.}}/// summary/// 单位向量/// /summarypublic Vector2D UnitVector{get{double sumSquares (X * X) (Y * Y);return new Vector2D(X / Math.Sqrt(sumSquares), Y / Math.Sqrt(sumSquares));}}public Vector2D(){}public Vector2D(double x, double y){X x;Y y;}public Vector2D(System.Windows.Point point){X point.X;Y point.Y;}public void Offset(double angle, double distance, AngleType angleType AngleType.Radian){var vector2D Vector2D.CalculateVectorOffset(this, angle, distance, angleType);X vector2D.X;Y vector2D.Y;}public void Rotate(double angle, Vector2D vectorCenter null, AngleType angleType AngleType.Radian){vectorCenter vectorCenter null ? this : vectorCenter;var vector2D Vector2D.CalculateVectorRotation(this, vectorCenter, angle, angleType);X vector2D.X;Y vector2D.Y;}#region 静态方法/// summary/// 计算两个向量之间的距离/// /summarypublic static double CalculateVectorDistance(Vector2D vector2DA, Vector2D vector2DB){Vector2D vector2D vector2DA - vector2DB;return vector2D.Mold;}/// summary/// 计算两点夹角右侧X轴线为0度向下为正向上为负/// /summarypublic static double IncludedAngleXAxis(Vector2D vector2DA, Vector2D vector2DB, AngleType angleType AngleType.Radian){double radian Math.Atan2(vector2DB.Y - vector2DA.Y, vector2DB.X - vector2DA.X); //弧度1.1071487177940904return angleType AngleType.Radian ? radian : ComputingHelper.RadianToAngle(radian);}/// summary/// 计算两点夹角下侧Y轴线为0度向右为正向左为负/// /summarypublic static double IncludedAngleYAxis(Vector2D vector2DA, Vector2D vector2DB, AngleType angleType AngleType.Radian){double radian Math.Atan2(vector2DB.X - vector2DA.X, vector2DB.Y - vector2DA.Y); //弧度0.46364760900080609return angleType AngleType.Radian ? radian : ComputingHelper.RadianToAngle(radian);}/// summary/// 偏移向量到指定角度指定距离/// /summarypublic static Vector2D CalculateVectorOffset(Vector2D vector2D, double angle, double distance, AngleType angleType AngleType.Radian){Vector2D pointVector2D new Vector2D();if (angleType AngleType.Angle){angle angle / (180 / Math.PI);//角度转弧度}double width Math.Cos(Math.Abs(angle)) * distance;double height Math.Sin(Math.Abs(angle)) * distance;if(angle Math.PI angle 0)//if (angle is Math.PI and 0){pointVector2D.X vector2D.X - width;pointVector2D.Y vector2D.Y - height;}if (angle (-Math.PI) angle 0)//if (angle is (-Math.PI) and 0){pointVector2D.X vector2D.X - width;pointVector2D.Y vector2D.Y height;}return pointVector2D;}/// summary/// 围绕一个中心点旋转一个向量,相对旋转/// /summarypublic static Vector2D CalculateVectorRotation(Vector2D vector2D, Vector2D vectorCenter, double radian, AngleType angleType AngleType.Radian){radian angleType AngleType.Radian ? radian : ComputingHelper.RadianToAngle(radian);double x1 (vector2D.X - vectorCenter.X) * Math.Sin(radian) (vector2D.Y - vectorCenter.Y) * Math.Cos(radian) vectorCenter.X;double y1 -(vector2D.X - vectorCenter.X) * Math.Cos(radian) (vector2D.Y - vectorCenter.Y) * Math.Sin(radian) vectorCenter.Y;return new Vector2D(x1, y1);}public static Vector2D CalculateVectorCenter(Vector2D vector2DA, Vector2D vector2DB){return new Vector2D((vector2DA.X vector2DB.X) / 2, (vector2DA.Y vector2DB.Y) / 2);}/// summary/// 判断坐标点是否在多边形区域内射线法/// /summarypublic static bool IsPointPolygonalArea(Vector2D vector2D, ListVector2D aolygonaArrayList){var N aolygonaArrayList.Count;var boundOrVertex true; //如果点位于多边形的顶点或边上也算做点在多边形内直接返回truevar crossNumber 0; //x的交叉点计数var precision 2e-10; //浮点类型计算时候与0比较时候的容差Vector2D p1, p2; //neighbour bound verticesvar p vector2D; //测试点p1 aolygonaArrayList[0]; //left vertex for (var i 1; i N; i){//check all rays if (p.X.Equals(p1.X) p.Y.Equals(p1.Y)){return boundOrVertex; //p is an vertex}p2 aolygonaArrayList[i % N]; //right vertex if (p.X Math.Min(p1.X, p2.X) || p.X Math.Max(p1.X, p2.X)){//ray is outside of our interests p1 p2;continue; //next ray left point}if (p.X Math.Min(p1.X, p2.X) p.X Math.Max(p1.X, p2.X)){//ray is crossing over by the algorithm (common part of)if (p.Y Math.Max(p1.Y, p2.Y)){//x is before of ray if (p1.X p2.X p.Y Math.Min(p1.Y, p2.Y)){//overlies on a horizontal rayreturn boundOrVertex;}if (p1.Y p2.Y){//ray is vertical if (p1.Y p.Y){//overlies on a vertical rayreturn boundOrVertex;}else{//before raycrossNumber;}}else{//cross point on the left side var xinters (p.X - p1.X) * (p2.Y - p1.Y) / (p2.X - p1.X) p1.Y; //cross point of Y if (Math.Abs(p.Y - xinters) precision){//overlies on a rayreturn boundOrVertex;}if (p.Y xinters){//before raycrossNumber;}}}}else{//special case when ray is crossing through the vertex if (p.X p2.X p.Y p2.Y){//p crossing over p2 var p3 aolygonaArrayList[(i 1) % N]; //next vertex if (p.X Math.Min(p1.X, p3.X) p.X Math.Max(p1.X, p3.X)){//p.X lies between p1.X p3.XcrossNumber;}else{crossNumber 2;}}}p1 p2; //next ray left point}if (crossNumber % 2 0){//偶数在多边形外return false;}else{//奇数在多边形内return true;}}/// summary/// 判断一个点是否在一条边内/// /summarypublic static bool IsPointEdge(Vector2D point, Vector2D startPoint, Vector2D endPoint){return (point.X - startPoint.X) * (endPoint.Y - startPoint.Y) (endPoint.X - startPoint.X) * (point.Y - startPoint.Y) Math.Min(startPoint.X, endPoint.X) point.X point.X Math.Max(startPoint.X, endPoint.X) Math.Min(startPoint.Y, endPoint.Y) point.Y point.Y Math.Max(startPoint.Y, endPoint.Y);}#endregion 静态方法#region 运算符重载/// summary/// 重载运算符和运算,可以用来计算两向量距离/// /summarypublic static Vector2D operator (Vector2D vector2DA, Vector2D vector2DB){Vector2D vector2D new Vector2D();vector2D.X vector2DA.X vector2DB.X;vector2D.Y vector2DA.Y vector2DB.Y;return vector2D;}/// summary/// 重载运算符差运算,可以用来计算两向量距离/// /summarypublic static Vector2D operator -(Vector2D vector2DA, Vector2D vector2DB){Vector2D vector2D new Vector2D();vector2D.X vector2DA.X - vector2DB.X;vector2D.Y vector2DA.Y - vector2DB.Y;return vector2D;}/// summary/// 重载运算符差运算,可以用来计算两向量距离/// /summarypublic static Vector2D operator -(Vector2D vector2D, double _float){return new Vector2D(vector2D.X - _float, vector2D.Y - _float);}/// summary/// 重载运算符点积运算,可以用来计算两向量夹角/// /summarypublic static double operator *(Vector2D vector2DA, Vector2D vector2DB){return (vector2DA.X * vector2DB.X) (vector2DA.Y * vector2DB.Y);}public static double operator *(Vector2D vector2D, double _float){return (vector2D.X * _float) (vector2D.Y * _float);}/// summary/// 重载运算符点积运算,可以用来计算两向量夹角/// /summarypublic static double operator /(Vector2D vector2D, double para){return (vector2D.X / para) (vector2D.Y / para);}/// summary/// 重载运算符/// /summarypublic static bool operator (Vector2D vector2D, double para){if (vector2D.Mold para){return true;}else{return false;}}public static bool operator (Vector2D vector2D, double para){if (vector2D.Mold para){return true;}else{return false;}}public static bool operator (Vector2D vector2D, double para){if (vector2D.Mold para){return true;}else{return false;}}public static bool operator (Vector2D vector2D, double para){if (vector2D.Mold para){return true;}else{return false;}}#endregion 运算符重载#region 隐式转换/// summary/// 重载隐式转换可以直接使用Point/// /summary/// param namev/parampublic static implicit operator Vector2D(System.Windows.Point v)//隐式转换{return new Vector2D(v.X, v.Y);}/// summary/// 重载隐式转换可以直接使用Point/// /summary/// param namev/parampublic static implicit operator System.Windows.Point(Vector2D v)//隐式转换{return new System.Windows.Point(v.X, v.Y);}/// summary/// 重载隐式转换可以直接使用double/// /summary/// param namev/parampublic static implicit operator Vector2D(double v)//隐式转换{return new Vector2D(v, v);}#endregion 隐式转换#region ToStringpublic override string ToString(){return X.ToString() , Y.ToString();}public string ToString(string symbol){return X.ToString() symbol Y.ToString();}public string ToString(string sender, string symbol){return X.ToString(sender) symbol Y.ToString(sender);}#endregion}public enum AngleType {Angle,Radian}
}2ComputingHelper.cs 代码如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace WPFDevelopers.Samples.ExampleViews.CanvasHandWriting
{public static class ComputingHelper{public static double AngleToRadian(double angle){return angle * (Math.PI / 180);}public static double RadianToAngle(double radian){return radian * (180 / Math.PI);}/// summary/// 将一个值从一个范围映射到另一个范围/// /summarypublic static double RangeMapping(double inputValue, double enterLowerLimit, double enterUpperLimit, double outputLowerLimit, double OutputUpperLimit, CurveType curveType CurveType.None){var percentage (enterUpperLimit - inputValue) / (enterUpperLimit - enterLowerLimit);switch (curveType){case CurveType.Sine:percentage Math.Sin(percentage);break;case CurveType.CoSine:percentage Math.Cos(percentage);break;case CurveType.Tangent:percentage Math.Tan(percentage);break;case CurveType.Cotangent:percentage Math.Atan(percentage);break;default:break;}double outputValue OutputUpperLimit - ((OutputUpperLimit - outputLowerLimit) * percentage);return outputValue;}public static string ByteToKB(double _byte){Liststring unit new Liststring() { B, KB, MB, GB, TB, P, PB };int i 0;while (_byte 1024){_byte / 1024;i;}_byte Math.Round(_byte, 3);//保留三位小数return _byte unit[i];}/// summary/// 缩短一个数组对其进行平均采样/// /summarypublic static double[] AverageSampling(double[] sourceArray, int number){if (sourceArray.Length number){return sourceArray;//throw new Exception(新的数组必须比原有的要小!);}double[] arrayList new double[number];double stride (double)sourceArray.Length / number;for (int i 0, jIndex 0; i number; i, jIndex){double strideIncrement i * stride;strideIncrement Math.Round(strideIncrement, 6);double sum 0;int firstIndex (int)(strideIncrement);double firstDecimal strideIncrement - firstIndex;int tailIndex (int)(strideIncrement stride);double tailDecimal (strideIncrement stride) - tailIndex;if (firstDecimal ! 0)sum sourceArray[firstIndex] * (1 - firstDecimal);if (tailDecimal ! 0 tailIndex ! sourceArray.Length)sum sourceArray[tailIndex] * (tailDecimal);int startIndex firstDecimal 0 ? firstIndex : firstIndex 1;int endIndex tailIndex;for (int j startIndex; j endIndex; j)sum sourceArray[j];arrayList[jIndex] sum / stride;}return arrayList;}public static ListVector2D AverageSampling(ListVector2D sourceArray, int number){if (sourceArray.Count number - 2){return sourceArray;}double[] x new double[sourceArray.Count];double[] y new double[sourceArray.Count];for (int i 0; i sourceArray.Count; i){x[i] sourceArray[i].X;y[i] sourceArray[i].Y;}double[] X AverageSampling(x, number - 2);double[] Y AverageSampling(y, number - 2);ListVector2D arrayList new ListVector2D();for (int i 0; i number - 2; i){arrayList.Add(new Vector2D(X[i], Y[i]));}arrayList.Insert(0, sourceArray[0]);//添加首arrayList.Add(sourceArray[sourceArray.Count - 1]);//添加尾return arrayList;}}public enum CurveType {Sine,CoSine,Tangent,Cotangent,None}
}3LineB.cs 代码如下using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;namespace WPFDevelopers.Samples.ExampleViews.CanvasHandWriting
{public class LineB{private ListVector2D _vector2DList new ListVector2D();public ListVector2D Vector2DList{get { return _vector2DList; }set{_vector2DList value;}}private ListBezierCurve _bezierCurveList new ListBezierCurve();public ListBezierCurve BezierCurveList{get { return _bezierCurveList; }private set { _bezierCurveList value; }}private double _tension 0.618;public double Tension{get { return _tension; }set{_tension value;if (_tension 10)_tension 10;if (_tension 0)_tension 0;}}private bool _isClosedCurve true;public bool IsClosedCurve{get { return _isClosedCurve; }set { _isClosedCurve value; }}private string _pathData string.Empty;public string PathData{get{if (_pathData string.Empty){_pathData Vector2DToBezierCurve();}return _pathData;}}private string Vector2DToBezierCurve() {if (Vector2DList.Count 3)return string.Empty;BezierCurveList.Clear();for (int i 0; i Vector2DList.Count; i){int pointTwoIndex i 1 Vector2DList.Count ? i 1 : 0;int pointThreeIndex i 2 Vector2DList.Count ? i 2 : i 2 - Vector2DList.Count;Vector2D vector2D1 Vector2DList[i];Vector2D vector2D2 Vector2DList[pointTwoIndex];Vector2D vector2D3 Vector2DList[pointThreeIndex];Vector2D startVector2D Vector2D.CalculateVectorCenter(vector2D1, vector2D2);double startAngle Vector2D.IncludedAngleXAxis(vector2D1, vector2D2);double startDistance Vector2D.CalculateVectorDistance(startVector2D, vector2D2) * (1 - Tension);Vector2D startControlPoint Vector2D.CalculateVectorOffset(vector2D2, startAngle, startDistance);Vector2D endVector2D Vector2D.CalculateVectorCenter(vector2D2, vector2D3);double endAngle Vector2D.IncludedAngleXAxis(endVector2D, vector2D2);double endDistance Vector2D.CalculateVectorDistance(endVector2D, vector2D2) * (1 - Tension);Vector2D endControlPoint Vector2D.CalculateVectorOffset(endVector2D, endAngle, endDistance);BezierCurve bezierCurve new BezierCurve();bezierCurve.StartVector2D startVector2D;bezierCurve.StartControlPoint startControlPoint;bezierCurve.EndVector2D endVector2D;bezierCurve.EndControlPoint endControlPoint;BezierCurveList.Add(bezierCurve);}if (!IsClosedCurve){BezierCurveList[0].StartVector2D Vector2DList[0];BezierCurveList.RemoveAt(BezierCurveList.Count - 1);BezierCurveList[BezierCurveList.Count - 1].EndVector2D Vector2DList[Vector2DList.Count - 1];BezierCurveList[BezierCurveList.Count - 1].EndControlPoint BezierCurveList[BezierCurveList.Count - 1].EndVector2D;}string path $M {BezierCurveList[0].StartVector2D.ToString()} ;foreach (var item in BezierCurveList){path $C {item.StartControlPoint.ToString( )},{item.EndControlPoint.ToString( )},{item.EndVector2D.ToString( )} ;}return path;}public LineB(){}public LineB(ListVector2D verVector2DList, bool isClosedCurve true){this.Vector2DList verVector2DList;this.IsClosedCurve isClosedCurve;}/// summary/// 重载隐式转换可以直接使用Point/// /summary/// param namev/parampublic static implicit operator Geometry(LineB lineB)//隐式转换{return Geometry.Parse(lineB.PathData);}}public class BezierCurve{private Vector2D _startVector2D new Vector2D(0, 0);public Vector2D StartVector2D{get { return _startVector2D; }set { _startVector2D value; }}private Vector2D _startControlPoint new Vector2D(0, 100);public Vector2D StartControlPoint{get { return _startControlPoint; }set { _startControlPoint value; }}private Vector2D _endControlPoint new Vector2D(100, 0);public Vector2D EndControlPoint{get { return _endControlPoint; }set { _endControlPoint value; }}private Vector2D _endVector2D new Vector2D(100, 100);public Vector2D EndVector2D{get { return _endVector2D; }set { _endVector2D value; }}}
}4CanvasHandWritingExample.xaml 代码如下UserControl x:ClassWPFDevelopers.Samples.ExampleViews.CanvasHandWriting.CanvasHandWritingExamplexmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006 xmlns:dhttp://schemas.microsoft.com/expression/blend/2008 xmlns:localclr-namespace:WPFDevelopers.Samples.ExampleViews.CanvasHandWritingmc:Ignorabled d:DesignHeight450 d:DesignWidth800UserControl.ResourcesStyle TargetType{x:Type TextBlock}Setter PropertyForeground Value{StaticResource PrimaryTextSolidColorBrush} //Style/UserControl.ResourcesGridGrid.RowDefinitionsRowDefinition Heightauto/RowDefinition//Grid.RowDefinitionsStackPanel OrientationHorizontal Margin4TextBlock Text张力: VerticalAlignmentCenter/TextBox Text{Binding Tension,RelativeSource{RelativeSource AncestorTypelocal:CanvasHandWritingExample}}/Slider Width100 SmallChange0.01 Value{Binding Tension,RelativeSource{RelativeSource AncestorTypelocal:CanvasHandWritingExample}} Maximum1 VerticalAlignmentCenter Margin5,0/TextBlock Text平滑采样: VerticalAlignmentCenter/TextBox Text{Binding SmoothSampling,RelativeSource{RelativeSource AncestorTypelocal:CanvasHandWritingExample}}Margin5,0/Slider Value{Binding SmoothSampling,RelativeSource{RelativeSource AncestorTypelocal:CanvasHandWritingExample}}Width100 VerticalAlignmentCenter SmallChange0.01 Maximum1 TickFrequency0.1/CheckBox Content橡皮擦 VerticalAlignmentCenterMargin5,0IsChecked{Binding IsEraser,RelativeSource{RelativeSource AncestorTypelocal:CanvasHandWritingExample}}/Button Content清空画布 ClickbtnClertCanvas_Click//StackPanelCanvas x:NamedrawingCanvas Grid.Row1 BackgroundBlack PreviewMouseLeftButtonDownDrawingCanvas_PreviewMouseLeftButtonDownPreviewMouseMoveDrawingCanvas_PreviewMouseMovePreviewMouseLeftButtonUpDrawingCanvas_PreviewMouseLeftButtonUp//Grid
/UserControl5CanvasHandWritingExample.xaml.cs 代码如下using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;namespace WPFDevelopers.Samples.ExampleViews.CanvasHandWriting
{/// summary/// CanvasHandWritingExample.xaml 的交互逻辑/// /summarypublic partial class CanvasHandWritingExample : UserControl{public static readonly DependencyProperty TensionProperty DependencyProperty.Register(Tension, typeof(double), typeof(CanvasHandWritingExample),new PropertyMetadata(0.618));public static readonly DependencyProperty SmoothSamplingProperty DependencyProperty.Register(SmoothSampling, typeof(double), typeof(CanvasHandWritingExample),new UIPropertyMetadata(OnSmoothSamplingChanged));public static readonly DependencyProperty IsEraserProperty DependencyProperty.Register(IsEraser, typeof(bool), typeof(CanvasHandWritingExample),new PropertyMetadata(false));private readonly DictionaryPath, ListVector2D _PathVector2DDictionary ;volatile bool _IsStart false;Path _DrawingPath default;private static void OnSmoothSamplingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var mWindow (CanvasHandWritingExample)d;foreach (var item in mWindow._PathVector2DDictionary.Keys){mWindow.DrawLine(item);}}public CanvasHandWritingExample(){InitializeComponent();_PathVector2DDictionary new DictionaryPath, ListVector2D();SmoothSampling 0.8;}private void DrawingCanvas_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e){_IsStart true;_DrawingPath new Path(){StrokeDashCap PenLineCap.Round,StrokeStartLineCap PenLineCap.Round,StrokeEndLineCap PenLineCap.Round,StrokeLineJoin PenLineJoin.Round,};if (IsEraser){_DrawingPath.Stroke new SolidColorBrush(Colors.Black);_DrawingPath.StrokeThickness 40;}else{var random new Random();var strokeBrush new SolidColorBrush(Color.FromRgb((byte)random.Next(200, 255), (byte)random.Next(0, 255), (byte)random.Next(0, 255)));_DrawingPath.Stroke strokeBrush;_DrawingPath.StrokeThickness 10;}_PathVector2DDictionary.Add(_DrawingPath, new ListVector2D());drawingCanvas.Children.Add(_DrawingPath);}private void DrawingCanvas_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e){_IsStart false;_DrawingPath default;}private void DrawingCanvas_PreviewMouseMove(object sender, MouseEventArgs e){if (!_IsStart)return;if (_DrawingPath is null)return;Vector2D currenPoint e.GetPosition(drawingCanvas);if (currenPoint.X 0 || currenPoint.Y 0)return;if (currenPoint.X drawingCanvas.ActualWidth || currenPoint.Y drawingCanvas.ActualHeight)return;if (_PathVector2DDictionary[_DrawingPath].Count 0){if (Vector2D.CalculateVectorDistance(currenPoint, _PathVector2DDictionary[_DrawingPath][_PathVector2DDictionary[_DrawingPath].Count - 1]) 1)_PathVector2DDictionary[_DrawingPath].Add(e.GetPosition(drawingCanvas));}else_PathVector2DDictionary[_DrawingPath].Add(e.GetPosition(drawingCanvas));DrawLine(_DrawingPath);}public double Tension{get (double)GetValue(TensionProperty);set SetValue(TensionProperty, value);}public double SmoothSampling{get (double)GetValue(SmoothSamplingProperty);set SetValue(SmoothSamplingProperty, value);}public bool IsEraser{get (bool)GetValue(IsEraserProperty);set SetValue(IsEraserProperty, value);}private void DrawLine(Path path){if (_PathVector2DDictionary[path].Count 2){var pathVector2Ds _PathVector2DDictionary[path];var smoothNum (int)(_PathVector2DDictionary[path].Count * SmoothSampling);if (smoothNum 1)pathVector2Ds ComputingHelper.AverageSampling(_PathVector2DDictionary[path], smoothNum);var lineB new LineB(pathVector2Ds, false);lineB.Tension Tension;path.Data lineB;}}private void btnClertCanvas_Click(object sender, RoutedEventArgs e){drawingCanvas.Children.Clear();_PathVector2DDictionary.Clear();}}
}