Пути
Какао предоставляет поддержку для рисования простых или сложных геометрических фигур с помощью путей. Путь является набором точек, используемых для создания примитивных форм, таких как строки, дуги и кривые. От этих примитивов можно создать более сложные формы, такие как круги, прямоугольники, многоугольники, и объединить искривленные формы и нарисовать их. Поскольку они составлены из точек (в противоположность растеризированному битовому массиву), пути легки, быстро, и масштаб к различным разрешениям, не теряя точность или качество.
Следующие разделы фокусируются прежде всего на использовании NSBezierPath
класс, обеспечивающий основной интерфейс для создания и управления путями. Какао также обеспечивает ряд функций, предлагающих подобное поведение для создания и рисования путей, но не требующих издержек создания объекта. Те функции упоминаются, где это необходимо, но для получения дополнительной информации, видят Ссылку Платформы Ссылки и AppKit Платформы Основы.
Соедините стандартные блоки каналом
Какао определяет несколько основополагающих типов данных для управления геометрическими данными в среде получения. Эти типы данных включают NSPoint
, NSRect
, и NSSize
. Вы используете эти типы данных для указания строк, прямоугольников и информации о ширине и высоте для форм, которые Вы хотите нарисовать. Все от строк и прямоугольников к кругам, дугам и Кривым Безье может быть указано с помощью один или больше этих структур данных.
Координатные значения для точки, прямоугольника и типов данных размера все указаны с помощью значений с плавающей точкой. Значения с плавающей точкой допускают намного более прекрасную точность, поскольку разрешение базового устройства назначения восстанавливает работоспособность.
NSPoint
, NSRect
, и NSSize
типы данных имеют эквиваленты в Кварцевой среде: CGPoint
, CGRect
, и CGSize
. Поскольку расположение типов Какао и Кварца идентично, можно преобразовать между двумя типами путем кастинга от одного типа до его дубликата.
Класс NSBezierPath
NSBezierPath
класс обеспечивает поведение для рисования самых примитивных форм, и для многих сложных форм, это - единственный инструмент, доступный в Какао. NSBezierPath
объект инкапсулирует информацию, связанную с путем, включая точки, определяющие путь и атрибуты, влияющие на появление пути. Следующие разделы объясняют как NSBezierPath
представляет информацию о пути, и также опишите атрибуты, влияющие на появление пути.
Элементы пути
NSBezierPath
возразите элементам пути использования для создания пути. Элемент пути состоит из примитивной команды и одной или более точек. Команда говорит объект контуров, как интерпретировать связанные точки. Когда собрано, ряд элементов пути создает ряд линейных сегментов, формирующих желаемую форму.
NSBezierPath
класс обрабатывает большую часть работы создания и организации элементов пути первоначально. Знание, как управлять элементами пути, становится важным, однако, если Вы хотите внести изменения в существующий путь. При создании сложного контура на основе ввода данных пользователем Вы могли бы хотеть дать пользователю опцию изменения того пути позже. Несмотря на то, что Вы могли создать новый объект контуров с изменениями, намного более просто изменить существующие элементы пути. (Для получения информации о том, как изменить элементы пути, посмотрите Элементы Отдельного тракта Управления.)
NSBezierPath
класс определяет только четыре основных команды элемента пути, перечисленные в Таблице 8-1. Этих команд достаточно для определения всех возможных форм контура. Каждая команда имеет одну или более точек, содержащих информацию, должен был расположить элемент пути. Большинство элементов пути использует текущую точку получения в качестве начальной точки для рисования.
Команда |
Число очков |
Описание |
---|---|---|
1 |
Перемещает текущую точку получения объекта контуров к указанной точке. Этот элемент пути не приводит ни к какому получению. Используя эту команду посреди пути приводит к разъединенному линейному сегменту. |
|
1 |
Создает прямую линию от текущей точки получения до указанной точки. Строки и прямоугольники указаны с помощью этого элемента пути. |
|
3 |
Создает изогнутый сегмент линии от текущей точки до указанной конечной точки с помощью двух контрольных точек для определения кривой. Точки сохранены в следующем порядке: |
|
1 |
Отмечает конец текущего подпути в указанной точке. (Обратите внимание на то, что точка, указанная для элемента Замкнутого контура, является по существу тем же как текущей точкой. |
Когда Вы добавляете новую форму к пути, NSBezierPath
разламывает ту форму на один или несколько элементов пути компонента в целях хранения. Например, вызов moveToPoint:
или lineToPoint:
создает Перемещение К элементу или Строку К элементу соответственно. В случае более сложных форм, как прямоугольники и овалы, могут быть созданы несколько строк или элементов кривой. Рисунок 8-1 показывает две формы и получающиеся элементы пути. Для изогнутого сегмента данные также показывают контрольные точки, определяющие кривую.
Перечисление 8-1 показывает код, создающий путь, показанный на рисунке 8-1.
Перечисление 8-1 , Создающее сложный контур
NSBezierPath* aPath = [NSBezierPath bezierPath]; |
[aPath moveToPoint:NSMakePoint(0.0, 0.0)]; |
[aPath lineToPoint:NSMakePoint(10.0, 10.0)]; |
[aPath curveToPoint:NSMakePoint(18.0, 21.0) |
controlPoint1:NSMakePoint(6.0, 2.0) |
controlPoint2:NSMakePoint(28.0, 10.0)]; |
[aPath appendBezierPathWithRect:NSMakeRect(2.0, 16.0, 8.0, 5.0)]; |
Подпути
Подпуть является серией связанной строки и сегментов кривой в NSBezierPath
объект. Единственный объект контуров может содержать многократные подпути с каждым подпутем, очерченным Перемещением К или элементом Замкнутого контура. Когда Вы устанавливаете начальную точку получения (обычно использующий moveToPoint:
метод), Вы устанавливаете начальную точку первого подпути. Как Вы рисуете, Вы создаете содержание подпути до Вас любое завершение путь (использующий closePath
метод), или добавляют другое Перемещение К элементу. В той точке подпуть считают закрытым, и любые новые элементы добавляются к новому подпути.
Некоторые методы NSBezierPath
автоматически создайте новый подпуть для Вас. Например, создавая прямоугольник или овальные результаты в добавлении Перемещения К элементу, нескольким элементам получения, и Замкнутому контуру и Перемещению К элементу (см. рисунок 8-1 для примера). Перемещение К элементу в конце списка элементов гарантирует, что текущую точку получения оставляют в известном расположении, которое в этом случае является в точке источника прямоугольника.
Подпути существуют, чтобы помочь Вам отличить различные части объекта контуров. Например, подпути влияют на способ, которым путь заполнен; см. Вьющиеся Правила. Подразделение пути в подпути также влияет на методы такой как bezierPathByReversingPath
, который инвертирует подпути по одному. В других случаях, тем не менее, подсоединяет каналом в NSBezierPath
возразите совместно используют те же атрибуты получения.
Атрибуты пути
NSBezierPath
объект поддерживает все атрибуты, должен был определить форму его пути. Эти атрибуты включают ширину строки, плоскость кривой, стиль окончания линии, стиль соединения строки и предельный угол стыка пути. Вы устанавливаете эти значения с помощью методов NSBezierPath
.
Атрибуты пути не вступают в силу, пока Вы не заполняете или перечеркиваете путь, поэтому при изменении атрибута несколько раз прежде, чем нарисовать путь только последнее значение используется. NSBezierPath
класс поддерживает и пользовательскую и версию по умолчанию каждого атрибута. Объекты контуров используют значения пользовательского атрибута, если они установлены. Если никакое значение пользовательского атрибута не установлено для данного объекта контуров, значение по умолчанию используется. NSBezierPath
класс не использует Кварцевые функции использования набора значений атрибута пути.
Следующие разделы описывают атрибуты, которые можно установить для объекта контуров и как те атрибуты влияют представленные пути.
Ширина строки
Атрибут ширины строки управляет шириной всего пути. Ширина строки измерена в точках и указана как значение с плавающей точкой. Ширина по умолчанию для всех строк равняется 1. Изменить ширину строки по умолчанию для всех NSBezierPath
объекты, Вы используете setDefaultLineWidth:
метод. Для установки ширины строки для текущего объекта контуров Вы используете setLineWidth:
метод того объекта контуров. Установить ширину строки по умолчанию для форм, представленных без NSBezierPath
объект, необходимо использовать CGContextSetLineWidth
функция в Кварце.
Дробные ширины строки представляются максимально близко к указанной ширине согласно ограничениям устройства назначения, позиции строки и текущей настройке сглаживания. Например, предположите, что Вы хотите чертить линию, чья ширина является 0,2 точками. Умножение этой ширины точками 1/72 на дюйм приводит к строке, которая 0,0027778 дюйма шириной. На экране на 90 точек на дюйм самая маленькая строка была бы 1 пиксель шириной или 0,0111 дюйма. Гарантировать Вашу строку не скрыто на экране, Какао номинально рисует его в большей минимальной ширине экрана (0,0111 дюйма). В действительности, если строка одновременно покупает и продает границу пикселей, или сглаживание включено, строка могла бы влиять на дополнительные пиксели по обе стороны от пути. Если бы устройство вывода было принтером на 600 точек на дюйм то вместо этого, Кварц был бы в состоянии представить строку ближе к ее истинной ширине 0,0027778 дюймов.
Перечисление 8-2 рисует несколько путей с помощью различных методов. NSFrameRect
функционируйте использует ширину строки по умолчанию для рисования прямоугольника, так, чтобы значение было установлено до вызывания функции. Объекты контуров используют значение по умолчанию, только если не было установлено пользовательское значение. Можно даже изменить ширину строки объекта контуров и нарисовать снова для достижения различной ширины пути, несмотря на то, что необходимо было бы также переместить путь для наблюдения различия.
Перечисление 8-2 , Устанавливающее ширину строки пути
// Draw a rectangle using the default line width: 2.0. |
[NSBezierPath setDefaultLineWidth:2.0]; |
NSFrameRect(NSMakeRect(20.0, 20.0, 10.0, 10.0)); |
// Set the line width for a single NSBezierPath object. |
NSBezierPath* thePath = [NSBezierPath bezierPath]; |
[thePath setLineWidth:1.0]; // Has no effect. |
[thePath moveToPoint:NSMakePoint(0.0, 0.0)]; |
[thePath lineToPoint:NSMakePoint(10.0, 0.0)]; |
[thePath setLineWidth:3.0]; |
[thePath lineToPoint:NSMakePoint(10.0, 10.0)]; |
// Because the last value set is 3.0, all lines are drawn with |
// a width of 3.0, not just the second line. |
[thePath stroke]; |
// Changing the width and stroking again draws the same path |
// using the new line width. |
[thePath setLineWidth:4.0]; |
[thePath stroke]; |
// Changing the default line width has no effect because a custom |
// value already exists. The path is rendered with a width of 4.0. |
[thePath setDefaultLineWidth:5.0]; |
[thePath stroke]; |
Стили окончания линии
Текущий стиль окончания линии определяет появление открытых точек сегмента контура. Какао поддерживает стили окончания линии, показанные на рисунке 8-2.
Установить стиль окончания линии для a NSBezierPath
объект, используйте setLineCapStyle:
метод. Стиль окончания линии по умолчанию установлен в NSButtLineCapStyle
. Для изменения стиля окончания линии по умолчанию используйте setDefaultLineCapStyle:
метод. Перечисление 8-3 демонстрирует оба из этих методов:
Перечисление 8-3 , Устанавливающее стиль окончания линии пути
[// Set the default line cap style |
[NSBezierPath setDefaultLineCapStyle:NSButtLineCapStyle]; |
// Customize the line cap style for the new object. |
NSBezierPath* aPath = [NSBezierPath bezierPath]; |
[aPath moveToPoint:NSMakePoint(0.0, 0.0)]; |
[aPath lineToPoint:NSMakePoint(10.0, 10.0)]; |
[aPath setLineCapStyle:NSSquareLineCapStyle]; |
[aPath stroke]; |
Стили соединения строки
Текущий стиль соединения строки определяет, как к связанным строкам по пути присоединяются в вершинах. Какао поддерживает стили соединения строки, показанные на рисунке 8-3.
Установить стиль соединения строки для NSBezierPath
объект, используйте setLineJoinStyle:
метод. Стиль соединения строки по умолчанию установлен в NSMiterLineJoinStyle
. Для изменения стиля соединения строки по умолчанию используйте setDefaultLineJoinStyle:
метод. Перечисление 8-4 демонстрирует оба из этих методов:
Перечисление 8-4 , Устанавливающее стиль соединения строки пути
[// Set the default line join style |
[NSBezierPath setDefaultLineJoinStyle:NSMiterLineJoinStyle]; |
// Customize the line join style for a new path. |
NSBezierPath* aPath = [NSBezierPath bezierPath]; |
[aPath moveToPoint:NSMakePoint(0.0, 0.0)]; |
[aPath lineToPoint:NSMakePoint(10.0, 10.0)]; |
[aPath lineToPoint:NSMakePoint(10.0, 0.0)]; |
[aPath setLineJoinStyle:NSRoundLineJoinStyle]; |
[aPath stroke]; |
Стиль тире строки
Стиль тире строки решает, что образец раньше перечеркивал путь. По умолчанию перечеркиваемые пути кажутся существенными. Используя пунктирный узор строки, можно указать переменную группу существенных и прозрачных образцов. При установке пунктирного узора строки Вы указываете ширину (в точках) каждого последовательного существенного или прозрачного образца. Ширины, которые Вы указываете, тогда повторяются по всей длине пути.
Рисунок 8-4 показывает, что некоторые демонстрационные пунктирные узоры строки, вместе со значениями раньше создавали каждый образец.
NSBezierPath
класс не поддерживает понятие стиля тире строки по умолчанию. Если Вы хотите стиль тире строки, необходимо применить его к пути явно с помощью setLineDash:count:phase:
метод как показано в Перечислении 8-5, представляющем последний образец от предыдущей фигуры.
Перечисление 8-5 , Добавляющее тире, разрабатывает к пути
void AddDashStyleToPath(NSBezierPath* thePath) |
{ |
// Set the line dash pattern. |
float lineDash[6]; |
lineDash[0] = 40.0; |
lineDash[1] = 12.0; |
lineDash[2] = 8.0; |
lineDash[3] = 12.0; |
lineDash[4] = 8.0; |
lineDash[5] = 12.0; |
[thePath setLineDash:lineDash count:6 phase:0.0]; |
} |
Плоскость строки
Атрибут плоскости строки определяет точность рендеринга для изогнутых сегментов. Значение плоскости измеряет допуск максимальной погрешности (в пикселях) для использования во время рендеринга. Меньшие значения приводят к более гладким кривым, но требуют большего количества времени вычисления. Большие значения приводят к более зубчатым кривым, но представляются намного быстрее.
Плоскость строки является одним параметром, который можно настроить, когда Вы хотите представить большое количество кривых быстро и не заботитесь о точности. Например, Вы могли бы увеличить эту стоимость во время живого, изменяют размеры или прокрутка работы, когда точность не так крайне важна. Независимо, необходимо всегда измерять производительность, чтобы удостовериться, что такая модификация фактически экономит время.
Рисунок 8-5 показывает, как изменение плоскости по умолчанию влияет на кривые поверхности. Данные слева показывают группу кривых поверхностей, представленных с набором значений плоскости к 0.6
(его значение по умолчанию). Данные справа показывают те же кривые поверхности, представленные с набором значений плоскости к 20
. Искривление каждой поверхности потеряно и теперь, кажется, ряд связанных линейных сегментов.
Установить плоскость для определенного NSBezierPath
объект, используйте setFlatness:
метод. Для установки значения плоскости по умолчанию использовать setDefaultFlatness:
, как показано в Перечислении 8-6:
Перечисление 8-6 , Устанавливающее плоскость пути
[- (void) drawRect:(NSRect)rect |
{ |
if ([self inLiveResize]) |
{ |
// Adjust the default flatness upward to reduce |
// the number of required computations. |
[NSBezierPath setDefaultFlatness:10.0]; |
// Draw live resize content. |
} |
// ... |
} |
Предельные углы стыка
Предельные углы стыка помогают Вам избежать скачков, происходящих, когда Вы присоединяетесь к двум линейным сегментам под резким углом. Если отношение длины среза — диагональная длина среза — к толщине строки превышает предельный угол стыка, угол нарисован с помощью косоугольного соединения вместо соединения среза.
Рисунок 8-6 показывает пример того, как различные предельные углы стыка влияют на тот же путь. Этот путь состоит из нескольких широких строк с 10 точками, соединенных соединениями среза. В числе слева, предельный угол стыка установлен в 5
. Поскольку длины среза превышают предельный угол стыка, соединения строки изменяются для скашивания соединений. Путем увеличения предельного угла стыка до 16
, как показано в числе справа, соединения среза восстанавливаются, но расширяются далеко вне точки, где встречаются эти две строки.
Установить предельные углы стыка для определенного NSBezierPath
объект, используйте setMiterLimit:
метод. Установить предельный угол стыка по умолчанию для недавно создаваемого NSBezierPath
объекты, использовать setDefaultMiterLimit:
. Перечисление 8-7 демонстрирует оба из этих методов:
Перечисление 8-7 , Устанавливающее предельный угол стыка для пути
// Increase the default limit |
[NSBezierPath setDefaultMiterLimit:20.0]; |
// Customize the limit for a specific path with sharp angles. |
NSBezierPath* aPath = [NSBezierPath bezierPath]; |
[aPath moveToPoint:NSMakePoint(0.0, 0.0)]; |
[aPath lineToPoint:NSMakePoint(8.0, 100.0)]; |
[aPath lineToPoint:NSMakePoint(16.0, 0.0)]; |
[aPath setLineWidth:5.0]; |
[aPath setMiterLimit:5.0]; |
[aPath stroke]; |
Проветривание правил
Когда Вы заполняете область, охваченную путем, NSBezierPath
применяет правило токовой обмотки определить который области экрана заполниться. Вьющееся правило является просто алгоритмом, отслеживающим информацию о каждой непрерывной области, составляющей полную закрашенную область пути. Луч нарисован из точки в данной области к любой точке вне границ пути. Общее количество пересеченных строк пути (включая неявные строки) и направление каждой строки пути тогда интерпретируется с помощью правил в Таблице 8-2, определяющих, должна ли область быть заполнена.
Операции заполнения подходят для использования и с открытыми и с закрытыми подпутями. Закрытый подпуть является последовательностью рисования вызовов, который заканчивается элементом пути Замкнутого контура. Открытый подпуть заканчивается Перемещением Для соединения каналом элемента. Когда Вы заполняете частичный подпуть, NSBezierPath
завершения это для Вас автоматически путем создания неявной (непредставленной) строки сначала к последней точке подпути.
Рисунок 8-7 показывает, как вьющиеся правила применяются к определенному пути. Подчисло a
показывает, что путь представил использование ненулевого правила и подчисла b
показывает, что это представило использование ровно-нечетного правила. Подчисла c
и d
добавьте метки направления и скрытую строку пути, закрывающую число, чтобы помочь Вам видеть, как правила применяются к двум из областей пути.
Устанавливать вьющееся правило для NSBezierPath
объект, используйте setWindingRule:
метод. Правило проветривания значения по умолчанию NSNonZeroWindingRule
. Изменить правило проветривания значения по умолчанию для всех NSBezierPath
объекты, используйте setDefaultWindingRule:
метод.
Управление геометрическими типами
Платформа Основы включает многочисленные функции для управления геометрическими значениями и для выполнения различных вычислений с помощью тех значений. В дополнение к основным проверкам равенства можно выполнить более сложные операции, такие как объединение и пересечение прямоугольников или включение точки в границах прямоугольника.
Таблица 8-3 перечисляет некоторые более обычно используемые функции и их способы поведения. Синтаксис функций предоставлен в краткой нотации с типами параметра, опущенными для демонстрации соглашения о вызовах. Для полного списка доступных функций и их полного синтаксиса, посмотрите раздел Functions в Ссылке Платформы Основы.
Работа |
Функция |
Описание |
---|---|---|
Создание |
|
Возвращается должным образом отформатированный |
|
Возвращается должным образом отформатированный |
|
|
Возвращается должным образом отформатированный |
|
Равенство |
|
Возвраты |
|
Возвраты |
|
|
Возвраты |
|
Прямоугольные манипуляции |
|
Возвраты |
|
Возвращает копию указанного прямоугольника с его сторонами, перемещенными внутрь указанными значениями дельты. Отрицательные значения дельты перемещают исходящие стороны. Не изменяет исходный прямоугольник. |
|
|
Возвращает пересечение этих двух прямоугольников. |
|
|
Возвращает объединение этих двух прямоугольников. |
|
|
Тесты, находится ли точка в указанном прямоугольнике представления. Корректирует алгоритм обнаружения хита для обеспечения непротиворечивого поведения с точки зрения пользователя. |
|
|
Тесты, находится ли точка в указанном прямоугольнике. Это - основное математическое сравнение. |
Рисование фундаментальных форм
Поскольку много типов довольных, находящегося на пути получения имеют несколько преимуществ перед основанным на изображении получением:
Поскольку пути указаны математически, они масштабируются легко к различным разрешениям. Таким образом те же объекты контуров могут использоваться для экрана и основанного на печати получения.
Информация о геометрии, связанная с путем, требует намного меньшего пространства памяти, чем большинство форматов данных изображения.
Рендеринг путей часто быстрее, чем составление композита сопоставимого изображения. Требуется меньше времени для передачи данных пути аппаратному обеспечению машинной графики, чем это берет для передачи данных текстуры, связанных с изображением.
Следующие разделы предоставляют информацию о примитивных формах, можно нарисовать пути использования. Можно объединиться один или больше этих форм, чтобы создать более сложный контур и затем перечеркнуть или заполнить путь, как описано в Рисовании Форм по Пути. Для некоторых форм может быть больше чем один способ добавить форму к пути, или могут быть альтернативные способы сразу нарисовать форму. Везде, где возможно, преимущества и недостатки каждого метода перечислены, чтобы помочь Вам решить, какой метод является самым надлежащим в особых ситуациях.
Добавление точек
NSPoint
структура отдельно представляет расположение на экране; это не имеет никакого веса и не может быть нарисовано как таковое. Для рисования эквивалента точки на экране необходимо было бы создать маленький прямоугольник в желаемом расположении, как показано в Перечислении 8-8.
Перечисление 8-8 , Получающее точку
void DrawPoint(NSPoint aPoint) |
{ |
NSRect aRect = NSMakeRect(aPoint.x, aPoint.y, 1.0, 1.0); |
NSRectFill(aRect); |
} |
Конечно, больше общего использования для точек должно указать позицию других форм. Много форм требуют, чтобы Вы указали текущую точку прежде фактически создать форму. Вы устанавливаете текущую точку с помощью moveToPoint:
или relativeMoveToPoint:
методы. Некоторые формы, как прямоугольники и овалы, уже содержат информацию о расположении и не требуют отдельного вызова к moveToPoint:
.
Добавление строк и многоугольников
Какао предоставляет несколько возможностей для добавления строк к пути с каждым методом, предлагающим различные компромиссы между эффективностью и правильностью. Можно провести линии следующими способами:
Создайте единственные горизонтальные и вертикальные строки путем заполнения прямоугольного использования
NSRectFill
. Этот метод менее точен, но часто немного быстрее, чем созданиеNSBezierPath
объект. Для создания диагональных строк с помощью этого метода необходимо применяться, вращение преобразовывают перед получением. Этот метод не является подходящим для создания связанных линейных сегментов.Используйте
lineToPoint:
,relativeLineToPoint:
, илиstrokeLineFromPoint:toPoint:
методыNSBezierPath
создать отдельные или связанные линейные сегменты. Этот метод быстр и является самой точной опцией для создания строк и сложных многоугольников.Используйте
appendBezierPathWithPoints:count:
метод для создания серии связанных строк быстро. Этот метод быстрее, чем добавление отдельных строк.
Многоугольники составлены из многократных связанных строк и должны быть созданы с помощью NSBezierPath
объект. Самый простой способ создать четырехстороннюю непрямоугольную форму, как параллелограм, ромб, или трапецоид, использует линейные сегменты. Вы могли также создать эти формы, которые преобразовывает использование, но вычисление корректных скошенных факторов потребовало бы намного большего количества работы.
Перечисление 8-9 показывает код для рисования использования параллелограма NSBezierPath
. Метод в этом примере наносит параллелограм в указанном прямоугольнике. withShift
параметр указывает, что горизонтальный сдвиг применился к верхнему левому и правым нижним углам прямоугольной области.
Перечисление 8-9 Используя строки для рисования многоугольника
void DrawParallelogramInRect(NSRect rect, float withShift) |
{ |
NSBezierPath* thePath = [NSBezierPath bezierPath]; |
[thePath moveToPoint:rect.origin]; |
[thePath lineToPoint:NSMakePoint(rect.origin.x + withShift, NSMaxY(rect))]; |
[thePath lineToPoint:NSMakePoint(NSMaxX(rect), NSMaxY(rect))]; |
[thePath lineToPoint:NSMakePoint(NSMaxX(rect) - withShift, rect.origin.y)]; |
[thePath closePath]; |
[thePath stroke]; |
} |
Добавление прямоугольников
Поскольку прямоугольники часто используются, существует несколько опций для привлечения их.
Используйте методы
NSBezierPath
создать Ваш прямоугольник. Следующие методы довольно быстры и предлагают лучшую точность:Создайте прямоугольники с помощью функций Какао, описанных в Рисовании Прямоугольников. Эти функции рисуют прямоугольники быстрее, чем, но с меньшей точностью, чем, методы
NSBezierPath
.Создайте прямоугольник с помощью отдельных строк, как описано в Добавляющих Строках и Многоугольниках. Вы могли использовать этот метод для создания по диагонали ориентированных прямоугольников — т.е. прямоугольники, стороны которых не параллельны осям x и y — не используя вращение, преобразовывают.
Перечисление 8-10 показывает простую функцию, заполняющую и перечеркивающую тот же прямоугольник с помощью двух различных методов. Текущие цвета заливки и цвета обводки используются при рисовании прямоугольника, вместе с работой составления композита значения по умолчанию. В обоих случаях прямоугольники сразу нарисованы; нет никакой потребности отправить отдельное fill
или stroke
сообщение.
Перечисление 8-10 , Получающее прямоугольник
void DrawRectangle(NSRect aRect) |
{ |
NSRectFill(aRect); |
[NSBezierPath strokeRect:aRect]; |
} |
Добавление скругленных прямоугольников
В OS X v10.5 и позже, NSBezierPath
класс включает следующие методы для создания скругленных прямоугольников:
Эти методы создают прямоугольники, углы которых изогнуты согласно указанным значениям радиуса. Радиусы описывают ширину и высоту овала для использования в каждом углу прямоугольника. Рисунок 8-8 показывает, как этот нанесенный овал используется для определения пути угловых сегментов прямоугольника.
Перечисление 8-11 показывает фрагмент кода, создающий и рисующий путь со скругленным прямоугольником.
Перечисление 8-11 , Получающее скругленный прямоугольник
void DrawRoundedRect(NSRect rect, CGFloat x, CGFloat y) |
{ |
NSBezierPath* thePath = [NSBezierPath bezierPath]; |
[thePath appendBezierPathWithRoundedRect:rect xRadius:x yRadius:y]; |
[thePath stroke]; |
} |
Добавление овалов и кругов
Для рисования овалов и кругов используйте следующие методы NSBezierPath
:
Оба метода наносят овальную внутреннюю часть прямоугольник, который Вы указываете. Необходимо тогда заполнить или перечеркнуть объект контуров для рисования овала в текущем контексте. Следующий пример создает овал из указанного прямоугольника и перечеркивает его путь.
void DrawOvalInRect(NSRect ovalRect) |
{ |
NSBezierPath* thePath = [NSBezierPath bezierPath]; |
[thePath appendBezierPathWithOvalInRect:ovalRect]; |
[thePath stroke]; |
} |
Вы могли также создать овальные дуги использования, но выполнение так копировало бы то, что предыдущие методы делают внутренне и были бы немного медленнее. Единственная причина добавить отдельные дуги состоит в том, чтобы создать частичный (незакрытый) овальный путь. Для получения дополнительной информации посмотрите Добавляющие Дуги.
Добавление дуг
Для рисования дуг используйте следующие методы NSBezierPath
:
appendBezierPathWithArcWithCenter:radius:startAngle:endAngle:
appendBezierPathWithArcWithCenter:radius:startAngle:endAngle:clockwise:
appendBezierPathWithArcFromPoint:toPoint:radius:
метод создает дуги путем нанесения их в углу, сформированном текущей точкой, и две точки передали методу. Нанесение круга этим способом может привести к дуге, не пересекающейся, любая из точек раньше указывала его. Это может также привести к созданию нежелательной строки от текущей точки до начальной точки дуги.
Рисунок 8-9 показывает три различных дуги, и контрольные точки раньше создавали их. Поскольку две дуги создали использование appendBezierPathWithArcFromPoint:toPoint:radius:
, текущая точка должна быть установлена прежде, чем вызвать метод. В обоих примерах точка установлена в (30, 30). Поскольку радиус второй дуги короче, и начальная точка дуги не является тем же как текущей точкой, линия проведена от текущей точки до начальной точки.
Перечисление 8-12 показывает фрагменты кода, которые Вы использовали бы для создания каждой из дуг от рисунка 8-9. (Несмотря на то, что данные показывают, что дуги индивидуально, выполняя следующий код представили бы дуги друг на друге.)
Перечисление 8-12 , Создающее три дуги
NSBezierPath* arcPath1 = [NSBezierPath bezierPath]; |
NSBezierPath* arcPath2 = [NSBezierPath bezierPath]; |
[[NSColor blackColor] setStroke]; |
// Create the first arc |
[arcPath1 moveToPoint:NSMakePoint(30,30)]; |
[arcPath1 appendBezierPathWithArcFromPoint:NSMakePoint(0,30) toPoint:NSMakePoint(0,60) radius:30]; |
[arcPath1 stroke]; |
// Create the second arc. |
[arcPath2 moveToPoint:NSMakePoint(30,30)]; |
[arcPath2 appendBezierPathWithArcFromPoint:NSMakePoint(30,40) toPoint:NSMakePoint(70,30) radius:20]; |
[arcPath2 stroke]; |
// Clear the old arc and do not set an initial point, which prevents a |
// line being drawn from the current point to the start of the arc. |
[arcPath2 removeAllPoints]; |
[arcPath2 appendBezierPathWithArcWithCenter:NSMakePoint(30,30) radius:30 startAngle:45 endAngle:135]; |
[arcPath2 stroke]; |
Добавление кривых Безье
Для рисования Кривых Безье необходимо использовать curveToPoint:controlPoint1:controlPoint2:
метод NSBezierPath
. Этот метод поддерживает создание кубической кривой от текущей точки до пункта назначения, который Вы указываете при вызове метода. controlPoint1
параметр определяет искривление, запускающееся с текущей точки, и controlPoint2
определяет искривление пункта назначения, как показано на рисунке 8-1.
Добавление текста
Поскольку NSBezierPath
только поддерживает находящееся на пути содержание, Вы не можете добавить текстовые символы непосредственно к пути; вместо этого, необходимо добавить глифы. Глиф является визуальным представлением символа (или неполный символ) в определенном шрифте. Для глифов в контурном шрифте это визуальное представление сохранено как ряд математических путей, которые могут быть добавлены к NSBezierPath
объект.
Для получения ряда глифов можно использовать текстовую систему Какао или NSFont
класс. Получение глифов от текстовой системы Какао обычно проще, потому что можно получить глифы для произвольной строки символов, тогда как использование NSFont
требует, чтобы Вы знали имена отдельных глифов. Для получения глифов от текстовой системы Какао необходимо сделать следующее:
Создайте текстовые системные объекты, должен был управлять текстовым расположением.
Используйте
glyphAtIndex:
илиgetGlyphs:range:
методNSLayoutManager
получать желаемые глифы.Добавьте глифы к Вашему
NSBezierPath
объект с помощью одного из следующих методов:
Когда добавлено к Вашему NSBezierPath
объект, глифы преобразовываются в серию элементов пути. Эти элементы пути просто указывают строки и кривые и не сохраняют информации о самих символах. Можно управлять путями, содержащими глифы точно так же, как Вы были бы любой другой путь путем изменения точек элемента пути или путем изменения атрибутов пути.
Рисование форм по пути
Существует две опции для рисования содержания пути: можно перечеркнуть путь или заполнить его. Перечеркивание пути представляет схему формы пути с помощью текущего цвета обводки и атрибутов пути. Заполнение пути представляет область, охваченную путем с помощью текущего цвета заливки и проветривая правило.
Рисунок 8-11 показывает тот же путь от рисунка 8-1, но с заполненным содержанием и различная штриховая примененная ширина.
Рисование прямоугольников
Какао обеспечивает несколько функций для рисования прямоугольников к текущему контексту сразу с помощью атрибутов по умолчанию. Эти функции используют Кварцевые примитивы для рисования одного или более прямоугольников быстро, но в пути, который может быть менее точным, чем если бы необходимо было использовать NSBezierPath
. Например, эти подпрограммы не применяют текущий стиль соединения к углам обрамленного прямоугольника.
Таблица 8-4 перечисляет некоторые более обычно используемые функции для рисования прямоугольников вместе с их способами поведения. Можно использовать эти функции в местах, где скорость более важна, чем точность. Синтаксис для каждой функции предоставлен в краткой нотации с типами параметра, опущенными для демонстрации соглашений о вызовах. Для полного списка доступных функций и их полного синтаксиса, посмотрите Ссылку Функций AppKit.
Функция |
Описание |
---|---|
|
Заполняет указанный прямоугольник белым. |
|
Рисует кадр прямоугольника с помощью текущего цвета заливки, ширины строки по умолчанию, и |
|
Рисует кадр прямоугольника с помощью текущего цвета заливки, указанной ширины, и |
|
Рисует кадр прямоугольника с помощью текущего цвета заливки, указанной ширины и указанной работы. |
|
Заполняет прямоугольник с помощью текущего цвета заливки и |
|
Заполняет прямоугольник с помощью текущего цвета заливки и указанной составляющей композит работы. |
|
Заполняет массив C-стиля прямоугольников с помощью текущего цвета заливки и |
|
Заполняет массив C-стиля прямоугольников с помощью соответствующего списка цветов. Каждый список должен иметь то же число записей. |
|
Заполняет массив C-стиля прямоугольников с помощью текущего цвета заливки и указанной работы составления композита. |
|
Заполняет массив C-стиля прямоугольников с помощью соответствующего списка цветов и указанной работы составления композита. Список прямоугольников и список цветов должны содержать то же число элементов. |
Работа с путями
Создание гладкого и привлекательного пользовательского интерфейса является тяжелой работой, и большинство программ использует комбинацию изображений и путей, чтобы сделать это. Пути имеют преимущество того, чтобы быть легким, масштабируемым, и быстро. Несмотря на это, пути не являются надлежащими во всех ситуациях. Следующие разделы обеспечивают некоторые основные подсказки и руководство о том, как использовать пути эффективно в Вашей программе.
Создание путей
Создание пути включает создание NSBezierPath
возразите и добавляющий элементы пути к нему. Все пути должны начать с Перемещения К элементу отмечать первую точку пути. В некоторых случаях этот элемент добавляется для Вас, но в других необходимо добавить его сами. Например, методы, создающие замкнутый путь (такой как овал или прямоугольник) вставляют элемент MoveTo для Вас.
Сингл NSBezierPath
объект может иметь многократные подпути. Каждый подпуть является самостоятельно полным путем, означая, что подпуть может не казаться связанным ни с какими другими подпутями, когда нарисовано. Заполненные подпути могут все еще взаимодействовать друг с другом, как бы то ни было. Наложение подпутей может отменить эффект заливки друг друга, приводящий к дырам в закрашенной области.
Все подпути в NSBezierPath
возразите совместно используют те же атрибуты получения. Единственный способ присвоить различные атрибуты различным путям состоит в том, чтобы создать отличающийся NSBezierPath
объекты для каждого.
Улучшение производительности рендеринга
Поскольку Вы работаете над своим кодом для прорисовки, необходимо помнить производительность. Получение является процессором интенсивное действие, но существует много способов сократить сумму рисования выполняемого Вашим приложением. Следующие разделы предлагают некоторые основные подсказки, связанные с улучшением производительности получения с приложениями Какао. Для дополнительных связанных с получением подсказок по производительности см. Инструкции по Производительности Получения.
Снова используйте свои объекты контуров
Если Вы неоднократно рисуете то же содержание, полагаете, что кэширование объектов раньше рисовало то содержание. Обычно более эффективно сохранить существующее NSBezierPath
объект, чем воссоздать его во время каждого цикла получения. Для содержания, которое могло бы измениться динамично, Вы могли бы также рассмотреть поддержание пула допускающих повторное использование объектов.
Правильность по сравнению с эффективностью
При записи кода для прорисовки необходимо всегда пытаться сделать тот код максимально эффективным, не жертвуя качеством представленного содержания. Если Ваш код для прорисовки кажется медленным, существуют некоторые компромиссы, которые можно сделать для повышения эффективности, которые сокращают качество только временно:
Используйте доступные прямоугольники обновления для рисования только, что изменилось. Используйте отличающийся
NSBezierPath
объекты для каждой части экрана, а не одного большого объекта, покрывающего все. Для получения дополнительной информации посмотрите, Сокращают Сложность Пути.Во время прокрутки живое изменение размеров или другие строго ограниченные во времени операции, рассматривает следующие опции:
Если Ваш экран содержит анимированный контент, приостановите анимацию, пока работа не завершена.
Попытка, временно увеличивающая стоимость плоскости для изогнутых контуров. Значение плоскости по умолчанию установлено в 0,6, который приводит к хорошим плавным кривым. Увеличивание этой стоимости выше 1.0 может заставить Ваши кривые выглядеть более зубчатыми, но должно улучшить производительность. Можно хотеть попробовать несколько различных значений для определения хорошего компромисса между появлением и скоростью.
Отключите сглаживание. Для получения дополнительной информации посмотрите Установку параметров сглаживания.
При рисовании прямоугольников использовать
NSFrameRect
иNSRectFill
для операций, где не требуется высшее качество. Эти функции предлагают близкие приближения тому, с чем Вы добрались быNSBezierPath
но часто немного быстрее.
Сократите сложность пути
При рисовании большой суммы содержания необходимо приложить все усилия для сокращения сложности данных пути, которые Вы храните на сингле NSBezierPath
объект. Объекты контуров с сотнями элементов пути требуют большего количества вычислений, чем те с 10 или 20 элементами. Каждый линейный сегмент или сегмент кривой, который Вы добавляете, увеличивают число вычислений, требуемых сгладить путь или определить, является ли точка в нем. Многочисленные пересечения пути также увеличивают число требуемых вычислений при заполнении пути.
Если точность представленных путей не крайне важна, попытайтесь использовать многократный NSBezierPath
объекты нарисовать то же содержание. Существует очень мало визуального различия между использованием одного объекта контуров или объектов разнообразного пути. Если Ваш путь уже сгруппирован в многократные подпути, то становится просто вставить некоторые из тех подпутей другой NSBezierPath
объекты. Используя разнообразный путь объекты сокращают количество вычислений для каждого подпути и также позволяют Вам ограничивать рендеринг только теми путями, которые находятся в текущем прямоугольнике обновления.
Управление элементами отдельного тракта
Данный NSBezierPath
объект с некоторыми существующими данными пути, можно получить точки, связанные с тем путем, и изменить их индивидуально. Программа иллюстрации могла бы сделать это в ответ на событие от нажатия мыши по одной из точек по пути. Если событие от нажатия мыши приводит к той точке, перетаскиваемой к новому расположению, можно быстро обновить элемент пути с новым расположением и перерисовать путь.
elementCount
метод NSBezierPath
возвращает общее количество элементов пути для всех подпутей объекта. Для обнаружения типа данного элемента пути используйте elementAtIndex:
или elementAtIndex:associatedPoints:
метод. Эти методы возвращают одно из значений, перечисленных в Таблице 8-1. Используйте elementAtIndex:associatedPoints:
метод, если Вы также хотите получить точки, связанные с элементом. Если Вы уже не знаете тип элемента пути, необходимо передать этот метод массив, способный к содержанию по крайней мере трех NSPoint
типы данных.
Для изменения точек, связанных с элементом пути, используйте setAssociatedPoints:atIndex:
метод. Вы не можете изменить тип элемента пути, только точки, связанные с ним. При изменении точек, NSBezierPath
берет только столько точек от Вашего массива точки, сколько необходимы. Например, при указании трех точек для Строки Для соединения каналом элемента, только первая точка используется.
Перечисление 8-13 показывает метод, обновляющий контрольную точку, связанную с элементом пути кривой на конце текущего пути. Точки, определяющие кривую, сохранены в порядке controlPoint1
, controlPoint2
, endPoint
. Этот метод заменяет точку controlPoint2
, который влияет на часть конца кривой.
Перечисление 8-13 , Изменяющее контрольную точку кривой, соединяет элемент каналом
- (void)replaceLastControlPointWithPoint:(NSPoint)newControl |
inPath:(NSBezierPath*)thePath |
{ |
int elemCount = [thePath elementCount]; |
NSBezierPathElement elemType = |
[thePath elementAtIndex:(elemCount - 1)]; |
if (elemType != NSCurveToBezierPathElement) |
return; |
// Get the current points for the curve. |
NSPoint points[3]; |
[thePath elementAtIndex:(elemCount - 1) associatedPoints:points]; |
// Replace the old control point. |
points[1] = newControl; |
// Update the points. |
[thePath setAssociatedPoints:points atIndex:(elemCount - 1)]; |
} |
Преобразование пути
Система координат NSBezierPath
возразите всегда соответствует систему координат представления, в котором она нарисована. Таким образом, учитывая путь, первая точка которого в (0, 0) в Вашем NSBezierPath
объект, таща путь в Ваших местах представления, указывающих на (0, 0) в текущей системе координат представления. Для рисования того пути в различном расположении необходимо применить преобразование одним из двух способов:
Примените преобразование к системе координат представления и затем нарисуйте путь. Для получения информации о том, как применяться, преобразовывает к представлению, посмотрите Создание и Применение Преобразования.
Примените преобразование к
NSBezierPath
сам объект с помощьюtransformUsingAffineTransform:
метод и затем рисует его в неизмененном представлении.
Оба метода заставляют путь быть нарисованным в том же расположении в представлении; однако, второй метод также имеет побочный эффект постоянного изменения NSBezierPath
объект. В зависимости от Вашего содержания это может или может не быть надлежащим. Например, в программе иллюстрации, Вы могли бы хотеть, чтобы пользователь был в состоянии перетащить формы вокруг представления; поэтому, Вы хотели бы изменить NSBezierPath
объект сохранить новую позицию пути.
Создание CGPathRef от объекта NSBezierPath
Могут быть времена, когда необходимо преобразовать NSBezierPath
возразите против a CGPathRef
тип данных так, чтобы можно было выполнить находящиеся на пути операции с помощью Кварца. Например, Вы могли бы хотеть нарисовать свой путь к Кварцевому слою прозрачности или использовать его, чтобы сделать усовершенствованное обнаружение хита. Несмотря на то, что Вы не можете использовать a NSBezierPath
возразите непосредственно от Кварца, можно использовать его элементы пути для создания a CGPathRef
объект.
Перечисление 8-14 показывает Вам, как создать a CGPathRef
тип данных от NSBezierPath
объект. Пример расширяет поведение NSBezierPath
класс с помощью категории. quartzPath
метод использует элементы пути NSBezierPath
объект вызвать надлежащие Кварцевые функции создания тракта. Несмотря на то, что метод создает непостоянное CGPathRef
объект, это возвращает неизменную копию для рисования. Гарантировать, что возвращенные возвраты пути корректные результаты во время обнаружения хита, этот метод неявно закрывает последний подпуть, если Ваш код не делает так явно. Кварц требует, чтобы пути были закрыты, чтобы сделать обнаружение хита на закрашенной области пути.
Перечисление 8-14 , создающее CGPathRef из NSBezierPath
@implementation NSBezierPath (BezierPathQuartzUtilities) |
// This method works only in OS X v10.2 and later. |
- (CGPathRef)quartzPath |
{ |
int i, numElements; |
// Need to begin a path here. |
CGPathRef immutablePath = NULL; |
// Then draw the path elements. |
numElements = [self elementCount]; |
if (numElements > 0) |
{ |
CGMutablePathRef path = CGPathCreateMutable(); |
NSPoint points[3]; |
BOOL didClosePath = YES; |
for (i = 0; i < numElements; i++) |
{ |
switch ([self elementAtIndex:i associatedPoints:points]) |
{ |
case NSMoveToBezierPathElement: |
CGPathMoveToPoint(path, NULL, points[0].x, points[0].y); |
break; |
case NSLineToBezierPathElement: |
CGPathAddLineToPoint(path, NULL, points[0].x, points[0].y); |
didClosePath = NO; |
break; |
case NSCurveToBezierPathElement: |
CGPathAddCurveToPoint(path, NULL, points[0].x, points[0].y, |
points[1].x, points[1].y, |
points[2].x, points[2].y); |
didClosePath = NO; |
break; |
case NSClosePathBezierPathElement: |
CGPathCloseSubpath(path); |
didClosePath = YES; |
break; |
} |
} |
// Be sure the path is closed or Quartz may not do valid hit detection. |
if (!didClosePath) |
CGPathCloseSubpath(path); |
immutablePath = CGPathCreateCopy(path); |
CGPathRelease(path); |
} |
return immutablePath; |
} |
@end |
Код от предыдущего примера закрывает только последний открытый контур по умолчанию. В зависимости от Ваших объектов контуров Вы могли бы также хотеть закрыть промежуточные подпути каждый раз, когда встречаются с новым Перемещением К элементу. Если Ваши объекты контуров обычно содержат только один путь, Вам не нужно для этого как бы то ни было.
Обнаружение хитов мыши на пути
Если необходимо определить, произошло ли событие от нажатия мыши на пути или его закрашенной области, можно использовать containsPoint:
метод NSBezierPath
. Этот метод тестирует точку против всех закрытых и открытых подпутей в объекте контуров. Если точка находится на или в каком-либо из подпутей, возвратов метода YES
. При определении, является ли точка в подпути, метод использует ненулевое вьющееся правило.
Если Ваше программное обеспечение работает в OS X v10.4 и позже, можно выполнить более усовершенствованное обнаружение хита с помощью CGContextPathContainsPoint
и CGPathContainsPoint
функции в Кварце. Используя эти функции можно определить, находится ли точка на самом пути или если точка в пути с помощью или ненулевого или ровно-нечетного вьющегося правила. Несмотря на то, что Вы не можете использовать эти функции на NSBezierPath
возразите непосредственно, можно преобразовать объект контуров в a CGPathRef
тип данных и затем использует их. Для получения информации о том, как преобразовать объект контуров в a CGPathRef
тип данных, посмотрите Создание CGPathRef От Объекта NSBezierPath.
Перечисление 8-15 показывает пример того, как Вы могли бы выполнить усовершенствованное обнаружение хита на NSBezierPath
объект. Этот пример добавляет метод к NSBezierPath
класс с помощью категории. Реализация метода добавляет a CGPathRef
версия текущего пути к текущему контексту и вызовам CGContextPathContainsPoint
функция. Эта функция использует указанный режим для анализа расположения указанной точки относительно текущего пути и возвращает надлежащее значение. Режимы могут включать kCGPathFill
, kCGPathEOFill
, kCGPathStroke
, kCGPathFillStroke
, или kCGPathEOFillStroke
.
Перечисление 8-15 , Обнаруживающее хиты на пути
@implementation NSBezierPath (BezierPathQuartzUtilities) |
// Note, this method works only in OS X v10.4 and later. |
- (BOOL)pathContainsPoint:(NSPoint)point forMode:(CGPathDrawingMode)mode |
{ |
CGPathRef path = [self quartzPath]; // Custom method to create a CGPath |
CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; |
CGPoint cgPoint; |
BOOL containsPoint = NO; |
cgPoint.x = point.x; |
cgPoint.y = point.y; |
// Save the graphics state before doing the hit detection. |
CGContextSaveGState(cgContext); |
CGContextAddPath(cgContext, path); |
containsPoint = CGContextPathContainsPoint(cgContext, cgPoint, mode); |
CGContextRestoreGState(cgContext); |
return containsPoint; |
} |
@end |