Модераторы: Snowy, Alexeis, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно реализовать Zoom? Работа с Bitmap 
:(
    Опции темы
ДЫМ
  Дата 2.6.2005, 01:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 6.1.2004

Репутация: нет
Всего: 8



Проблема вот в чем. У меня есть чертеж - куча многоугольников,
координаты вершин известны. Мне нужно нарисовать все это
хозяйство и сделать так, чтобы пользователь мог увеличить/уменьшить
изображение (Zoom).

Так вроде никаких проблем - создаю Bitmap, на его канве рисую
полигоны по координатам, если надо увеличить, то умножаю все
координаты вершин на коэффициент и перерисовываю.
Но, естественно, увеличиваются и размеры самого Bitmap'a.
На экран я вывожу чертеж кусками по размеру окна, но в памяти для этого должен висеть огромный Bitmap (при 150% увеличения получается где-то 5000x4000). Вот тут начинаются тормоза.

Код

procedure Zoom_In;
begin
 Coefficient:=flCoefficient+0.1;

 // увеличиваю ширину и высоту Bitmap' а 
 Bitmap.Width:=Round(flCoefficient*SourceWidth);
 Bitmap.Height:=Round(flCoefficient*SourceHeight);

 // перерисовываю многоугольники на канве увеличенного рисунка
 RedrawPolygons;
end;


Есть ли замена Bitmap' у, в таких случаях, чтобы память
расходовалась экономнее, да и вообще работало быстрее?
PM MAIL WWW   Вверх
MBo
Дата 2.6.2005, 06:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 234
Регистрация: 10.6.2002

Репутация: 1
Всего: 18



Битмап размером в экран делай, а координаты пересчитывай - тогда будет выводиться только то, что попадает в это окошко (если примитивов много, то для оптимизации можно сначала проверять, попадают ли они в прямоугольник вывода)
PM MAIL   Вверх
s-mike
Дата 2.6.2005, 06:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



ДЫМ, попробуй WMF/EMF (класс TMetafile). Или отрисовку проводи непосредственно на экран, а не битмап, но тогда действительно придется высчитывать видимые объекты, потому что будут тормоза.
PM MAIL WWW   Вверх
ДЫМ
Дата 3.6.2005, 01:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 6.1.2004

Репутация: нет
Всего: 8



Цитата
Битмап размером в экран делай, а координаты пересчитывай - тогда будет выводиться только то, что попадает в это окошко (если примитивов много, то для оптимизации можно сначала проверять, попадают ли они в прямоугольник вывода)


А как же тогда нарисовать многоугольник, да еще закрашенный, который лишь частично попадает в окно вывода? Для этого надо где-то его нарисовать целиком, а уже потом копировать нужный кусок изображения.

Цитата
ДЫМ, попробуй WMF/EMF (класс TMetafile).

s-mike , а как работать с метафайлом, деоо в том, что в FAQ очень мало информации, есть ли у тебя документация какая, или примеры.

И вот еще что, вот у тебя в в твоей библилтеке, можно загрузить Bitmap, затем увеличить до невероятных размеров, причем никаких тормозов, скроллинг довольно быстрый. Или это касается только растровых изображений, а у меня векторные.
PM MAIL WWW   Вверх
MBo
Дата 3.6.2005, 07:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 234
Регистрация: 10.6.2002

Репутация: 1
Всего: 18



>Для этого надо где-то его нарисовать целиком, а уже потом копировать нужный кусок изображения

Нет, GDI самостоятельно проведет отсечение
PM MAIL   Вверх
s-mike
Дата 3.6.2005, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Цитата

А как же тогда нарисовать многоугольник, да еще закрашенный, который лишь частично попадает в окно вывода? Для этого надо где-то его нарисовать целиком, а уже потом копировать нужный кусок изображения.

Тебе надо определить все объекты, которые должны быть отображены при текущей позиции изображения, например с помощью функции IntersectRect. Их и надо отрисовывать. В метафайле это автоматизировано.

Работать с ним аналогично - создаешь объект (или используешь готовый TImage.Picture.Metafile) TMetafile. У него тоже есть Canvas. На нем рисуешь все свои объекты и все. При любом перемещении метафайла изображение будет само восстанавливаться и довольно быстро.


Цитата
И вот еще что, вот у тебя в в твоей библилтеке, можно загрузить Bitmap, затем увеличить до невероятных размеров, причем никаких тормозов, скроллинг довольно быстрый. Или это касается только растровых изображений, а у меня векторные.

Потому что отрисовывается только та часть изображения, которая должна быть отображена на экране.

Цитата
Или это касается только растровых изображений, а у меня векторные.

Нет, векторных изображений моя библиотека не поддерживает. Но я постараюсь сделать их поддержку уже в самом скором времени.
PM MAIL WWW   Вверх
ДЫМ
Дата 4.6.2005, 01:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 6.1.2004

Репутация: нет
Всего: 8



Цитата
Тебе надо определить все объекты, которые должны быть отображены при текущей позиции изображения, например с помощью функции IntersectRect. Их и надо отрисовывать


Как я понял, функция IntersectRect проверяет пересекаются ли прямоугольники. А как быть с полигонами и полилиниями?

Скажите, я правильно понял, что надо в цикле проверять лежит ли в пределах окна вывода хотя бы одна вершина полигона, и если лежит, то отрисовывать целиком полигон на канве окна (все ненужное отсечется)?

А у меня есть полигоны с несколькими сотнями вершин. Не получится ли "шило на мыло"?





PM MAIL WWW   Вверх
s-mike
Дата 4.6.2005, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Цитата
Как я понял, функция IntersectRect проверяет пересекаются ли прямоугольники. А как быть с полигонами и полилиниями?

Нужно по минимальным/максимальным координатам найти прямоугольник, занимаемый объектом.
Цитата
А у меня есть полигоны с несколькими сотнями вершин. Не получится ли "шило на мыло"?

Если их отрисовывать - будет гораздо дольше.
Цитата
Скажите, я правильно понял, что надо в цикле проверять лежит ли в пределах окна вывода хотя бы одна вершина полигона, и если лежит, то отрисовывать целиком полигон на канве окна (все ненужное отсечется)?

Да, естественно.
Добавлено @ 11:21
Цитата(s @ 4.6.2005, 11:20)
Нужно по минимальным/максимальным координатам найти прямоугольник, занимаемый объектом.

А еще лучше хранить эту информацию в самом объекте. А пересчитывать только при добавлении/удалении точек.
PM MAIL WWW   Вверх
ДЫМ
Дата 5.6.2005, 02:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 6.1.2004

Репутация: нет
Всего: 8



Цитата
Нужно по минимальным/максимальным координатам найти прямоугольник, занимаемый объектом.

Для небольших объектов это покатит, но у меня есть невыпуклый многоугольник, который начинается в левом верхнем угле, петляет по всему чертежу и заканчивается в правом нижнем угле (такая затейливая полоска). Получается. что этому многоугольнику соответствует прямоугольник чертежа.

Цитата
Цитата
Скажите, я правильно понял, что надо в цикле проверять лежит ли в пределах окна вывода хотя бы одна вершина полигона, и если лежит, то отрисовывать целиком полигон на канве окна (все ненужное отсечется)?

Да, естественно.


К сожалению, это тоже не будет работать. Может случиться так, что ни одна из вершин полигона не находится в пределах окна вывода, а какая-то часть полигона - находится. Например, треугольник, все вершины которого лежат вне окна, а середина в окно попадает. В окне получается трапеция. Конечно, для треугольника можно, как ты писал, "по минимальным/максимальным координатам найти прямоугольник, занимаемый объектом", но что делать с навороченными полигонами?

По-поводу TMetafile. Я не могу его использовать, потому что для некоторых объектов пользуюсь библиотекой EZLines, которая рисует линии с антиалиасингом, но только на Bitmap' е.

s-mike, я не стал бы без нужды грузить участников форума, но задача, как мне кажется, довольно распространенная. Наверняка многие пытались сделать что-то подобное, не чертеж, так какую-нибудь карту-схему. Неужели никто не знает решения?

smile Пока писал пост, в голову пришла идейка. А что если использовать регионы? Нашел в справке по API функцию

Цитата
function RectInRegion(Region: HRgn; var Rect: TRect): Bool;
Опpеделяет, лежит ли какая-либо часть пpямоугольника Rect внутpи указанной области.


Что если на основе массива координат полигона создать регион, а затем проверить, "лежит ли какая-либо часть пpямоугольника" окна вывода внутpи указанной области. Ведь даже если полигон целиком лежит в окне, то и часть окна находится внутри полигона. Интересно попробовать. Только не работал я еще с регионами, как насчет скорости и объема памяти будут себя вести?
А что делать с полилиниями?

PM MAIL WWW   Вверх
s-mike
Дата 5.6.2005, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Цитата
Пока писал пост, в голову пришла идейка. А что если использовать регионы?

В общем-то практически тоже самое, что я предлагал. Производительность не сравнивал, но думаю, что на уровне.

В таком случае тебе придется хранить вместе с точечным объектом и его регион, а при добавлении/удалении/изменении точек создавать его заново. И пожалуй проверка того, находится ли регион в определенном прямоугольнике будет дольше, если хранить и проверять прямоугольник.

Насчет невыпуклых многоугольников и полилиний - все аналогично. Находятся минимальные и максимальные координаты и получаешь прямоугольник.

Кстати, эта тема навела меня на мысль создать на основе моего TScrollingImage компонент для отображения вектора, например TVectorImage. И дополнительный компонент от TGraphic - TVectorGraphic. Буду делать.
PM MAIL WWW   Вверх
ДЫМ
Дата 6.6.2005, 02:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 6.1.2004

Репутация: нет
Всего: 8



Цитата
Насчет невыпуклых многоугольников и полилиний - все аналогично. Находятся минимальные и максимальные координаты и получаешь прямоугольник.


Боюсь, мы друг друга не понимаем. У меня полилиния с минимальными координатами, допустим, (0,0) и максимальными (3000,3000). Но, по твоей логике, получается, что ее надо рисовать всегда, так как ей соответствует прямоугольник (0,0,3000,3000).

Опять же, представь полигон в виде подковы, если вокруг него описать прямоугольник, то полигон будет занимать не более 20-30% этого прямоугольника, то есть если часть этого прямоугольника попадает в окно вывода, совсем необязательно, что и сам полигон будет торчать в окне.
PM MAIL WWW   Вверх
s-mike
Дата 6.6.2005, 06:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 425
Регистрация: 16.1.2005
Где: Киев

Репутация: 5
Всего: 16



Все, понял, справедливо. Тогда действительно стоит попробовать с регионами.
PM MAIL WWW   Вверх
p0s0l
Дата 6.6.2005, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Г-н Посол
****


Профиль
Группа: Экс. модератор
Сообщений: 3668
Регистрация: 13.7.2003
Где: 58°38' с.ш. 4 9°41' в.д.

Репутация: 16
Всего: 112



Мне кажется ручных проверок делать не надо (с помощью регионов), иначе будет медленнее. Т.к. имхо, GDI сама проверяет и отсекает куски примитивов, невходящих в видимую область (возможно не оптимальным способом, но должна делать)... Поэтому если сделать еще ручную проверку, то получается, что будет двойная проверка видимости.
Вместо этого, нужно просто пересчитать координаты (промасштабировать, сдвинуть) и просто вывести на битмап размером с экран... Ну и как советовал s-mike, всё-таки делать проверку на видимость окаймляющего прямоугольника на тот случай, если прямоугольник этот вообще не видим на экране. Если видим - то выбирать, какие линии рисовать, а какие нет - пусть остаётся на совести системы... Судя по тому, что без увеличения ничего не тормозит, то так тоже не должно тормозить...
Правда, это всё ИМХО, так что могу ошибаться...
(возможно, нужно экспериментальным путём сравнить время разных способов)...

Это сообщение отредактировал(а) p0s0l - 6.6.2005, 18:09


--------------------
С уважением, г-н Посол.
PM   Вверх
andrej22
Дата 6.6.2005, 20:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 6.6.2005

Репутация: нет
Всего: нет



Попробуй держать это в памяти как GIF или PNG, если нет алгоритмов преобразования BitMap в GIF, PNG, то можешь скинуть мне на мыло [email protected], а лучше смотри на сайте http://abouticons.narod.ru
PM MAIL   Вверх
ДЫМ
Дата 7.6.2005, 01:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 6.1.2004

Репутация: нет
Всего: 8



Цитата
Мне кажется ручных проверок делать не надо (с помощью регионов), иначе будет медленнее. Т.к. имхо, GDI сама проверяет и отсекает куски примитивов, невходящих в видимую область (возможно не оптимальным способом, но должна делать)...

Цитата
Вместо этого, нужно просто пересчитать координаты (промасштабировать, сдвинуть) и просто вывести на битмап размером с экран...

Я именно так и делал - пересчитывал координаты и просто выводил в окно.
Потом попробовал делать проверку с помощью регионов. Так вот - тормоза не заметны, напротив - с проверкой рисуется все гораздо быстрее. Но тут вот какая "заковыка" - память я сэкономил кардинально, и отрисовка окна занимает в среднем 0,5 секунды (всего у меня объектов около 2000, а машина - мягко скажем, не самая мощная по сегодняшним меркам - Duron 950, 128 Mb ОЗУ). Но "Прощай, плавный скроллинг" - чтобы перемещаться по чертежу, надо при каждом сдвиге перерисовывать окно, тогда как раньше (с большим Bitmap' ом), надо было лишь скопировать в окно нужный кусок, а сам Bitmap перерисовывался только при изменении масштаба. Я уж пытался с помощью API все сделать, напрямую через DIB.
Стало чуть-чуть быстреее, но все равно не приемлемо. Попытался с помощью метафайла - никакого выигрыша в скорости.

Если бы я не видел аналогичные программы, где подобные проблемы решены, я бы подумал, что это невозможно. smile Например, карты-схемы городов, написанные на Delphi. К сожалению - это коммерческие проекты - в исходники не заглянешь...

Обобщая, я пришел к выводу, что все упирается в скорость отрисовки примитивов на Canvas. Нужна, наверное, какая-то графическая библиотека, которая очень быстро рисует линии и полигоны на канве.
Может кто знает такую?

P. S. Наверное создам топик с этим вопросом.


PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.0568 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.