Как настроить пользователя система координат Quartz2D с масштабированием, которое избегает нечеткого рисунка?

Эта тема была поцарапана несколько раз, но я все еще озадачен. И Google не был дружественным также.

Так как Кварц позволяет, чтобы произвольные системы координат использовали аффинные преобразования, я хочу смочь потянуть вещи, такие как планы размещения с помощью реальной координаты, например, ног.

Так в основном, ради примера, я хочу масштабировать представление так, чтобы, когда я тяну 10x10 прямоугольник (думают 10-дюймовое поле, например), я получил прямоугольник на 60x60 пикселей.

Это работает, кроме прямоугольника, который я получаю, довольно нечетко. Другой вопрос здесь получил ответ, который объясняет почему. Однако я не уверен, что понял, что причина, почему, и кроме того, я не знаю, как зафиксировать ее. Вот мой код:

Я установил свою систему координат в моем awakeFromNib пользовательский метод просмотра:

- (void) awakeFromNib {
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0);
    self.transform = scale;
}

И вот моя стандартная программа ничьей:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGRect r = CGRectMake(10., 10., 10., 10.);
    CGFloat lineWidth = 1.0;
    CGContextStrokeRectWithWidth(context, r, lineWidth);
}

Квадрат, который я получаю, масштабируется очень хорошо, но полностью нечеткий. Проигрывание с lineWidth не помогает: когда lineWidth установлен меньший, это становится легче, но не более свежее.

Так существует ли способ настроить представление, чтобы иметь масштабированную систему координат, так, чтобы я мог использовать свои доменные координаты? Или я должен возвратиться и реализующий масштабирующийся в моих стандартных программах рисунка?

Обратите внимание, что эта проблема не происходит для перевода или вращения.

Спасибо

5
задан Jean-Denis Muys 21 March 2010 в 18:09
поделиться

2 ответа

Что ж, объяснение проблемы часто приводит меня к ее решению.

Проблема в том, что свойство преобразования представления применяется к нему после того, как оно было помещено в битовый буфер. Масштабирующее преобразование должно применяться перед рисованием, т.е. в методе drawRect . Так что поцарапайте awakeFromNib , который я дал, и вот правильный drawRect:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGAffineTransform scale = CGAffineTransformMakeScale(6.0, 6.0);
    CGContextConcatCTM(context, scale);
    CGRect r = CGRectMake(10., 10., 10., 10.);
    CGFloat lineWidth = 0.1;
    CGContextStrokeRectWithWidth(context, r, lineWidth);
}
2
ответ дан 13 December 2019 в 05:33
поделиться

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

Обычно это происходит из-за того, что вы нарисовали прямоугольник с целочисленными координатами, а ширина вашей линии равна 1.

В PostScript (и, следовательно, в его потомках: AppKit, PDF и Quartz) единицы рисования по умолчанию равны точки, 1 точка составляет ровно 1/72 дюйма. В настоящее время Mac и iPhone * обрабатывают каждую такую ​​точку как 1 пиксель, независимо от фактического разрешения экрана (ов), поэтому на практике точки (по умолчанию на Mac и iPhone) равны пикселям.

В PostScript и его потомках интегральные координаты проходят между точками. 0, 0, например, это нижний левый угол левой нижней точки. 1, 0 - это нижний правый угол той же точки (и нижний левый угол следующей точки справа).

Обводка центрируется на контуре, который вы проводите. Таким образом, половина будет внутри дорожки, половина - снаружи.

В (концептуальном) мире Mac с разрешением 72 dpi эти два факта вместе создают проблему. Если 1 pt равен 1 пикселю, и вы применяете обводку размером 1 pt между двумя пикселями, то половина обводки попадет в каждый из этих пикселей.

Кварц, по крайней мере, отрендерит это, закрасив текущий цвет в оба пикселя на половину альфа-канала цвета. Он определяет это тем, какая часть пикселя покрыта концептуальным штрихом; если вы использовали ширину линии 1,5 пт, половина от этой ширины составляет 0,75 пт, что составляет три четверти каждого пикселя в 1 пт, поэтому цвет будет отображаться с альфа-каналом 0,75. Это, конечно, приводит к естественному выводу: если вы используете ширину линии в 2 пункта, каждый пиксель будет полностью покрыт, поэтому альфа будет равна 1. Вот почему вы можете увидеть этот эффект с обводкой в ​​1 пункт, а не с Обводка 2 точки.

Есть несколько обходных путей:

  • Перевод на половину пункта: именно то, что написано на коробке, вы переводите вверх и вправо на полпункта, компенсируя вышеупомянутое разделение на половину пункта в 1 пункт.

    Это работает в простых случаях, но не работает, когда вы задействуете любые другие преобразования координат, кроме перевода целой точки. То есть вы можете переводить на 30, 20, и это все равно будет работать, но если вы переведете на 33 + 1/3, 25,252525… или если вы вообще масштабируете или вращаете, ваш перевод на пол-точки будет бесполезен .

  • Внутренняя обводка: сначала обрежьте, затем удвойте ширину линии (потому что вы собираетесь нарисовать только половину), затем обводите.

    Это может потребовать манипуляций с gstate, если вам нужно сделать много другого рисунка, поскольку вы не хотите, чтобы этот контур обрезки влиял на ваш другой рисунок.

  • Внешний обводка: По сути, то же самое, что и внутренний обводка, за исключением того, что вы перевернули контур перед обрезкой.

    Может быть лучше (меньше жонглирования gstate), чем внутренний штрих, если вы уверены, что пути, которые вы хотите провести, не будут перекрываться. С другой стороны, если вы также хотите заполнить путь, жонглирование gstate возвращается.

* Это не будет длиться вечно. Apple уже некоторое время намекает, что в какой-то момент они собираются изменить, по крайней мере, разрешение рисования Mac. Фундамент API для такого изменения сейчас практически полностью готов; все дело в том, что Apple перекидывает переключатель.

10
ответ дан 13 December 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: