BIMIT
Разработка плагинов

bimutils

Интерфейс вспомогательных геометрических расчётов над элементами модели: поиск соседних и контактирующих элементов, проверки смежности стен и помещений, определение внутренних и наружных элементов, поиск этажей без элементов. Доступен во всех типах плагинов, в том числе внутри form().

Многие методы принимают карту сеток Map<UUID, GeometryObject> geometryObjectMap - её получают одним запросом через bim.getGeometryObjectsMap(...), и в ней должны быть все участвующие в проверке элементы.

Единицы допуска (gap / tolerance) у методов разные:
  • мм (точная проверка по сеткам): getElementConnectedElements с GeometryObject и пакетная форма с двумя наборами, getConnectedElementsByClassName;
  • единицы габаритов GeometryElement.bounds (единицы модели), сравниваются только габаритные боксы: getElementAdjacentElementsWithGap, getElementConnectedElementsByClassName;
  • м (для сеток внутри пересчитываются в мм): areAdjacent, isElementInteriorAdjacentToSpace, getElementInteriorAdjacentToSpace, testElementInternalAdjacent, getElementsInternalAdjacentToElement, testElementExternalAdjacentToSpace, getElementSpaceExternalWallElements;
  • в остальных методах одно значение используется и для габаритов, и для сеток - задавайте небольшой допуск и проверяйте результат на модели.

Соседние и контактирующие элементы

  • getElementAdjacentElementsWithGap - извлечение элементов, соседствующих с заданным элементом
  • getElementConnectedElements - извлечение всех элементов, которые находятся в контакте с данным элементом среди множества элементов
  • getElementConnectedElementsByClassName - извлечение элементов заданного типа, находящихся в контакте с данным элементом
  • getConnectedElementsByClassName - извлечение элементов заданного типа, находящихся в контакте с каждым элементом набора

Смежность стен и помещений

Внутренние и наружные элементы

Этажи и наличие элементов

getElementAdjacentElementsWithGap - извлечение элементов, соседствующих с заданным элементом
  • bimutils.getElementAdjacentElementsWithGap(GeometryElement geometryElement, double gap) → Set<GeometryElement> - элементы той же модели, габаритный бокс которых пересекается с боксом элемента, расширенным на gap (единицы габаритов элемента)
Метод на каждый вызов загружает все элементы модели - это медленно. Для обработки в цикле выберите кандидатов заранее и используйте getElementConnectedElements.

Пример использования:

def conditionSpace = bim.createCondition("class", "eq", "IfcSpace")
def elementSpaces = bim.getGeometryElements(conditionSpace)
for (def space : elementSpaces) {
    def contactedElements = bimutils.getElementAdjacentElementsWithGap(space, 0.05)
    // contactedElements : Использовать по своему усмотрению и в зависимости от потребностей
}
getElementConnectedElements - извлечение всех элементов, которые находятся в контакте с данным элементом среди множества элементов
  • bimutils.getElementConnectedElements(GeometryElement geometryElement, Set<GeometryElement> elements, double gap) → Set<GeometryElement> - кандидаты из elements сначала отбираются по габаритам с запасом gap, затем по сеткам: пересекаются или находятся на расстоянии не больше gap (мм). Если сетку самого элемента получить не удалось, возвращается результат отбора по габаритам
  • bimutils.getElementConnectedElements(GeometryObject geoObject, Set<GeometryObject> geometryObjects, double gap) → Set<UUID> - идентификаторы сеток из geometryObjects, пересекающихся с geoObject с зазором gap (мм); сетки не загружаются, передаются готовые
  • bimutils.getElementConnectedElements(double gap, Set<GeometryElement> geometryElements, Set<GeometryElement> elementCandidates) → Map<GeometryElement, Set<GeometryElement>> - пакетная форма: для каждого элемента из geometryElements - контактирующие с ним элементы из elementCandidates (зазор gap в мм, сетки загружаются одним запросом). Элементы без контактов в карту не попадают

Пример использования:

def spaces = bim.getGeometryElements(bim.createCondition("class", "eq", "IfcSpace"))
def windows = bim.getGeometryElements(bim.createCondition("class", "eq", "IfcWindow"))
def spaceWindows = bimutils.getElementConnectedElements(200.0, spaces, windows)
spaceWindows.each { space, connected ->
    console.info(space.name + ": окон " + connected.size())
}

// по готовым сеткам
def windowObjects = bim.getGeometryObjects(bim.createCondition("class", "eq", "IfcWindow"))
def spaceObjects = bim.getGeometryObjects(bim.createCondition("class", "eq", "IfcSpace"))
for (def spaceObject : spaceObjects) {
    def connectedUuids = bimutils.getElementConnectedElements(spaceObject, windowObjects, 200.0)
}
getElementConnectedElementsByClassName - извлечение элементов заданного типа, находящихся в контакте с данным элементом
  • bimutils.getElementConnectedElementsByClassName(GeometryElement geometryElement, Set<GeometryElement> elements, Set<String> classNames, double gap) → Set<GeometryElement> - из elements берутся элементы указанных IFC-классов, габаритный бокс которых пересекается с боксом geometryElement, расширенным на gap (единицы габаритов). Если classNames пустой, метод работает как getElementConnectedElements

