Спасибо, что включили ваш код! (+1 к вопросу об уточнении и включении всей соответствующей информации).
Это показывает, что ваша теория масштабирования верна. На каждом шаге xrange
и yrange
будут масштабироваться с постоянным коэффициентом (0,975?), И окно будет двигаться в направлении foundPointOnHost
, сохраняя одинаковое относительное положение в окне (ratioX
и ratioY
) , Это определенно правильная теория за масштабирование. Однако на практике реализация масштабирования приведет к быстрому накоплению ошибок округления из-за способа работы арифметики с плавающей запятой.
Мои эмпирические правила:
- каждый раз, когда вы умножаете или делите два числа с плавающей запятой, у вас есть шанс ввести ошибку, размер которой равен последнему биту результата ;
- но каждый раз, когда вы добавляете или вычитаете два числа с плавающей запятой, у вас есть шанс ввести ошибку, размер которой равен последний бит самого большого операнда .
Сработал пример. Предположим, вы увеличиваете масштаб (0,5,0,3), и вы уже увеличены, поэтому xrange
и yrange
составляют около 0,001. Допустим, вы используете числа с плавающей запятой (23 бита, около 7 знаков после запятой). В вашем коде, когда вы вычитаете два x
значения для пересчета xrange
, вы вычитаете два числа, оба из которых близки к 0,5, что означает, что ваша ошибка в xrange
составляет целых 0,0000001 - седьмое десятичное место 0,5 - и так как результат составляет около 0,001, ваш xrange
только с точностью до четырех знаков после запятой. Затем вы масштабируете, масштабируете и добавляете xrange
обратно к краям окна (на величину, которая сейчас составляет около 0,00025), что снова составляет около 0,5, так что арифметическая операция также точна только до 0,0000001, и окно Сами ребра неточны по сравнению с предыдущим вызовом. Очевидно, что лучше, если вы используете double, но, опять же, ваш xrange
теряет точность каждый раз в цикле; и к тому времени, как вы достигнете уровня зуммирования x6, возможно, вы потеряли все это.
«Хитрость» заключается в том, чтобы уменьшить количество сложений и вычитаний (в настоящее время вы делаете 6 шагов масштабирования) и следите за тем, чтобы ваши ошибки не накапливали на каждой итерации. Я бы предложил что-то вроде следующего: оставьте xrange
и yrange
и пересчитывайте края каждый шаг: (ratioX
и ratioY
являются постоянными, и вам, возможно, придется определить, какой из них ratio
и который 1-ratio
:)
xrange *= 0.975;
xld = foundPointOnHost.x - ratioX * xrange;
xru = foundPointOnHost.x + (1-ratioX) * xrange;
и то же самое для y
. Более того, вычислите xrange
, используя операцию, которая сама по себе не будет накапливать ошибки при каждом умножении:
// xrange = INITIAL_RANGE * SCALE_FACTOR^frame_number
xrange = exp ( log(INITIAL_RANGE) + frame_number*log(SCALE_FACTOR) );