Кусочно-линейная интерполяция на JavaScript для массивов

Полезные скрипты
Ответить
Аватара пользователя
mihas
Администратор
Сообщения: 1368
Зарегистрирован: 18 авг 2004, 16:58
Откуда: Москва
Контактная информация:

Кусочно-линейная интерполяция на JavaScript для массивов

Сообщение mihas »

Для данных с резкими гранями, вроде такой как на рисунке, не подходят полиноминальные итерполяции, они все гладкие кривые рисуют, а понадобилась просто ломанная. Вот написал функцию обычной линейной интерполяции для массивов - пусть будет на память.

Код: Выделить всё

function linearinterp(x1a,y1a,x2a) {
	var y2a = [];
	var countlin = 0;
	for (var f=0; f<x2a.length-1; f++) {
		if (x2a[f] >= x1a[countlin] && x2a[f] < x1a[countlin+1]) {
			y2a[f] = parseInt(y1a[countlin] + (y1a[countlin+1] - y1a[countlin]) * (x2a[f] - x1a[countlin]) / (x1a[countlin+1] - x1a[countlin]));
		}
		else {
			countlin++;
			y2a[f] = parseInt(y1a[countlin] + (y1a[countlin+1] - y1a[countlin]) * (x2a[f] - x1a[countlin]) / (x1a[countlin+1] - x1a[countlin]));
		}
	}
	y2a.push(parseInt(y1a[y1a.length-1])); // целые числа parseInt можно отключить
	return y2a;
}
На вход подается массив значений X₁, массив значений Y₁ и массив новых значений X₂ для интерполяции по нему. На выходе - новый массив интерполированных значений Y₂.
Например массив X₂ для интерполяции от 0 до 100 с шагом 1 можно так создать:

Код: Выделить всё

var x2a = new Array();
for (var i=0; i<101; i++) {
	x2a.push(i);
}
Обращаю внимание, что эта функция linearinterp выдает массивы с целыми числами. Если уберете там три раза по коду parseInt - будут на выходе в массиве обычные числа с плавающей точкой. Так же на входе функции не сравнивается длина массивов X₁ и Y₁ и не проверяется по крайним значениям массив x2a. Очевидно, что крайние значения массива x2a не должны превосходить крайние для x1a, иначе речь пойдет уже не об интерполяции, а об экстраполяции. Очевидно, что x1a - массив, упорядоченный по возрастанию. Чтобы упорядочить массив с именем arr по возрастанию или по убыванию подойдет простая функция:

Код: Выделить всё

// по возрастанию
arr.sort(function(a, b){return a - b});
// по убыванию
arr.sort(function(a, b){return b - a});
Если массив многомерный и надо отсортировать по имени по строке [0] я использую такие функции:

Код: Выделить всё

function Sortirovka(aa, bb) { // По имени (убывание)
    if (aa[0] > bb[0])
        return -1;
    else if (aa[0] < bb[0])
        return 1;
    else
        return 0;
}

function SortirovkaPlus(aa, bb) { // По имени (возрастание)
    if (aa[0] < bb[0])
        return -1;
    else if (aa[0] > bb[0])
        return 1;
    else
        return 0;
}
Вызываются они так: arr.sort(Sortirovka); или arr.sort(SortirovkaPlus);
Ну и еще полезная сортировочка такая с преобразованием элементов массива в числа (на яваскрипте зачастую в процессе программирования сложных функций число перестает быть числом. Я устал выверять, где число превратилось в строку, и просто возвращаю его в реальность функциями parseInt или parseFloat):

Код: Выделить всё

function compareNumbers(a, b) { // Сортировка по числам по возрастанию
  return parseFloat(a) - parseFloat(b);
}
Вызывается arr.sort(compareNumbers);
Более громоздкие билинейную и трилинейную интерполяции на JavaScript вы у меня найдете в открытом коде вот этого калькулятора https://cielab.xyz/colorconv/ - в нем трехмерные и четырехмерные массивы цветовых координат Lab и CMYK как раз так и интерполируются.
Вложения
трехмерная фигура с острыми гранями и промежуточными поперечинами - гексагональная бипирамида с одним усеченным конусом
трехмерная фигура с острыми гранями и промежуточными поперечинами - гексагональная бипирамида с одним усеченным конусом
• 108.67 КБ • 4389 просмотров
Ответить

Вернуться в «JavaScript»