Используя zoomCallback, как я могу «привязать» масштаб к существующим значениям x? - PullRequest
1 голос
/ 29 мая 2019

Я пытаюсь использовать функцию zoomCallback, чтобы настроить взаимодействие между моей диаграммой и диаграммой.Мои значения x представляют собой временные метки в секундах, но, поскольку частота дискретизации составляет около 100 Гц, временные метки сохраняются в виде числа с плавающей запятой .

Цель состоит в том, чтобы при увеличении диаграммы dygraphs новый x1 и x2 будут использоваться для извлечения фрагмента GPS-трека (широта, точка lng).Извлеченная дорожка будет использоваться для повторного соответствия границ карты - это будет выглядеть как «увеличение» на диаграмме карты.

В параметрах моих графиков я указала обратный вызов:

zoomCallback: function(x1,x2) {
  let x1Index = graphHolder.getRowForX(x1);
  let x2Index = graphHolder.getRowForX(x2);
  // further code
}

Но похоже, что масштаб не «привязан» к существующим временным отметкам, поэтому и x1Index, и x2Index равны null .Только когда я уменьшу масштаб, они будут правильно указывать на строку 0 и последнюю строку данных.

Итак, вопрос в том, есть ли способ сделать масштабирование привязанным только к ближайшему существующему значению x, чтобыномер строки можно вернуть?Или есть альтернатива делать то, что я хочу?

Спасибо за любые идеи!

1 Ответ

1 голос
/ 29 мая 2019

Вы можете получить доступ к значениям оси X через g.getValue(row, 0).Исходя из этого, вы можете выполнить линейное сканирование, чтобы найти первую строку в диапазоне, или (причудливее, но быстрее) использовать двоичный поиск.

Вот способ выполнить линейное сканирование:

const [x1, x2] = g.xAxisRange();
let letRow = null, highRow = null;
for (let i = 0; i < g.numRows(); i++) {
    if (g.getValue(i, 0) >= x1) {
        lowRow = i;
        break;
    }
}
for (let i = g.numRows() - 1; i >= 0; i--) {
    if (g.getValue(i, 0) <= x2) {
        highRow = i;
        break;
    }
}
const dataX1 = g.getValue(lowRow, 0);
const dataX2 = g.getValue(highRow, 0);

Для больших наборов данных вы можете выполнить бинарный поиск, используя что-то вроде lodash _.sortedIndex.

Обновление Вот реализация бинарного поиска.Никаких обещаний о точном поведении границ (то есть, всегда ли он возвращает индексы, которые находятся внутри видимого диапазона, или индексы, которые содержат видимый диапазон).

function dygraphBinarySearch(g, x) {
    let low = 0;
    let high = g.numRows() - 1;
    while (high > low) {
        let i = Math.floor(low + (high - low) / 2);
        const xi = g.getValue(i, 0);
        if (xi < x) {
            low = i + 1;
        } else if (xi > x) {
            high = i - 1;
        } else {
            return i;
        }
    }
    return low;
}
function getVisibleDataRange(g) {
    const [x1, x2] = g.xAxisRange();
    let lowI = dygraphBinarySearch(g, x1);
    let highI = dygraphBinarySearch(g, x2);
    return [lowI, highI];
}
...