pozitronik (
pozitronik) wrote2012-03-17 02:53 pm
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Поведение GeoCollectionBounds после вызова Clear()
Скучная, но полезная часть:
При работе с API Yandex Maps наткнулся на странное поведение класса GeoCollectionBounds. Этот класс высчитывает границы минимального прямоугольника, в который входят все указанные точки, и, при необходимости, подгоняет карту под этои границы.
Мне понадобилось сделать динамическую карту, расположение точек на которой может многократно меняться. Соответственно, GeoCollectionBounds используется на полную катушку. Алгоритм работы с картой довольно прост:
/*Инициализация*/
map = new YMaps.Map(parent_div);//Создали экземпляр карты
bounds = new YMaps.GeoCollectionBounds();//Создали экземпляр класа для расчёта границ
/*Заполнение границ*/
for (var int = 0; int < points.length; int++) {//points - массив с координатами точек
bounds.add(YMaps.Point.fromString(points[int])); //добавляем новую точку
}
map.setBounds(bounds);//Вписываем карту в вычисленные границы
/*Обновление набора точек*/
bounds.Clear();//Сбрасываем границы, см документацию
for (var int = 0; int < new_points.length; int++) {//new_points - массив с координатами точек
bounds.add(YMaps.Point.fromString(new_points[int]); //добавляем новую точку
}
map.setBounds(bounds);//Вписываем карту в вычисленные границы
Если так сделать - карта отмасштабируется неверно. Удаление будет максимальным, в границы почему-то попадает вся планета.
Внимательное изучение под отладчиком показывает, что bounds после инициализации и bounds после вызова Clear() не идентичны. Параметр _empty у только что инициализированного экземпляря равен 0, после добавления первой точки становится равен 1, и не меняется при вызове Clear(). При этом Clear() корректно обнуляет границы, но при bounds._empty==1 нижняя граница прямоугольника (bounds._bottom) перестаёт вычисляться, что и приводит к виду на планету из верхних слоёв атмосферы.
Лечение, соответственно, простое - сразу после bounds.Clear(); делать присвоение bounds._empty=1;
Интересная, но бесполезная часть:
Параллельно задумался: а ведь сколько интересных, трудных, головоломных и непонятных ошибок доводилось мне встречать с того времени, когда я впервые запустил qbasic. Ну, например:
- Ошибки-призраки. Не работает, не понятно почему, вчера всё работало, а сегодня - нет. Не лечится никак и ничем. Откладываешь код, всю ночь играешь в кваку, на следующий день смотришь - тот же самый код работает.
- Трололо-ошибки. Код собирается без единого ворнинга, но не работает. Потом оказывается, например, что написал класс с таким же названием и операторами, что и стандартный, и компилятор, естественно, вызывает не тот, что нужен. Но иногда бывают необъяснимые случаи - стираешь, переписываешь чуть ли не символ в символ, и работает.
- Трололо-отладчик. Под отладчиком программа работает не так, как при запуске. Проходишь пошагово - всё чистенько, четкенько, красота. Запускаешь тот же код вне отладчика - еггог ололо. Иногда помогает дубовый способ понапихивания после каждой строчки вызова собственного логгера (самое ffffuuuuu начинается, когда и при добавленном логгере всё работает, а без него - хуйс). Реже бывает обратное - в отладчике код работает неверно. Вернее, это просто обнаруживается реже - потому что кто же будет отлаживать код, который и так работает.
- Зеркальные ошибки. Оператор работает ровно наоборот от положенного. Скажем, итератор for x=0 to 100 начинает не инкрементировать переменную x, а наоборот - инициализирует её, как 100, а потом делает декремент. Или if/case/switch начинают путать ветки. Этим борландовские компиляторы грешили, но чтобы наткнуться на такой глюк, надо было написать много-много-много кода, так как грешили они редко, но исключительно в жилу.
- Кстати, о Борланде. В какой-то из версий их среды разработки под Delphi иногда тупо переставали работать Insert и Space. Но это фигня, обычно решалось перезапуском. А вот что немало нервов мне пожрало в свой время - на больших участках кода, в десятки тысяч строк, отладчик при пошаговой отладке скакал не по тем строкам. Причём в некоторых функциях работал как надо, а в некоторых - сбивался.
- Мультипоточные глюки. Отлаживать код, который работает в несколько потоков можно только свою судьбу хуйня и бля. Лучше сразу писать правильно.
- Глюки ассемблирования. Поскольку грешил с ассемблером я не так много, то и ошибку помню только одну: в одной из моих досовских программ код собирался неверно, кажется, вместо JE ставилось JNE и последующий оператор тоже менялся. Причём вся отладочная информация и прочее были нормальными. Если кто не знает - код на ассемблере, и код с отладочной информацией в дебаггере должны быть одинаковыми, но вот у меня они одинаковыми не были. Скриншот я показывал сокурсникам и преподавателям, но и те и другие от ассемблера шарахались, как еврей от работы, потому выяснить причину глюка не удалось.
А какие необычные мозговыносящие глюки встречались вам?
При работе с API Yandex Maps наткнулся на странное поведение класса GeoCollectionBounds. Этот класс высчитывает границы минимального прямоугольника, в который входят все указанные точки, и, при необходимости, подгоняет карту под этои границы.
Мне понадобилось сделать динамическую карту, расположение точек на которой может многократно меняться. Соответственно, GeoCollectionBounds используется на полную катушку. Алгоритм работы с картой довольно прост:
/*Инициализация*/
map = new YMaps.Map(parent_div);//Создали экземпляр карты
bounds = new YMaps.GeoCollectionBounds();//Создали экземпляр класа для расчёта границ
/*Заполнение границ*/
for (var int = 0; int < points.length; int++) {//points - массив с координатами точек
bounds.add(YMaps.Point.fromString(points[int])); //добавляем новую точку
}
map.setBounds(bounds);//Вписываем карту в вычисленные границы
/*Обновление набора точек*/
bounds.Clear();//Сбрасываем границы, см документацию
for (var int = 0; int < new_points.length; int++) {//new_points - массив с координатами точек
bounds.add(YMaps.Point.fromString(new_points[int]); //добавляем новую точку
}
map.setBounds(bounds);//Вписываем карту в вычисленные границы
Если так сделать - карта отмасштабируется неверно. Удаление будет максимальным, в границы почему-то попадает вся планета.
Внимательное изучение под отладчиком показывает, что bounds после инициализации и bounds после вызова Clear() не идентичны. Параметр _empty у только что инициализированного экземпляря равен 0, после добавления первой точки становится равен 1, и не меняется при вызове Clear(). При этом Clear() корректно обнуляет границы, но при bounds._empty==1 нижняя граница прямоугольника (bounds._bottom) перестаёт вычисляться, что и приводит к виду на планету из верхних слоёв атмосферы.
Лечение, соответственно, простое - сразу после bounds.Clear(); делать присвоение bounds._empty=1;
Интересная, но бесполезная часть:
Параллельно задумался: а ведь сколько интересных, трудных, головоломных и непонятных ошибок доводилось мне встречать с того времени, когда я впервые запустил qbasic. Ну, например:
- Ошибки-призраки. Не работает, не понятно почему, вчера всё работало, а сегодня - нет. Не лечится никак и ничем. Откладываешь код, всю ночь играешь в кваку, на следующий день смотришь - тот же самый код работает.
- Трололо-ошибки. Код собирается без единого ворнинга, но не работает. Потом оказывается, например, что написал класс с таким же названием и операторами, что и стандартный, и компилятор, естественно, вызывает не тот, что нужен. Но иногда бывают необъяснимые случаи - стираешь, переписываешь чуть ли не символ в символ, и работает.
- Трололо-отладчик. Под отладчиком программа работает не так, как при запуске. Проходишь пошагово - всё чистенько, четкенько, красота. Запускаешь тот же код вне отладчика - еггог ололо. Иногда помогает дубовый способ понапихивания после каждой строчки вызова собственного логгера (самое ffffuuuuu начинается, когда и при добавленном логгере всё работает, а без него - хуйс). Реже бывает обратное - в отладчике код работает неверно. Вернее, это просто обнаруживается реже - потому что кто же будет отлаживать код, который и так работает.
- Зеркальные ошибки. Оператор работает ровно наоборот от положенного. Скажем, итератор for x=0 to 100 начинает не инкрементировать переменную x, а наоборот - инициализирует её, как 100, а потом делает декремент. Или if/case/switch начинают путать ветки. Этим борландовские компиляторы грешили, но чтобы наткнуться на такой глюк, надо было написать много-много-много кода, так как грешили они редко, но исключительно в жилу.
- Кстати, о Борланде. В какой-то из версий их среды разработки под Delphi иногда тупо переставали работать Insert и Space. Но это фигня, обычно решалось перезапуском. А вот что немало нервов мне пожрало в свой время - на больших участках кода, в десятки тысяч строк, отладчик при пошаговой отладке скакал не по тем строкам. Причём в некоторых функциях работал как надо, а в некоторых - сбивался.
- Мультипоточные глюки. Отлаживать код, который работает в несколько потоков можно только свою судьбу хуйня и бля. Лучше сразу писать правильно.
- Глюки ассемблирования. Поскольку грешил с ассемблером я не так много, то и ошибку помню только одну: в одной из моих досовских программ код собирался неверно, кажется, вместо JE ставилось JNE и последующий оператор тоже менялся. Причём вся отладочная информация и прочее были нормальными. Если кто не знает - код на ассемблере, и код с отладочной информацией в дебаггере должны быть одинаковыми, но вот у меня они одинаковыми не были. Скриншот я показывал сокурсникам и преподавателям, но и те и другие от ассемблера шарахались, как еврей от работы, потому выяснить причину глюка не удалось.
А какие необычные мозговыносящие глюки встречались вам?