Пример использования:

def classNames = ["IfcWindow", "IfcDoor"] as Set
def connected = bimutils.getElementConnectedElementsByClassName(wall, candidates, classNames, 0.05)
getConnectedElementsByClassName - извлечение элементов заданного типа, находящихся в контакте с каждым элементом набора
  • bimutils.getConnectedElementsByClassName(Set<GeometryElement> geometryElements, Set<String> classNames, double gap) → Map<GeometryElement, Set<GeometryElement>> - сам загружает элементы указанных IFC-классов из моделей переданных элементов и для каждого элемента набора находит контактирующие с ним по сеткам (зазор gap в мм). Элементы без контактов в карту не попадают

Пример использования:

def conditionWall = bim.createCondition("class", "eq", "IfcWall")
def elementWall = bim.getGeometryElements(conditionWall)
def classNames = ["IfcSpace", "IfcSlab"] as Set
def contacted = bimutils.getConnectedElementsByClassName(elementWall, classNames, 5)
for (def wall : contacted.keySet()) {
    def contactedElements = contacted.get(wall)
    // contactedElements : Использовать по своему усмотрению и в зависимости от потребностей
}
areAdjacent - являются ли два элемента смежными (имеют общую грань)
  • bimutils.areAdjacent(double tolerance, GeometryElement a, GeometryElement b, Map<UUID, GeometryObject> geometryObjectMap) → boolean - проверка общей грани: сначала по габаритным боксам, затем по сеткам из карты (если сетки элемента в карте нет - false). tolerance в метрах

Пример использования:

def meshes = bim.getGeometryObjectsMap([wall.uuid, space.uuid])
if (bimutils.areAdjacent(0.05, wall, space, meshes)) {
    console.info(wall.name + " примыкает к " + space.name)
}
isElementInteriorAdjacentToSpace - является ли элемент внутренним смежным элементом пространства
  • bimutils.isElementInteriorAdjacentToSpace(GeometryElement element, GeometryElement space, Map<UUID, GeometryObject> geometryObjectMap, double gap) → boolean - true, если элемент находится внутри пространства (с допуском gap, м) и имеет с ним общую грань. Обратите внимание: допуск - последний аргумент

Пример использования:

def inside = bimutils.isElementInteriorAdjacentToSpace(column, space, meshes, 0.05)
getElementInteriorAdjacentToSpace - все элементы, смежные заданному пространству
  • bimutils.getElementInteriorAdjacentToSpace(double tolerance, GeometryElement space, Collection<GeometryElement> allElements, Map<UUID, GeometryObject> geometryObjectMap) → List<GeometryElement> - элементы из allElements, смежные с пространством (проверка как в areAdjacent); само пространство в результат не попадает
Вложенность элемента в пространство этот метод не проверяет. Если нужны только элементы внутри пространства - используйте isElementInteriorAdjacentToSpace.

Пример использования:

def adjacent = bimutils.getElementInteriorAdjacentToSpace(0.05, space, walls, meshes)
testElementInternalAdjacent - является ли стена внутренне смежной с пространством
  • bimutils.testElementInternalAdjacent(GeometryElement wallElement, GeometryElement spaceElement, Map<UUID, GeometryObject> geometryObjectMap, double tolerance) → boolean - true, если стена касается пространства (по сеткам или габаритам с допуском tolerance, м) и находится внутри него

Пример использования:

if (bimutils.testElementInternalAdjacent(wall, space, meshes, 0.05)) {
    // перегородка внутри помещения
}
getElementsInternalAdjacentToElement - элементы, внутренне смежные с пространством
  • bimutils.getElementsInternalAdjacentToElement(double gap, GeometryElement spaceElement, Set<GeometryElement> innerCandidates, Map<UUID, GeometryObject> geometryObjectMap) → Set<GeometryElement> - элементы из innerCandidates, для которых выполняется testElementInternalAdjacent

Пример использования:

def innerWalls = bimutils.getElementsInternalAdjacentToElement(0.05, space, walls, meshes)
testElementExternalAdjacentToSpace - является ли стена смежной с пространством снаружи
  • bimutils.testElementExternalAdjacentToSpace(double tolerance, GeometryElement wallElement, GeometryElement spaceElement, Map<UUID, GeometryObject> geometryObjectMap) → boolean - true, если стена касается пространства с допуском tolerance (м), но не находится внутри него

Пример использования:

def isBoundary = bimutils.testElementExternalAdjacentToSpace(0.05, wall, space, meshes)
getElementSpaceExternalWallElements - наружные стены, смежные с пространством
  • bimutils.getElementSpaceExternalWallElements(double gap, GeometryElement spaceElement, Set<GeometryElement> wallElements, Map<UUID, GeometryObject> geometryObjectMap) → Set<GeometryElement> - стены из wallElements, для которых выполняется testElementExternalAdjacentToSpace

Пример использования:

