Xamarin NGraphics:使用 Path.CurveTo 和 Path.ContineCurveTo 没有平滑的路径
Xamarin NGraphics: Using Path.CurveTo and Path.ContineCurveTo doesn't have a smooth path
我正在使用 NGraphics 在自定义视图上绘制连续笔画。这是我在上面绘制笔划时得到的图像。红色圆圈表示边缘不光滑。第二张图片显示了我在调用鼠标移动事件时收到的控制点的红色小矩形。如果控制点足够接近,曲线看起来会更好。
我查看了 NGraphics 代码,看起来曲线确实绘制为贝塞尔曲线路径。
public Point GetPoint (Point prevPoint, double t)
{
var u = 1 - t;
return
u * u * u * prevPoint +
3 * u * u * t * Control1 +
3 * u * t * t * Control2 +
t * t * t * Point;
}
public override EdgeSamples[] GetEdgeSamples (Point startPoint, Point prevPoint, double tolerance, int minSamples, int maxSamples)
{
var n = (3*prevPoint.DistanceTo (Point)) / tolerance;
if (n < minSamples)
n = minSamples;
if (n > maxSamples)
n = maxSamples;
var r = new List<Point> ();
var dt = 1.0 / (n - 1);
for (var i = 0; i < n; i++) {
var t = i * dt;
var p = GetPoint (prevPoint, t);
r.Add (p);
}
return new[]{ new EdgeSamples { Points = r.ToArray () } };
}
我使用curveTo和continueCurveTo的触摸事件:
#region Drawing Event
private bool DrawingBegan(TouchData touchData)
{
var stroke = new StrokeModel();
stroke.Points = new ObservableCollection<PointModel>();
stroke.Pointer = touchData.PointerId;
stroke.Path = new Path();
stroke.PenColor = Pen.Color;
stroke.PenWidth = Pen.Width;
stroke.DeviceOrientation = DeviceInfo.DeviceOrientation;
_localStroke.Add(stroke);
return base.TouchesBegan(touchData);
}
private bool DrawingMove(TouchData touchData)
{
foreach (var stroke in _localStroke)
{
if (stroke.Pointer == touchData.PointerId)
{
var length = stroke.Points.Count - 1;
if (stroke.Points.Count == 2)
{
var p1 = ConvertGlobalToLocal(new Point(stroke.Points[length - 1].X, stroke.Points[length - 1].Y));
var p2 = ConvertGlobalToLocal(new Point(stroke.Points[length].X, stroke.Points[length].Y));
var p3 = touchData.Point;
stroke.Path.MoveTo(p1);
stroke.Path.CurveTo(p1, p2, p3);
}
else if (stroke.Points.Count > 2)
{
var p2 = ConvertGlobalToLocal(new Point(stroke.Points[length].X, stroke.Points[length].Y));
var p3 = touchData.Point;
stroke.Path.LineTo(p2);
stroke.Path.ContinueCurveTo(p2, p3);
}
var newPoint = ConvertLocalToGlobal(touchData.Point);
var point = new PointModel();
point.X = newPoint.X;
point.Y = newPoint.Y;
stroke.Points.Add(point);
break;
}
}
return base.TouchesMoved(touchData);
}
会不会是因为样本量不够?
我已经通过使用 HistoricalX 和 HistoricalY 解决了这个问题...如果不使用,一些触摸数据将会丢失。
我正在使用 NGraphics 在自定义视图上绘制连续笔画。这是我在上面绘制笔划时得到的图像。红色圆圈表示边缘不光滑。第二张图片显示了我在调用鼠标移动事件时收到的控制点的红色小矩形。如果控制点足够接近,曲线看起来会更好。
我查看了 NGraphics 代码,看起来曲线确实绘制为贝塞尔曲线路径。
public Point GetPoint (Point prevPoint, double t)
{
var u = 1 - t;
return
u * u * u * prevPoint +
3 * u * u * t * Control1 +
3 * u * t * t * Control2 +
t * t * t * Point;
}
public override EdgeSamples[] GetEdgeSamples (Point startPoint, Point prevPoint, double tolerance, int minSamples, int maxSamples)
{
var n = (3*prevPoint.DistanceTo (Point)) / tolerance;
if (n < minSamples)
n = minSamples;
if (n > maxSamples)
n = maxSamples;
var r = new List<Point> ();
var dt = 1.0 / (n - 1);
for (var i = 0; i < n; i++) {
var t = i * dt;
var p = GetPoint (prevPoint, t);
r.Add (p);
}
return new[]{ new EdgeSamples { Points = r.ToArray () } };
}
我使用curveTo和continueCurveTo的触摸事件:
#region Drawing Event
private bool DrawingBegan(TouchData touchData)
{
var stroke = new StrokeModel();
stroke.Points = new ObservableCollection<PointModel>();
stroke.Pointer = touchData.PointerId;
stroke.Path = new Path();
stroke.PenColor = Pen.Color;
stroke.PenWidth = Pen.Width;
stroke.DeviceOrientation = DeviceInfo.DeviceOrientation;
_localStroke.Add(stroke);
return base.TouchesBegan(touchData);
}
private bool DrawingMove(TouchData touchData)
{
foreach (var stroke in _localStroke)
{
if (stroke.Pointer == touchData.PointerId)
{
var length = stroke.Points.Count - 1;
if (stroke.Points.Count == 2)
{
var p1 = ConvertGlobalToLocal(new Point(stroke.Points[length - 1].X, stroke.Points[length - 1].Y));
var p2 = ConvertGlobalToLocal(new Point(stroke.Points[length].X, stroke.Points[length].Y));
var p3 = touchData.Point;
stroke.Path.MoveTo(p1);
stroke.Path.CurveTo(p1, p2, p3);
}
else if (stroke.Points.Count > 2)
{
var p2 = ConvertGlobalToLocal(new Point(stroke.Points[length].X, stroke.Points[length].Y));
var p3 = touchData.Point;
stroke.Path.LineTo(p2);
stroke.Path.ContinueCurveTo(p2, p3);
}
var newPoint = ConvertLocalToGlobal(touchData.Point);
var point = new PointModel();
point.X = newPoint.X;
point.Y = newPoint.Y;
stroke.Points.Add(point);
break;
}
}
return base.TouchesMoved(touchData);
}
会不会是因为样本量不够?
我已经通过使用 HistoricalX 和 HistoricalY 解决了这个问题...如果不使用,一些触摸数据将会丢失。