WPF InkCanvas: рисование линии с помощью DynamicRenderer

Я пишу базовый графический редактор в WPF, используя InkCanvas. Я сделал несколько пользовательских форм (унаследованных от Stroke). Когда я рисую линию на InkCanvas, я беру первую и последнюю точки и строю линию. Это прекрасно работает, но теперь мне не нравится «росчерк пера» по умолчанию, поэтому я решил переписать DynamicRenderer для рендеринга линий в реальном времени.

Проблема в том, что DynamicRenderer рисует линию от исходной точки до каждой точки обводки, и я, очевидно, этого не хочу, потому что это делает "fan" вместо строки.

Есть мой собственный код, и я ищу решение для рисования линии только от исходной точки до последней точки, если это возможно.

class LineRenderer : DynamicRenderer
{
    private Point firstPoint;
    private Pen pen = new Pen(new SolidColorBrush(Colors.Gray),1);

    public LineRenderer()
    {
        firstPoint = new Point(double.PositiveInfinity, double.PositiveInfinity);
    }

    protected override void OnStylusDown(RawStylusInput rawStylusInput)
    {
        firstPoint = new Point(rawStylusInput.GetStylusPoints().First().ToPoint().X, rawStylusInput.GetStylusPoints().First().ToPoint().Y);
        base.OnStylusDown(rawStylusInput);
    }

    protected override void OnDraw(DrawingContext drawingContext,
                                   StylusPointCollection stylusPoints,
                                   Geometry geometry, Brush fillBrush)
    {
        drawingContext.DrawLine(pen, firstPoint, stylusPoints.First().ToPoint());
    }

    protected override void OnStylusUp(RawStylusInput rawStylusInput)
    {
        firstPoint = new Point(double.PositiveInfinity, double.PositiveInfinity);
        base.OnStylusUp(rawStylusInput);
    }
}

person Errol Piper    schedule 16.07.2013    source источник


Ответы (2)


Это очень поздно. Чтобы избежать «веера» во время рисования штриха, попробуйте следующее:

protected override void OnDraw(DrawingContext drawingContext,
                               StylusPointCollection stylusPoints,
                               Geometry geometry, Brush fillBrush)
        {
            if (!_isManipulating)
            {
                _isManipulating = true;
                StylusDevice currentStylus = Stylus.CurrentStylusDevice;
                this.Reset(currentStylus, stylusPoints);
            }
            _isManipulating = false;

            var pen = new Pen(brush, 2);
            drawingContext.DrawLine(pen, startPoint,stylusPoints.First().ToPoint());
       }


protected override void OnStylusDown(RawStylusInput rawStylusInput)
        {
            StylusPointCollection y = rawStylusInput.GetStylusPoints();
            startPoint = (Point)y.First();

            // Allocate memory to store the previous point to draw from.
            prevPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
            base.OnStylusDown(rawStylusInput);
        }

Хитрость здесь заключается в использовании DynamicRenderer.Reset, который:

Очищает рендеринг текущего штриха и перерисовывает его.

Перерисовка повторно войдет в метод OnDraw, поэтому _isManipulating предоставляет простой флаг для прекращения зацикливания.

person Alan Wayne    schedule 18.02.2018
comment
Это должно быть помечено как правильный ответ. Сэкономил мне много времени. Спасибо! - person son of the northern darkness; 20.05.2018

что я думаю, в вашей функции ondraw ваша первая точка зафиксирована, поэтому она всегда принимает ее за начало, поэтому вы можете попробовать это для непрерывного рисования.

protected override void OnDraw(DrawingContext drawingContext,
                               StylusPointCollection stylusPoints,
                               Geometry geometry, Brush fillBrush)
{
    drawingContext.DrawLine(pen, firstPoint, stylusPoints.First().ToPoint());
firstPoint = stylusPoints.First().ToPoint();
}

он обновит вашу первую точку, если вы получите такое же исключение точки, поставьте на нем галочку (или вы можете определить новое имя точки как предыдущую точку и изначально сделать ее равной первой точке и поддерживать ее обновление в вашем методе ondraw, как я сделал с первой точкой. .

и если вам нужна прямая линия от первой точки до последней точки, вы можете вызвать вас методом рисования после получения последней точки из метода onstylusup. Надеюсь, это может вам помочь.

person loop    schedule 16.07.2013
comment
Когда я перемещаю мышь, я хочу провести линию от первой точки (поэтому она фиксирована) до точки, где находится курсор. Это работает, но рисует линию для каждой точки на пути движения. Мне нужна только одна строка: от первой точки (где я щелкнул/фиксированная) до текущей позиции курсора, когда я его перемещаю. - person Errol Piper; 16.07.2013
comment
посмотрите, что происходит, ваш ondraw вызывается каждой точкой на линии правильно, поэтому он рисует линию от вашей первой точки до каждой точки, которую вы получаете на холсте ... поэтому вам нужно просто обновить свою первую точку до вашей текущей точки, пока эта линия не будет нарисована .. код, который я дал, просто проверьте его .. он будет работать .. вы можете проверить это, поставив точку останова на методе ondraw .. - person loop; 16.07.2013
comment
Похоже, мы не понимаем друг друга, поэтому я рисую небольшую диаграмму ссылка. Я нажимаю (красный кружок) и двигаю мышью (красная линия). Красные прямоугольники — это точки сбора. Я хочу рисовать синюю линию (по одной за раз), когда я перемещаю мышь. Ваш код просто соединяет красные прямоугольники и делает линию вдоль красного. - person Errol Piper; 16.07.2013
comment
посмотри, что я думаю.. тебе нужна только одна линия от первой точки до последней точки (точка, когда ты покидаешь холст.хорошо).. - person loop; 17.07.2013