Предыстория задачи
Возникла у заказчика задача, допустим, такая:
- Скинуть в 1С элементы модели здания.
- В 1С использовать эти части модели в договорах – ну, допустим, указать, что вот такие-то элементы уже построены, такие-то – только запланированы, и т.п..
- В Navisworks на чертеже как-то увидеть это – например, отобразив элементы модели разными цветами. Для этого сделали к Navisworks плагин, который умеет копировать в 1С данные из таблиц Quantification (Takeoff tables), а также забирать их из 1С обратно и запихивать в Takeoff tables.
А в 1С предполагалось у используемых в договоре элементов модели (помещений) менять цвета.
Только вот оказалось, что после изменения этих табличных данных в 1С – Navisworks не понимает, что они изменились, и надо бы их обновить. Стало быть, мне, программисту, надо ему это подсказать.
Итак, задача для программиста
После обмена с 1С изменились данные в таблице TK_Item – в частности, поле Color. Необходимо привести цвета на отображаемом чертеже в соответствие с указанными в таблице.
Ищем, как это сделать. Копаем описание. Находим функцию –
public void OverridePermanentColor(IEnumerable<ModelItem> 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.
Повторяем процедуру несколько раз и сводим результаты в текстовый файл.
Название | Цвет | Значение цвета в таблице | Двоичное представление цвета в таблице |
---|---|---|---|
Стены Тип 1.1 выше отм. 0,000 | Red | -65536 | 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 0000 |
Стены Тип 1.2 выше отм. 0,000 | Green | -16711936 | 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 1111 1111 0000 0000 |
Стены Тип 2.1 выше отм. 0,000 | Blue | -16776961 | 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0000 0000 0000 0000 1111 1111 |
Стены Тип 0.1 ниже отм. 0,000 | Red=16 | -15728640 | 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0000 0000 0000 0000 0000 |
Стены Тип 0.2 ниже отм. 0,000 | Red=17 | -15663104 | 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 0001 0001 0000 0000 0000 0000 |
Стяжки на отм. 0,000 | Red=193 Green=32 Blue=74 | 12 656 714 | 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 1100 0001 0010 0000 0100 1010 |
Сначала меня сильно удивили цифры в таблице, а особенно – наличие положительных и отрицательных значений.
Поэкспериментировав со значениями компонент 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);