def spaces = bim.getGeometryElements(bim.createCondition("class", "eq", "IfcSpace"))
def walls = bim.getGeometryElements(bim.createCondition("class", "eq", "IfcWall"))
def meshes = bim.getGeometryObjectsMap(spaces*.uuid + walls*.uuid)
for (def space : spaces) {
    def boundaryWalls = bimutils.getElementSpaceExternalWallElements(0.05, space, walls, meshes)
    console.info(space.name + ": стен по контуру " + boundaryWalls.size())
}
testElementBetweenTwoElements - находится ли элемент между двумя элементами
  • bimutils.testElementBetweenTwoElements(GeometryObject middleElement, GeometryObject element1, GeometryObject element2, double tolerance) → boolean - true, если middleElement касается обоих элементов (с допуском tolerance), не находится внутри ни одного из них и расположен между ними. Например, проверка, есть ли пространство между двумя стенами

Пример использования:

def between = bimutils.testElementBetweenTwoElements(meshes[space.uuid], meshes[wall1.uuid], meshes[wall2.uuid], tolerance)
testElementGeometricallyInternal - является ли элемент геометрически внутренним
  • bimutils.testElementGeometricallyInternal(GeometryElement geometryElement, Set<GeometryElement> spaceElements, Set<GeometryElement> openingElements, Map<UUID, GeometryObject> geometryObjectMap, double tolerance) → boolean - true, если хотя бы один проём из openingElements касается двух и более помещений из spaceElements; иначе элемент проверяется геометрически относительно помещений своего этажа
Проверка проёмов не связывает их с элементом: передавайте в openingElements только проёмы (двери, окна) самого проверяемого элемента. На каждый вызов метод запрашивает список этажей проекта.

Пример использования:

def internal = bimutils.testElementGeometricallyInternal(wall, spaces, wallOpenings, meshes, 0.05)
testElementGeometricallyExternal - является ли элемент геометрически наружным
  • bimutils.testElementGeometricallyExternal(double tolerance, GeometryElement geometryElement, Set<GeometryElement> spaceElements, Set<GeometryElement> openingElements, Map<UUID, GeometryObject> geometryObjectMap) → boolean - true, если каждый проём из openingElements касается ровно одного помещения; иначе элемент проверяется геометрически относительно помещений своего этажа
При пустом наборе openingElements метод всегда возвращает true. Передавайте проёмы самого проверяемого элемента; для стен без проёмов используйте isGeometricallyInternalWallElement. На каждый вызов метод запрашивает список этажей проекта.

Пример использования:

def external = bimutils.testElementGeometricallyExternal(0.05, wall, spaces, wallOpenings, meshes)
isGeometricallyInternalWallElement - является ли стена внутренней по отношению к помещениям
  • bimutils.isGeometricallyInternalWallElement(GeometryElement geometryElement, GeometryObject objectElement, Set<GeometryElement> spaceElements, double tolerance) → boolean - true, если стена пересекается не менее чем с двумя помещениями и либо целиком лежит в габаритах одного из них, либо примыкает к двум помещениям противоположными гранями. Стена, пересекающая одно помещение или ни одного, - false. objectElement - сетка этой же стены

Пример использования:

def internal = bimutils.isGeometricallyInternalWallElement(wall, meshes[wall.uuid], spaces, 0.05)
getFloorsWithMissingElements - этажи, на которых нет переданных элементов
  • bimutils.getFloorsWithMissingElements(String modelOption, String floorOption, Set<GeometryElement> elements) → Set<GeometryElement> - этажи выбранных моделей, на которых нет ни одного элемента из elements. modelOption и floorOption - значения полей формы с выбором моделей и этажей (строки вида ["АР","КР"]); пустой floorOption - все этажи выбранных моделей
  • bimutils.getFloorsWithMissingElements(Set<String> modelNames, Set<String> floorNames, Set<GeometryElement> elements) → Set<GeometryElement> - то же по наборам имён моделей и этажей. Если не заданы модели или этажи, проверяются все этажи проекта (с фильтром по floorNames, если он задан)
  • bimutils.getFloorsWithMissingElements(Set<GeometryElement> floorElements, Set<GeometryElement> elements) → Set<GeometryElement> - из переданных этажей (элементов IfcBuildingStorey) те, к которым не относится ни один элемент из elements

Результат - элементы этажей IfcBuildingStorey.

Пример использования:

def doors = bim.getGeometryElements(bim.createCondition("class", "eq", "IfcDoor"))
def emptyFloors = bimutils.getFloorsWithMissingElements(["АР"] as Set, ["Этаж 1", "Этаж 2"] as Set, doors)
emptyFloors.each { console.warn("Нет дверей: " + it.name) }
checkExistenceElementFromIfcQl - есть ли элементы, соответствующие запросу IFCQL
  • bimutils.checkExistenceElementFromIfcQl(String ifcQlString) → boolean - есть ли в проекте элементы, соответствующие выражению IFCQL
  • bimutils.checkExistenceElementFromIfcQl(LogicGroup lg) → boolean - то же для условия, созданного через bim.createCondition или ifcql

Пример использования:

if (!bimutils.checkExistenceElementFromIfcQl('entity = "IfcSpace"')) {
    console.warn("В модели нет помещений")
}
Copyright © 2026