Вычислить ограничивающую рамку чертежа GDI+

Я рисую изображение из MetaFile (emf), а затем применяю ко всему этому некоторые преобразования вращения в OnPaint пользовательского элемента управления. После применения этих преобразований, как я могу вычислить обычную непреобразованную прямоугольную ограничивающую рамку этого в координатах экрана? Мне это нужно, чтобы изменить размер повернутого изображения до размера UserControl.

protected override void OnPaint(PaintEventArgs e)
{
    // rotate around the center of this UserControl
    e.Graphics.TranslateTransform(this.Width / 2.0f, this.Height / 2.0f);
    e.Graphics.RotateTransform(this.Rotation);
    e.Graphics.TranslateTransform(this.Width / -2.0f, this.Height / -2.0f);

    // TODO: now scale so the image so it fits exactly into this UserControl

    // draw the image at the center of this UserControl
    float left = (this.Width - ResourceManager.MyDrawingMetaFile.Width) / 2.0f;
    float top = (this.Height - ResourceManager.MyDrawingMetaFile.Height) / 2.0f;
    e.Graphics.DrawImage(Resources.MyDrawingMetaFile, left, top);
}

Вся идея заключается в том, что я хочу отображать повернутый файл .emf в UserControl, и чтобы рисунок emf всегда заполнял доступное пространство в UserControl. Может быть, есть лучший подход?

Режим заполнения/растягивания, который мне нужен, — это Uniform и UniformToFill (как в окне просмотра WPF). ЭДС не должна искажаться, а в режиме Uniform ЭДС полностью заполняет пользовательский элемент управления по крайней мере в одном измерении, ничего не обрезается. В UniformToFill ЭДС заполняет UserControl в обоих измерениях, и если пропорции не совпадают, ЭДС обрезается в одном измерении.


person bitbonk    schedule 22.11.2009    source источник
comment
Как вы хотите, чтобы он заполнялся? Должна ли ЭДС полностью покрывать пользовательский элемент управления (должна ли быть обрезана какая-то часть ЭДС) или она должна иметь такой размер, чтобы была видна вся ЭДС, оставляя части пользовательского управления закрытыми? И должен ли ЭДС сохранять исходное соотношение сторон или нет?   -  person Dan Byström    schedule 23.11.2009
comment
Режим заполнения/растягивания, который мне нужен, — это Uniform и UniformToFill (как в окне просмотра WPF). ЭДС не должна искажаться, а в режиме Uniform ЭДС полностью заполняет пользовательский элемент управления по крайней мере в одном измерении, ничего не обрезается. В UniformToFill ЭДС заполняет UserControl в обоих измерениях, и если пропорции не совпадают, ЭДС обрезается в одном измерении.   -  person bitbonk    schedule 23.11.2009


Ответы (2)


Если я вас правильно понял, вам нужно выяснить, как вращение влияет на ограничивающую рамку вашего изображения, чтобы вы могли соответствующим образом масштабировать его.

Тогда вы можете сделать так:

  1. Вставьте четыре координаты ограничивающей рамки в Point[].
  2. Настройте матрицу с вашим вращением (.RotateAt)
  3. Пусть матрица преобразует четыре точки.
  4. Отсортируйте четыре преобразованные координаты X и сравните ширину новой ограничивающей рамки (pts[3].X - pts[0].X после сортировки).
  5. Теперь вы знаете, как масштабировать ширину для идеальной подгонки.
  6. Повторите шаг 4 для высоты.
person Dan Byström    schedule 23.11.2009
comment
Мои рисунки не обязательно прямоугольные. Например, если рисунок представляет собой круг, само вращение не повлияет на коэффициент масштабирования. - person bitbonk; 23.11.2009
comment
Затем вам нужно проделать описанное выше для каждого угла изображения. Окружность, конечно, должна быть аппроксимирована и представлена ​​как состоящая из нескольких отрезков. - person Dan Byström; 23.11.2009
comment
Интересно, как это делает WPF (возможно, где-то на уровне DWM). - person bitbonk; 24.11.2009

Как это будет сделано с GDI:

BeginPath()
// Draw stuff
EndPath()
PathToRegion()
GetRgnBox()

У GDI+ есть эквиваленты — классы GraphicsPath и Region могут делать вышеперечисленное.

person rep_movsd    schedule 22.11.2009
comment
Мой рисунок исходит из метафайла, поэтому я думаю, что GraphicsPath не будет применяться. - person bitbonk; 22.11.2009
comment
Метафайл — это просто сериализация вызовов GDI, поэтому он должен работать с GraphicsPath. В любом случае класс MetaFile имеет метод GetMetafileHeader, вы можете получить ограничивающую рамку метафайла и использовать тригинометрию для получения повернутого размера. - person rep_movsd; 22.11.2009
comment
Ну, GraphicsPath не имеет AddMetaFile или AddDrawing или подобного метода. - person bitbonk; 22.11.2009
comment
Кроме того, поскольку рисунок не является прямоугольным (это может быть круг или сложный путь), чтобы получить правильную ограничивающую рамку, мне нужно было бы получить ограничивающую рамку ПОСЛЕ применения преобразований. Использование тригонометрии для пересчета размера повернутой ограничивающей рамки недостаточно. - person bitbonk; 22.11.2009