Режимы отображения координат
Масштабирование изображения
В Windows любые операции вывода являются графическими. Подсистема GDI делает вывод анпаратно независимым. Это означает, что информация, выводимая на любое физическое устройство, будет выглядеть почти одинаково. На экране монитора, на плоттере и на принтере будут отражены все детали текста или изображения. Кроме того, GDI поддерживает логические устройства вывода, такие как память или диск. Для осуществления вывода в среде Windows необходимо сначала создать так называемый контекст устройства (device context). Контекст устройства — это объект, определенный в GDI, который содержит содержат подробную информацию об устройстве, куда предполагается направить графический вывод. Например: основной цвет и цвет фона, используемая палитра, шрифт по умолчанию и т. д.
MFC имеет специальный набор классов, упрощающий процедуру общения с контекстом устройства. Класс CDC содержит большую часть функций, которые могут понадобиться для управления выводом. Классы, производные от CDC, обеспечивают специальные возможности, например класс cciientoc обеспечивает доступ к клиентской области окна, где в основном разворачиваются события, управляемые программистом. Класс CPaintDC позволяет управлять процессом перерисовки окон, обеспечивая вызовы функций BeginPaint и EndPaint в ответ на сообщение WM_PAINT. Создание рисунка в окне производится с помощью функций API, инкапсулированных в одноименных методах класса CDC
Если мы зададимся целью масштабировать изображение, то есть дать пилы-юним-;-лю возможность изменять его размеры, то нам следует научиться управлять режимами и параметрами отображения логической системы координат в физическую. Вы уже знаете, что Win32 API использует четыре координатных пространства (spaces): World space, Page space, Device space, и Physical Device space. Однако большая часть документации и книг но MFC оперируют только двумя терминами: логическая и физическая системы координат. Мы будем использовать термин, логическая система координат, имея в виду Page space.
Заметьте, что и World space и Page space измеряют плоскую область, размах которой по обеим координатам равняется 232 логических единиц, то есть более 4 миллиардов единиц. Page space работает совместно с Device space, чтобы обеспечить приложение единицами, не зависящими от типа физического устройства, такими как миллиметры и дюймы-(inches). Конечным координатным пространством, Physical Device space обычно является клиентская область окна приложения, или весь экран монитора, или страница бумаги принтера (плоттера). Размеры области физического устройства изменяются в зависимости от марки, технологии и т. д. Чтобы верно передать детали изображения, созданного в логической системе, в физическое устройство, система преобразовывает их путем отображения (mapping) прямоугольной области из одного координатного пространства в другое. При копировании каждой точки прямоугольной области из одного пространства в другое Windows применяет алгоритм трансформации, который в конечном счете изменяет размеры, ориентацию и форму всего объекта.
Так как рисование производится в логической структуре, называемой контекстом устройства, то рисунок не зависит от конкретного устройства, в которое будет осуществлен вывод изображения. Функциональность контекста устройства поддерживается классом CDC или одним из его потомков. Для выбора режима отображения используются методы этого класса:
SetMapMode — задание режима отображения координат;
SetWindowOrg — задание выделенной точки (начала отображения) в логической системе координат;
Setviewportorg — задание выделенной точки (начала отображения) в физической системе координат;
SetwindowExt — характеристика протяженности окна вдоль двух логических координат;
SetviewportExt — характеристика протяженности окна вдоль двух физических координат.
Восемь существующих режимов отображения координат задаются с помощью символьных констант, определенных в файле Wingdi.h:
#define MM_TEXT 1 // 1 лог. ед. - 1 пиксел
#define MM_LOMETRIC 2 // 1 лог. ед. - 0,1 мм
#define MM_HIMETRIC 3 // 1 лог. ед. - 0,01 мм
#define MM_LOENGLISH 4 // 1 лог. ед. - 0,01 дюйма
#define MM_HIENGLISH 5 // 1 лог. ед. - 0,001 дюйма
#define MMJTWIPS 6 //1 лог. ед. - 1/1440 дюйма
//========== Преобразования по формуле ==========//
#define MM_ISOTROPIC 7 // Растяжение одинаково
#define MM_ANISOTROPIC 8 // Растяжение различно
По умолчанию действует режим ММ_ТЕХТ, в котором ось Y имеет направление сверху вниз. Последующие пять режимов предполагают, что ось Y направлена снизу-вверх. В двух последних режимах преобразование координат из логической системы в физическую выполняется в соответствии с формулами, которые приведены ниже. При этом используются следующие обозначения:
Viewport — область вывода, задаваемая физическими координатами;
Window — окно, задаваемое логическими координатами.
Выделенные точки window и viewport совмещаются, а изображение растягивается или сжимается так, что горизонтальная координата каждой точки изображения при выводе в физическое устройство вычисляется по формуле линейного преобразования:
Dx=Vox+(Vex/Wex)*(Lx-Wox)
где: Dx — аппаратная (device) или физическая Х-координата точки,
Lx - логическая (logical) Х-координата точки,
Vex - протяженность области вывода, задаваемая SetVievvportExt,
Wex — протяженность окна, задаваемая SetWindowExt,
Vox — X начала координат области вывода (SetViewportOrg),
Wox — X начала координат логического окна (SetWindowOrg).
Аналогичная формула справедлива для Y-координаты точки. Опробуем формулу на произвольном наборе данных. (Такого типа вопросы вы можете встретить на сертификационном экзамене Microsoft.) Предположим, что в режиме MM_ANISOTROPIC заданы такие параметры отображения:
//====== Выделенная точка в логическом окне
pDC->SetWindowOrg (300, 0) ;
//====== Выделенная точка в физическом окне
pDC->SetViewportOrg (200, 200);
//====== Протяженность логического окна pDC->SetWindowExt (100, 100);
//====== Протяженность физического окна
pDC->SetViewportExt (50, -200);
Какие координаты в окне на экране будут иметь точки, заданные оператором: CPoint pl(0, 0), р2(100, 100)? Ответ: они преобразуются в аппаратные (физические) координаты: (50, 200) и (100, 0). Проверим первую координату подстановкой в формулу:
200 + 50/100(0-300)=50
Таким образом, если мы хотим увеличить или уменьшить изображение, то нужно изменять следующие величины:
Vex / Wex— коэффициент растяжения (сжатия) вдоль оси X,
Vey / Wey— коэффициент растяжения (сжатия) вдоль оси Y.
Эти формулы работают независимо только в режиме MM_ANISOTROPIC. Несколько иначе они работают в режиме MM_ISOTROPIC и вовсе не работают в остальных шести режимах.
В режиме MM_ISOTROPIC система обеспечивает одинаковое расширение (сжатие) по обеим осям, поэтому результат вычислений по приведенным формулам зависит от соотношения величин коэффициентов растяжения (сжатия). Теперь видно, что режим MM_ANISOTROPIC обеспечивает наибольшую свободу и гибкость в преобразовании координат. Числитель и знаменатель в формулах для коэффициентов растяжения (сжатия) задаются по отдельности с помощью методов класса CDC. Метод SetviewportExt задает числитель обоих отношений, следовательно, определяет свойства физического устройства, а метод SetwindowExt задает знаменатель, то есть задает свойства логической системы координат. Имена функций вводят нас в заблуждение, так как на самом деле эти функции ничего не задают и не определяют. Работая в паре, они дают способ задания двух вещественных коэффициентов растяжения (сжатия) путем задания четырех целых чисел. Параметры функций должны быть целыми или объектами класса csize, которые тоже создаются из двух целых. Значительно проще было бы задать два вещественных числа и использовать их в качестве коэффициентов. Объяснение наблюдаемой реальности, видимо, кроется в истории разработки функций API (сложности с floating point-арифметикой).
Содержание раздела