Постобработка IFC без Revit, часть 2: площади ТЭП, дубли и правки, которые можно переслать

Хабр, привет! Это Кирилл, с коллегой Анастасией @nobimnolife делаем IDS Core. Сейчас усиленно взялись за постобработку и немного расскажем о новых инструментах.
В прошлой статье мы рассказывали, как научились править IFC прямо в браузере: заполнять параметры, менять класс и этаж, удалять лишнее — и при этом не ломать файл. После публикации просмотрщиком начали пользоваться не только мы, и вопросы пошли другие. Уже не «как поменять тип данных», а «почему у нас не сходится общая площадь», «что делать с дублями из отчёта» и «как передать правки коллеге, чтобы он не делал всё заново».
Ниже — что мы на эти вопросы сделали и что выяснили по дороге. Почти в каждой истории оказалось, что очевидное решение не работает.
Площадь не сходится, а какая зона виновата — непонятно
Ситуация знакомая всем, кто сдаёт модели на АГР. Проверка при подаче возвращает XML с показателями ТЭП, и общая площадь в нём не совпадает с вашей. Разница — двадцать квадратных метров. В Revit всё правильно, спецификация сходится, а итог в XML другой. Где искать — непонятно: зон в модели десятки, а XML содержит только итоговые суммы, без разбивки.
Сначала мы думали, что расхождение — в округлении или в том, какие зоны попадают в подсчёт. Взяли три реальных объекта, на которых XML расходился с моделью, и посчитали площадь каждой зоны двумя способами: по атрибуту RUS_Area, который записывается из системной площади (и перед выгрузкой забывает обновляться), и по геометрии — то есть по тому телу, которое реально лежит в IFC.
Результат оказался однозначным. На всех трёх объектах сумма площадей по геометрии совпала с XML с точностью до сотых. Проверка считает не по атрибуту, а по телу зоны. А на одном из объектов всё расхождение — 20,63 м² — дали ровно две зоны: у одной геометрия была меньше RUS_Area на 14,67 м², у другой на 5,96. Остальные сходились идеально.

Почему так бывает: контур зоны в Revit может быть построен с ошибкой, которую Revit прощает, а экспорт — нет. Вырожденный сегмент в несколько десятых миллиметра, отверстие, которое не сшилось, зона, «вытекшая» за стену. В Revit площадь считается по-своему и выходит правильной, а в IFC уходит другое тело. Или же, если Вы используете свой параметр площади зоны/помещения - можете забыть обновить значения после перепланировки или вычитания шахт из зоны.
Отсюда и инструмент. Открываете модель, загружаете XML — и видите по каждой зоне три числа: RUS_Area, площадь геометрии и разницу. Зоны сгруппированы по корпусам, секциям и этажам. Виноватые подсвечены в 3D красным, клик — и камера подлетает к зоне. Клик по этажу — он остаётся один, вид сверху, и видно, где зоны не покрывают план.
Площадь геометрии мы считаем как проекцию верхних граней тела на план. Это быстро: модель на 24 МБ с двумя тысячами элементов открывается за 4,7 секунды, а таблица считается за 0,2.
С благоустройством — наоборот
Тут нас ждал сюрприз. Для газонов и площадок мы ожидали того же: XML совпадёт с геометрией. Не совпал. На объекте, где всё было правильно, площадь газонов в XML — 2076,69, ровно сумма RUS_Area, а по геометрии — 2076,10.
Разница в полметра — это дуги. Газоны с криволинейными краями в IFC разбиты на отрезки, и площадь многоугольника чуть меньше площади фигуры с настоящей дугой. Похоже, для благоустройства проверка берёт атрибут, а не тело. Так что в БиО мы мелкие расхождения с геометрией ошибкой не считаем, а смотрим на другое.
Частая причина, по которой площадь благоустройства не бьётся, — несколько газонов, нарисованных одним эскизом перекрытия. В Revit это один элемент, у него одна площадь, а участков на плане три. Такие элементы мы ищем по связности поверхности: если верхние грани распадаются на несколько отдельных кусков — это несколько участков в одном элементе.
Отчёт, который можно отдать
Таблицу на экране хорошо смотреть, но исправлять всё равно в Revit, и часто — другому человеку. Поэтому отчёт выгружается в Excel: на первом листе сводка — итоги рядом с XML, суммы по корпусам и секциям, список «что исправить»; на втором — каждая зона с ElementId, по которому её находят в Revit через «Выбрать по коду». Ошибки подсвечены, у шапки фильтр.
Excel мы собираем сами, без библиотек: xlsx — это zip-архив с несколькими XML внутри. Минимальный набор — шесть файлов, стили и два листа.
Маленькая деталь, которую мы не сразу заметили: у зон из Revit нет атрибута Tag, где обычно лежит ElementId. Номер зоны есть только в конце её имени — «Площадь:609202». Без этого в первой версии отчёта колонка ElementId у зон была пустой.
Дубли: проверка видит, а глазами не найти
Второй частый вопрос — дубли. Проверка находит две одинаковые стены одна в другой, двойные импосты, лестничный марш в двух экземплярах. В 3D их не видно: элементы совпадают. Найти в Revit можно, но долго, а иногда модель уже выгружена и отправлена.
Мы сделали два пути. Можно загрузить отчёт проверки (тот самый report-result.zip), и пары найдутся в модели по GlobalId. А можно найти дубли самому, ещё до отправки.
Для самопроверки нужно было решить, что считать дублем. Первая мысль — элементы одного класса с одинаковой геометрией: совпадают габарит, объём и площадь поверхности. Сделали, проверили на модели с заведомым дублем — копией стены — и не нашли ни одной пары.
Причина нашлась быстро и оказалась поучительной. У оригинальной стены были окна и двери, а у копии нет. Revit вырезает проёмы только в одной стене из двух — в той, где стоят окна. Объёмы разошлись на 2,3 %, а мы требовали совпадения в 1 %. При этом в отчётах проверки такие пары идут с совпадением 100 %.
Так что главный признак дубля — не объём, а габарит: два элемента одного класса, чьи границы совпадают в пределах 5 мм. Объём мы оставили мягкой отсечкой — не меньше 70 %, чтобы не путать, например, стену и её тонкую облицовку с тем же габаритом. Помещения и зоны считаются дублем, только если это одна и та же зона: «СПП в ГНС» и «Общая площадь» на этаже без стен вполне могут совпасть по контуру, и это не ошибка.

