|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Перемещение + Масштабирование
Здравствуйте уважаемые форумчане.
Такой вот вопросик назрел в связи с разрабатываемой программой, связанный с графикой. В моей программе на холсте TImage отрисовываются различные объекты. Данные объекты состоят из точек, имеющих координаты. Точки соединяются линиями. И вот задумал я сделать масштабирование и перемещение изображение холста с помощью мыши. Ну то есть колесико крутим меняется масштаб, зажимаем клавишу и тащим, изображение холста движется с мышью. Данные действия я реализовал простыми математическими операциями - перемещение добавлением к координатам точек dx и dy, масштабирование умножением координат точек на dz. При всем при этом изначальные координаты точек остаются теми же. Просто в процедуру рисования на холсте я передаю параметры dx, dy, dz, которые являются глобальными переменными, которые в зависимости от действий пользователя меняются. Ну то есть зажал пользователь клавишу и подвинул мышь на 100 px вправо и 50 px вниз, dx стал равен 100 dy стал равен 50. Затем пользователь подвинул мышь вверх на 20 px и влево на 30 px и dx стал равен 70, а dy 30. При масштабировании же при прокрутке колесика мышки вверх на 3 деления dz становится равным 0,7, затем если прокрутить колесо мыши вниз на 5 делений то равным 1,2. По отдельности эти операции работают замечательно. А вот если вместе то беда все координаты сбиваются. Можно было бы решить данную проблему путем запоминания нового значения координаты как после перемещения так и после масштабирования, но вся беда в том что после масштабирования не всегда получается то что было изначально. Т.е. когда мы умножаем координаты на множитель dz мы же должны округлить получившееся значение что бы вывести его на холст. И в результате сжав и развернув изображение мы можем получить не то что было в начале. Поэтому изначальные координаты приходится хранить. Теперь допустим пользователь сначала передвинул изображение, потом сжал его, а затем передвинул и расжал масштаб. Уверяю получится не совсем то что задумывалось изначально. Вот как написать процедуру, которая всегда корректно отображает положение объектов и их масштаб. Для более красочного понимания того что я здесь понаписал зайдите на любую версию карт - Gooogle, Yandex и т.д. и попробуйте подвигать и помасштабировать их. Всегда все корректно. А как это работает не пойму. |
#2
|
||||
|
||||
Цитата:
Суть в том, что исходную картинку нужно хранить в виде списка объектов и не "портить" каждый раз при движении и масштабировании. Вместо этого хранить два числа -- значения масштаба по X и Y, пересчитывать их каждый раз при изменении масштаба, после чего перегенерировать видимую картинку из неизменного исходного списка. Хотел было пример написать, но лень. Читайте учебники. |
#3
|
|||
|
|||
Цитата:
То что Вы тут понаписали не внесло никакой ясности. 1. Объекты (т.е. координаты точек этих объектов) я не порчу. Если Вы внимательно прочли, а Вы этого не сделали, координаты остаются неизменными. 2. В каких конкретно книгах написано про это? Пожалуйста конкретно. 3. Приемами ООП владею. Но с координатами до сих пор в голове путаница. Последний раз редактировалось xabik, 26.05.2013 в 00:56. |
#4
|
||||
|
||||
Прошу показать код вывода.
|
#5
|
|||
|
|||
Описание записи точки. Думаю можно обойтись и записями.
Код:
Dot = record x,y,xz,yz:integer; TypeDot:byte; ID:int64; end; ArrDot:array of Dot; Описание процедуры пересчета координат при масштабировании Код:
procedure ResizeMap(df:extended); var i:integer; begin for i:=0 to High(ArrDot) do begin ArrDot[i].xz:=Round(ArrDot[i].x*df); ArrDot[i].yz:=Round(ArrDot[i].y*df); end; end; Описание процедуры пересчета координат при перемещении Код:
procedure MoveMap(dx,dy:integer); var i:integer; begin for i:=0 to High(ArrDot) do begin ArrDot[i].xz:=ArrDot[i].x+dx; ArrDot[i].yz:=ArrDot[i].y+dy; end; end; Вывод осуществляется по координатам xz и yz |
#6
|
||||
|
||||
Вот таков пример работает? У тебя написано одно (о сохранении координат), а здесь ты их изменяешь. Изменение должно происходить только при выводе на экран.
|
#7
|
|||
|
|||
Я не уверен, но у Вас всё работает кажется правильно. Т.е. пересчитывается из начальных координат. Спасибо. Завтра разберусь с кодом. И пойму свои ошибки. А насчет изменения при выводе, ну тык начальные то координаты хранятся не в xz, yz, а в x и y. В любом случае большое Спасибо!!!
|
#8
|
||||
|
||||
Цитата:
Смею предположить, что в данном случае может происходить накопление погрешности из-за использования целочисленных координат. Округление при каждом вычислении, -- и вот тебе на. Можно либо перейти на вещественные xz и yz, либо оперировать дробными пикселями, как это делает формат Flash (SWF). Целому пикселю соответствует изображение при максимальном приближении, а при выводе делится на масштаб и округляется. Не помню, возможны ли в SWF масштабы не в степенях двойки. Кроме того, как мне кажется, логично и правильно будет отделить хранение от представления. Хранение -- исходные данные -- остаются неизменными. Представление характеризуется масштабом и прямоугольником отсечения, которые передаются в процедуру отрисовки отдельными параметрами. Координаты будут пересчитываться при каждом отображении, и округление будет делаться один раз -- непосредственно перед отрисовкой. Я бы сделал именно так. |