2010-03-21 1 views
5

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

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

В основном, для примера, я хочу масштабировать вид, чтобы при рисовании прямоугольника 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 установлен меньше, он становится легче, но не более четким.

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

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

Благодаря

ответ

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); 
} 
+1

Если вы хотите установить ширину линии в точках независимо от масштабного коэффициента, установите ее на «желаемое количество точек/масштабный коэффициент». Примеры: Значение по умолчанию - 1 pt/1 × = 1; линия 1-pt на вашем 6 × -факторе равна '1.0/6.0'; строка 2-pt будет '2.0/6.0'. –

10

кнопку [погладил] прямоугольник Я получаю довольно размыто.

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

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

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

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

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

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

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

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

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

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

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

  • Наружный ход: по существу такой же, как внутренний ход, за исключением того, что вы переверните путь перед обрезкой.

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

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

+0

все очень верно, за исключением того, что это не причина размытости, которую я испытал. Нечеткость вызвана тем фактом, что 'UIView.transform' применяется к представлению в качестве этапа после бьет. Таким образом, это масштабирование бит-карты, нарисованной 'drawRect'. Просто применяя преобразование * в начале * 'drawRect', он исправляет его. Это делает 'UIView.transform' бесполезным для масштабирования. Конечно, я все еще вижу то, что вы описываете, - пиксельный трансграничный. Визуальное впечатление на вертикальные и горизонтальные штрихи по 1 пикселю должно выглядеть серым, а не черным, а не размытым. –