Удалить дубль — полдела. Важно удалить правильный. Из двух стен у одной могут быть заполнены все параметры АГР, а у другой — ничего. Поэтому у каждой пары мы показываем, у кого больше заполненных параметров, и чем параметры отличаются. Есть и кнопка «удалить лишние во всех парах» — она оставляет в каждой паре элемент с бОльшим числом заполненных параметров. Любое удаление отменяется.
Отчёт проверки мы читаем из report.html. Раньше данные лежали прямо в HTML-таблицах, теперь — в JSON внутри скрипта страницы. Этот JSON приходится вырезать вручную, считая фигурные скобки и пропуская те, что внутри строк, — регулярным выражением его не взять.
Сравнение двух версий
Ещё одна задача, которую раньше решали глазами: пришла новая выгрузка — что в ней поменялось?
Элементы двух версий мы сопоставляем по GlobalId: Revit сохраняет его между выгрузками. Дальше для каждой пары сравниваем геометрию (габарит, объём, площадь) и параметры — класс, имя, тип, все наборы свойств. Добавленное подсвечивается зелёным, удалённое красным, изменённая геометрия оранжевым, параметры фиолетовым. По каждому элементу видно «было → стало».
Для сравнения пригодился режим «Рядом»: экран пополам, слева старая версия, справа новая. Сделан он просто: сцена рисуется дважды одной камерой в две половины холста, и перед каждой отрисовкой прячется «чужая» модель. Поэтому вращение и масштаб всегда совпадают, а клик выбирает элемент в той половине, где нажали.
Библиотека помнит старый класс
На сравнении всплыла история, которая на самом деле касалась смены класса из прошлой статьи. Пользователь написал: «меняю класс элемента с ошибкой IDS, а он не меняется». Мы проверили — меняется, в сохранённом файле класс новый. Но просмотрщик показывал старый, и проверка IDS считала элемент прежним классом.
Оказалось, web-ifc хранит тип каждой записи отдельно от её содержимого. Когда мы переписываем запись с новым классом, содержимое меняется, а тип в этом отдельном хранилище — нет. И функция «какого класса эта запись» продолжает отвечать по-старому. Пришлось запоминать переписанные классы самим и подменять ответ библиотеки — сразу для всех, кто её спрашивает: свойств, проверки, сравнения.
Правки, которые можно переслать
Последний вопрос оказался самым практичным. Человек исправил модель в браузере — заполнил параметры, удалил дубли, поменял классы. Теперь модель нужно передать коллеге или сделать то же самое на следующей выгрузке. Пересылать IFC на сотни мегабайт неудобно, а повторять правки руками — долго и с ошибками.
Мы сделали журнал правок. Каждая правка записывается не как изменённые строки файла, а как действие: «заполнить параметр RUS_Name значением „Стена“ у этих элементов», «сменить класс на IfcCovering», «удалить». Элементы указаны по GlobalId. Журнал сохраняется в маленький .json. Коллега открывает тот же исходный IFC, перетаскивает файл — и все правки применяются по очереди. Поэтому лучше хранить его где-нибудь рядом, на общем диске, чтобы у всех был доступ к нему.

