[Из песочницы] Сохранение цвета элемента в БД Navisworks
Предыстория задачи
Возникла у заказчика задача, допустим, такая:
- Скинуть в 1С элементы модели здания.
- В 1С использовать эти части модели в договорах — ну, допустим, указать, что вот такие-то элементы уже построены, такие-то — только запланированы, и т.п…
- В Navisworks на чертеже как-то увидеть это — например, отобразив элементы модели разными цветами. Для этого сделали к Navisworks плагин, который умеет копировать в 1С данные из таблиц Quantification (Takeoff tables), а также забирать их из 1С обратно и запихивать в Takeoff tables.
А в 1С предполагалось у используемых в договоре элементов модели (помещений) менять цвета.
Только вот оказалось, что после изменения этих табличных данных в 1С — Navisworks не понимает, что они изменились, и надо бы их обновить. Стало быть, мне, программисту, надо ему это подсказать.
Итак, задача для программиста
После обмена с 1С изменились данные в таблице TK_Item — в частности, поле Color. Необходимо привести цвета на отображаемом чертеже в соответствие с указанными в таблице.
Ищем, как это сделать. Копаем описание. Находим функцию —
public void OverridePermanentColor(IEnumerable items, Color color)
Ну, как найти соответствующие выбранному элементу TK_Item элементы модели — это другая история, в другой раз расскажу, если будет интересно. Но кому надо — и сам разберется. А вот с цветом все оказалось интереснее.
Во-первых, указанный в параметрах функции Color — это не System.Drawing.Color, а вовсе даже Autodesk.Navisworks.Api.Color, со своим блекджеком и … ну, вы поняли. Ну, пускай, зато у него есть вот такой конструктор:
public static unsafe Color FromByteRGB(byte red, byte green, byte blue)
Стало быть, без проблем сделаем такой Color, какой Автодесковскому API нужен.
(Собственно, первым делом я это и попробовать — найти элементы, соответствующие выбранному Item’у, выбрать цвет — и установить им это цвет.)
Но. В таблице-то у нас в поле Color стоит одно значение типа Int64. И как его сопоставить с объектом типа Color — непонятно.
Причем ни в документации, ни на форуме, ни в примерах мне не удалось найти, как это пишется в БД.
ОК, будем копать экспериментальным путем.
Берем Navisworks, открываем Quantification, меняем у какого-нибудь элемента цвет. Скажем, на честный беспримесный Red.
После этого берем наш плагин, выкачиваем им данные из таблицы TK_Item, и смотрим, что там в таблице?
(Благо, в плагине для отладочных целей был предусмотрен такой вариант — выкачать данные и показать на форме.)
Там, оказывается, стоит -65536.
Повторяем процедуру несколько раз и сводим результаты в текстовый файл.
Сначала меня сильно удивили цифры в таблице, а особенно — наличие положительных и отрицательных значений.
Поэкспериментировав со значениями компонент R, G, B, я сообразил, что эти три компоненты отображаются последними тремя байтами числа.
Но тогда странно — почему старшие байты оказываются заполнены не нулями, а единицами?
Впрочем, если предположить, что их всегда заполняют единицами — то получает объяснение наличие отрицательных чисел. Просто заполняют и старший байт, определяющий знак числа.
Но ведь там не всегда отрицательные числа!
И вот только вспомнив, как работают функции >> и <<, я сообразил, что они могут тупо заполнять цифрами старшие биты, в том числе знаковый бит. А поскольку старшие биты не нужны – то и неважно, что там стоит.
Тогда вопрос –, а нафига им потребовалось такое большое значение для цвета? Аж 64 бита? Посмотрел структуру таблиц, в которых хранятся эти данные — там просто для всех целых чисел используется Int64. Действительно, чего мелочиться?
Итог
Значение цвета, записываемого в таблице, получаем так:
Int64 dbColor = Rb<<16 + Gb<<8 + Bb;
Обратное преобразование — табличного цвета в используемый для элементов модели цвет — делаем так:
byte R = (byte)(dbColorValue >> 16 % 256);
byte G = (byte)(dbColorValue >> 8 % 256);
byte B = (byte) (dbColorValue % 256);
var color = Autodesk.Navisworks.Api.Color.FromByteRGB(R, G, B);