[Из песочницы] Сохранение цвета элемента в БД 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.

image

После этого берем наш плагин, выкачиваем им данные из таблицы TK_Item, и смотрим, что там в таблице?

(Благо, в плагине для отладочных целей был предусмотрен такой вариант — выкачать данные и показать на форме.)

Там, оказывается, стоит -65536.

image

Повторяем процедуру несколько раз и сводим результаты в текстовый файл.

Сначала меня сильно удивили цифры в таблице, а особенно — наличие положительных и отрицательных значений.

Поэкспериментировав со значениями компонент 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);

© Habrahabr.ru