я хочу отрисовать сюжет с большим количеством точек (> 1.000.000) и разными цветами на заказ QQuickItem
,
Позже я хочу анимировать эти точки (исчезновение между координатами и цветами), поэтому я думаю, QQuickPaintedItem
не достаточно быстро для этого, и я должен использовать updatePaintNode
интерфейс QQuickItem
,
Проблема состоит в том, чтобы установить цвет для каждой точки. Должен ли я создать для каждой точки QSGGeometryNode
и добавить геометрию и ColorMaterial? Или есть более быстрое решение?
С уважением
2 миллиона элементов это довольно много, я считаю, что GUI зависает из-за этого цикла внутри updatePaintNode
(Поток GUI заблокирован во время updatePaintNode
исполнение, как состояние документации).
Идея № 1
Если вы не часто меняете весь массив точек, вы можете обновить в updatePaintNode
только те вершины, которые изменились со времени последней краски, вместо того, чтобы каждый раз запускать огромный цикл 2kk. Но AFAIK вам все равно нужно обновить все вершины в случае изменения размера гистограммы.
Идея № 2
Другой потенциальной оптимизацией может быть подготовка массива данных вершин перед updatePaintNode
а затем скопировать весь массив с помощью memcpy
или же std::copy
Внутри updatePaintNode
, Копирование непрерывного массива памяти в целом имеет тенденцию быть намного быстрее чем копирование по элементам, и так как вы заполняете массив с помощью функции доступа, я не уверен, оптимизирован ли он компилятором.
Идея № 3
2 миллиона точек кажется слишком большим, чтобы представить их на одном графике. Представление такого большого количества данных одновременно может повредить UX, потому что точки разных цветов будут перекрываться, пользователь может пропустить ценную информацию.
Вы можете уменьшить уровень детализации путем объединения точек одного цвета и визуализации этих кластеров вместо отдельных точек. Однако этот подход потребует значительных усилий, поэтому я предлагаю попробовать его, когда менее сложные решения не помогают.
Я немного поработал с openGL и нашел решение, которое помогло мне
Используются обычные примеры OpenGL QSGGeometry::Point2D
установить вершины. Но есть и версия с поддержкой цвета (QSGGeometry::defaultAttributes_ColoredPoint2D())
, Так что я могу установить вершины с
vertices[i].set(x, y, r,g, b, a);
//РЕДАКТИРОВАТЬ:
следующая проблема заключается в том, что графический интерфейс время от времени зависает, если объект QSGeometry имеет много вершин. Я не знаю почему.
Графический интерфейс замедляется после выделения памяти для вершин, поэтому этот подход не имеет хорошей производительности.
// РЕДАКТИРОВАТЬ 2:
Я добавил упрощенный код текущего updatePaint
-метод. Если объект данных очень большой (> 2.000.000 точек), виджеты отображают точки, но затем весь графический интерфейс зависает и заикается.
QSGNode *HistogramView::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
QSGGeometryNode *node = 0;
QSGGeometry *geometry = 0;
if (!oldNode) {
node = new QSGGeometryNode;
geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), data.size());
geometry->setDrawingModeelsize(GL_POINTS);
node->setGeometry(geometry);
node->setFlag(QSGNode::OwnsGeometry);
QSGVertexColorMaterial *material = new QSGVertexColorMaterial();
//material->setColor(QColor(255, 0, 0));
node->setMaterial(material);
node->setFlag(QSGNode::OwnsMaterial);
} else {
node = static_cast<QSGGeometryNode *>(oldNode);
geometry = node->geometry();
geometry->allocate(222);
}
QSGGeometry::ColoredPoint2D *vertices = geometry->vertexDataAsColoredPoint2D();
for (int i = 0; i < data.size(); i++) {
vertices[id].set(x, y,red, green, blue, 255);
}
}
}
node->markDirty(QSGNode::DirtyGeometry);
return node;}
Я мог бы локализовать ошибку.
после вызова инициализации QSGGeometry
-объект (
geometry = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), data.size());
) интерфейс очень медленный.
Привет