Журнал правок: действия с GlobalId элементов ложатся на тот же IFC у коллеги
Почему действия, а не строки: номера записей в IFC — внутренние, при следующей выгрузке они другие. GlobalId же у элемента остаётся. Поэтому журнал ложится не только на тот же файл, но и на новую выгрузку той же модели — к элементам с теми же GlobalId.
Проверяли так: четыре правки подряд — параметр зданию, параметр 146 стенам, смена класса, удаление, — сохранили журнал, открыли тот же IFC с нуля и применили. Все четыре сработали, результат совпал.
И тут же нашли собственную ошибку. При удалении журнал пытался прочитать GlobalId элемента уже после того, как элемент удалён, — и падал. Хуже того: сама правка к этому моменту прошла, а в стек отмены не попала. Получалась модель, изменённая без возможности отменить. Исправили простым правилом: всё, что нужно для журнала, собирается до правки, а не после.
Чаще всего мы его используем, когда в исходной модели появляются критические изменения, которые мы не можем воспроизвести в постобработке – например, перепланировка, изменение большого участка здания. Конечно, лучше все поправить в проприетарном формате, чтобы при выгрузке не обнаружить новых проблем, но когда сталкиваешься с проблемами, которые не решаются в Revit – поправить тут это спасение. А для того, чтобы ничего не забыть, появилась идея этой кнопки.
По мелочи
Оси. Координационные оси в IFC — это IfcGrid, у которого нет тела, и web-ifc его не рисует. Пришлось строить самим: разобрать размещение сетки, перевести координаты так же, как библиотека переводит остальную геометрию, и нарисовать оси пунктиром с марками. Revit пишет оси не ломаной, а IfcIndexedPolyCurve, и выгружает сетку на каждый этаж — одинаковые оси мы показываем один раз. А первая версия поставила оси в километрах от модели: геометрию библиотека переводит из миллиметров в метры, а наши оси — нет.
Линейка. Два клика по модели — расстояние, в подсказке горизонталь и перепад высоты. Рядом с вершиной точка прилипает к ней.
Архивы. .ifczip и обычный .zip с IFC внутри открываются как модель. Zip мы разбираем сами — через встроенный в браузер DecompressionStream, без библиотек. Тут же поймали неочевидное: архиваторы под Windows иногда пишут пути через обратную косую черту, папка\файл.ifc. Python такое молча исправляет, а наш разбор поначалу — нет.
Здание и участок. У IfcBuilding и IfcSite нет геометрии, кликом по модели их не выбрать, а параметры им нужны: адрес, наименование проекта, ФНО. Теперь под каждой моделью есть кнопки «Здание», «Участок», «Проект».
Готовые IDS для АГР. Общие требования, БиО, ПС и классификация МССК подключаются одной кнопкой — искать файлы каждый раз не нужно.
Что в итоге
Порядок работы у нас сейчас такой. Перед отправкой модели — проверка по IDS, поиск дублей и сверка площадей. Если проверка при подаче всё же что-то нашла — открываем отчёт и XML в браузере, находим виноватые элементы и либо правим IFC тут же, либо выгружаем таблицу с ElementId и правим в Revit. Правки сохраняем журналом, чтобы следующая выгрузка не потеряла их.
Все эти обновления мы сделали на основе трудностей, с которыми сталкиваются специалисты при разработке ЦИМ АГР. Если у Вас есть какая-то проблема, с которой Вы постоянно сталкиваетесь – добро пожаловать в комментарии или личку, чтобы мы смогли попробовать помочь с этим.
Также расскажите – как вы укрощаете зоны и боретесь с дублями?
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.