Эта статья написана, чтобы собрать воедино разрозненную информацию про цвета в AutoCAD .NET API. А также немного рассказать о практическом применении, помимо изменения цвета.
В AutoCAD существует несколько типов цветов:
- Индексные (ACI) – задаются индексами, присвоенными по внутренней системе AutoCAD. Сюда относятся и специальные цвета «ПОСЛОЮ» и «ПОБЛОКУ»;
- RGB – задаются тремя основными цветами от 0 до 255: красным, зеленым и синим;
- Цвета из альбомов цветов – по сути, это цвет из RGB, который был занесен в альбом и которому было присвоено имя.
- Печатный цвет (Pen color) – используется при печати и зависит от настроек устройства вывода. В данной статье обсуждаться почти не будет.
В .NET API цвета представлены двумя похожими классами:
- Color – описывает, сам цвет и содержит свойство ColorNameForDisplay, в котором содержится локализованное название, которое видит пользователь. Объекты этого класса можно присваивать объектам, наследующих Entity.
- EntityColor – описывает цвет, примененный к объекту, а так же подробности не относящиеся к цвету напрямую, вроде состояния. Объекты этого класса можно только получать из объектов, наследующих Entity, или из объектов класса Color.
Оба объекта могут определить, является ли цвет индексным, RGB, или печатным. Но определить, взят ли цвет из альбома цветов возможно только через класс Color. Разным типам соответствуют следующие свойства:
- Индексные (ACI) – «IsByAci», а также «IsByLayer» и «IsByBlock». Задаются свойством ColorIndex;
- RGB – «IsByColor». Задаются тремя свойствами Red, Green и Blue;
- Печатные цвета (Pen color) – IsByPen. Задаются свойством PenIndex;
- Цвета из альбомов цветов – только в классе Color: HasColorName и HasBookName. Задаются как RGB-цвета, но имеют непустые ColorName и BookName.
Так же тип объекта можно определить по перечисления ColorMethod, которое доступно что в Color, что в EntityColor.
Следует разъяснить некоторые детали о индексных цветах. Сам индекс представлен типом short, однако всего индексных цветов 255. Значения 0 и 256 отвечают за «IsByBlock» и «IsByLayer» соответственно. Иные значения приводят к ошибкам.
Следует отметить, что у индексных цветов свойства Red, Green и Blue равны нулю, и для получения RGB-значения этих цветов придется провести несколько дополнительных действий.
Получение RGB-значения из индексного цвета
Для того чтобы понять, как получить RGB-значение из индексного цвета, сначала нужно понять, что такое TrueColor.
TrueColor – закодированное в 32-битное число 24-битное представление RGB, в котором каждому цвету отводится по 8 бит. В .NET API TrueColor можно получить из EntityColor двумя способами:
- Через свойство TrueColor;
- Через статический метод класса EntityColor.LookUpRgb(byte index).
Про второй способ следует отметить, что он принимает индекс цвета, но из-за того, что индекс задается типом short, приходится вручную производить типизацию до byte.
Однако, таким образом мы получаем три закодированных цвета. Чтобы их раскодировать легче всего использовать битовые маски. Далее приведен пример реализации такого декодирования.
byte colorByte = (byte)color.ColorIndex;
int rgb = EntityColor.LookUpRgb(colorByte);
byte blue = (byte)(rgb & 0xffL);
byte green = (byte)((rgb & 0xff00L) >> 8);
byte red = (byte)(rgb >> 16);
Фильтры по цветам
Цвета можно использовать для фильтрации объектов с помощью DXF-кодов через SelectionFilter. Но есть несколько нюансов:
Всего есть 3 стандартных DXF-кода, относящихся к цветам:
- 62 – индекс цвета в виде целого числа (short), есть у любого объекта с Color и EntityColor. Может иметь значение, обозначающее «ByBlock» (0) или «ByLayer» (256).
- 420 – 32-битное число, закодированное в формате TrueColor. Несет в себе полезную информацию только при использовании RGB-цвета.
- 430 – название цвета (если оно есть) в виде строки.
Можно осуществлять фильтрацию только по 62 коду, однако при этом легко может возникнуть ситуация, когда у RGB-цвета совпал индекс и была произведена неверная фильтрация. Чтобы это учесть можно использовать логические операторы «<OR OR>» для фильтрации по нескольким условиям.
Код 430 может использоваться для отделения альбомных цветов, даже если они полностью совпадают с одним из RGB-цветов, используемых в документе.
Так же стоит отметить, что TrueColor, получаемый из EntityColor.LookUpRGB или напрямую из EntityColor.TrueColor, может возвращать неверное значение для некоторых цветов, в связи с чем может быть необходимо самостоятельно закодировать RGB в TrueColor. Для этого можно использовать битовый сдвиг, собрать шестнадцатеричную строку, или любой другой удобный метод. Далее приведен пример реализации такого кодирования.
long redL = 15;
long greenL = 100;
long blueL = 26;
long trueColor = (redL << 16) | (greenL << 8) | blueL;