Подтвердить что ты не робот

Как рисовать графику как можно эффективнее в WPF

Я создаю инструмент, который в значительной степени опирается на деревья с графами node. Текущая реализация выполняется в Java, и я переношу ее на общую базу кода на С#, поэтому ее можно использовать различными реализациями рендеринга, а также потому, что я хочу использовать WPF для удобного интерфейса.

После просмотра в течение дня я наткнулся на различные методы рисования векторной графики через WPF.

Этот парень говорит о разных уровнях в WPF-разработчиках. Поскольку я хочу сначала использовать WPF PURELY для его рендеринга, я хочу работать над "Visual Layer".

Затем я встретил такие вещи, как: DrawingVisual, GeometryDrawing, FrameworkElement/UIElement/Shapes

Итак, я немного перегружен всеми различными реализациями, которые в конечном итоге делают то же самое совершенно по-другому.

Библиотека Graph- node была перенесена на С# уже со всей логикой (включая обнаружение конфликтов и перетаскивание мышью). Как это сделано с графическими рендерерами в виду (например, XNA, SlimDX, OpenTK и т.д.), Что было бы лучшим способом с точки зрения производительности для реализации рендеринга WPF (как в нем, он будет рисовать все, что говорит библиотека графов рисовать?

В принципе, результирующий элемент управления WPF действует как холст, но он должен быть SUPER легким и не иметь каких-либо опрятных функций WPF, кроме того, чтобы предоставить мне способ рисовать круги, линии и другие фигуры:)

EDIT:

В основном я хочу знать: как идти? Расширить ли Canvas как "Host" для моей графики, а затем добавить пользовательскую реализацию UIElement? Или у меня есть один класс, который может рисовать ВСЕ (как в одной мега супер ультра графике). Очень похоже на переопределение OnPaint в GDI или Paint-метод в Java (который дает объекту Graphics делать все с).

4b9b3361

Ответ 2

Как правило, более высокая производительность достигается при обслуживании более низкого уровня. В WPF это означает семейство объектов Drawing. Все, что вы получаете: Drawing, DrawingGroup, GeometryDrawing, GlyphRunDrawing, ImageDrawing и VideoDrawing. Однако они достаточны для всех потребностей. Использование этих типов очень дружит с WPF, потому что Drawing - это концептуальная единица, которая WPF обменивается с вашим ускорителем GPU, возможно, сохраняя и управляя им там, если это возможно. Это работает, потому что Drawing выражается в терминах переносимых примитивов векторного рисования.

Как только вы начнете повторное архивирование своего приложения вокруг Drawings, однако вам может потребоваться некоторое взаимодействие с вашим кодом более высокого уровня, который по-прежнему основан на UIElement, FrameworkElement и т.д. Одна вещь, найденный встроенным в WPF, - это простой способ обернуть Drawing как элемент Framework с наименьшим возможным способом. DrawingVisual не является полным решением, так как оно происходит только от Visual - это значит, что для него все еще требуется элемент хостинга.

Следующий класс будет размещать любой WPF Drawing напрямую без использования промежуточного DrawingVisual. Я добавил поддержку свойства FrameworkElement Margin (без штрафа за производительность, если он не использовался), но немного больше. Из-за потока рендеринга WPF он безопасен и легко кэширует один объект TranslateTransform для реализации поля. Я бы рекомендовал вам поставлять только рисунки, которые были заморожены; на самом деле, в версии, которую я использую, у меня есть утверждение об этом в конструкторе.

public class DrawingElement : FrameworkElement
{
    static readonly TranslateTransform tt_cache = new TranslateTransform();

    public DrawingElement(Drawing drawing)
    {
        this.drawing = drawing;
    }
    readonly Drawing drawing;

    TranslateTransform get_transform()
    {
        if (Margin.Left == 0 && Margin.Top == 0)
            return null;
        tt_cache.X = Margin.Left;
        tt_cache.Y = Margin.Top;
        return tt_cache;
    }
    protected override Size MeasureOverride(Size _)
    {
        var sz = drawing.Bounds.Size;
        return new Size
        {
            Width = sz.Width + Margin.Left + Margin.Right,
            Height = sz.Height + Margin.Top + Margin.Bottom,
        };
    }
    protected override void OnRender(DrawingContext dc)
    {
        var tt = get_transform();
        if (tt != null)
            dc.PushTransform(tt);
        dc.DrawDrawing(drawing);
        if (tt != null)
            dc.Pop();
    }
};

[edit:] Это также полезно для вставки WPF Drawing в свойство InlineUIContainer.Child (т.е. с помощью TextBlock.InlinesCollection для более глубокого форматирования содержимого TextBlock).

Ответ 3

DrawingVisual кажется правильным выбором:

DrawingVisual - это легкий класс рисования, который используется для визуализировать фигуры, изображения или текст. Этот класс считается легким потому что он не обеспечивает компоновку или обработку событий, что улучшает его производительность. По этой причине чертежи идеально подходят для фона и клипа.

source: Использование DrawingVisual Objects

так что это, кажется, абсолютно то, что вы просите, легкий холст SUPER.