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 - извлечение элементов заданного типа, находящихся в контакте с каждым элементом набора
Смежность стен и помещений
- areAdjacent - являются ли два элемента смежными (имеют общую грань)
- isElementInteriorAdjacentToSpace - является ли элемент внутренним смежным элементом пространства
- getElementInteriorAdjacentToSpace - все элементы, смежные заданному пространству
- testElementInternalAdjacent - является ли стена внутренне смежной с пространством
- getElementsInternalAdjacentToElement - элементы, внутренне смежные с пространством
- testElementExternalAdjacentToSpace - является ли стена смежной с пространством снаружи
- getElementSpaceExternalWallElements - наружные стены, смежные с пространством
- testElementBetweenTwoElements - находится ли элемент между двумя элементами
Внутренние и наружные элементы
- testElementGeometricallyInternal - является ли элемент геометрически внутренним
- testElementGeometricallyExternal - является ли элемент геометрически наружным
- isGeometricallyInternalWallElement - является ли стена внутренней по отношению к помещениям
Этажи и наличие элементов
- getFloorsWithMissingElements - этажи, на которых нет переданных элементов
- checkExistenceElementFromIfcQl - есть ли элементы, соответствующие запросу IFCQL
- bimutils.getElementAdjacentElementsWithGap(GeometryElement geometryElement, double gap) →
Set<GeometryElement>- элементы той же модели, габаритный бокс которых пересекается с боксом элемента, расширенным наgap(единицы габаритов элемента)
Пример использования:
def conditionSpace = bim.createCondition("class", "eq", "IfcSpace")
def elementSpaces = bim.getGeometryElements(conditionSpace)
for (def space : elementSpaces) {
def contactedElements = bimutils.getElementAdjacentElementsWithGap(space, 0.05)
// contactedElements : Использовать по своему усмотрению и в зависимости от потребностей
}
- 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)
}
- 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)
- 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 : Использовать по своему усмотрению и в зависимости от потребностей
}
- 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)
}
- bimutils.isElementInteriorAdjacentToSpace(GeometryElement element, GeometryElement space, Map<UUID, GeometryObject> geometryObjectMap, double gap) →
boolean-true, если элемент находится внутри пространства (с допускомgap, м) и имеет с ним общую грань. Обратите внимание: допуск - последний аргумент
Пример использования:
def inside = bimutils.isElementInteriorAdjacentToSpace(column, space, meshes, 0.05)
- bimutils.getElementInteriorAdjacentToSpace(double tolerance, GeometryElement space, Collection<GeometryElement> allElements, Map<UUID, GeometryObject> geometryObjectMap) →
List<GeometryElement>- элементы изallElements, смежные с пространством (проверка как в areAdjacent); само пространство в результат не попадает
Пример использования:
def adjacent = bimutils.getElementInteriorAdjacentToSpace(0.05, space, walls, meshes)
- bimutils.testElementInternalAdjacent(GeometryElement wallElement, GeometryElement spaceElement, Map<UUID, GeometryObject> geometryObjectMap, double tolerance) →
boolean-true, если стена касается пространства (по сеткам или габаритам с допускомtolerance, м) и находится внутри него
Пример использования:
if (bimutils.testElementInternalAdjacent(wall, space, meshes, 0.05)) {
// перегородка внутри помещения
}
- 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)
- bimutils.testElementExternalAdjacentToSpace(double tolerance, GeometryElement wallElement, GeometryElement spaceElement, Map<UUID, GeometryObject> geometryObjectMap) →
boolean-true, если стена касается пространства с допускомtolerance(м), но не находится внутри него
Пример использования:
def isBoundary = bimutils.testElementExternalAdjacentToSpace(0.05, wall, space, meshes)
- 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())
}
- 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)
- 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)
- 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)
- 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)
- 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) }
- bimutils.checkExistenceElementFromIfcQl(String ifcQlString) →
boolean- есть ли в проекте элементы, соответствующие выражению IFCQL - bimutils.checkExistenceElementFromIfcQl(LogicGroup lg) →
boolean- то же для условия, созданного черезbim.createConditionили ifcql
Пример использования:
if (!bimutils.checkExistenceElementFromIfcQl('entity = "IfcSpace"')) {
console.warn("В модели нет помещений")
}

