在画布上绘制一个大像素

时间:2011-10-19 13:16:50

标签: c# .net silverlight windows-phone-7 drawing

我正在编写一个允许用户在触摸屏上显示的应用程序。我目前正在使用下面的方法,它工作得很好。该方法产生“高分辨率图像”,因为对于几乎每个单个像素绘制一条线(例如100,100-> 102,103)。

这是我的问题。我希望用户绘制一个“低分辨率图片”(大像素板),你可以有意识地看到50×50的像素(例如100,100 - > 150,150)。有没有人知道如何实现这一目标?我正在使用Silverlight for Windows Phone。我正在考虑建立一个50×50像素的大网格,但可能有太多的控件。

void FingerMove(object sender, MouseEventArgs e)
{
    if (this.IsDrawing)
    {
        this.DestinationPoint = e.GetPosition(paint);
        Line line = new Line
        {
            Stroke = this.Color,
            X1 = this.DestinationPoint.X,
            Y1 = this.DestinationPoint.Y,
            X2 = this.OriginPoint.X,
            Y2 = this.OriginPoint.Y,
            StrokeStartLineCap = PenLineCap.Round,
            StrokeEndLineCap = PenLineCap.Round,
            StrokeThickness = 15,
            Opacity = 1,
        };

        Debug.WriteLine(string.Join(",", line.X1, line.Y1, line.X2, line.Y2));

        paint.Children.Add(line);
    }

    this.OriginPoint = this.DestinationPoint;
}

2 个答案:

答案 0 :(得分:1)

@Amr有正确的想法。我会告诉你这段代码,但我还没有对它进行过测试。我从here获取了线段交叉算法。

首先,您需要设置一个矩形列表并将它们添加到您的"像素"的画布中:

    private List<Rectangle> _rects = new List<Rectangle>();

    private void GenerateRects()
    {
        int width = 300; // or whatever dimensions...
        int height = 300;
        int gridSize = 50;

        for (int x = 0; x < width; x += gridSize)
        {
            for (int y = 0; y < height; y += gridSize)
            {
                var rect = new Rectangle
                {
                    Opacity = 0,
                    Width = Math.Min(gridSize, width - x),
                    Height = Math.Min(gridSize, height - y),
                };

                Canvas.SetLeft(rect, x);
                Canvas.SetTop(rect, y);

                _rects.Add(rect);
                this.paint.Children.Add(rect);
            }
        }
    }

我们需要这些辅助方法:

    class LineSegment
    {
        public double X1 { get; set; }
        public double X2 { get; set; }
        public double Y1 { get; set; }
        public double Y2 { get; set; }
    }

    private static bool SegmentsIntersect(LineSegment A, LineSegment B)
    {
        double x1 = A.X1, x2 = A.X2, x3 = B.X1, x4 = B.X2;
        double y1 = A.Y1, y2 = A.Y2, y3 = B.Y1, y4 = B.Y2;

        double denominator = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);

        if (denominator == 0)
            return false;

        double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator;
        double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator;

        return (ua > 0 && ua < 1 && ub > 0 && ub < 1);
    }

    private static bool RectIntersectsLine(Rect A, LineSegment B)
    {
        return (SegmentsIntersect(B, new LineSegment { X1 = A.X, Y1 = A.Y, X2 = A.X, Y2 = A.Y + A.Height }) ||
            SegmentsIntersect(B, new LineSegment { X1 = A.X, Y1 = A.Y + A.Height, X2 = A.X + A.Width, Y2 = A.Y + A.Height }) ||
            SegmentsIntersect(B, new LineSegment { X1 = A.X + A.Width, Y1 = A.Y + A.Height, X2 = A.X + A.Width, Y2 = A.Y }) ||
            SegmentsIntersect(B, new LineSegment { X1 = A.X + A.Width, Y1 = A.Y, X2 = A.X, Y2 = A.Y }) ||
            RectContainsPoint(A, new Point(B.X1, B.Y1)) ||
            RectContainsPoint(A, new Point(B.X2, B.Y2)));
    }

    private static bool RectContainsPoint(Rect A, Point B)
    {
        return (B.X > A.X && B.X < A.X + A.Width && B.Y > A.Y && B.Y < A.Y + A.Height);
    }

然后,在FingerMove函数中,我们遍历每个Rectangle以查看它是否相交。如果是,我们改变它的颜色:

    void FingerMove(object sender, MouseEventArgs e)
    {
        if (this.IsDrawing)
        {
            this.DestinationPoint = e.GetPosition(paint);
            LineSegment line = new LineSegment
            {
                X1 = this.DestinationPoint.X,
                Y1 = this.DestinationPoint.Y,
                X2 = this.OriginPoint.X,
                Y2 = this.OriginPoint.Y
            };

            foreach (var rect in _rects)
            {
                var x = Canvas.GetLeft(rect);
                var y = Canvas.GetTop(rect);

                if (RectIntersectsLine(new Rect(x, y, rect.Width, rect.Height) , line))
                {
                    rect.Opacity = 1;
                    rect.Fill = Color;
                }
            }
        }

        this.OriginPoint = this.DestinationPoint;
    }

答案 1 :(得分:0)

如果您只是想让线条变粗,只需尝试使用StrokeThickness的可能值,直到获得所需的效果。

如果您想通过填充屏幕的大部分区域(50x50)矩形来手动绘制线条,您可以执行以下操作:

  1. 将屏幕划分为50x50矩形
  2. 检查哪些矩形与用户绘制的线相交
  3. 仅绘制第2步中的矩形
  4. 这将为您提供所需的“对齐网格”行。