Алгоритм для бесконечного графа
Мне нужно реализовать "бесконечный граф", но я понятия не имею, как именно составить алгоритм для этого.
Я использую Qt с Qwt, где все мои очки хранятся в QVector<double>
; когда поступают новые данные, они добавляются в конец вектора. В отличие от классического графика, где все данные, отображаемые на экране, обновляются в некоторый момент, бесконечный график теоретически хранит все данные, полученные с момента начала построения графика. Это производит эффект "уменьшения кривой, как она появляется слева от графика", как на этом изображении:,
Но я не могу сохранить все данные внутри вектора точек, поскольку на экране нет бесконечных пикселей; Мне нужно убирать одно очко каждый раз, когда приходит новое.
Но как сделать это таким образом, чтобы получить эффект "бесконечного графа"? Я думаю, что не могу просто случайно удалить точку из любой части кривой, когда поступают новые данные; это, конечно, не создаст эффект "уменьшения".
Я подумал об идее удаления точки И сделать так, чтобы все оставшиеся точки получили второстепенное значение, чем то, которое у них есть (поэтому, когда приходят новые данные, все уже существующие точки получат -1 в своих значениях x), но я не уверен, что сработает. У кого-нибудь есть идеи?
РЕДАКТИРОВАТЬ
Некоторые пользователи задали несколько вопросов ниже, и вот мои ответы:
Стив: нет; ось х не постоянно меняется, чтобы соответствовать количеству полученных баллов; Это только то, что ДОЛЖНО выглядеть, поскольку это должен быть график, показывающий "все" полученные данные. Но экран ограничен по размеру, и, следовательно, ось X также будет ограничена по размеру, поскольку я не претендую на то, чтобы отображать на экране более одной точки на пиксель (более конкретно, 570). Теперь имейте в виду: говоря, что ось x будет ограничена по размеру, это не означает, что она обязательно будет иметь масштаб 0-570; сами значения шкалы могут измениться, но векто, содержащее точки, которые будут нанесены, будет иметь фиксированный размер, поскольку я не хочу хранить вектор в 100000 точек внутри моего встроенного приложения!
Quantdev: "Бесконечный граф" - это график, который теоретически отображает все данные, полученные с начала построения графика, в отличие от графиков с фиксированным временем (на каких графиках, скажем, "данные, полученные за последние 10 секунд"). Но очевидно, что это чистая теория, поскольку нет экрана бесконечного размера, чтобы показать все точки, и не хватает памяти для хранения вектора точек бесконечного размера. Поэтому я хотел бы сохранить вектор минимального размера с точками, которые должны быть нанесены (которые я принимаю равными количеству пикселей на экране) и при этом иметь эффект бесконечного графика. Более того, график должен иметь эффект, показанный на прикрепленном изображении: чем старше данные, тем меньше становится на графике (примечание: но в противоположном положении к изображению, так как рисунок будет справа налево).
Tay2510: поехали! И просто чтобы быть уверенным, не будет никакого скользящего эффекта, как в осциллографе; график будет фиксирован по оси X.
3 ответа
Не удаляйте одну точку за раз. Это становится довольно грязно, математически. Вы должны интерполировать слишком часто, что приводит к потере числовой точности.
Вместо этого продолжайте добавлять точки к вашему вектору, пока размер не станет в два раза больше, чем нужно. В этот момент усредните все пары точек, чтобы делить вектор на половину длины. Т.е. новый x[3]
старый (x[6]+x[7])/2
,
Чтобы рисовать, не используйте x[]
напрямую, так как у вас обычно слишком много очков. Вместо этого вы должны интерполировать между 2 соседними точками.
Я думаю, что не могу просто случайно удалить точку из любой части кривой, когда поступают новые данные; это, конечно, не создаст эффект "уменьшения".
Это правильно. Первый шаг, который вы должны сделать, это увеличить ширину количества точек на оси X до максимального значения. Когда вы это сделали, вы удаляете точки с наименьшим отклонением от оси Y между большими, когда это необходимо.
Эти точки создадут наименьшее количество графических изменений на вашем графике, в то время как те, которые имеют наибольшее отклонение, будут гораздо более заметны, когда будут сталкиваться друг с другом.
Я подумал об идее удаления точки И сделать так, чтобы все оставшиеся точки получили второстепенное значение, чем то, которое у них есть (поэтому, когда приходят новые данные, все уже существующие точки получат -1 в своих значениях x), но я не уверен, что сработает.
Это приведет к тому, что график сдвинется влево, а это не то, что вам нужно.
Решение с фиксированной памятью для этого класса проблем было забито до смерти на цифровых фосфорных осциллографах.
Что вы делаете, это:
Начните с фиксированного размера
QImage
для графика, где каждая входящая выборка приводит к построенной точке, и есть одна координата X на выборку. Образцы участков слева направо. Нет необходимости хранить значения где-либо еще: изображение - это ваше хранилище.Если вы исчерпали пространство для образца по горизонтали, измените размер содержимого существующего изображения до половины его горизонтального размера, выровняйте по левому краю и очистите правую половину изображения.
Отобразите новые входящие сэмплы начиная со средней точки - поверх очищенной части изображения.
Перейти к 2.
Опции:
Измените точку разделения, чтобы она была чем-то большим, чем половина горизонтального размера.
Перепланируйте шкалы без сохранения каких-либо дополнительных данных, кроме счетчика деления - счетчика деления достаточно, чтобы точно знать, где были все точки деления и т. Д.
Перед масштабированием изображения на шаге 2 вы можете масштабировать значения интенсивности на изображении, которое вы собираетесь масштабировать, с коэффициентом 0,5. Таким образом, вы получите эффект, подобный люминофору, для каждого пикселя, где пиксели с перекрывающимися выборками являются более интенсивными.
Шкала интенсивности может быть насыщающей, так что, например, вы никогда не обнуляете любую интенсивность ниже 1/255. Это позволяет избежать возможного исчезновения пикселей. На самом деле вы можете выбрать даже более изящные нелинейные и вариативные масштабирования в соответствии со своими вкусами.