Set-Connectivity-PrüfungF&E · in Arbeit
Problem
Im Modulbau werden Bauteile zu „Sets" gruppiert. Ein Set ist nur gültig, wenn seine Mitglieder tatsächlich verbunden sind - Lücken stören Montage und QS. Solibri bot keine eingebaute Prüfung der Konnektivität innerhalb eines Sets.
Ansatz
Eine eigene Java-Regel (Solibri SDK), die je Set einen Adjazenzgraphen der Mitglieder bildet und nicht verbundene Mitglieder markiert. Kandidaten werden über Bounding-Box-Schnitt gefunden und anschließend verfeinert.
Parameter
| Set-Filter | welche Bauteile ein Set bilden |
| Konnektivitäts-Toleranz | max. Spalt, der als „verbunden" gilt |
| Gruppierung nach Eigenschaft | Meldung je Eigenschaftswert |
Ergebnis
Nicht verbundene Mitglieder werden im Modell hervorgehoben. Aktuell in aktiver Entwicklung: Adjazenz nutzt AABB-Boxen statt exakter Geometrie - die nächste Iteration nutzt präzisen geometrischen Kontakt.
Wie der Code funktioniert
/** Two components "touch" when their real geometry is within tolerance. */
private boolean areTouching(Component a, Component b, double tolerance) {
// Broad phase: the AABB gap is a lower bound on the true distance -
// if even the bounding boxes are too far apart, skip the costly test.
if (bboxDistance(a, b) > tolerance) {
return false;
}
// Narrow phase: precise surface-to-surface distance between the solids.
Optional<Double> distance = a.distance(b);
if (distance.isPresent()) {
return distance.get() <= tolerance;
}
return true; // no geometry - trust the AABB proximity already established
}
- Broad phaseDer Bounding-Box-Abstand ist eine untere Schranke für den echten Abstand - weit entfernte Paare werden günstig verworfen, bevor teure Geometrie-Berechnungen laufen.
- Narrow phasea.distance(b) ist der echte Oberflächenabstand der beiden Körper. Genau das entfernt die falschen 'Brücken', die eine große Bounding-Box sonst erzeugt.
- BFS-ClusteringBerührende Paare bilden einen Adjazenzgraphen; eine Breitensuche gruppiert die Elemente in verbundene Cluster. Ein Set mit mehr als einem Cluster ist getrennt - jeder nicht-größte Cluster wird gemeldet.

Bauteil-Anzahl-Prüfung
Problem
Baugruppen benötigen eine bestimmte Anzahl von Unterbauteilen - Verbinder je Seite, Winkel je Element. Das manuelle Prüfen im Modell ist langsam und fehleranfällig.
Ansatz
Eine eigene Java-Regel, die je Elternbauteil die Kindbauteile findet, deren Schwerpunkt innerhalb des Elternteils liegt, und sie zählt - gesamt oder je Fläche (je Seite / gegenüberliegend / alle Seiten).
Parameter
| Eltern-/Kind-Filter | was enthält was |
| Prüfmodus | Gesamt · je Seite · gegenüber · alle Seiten |
| Min/Max-Anzahl | zulässiger Bereich |
| Aktive Flächen & Zone | welche Flächen, Band je Fläche |
Ergebnis
Bauteile mit zu wenigen oder zu vielen Kindern werden markiert, mit seitenbezogenen Meldungen (z. B. „zu wenige Bauteile auf Seite +X").
Wie der Code funktioniert
// Spatial pre-filter by bounding box, then keep only children whose
// centroid actually falls inside the parent's bounding box.
ComponentFilter spatialFilter = AABBIntersectionFilter
.ofComponentBounds(parent)
.and(childFilter);
Collection<Component> candidates = SMC.getModel().getComponents(spatialFilter);
List<Component> children = new ArrayList<>();
for (Component candidate : candidates) {
if (!candidate.equals(parent) && isCentroidInsideParent(candidate, parent)) {
children.add(candidate);
}
}
- Broad-Phase-FilterAABBIntersectionFilter.ofComponentBounds(parent) fragt Solibri nur nach Komponenten in der Nähe der Eltern-Bounding-Box, statt das ganze Modell zu durchsuchen.
- Schwerpunkt-TestisCentroidInsideParent behält ein Kind nur, wenn sein Mittelpunkt in der Eltern-Box liegt - zuverlässiger als getIntersections() für eingebettete Teile (z. B. Bewehrung).
- Dann zählenDie bereinigte Kinderliste speist die vier Modi - Total, Pro Seite, Gegenüber, Alle Seiten - die je Flächenzone der Bounding-Box zählen.
Öffnungsgeometrie-Prüfung
Problem
Öffnungen (Aussparungen) in Wänden und Decken müssen das Bauteil sauber durchdringen. Eine Öffnung, die die gegenüberliegende Fläche nicht erreicht („unvollständig") oder darüber hinausragt („herausragend"), stört die weitere Bearbeitung - TGA-Durchbrüche, Türen und Fenster passen nicht mehr. Per Auge im Modell ist das kaum zuverlässig zu finden.
Ansatz
Die Regel ordnet jede Öffnung/Aussparung ihrem Host (Wand oder Decke) zu und prüft die Öffnungsgeometrie gegen den Host: Sie verifiziert, dass die Aussparung die volle Bauteildicke innerhalb einer Toleranz durchläuft, und markiert Öffnungen, die die Gegenfläche nicht erreichen oder herausragen. Host- und Öffnungsbauteile werden über Elementtyp-Filter ausgewählt.
Parameter
| Host-Bauteile | Wände / Decken, welche die Öffnungen tragen |
| Öffnungsbauteile | die zu prüfende Aussparungsgeometrie |
| Toleranz | max. zulässiger Spalt / Überstand an den Bauteilflächen |
Ergebnis
Unvollständige und herausragende Öffnungen werden mit präziser Meldung und Spaltmaß hervorgehoben - z. B. „Opening '(B) Objekt-2.49' does not reach the far face (X-max) of '(B) Wand-2.6'. Gap: 218 mm."
Wie der Code funktioniert
// Thickness axis = the thinnest span of the host's bounding box
// (Z for a slab, X or Y for a wall).
int thicknessAxis = findThinnestAxis(hostBox);
double hostMin = getAxisMin(hostBox, thicknessAxis);
double hostMax = getAxisMax(hostBox, thicknessAxis);
double openMin = getAxisMin(openingBox, thicknessAxis);
double openMax = getAxisMax(openingBox, thicknessAxis);
// A valid opening reaches BOTH faces within tolerance.
boolean reachesNearFace = openMin <= hostMin + tolerance;
boolean reachesFarFace = openMax >= hostMax - tolerance;
if (reachesNearFace && reachesFarFace) {
return null; // full penetration - OK
}
// else: report the gap to the face it falls short of
double shortfallFar = reachesFarFace ? 0 : (hostMax - openMax);
- VorfilterAABBIntersectionFilter.ofComponentBounds(host) fragt Solibri nur nach Öffnungen nahe der Host-Bounding-Box; getIntersections(host) bestätigt anschließend die echte geometrische Überlappung, bevor gemessen wird - dasselbe Broad/Narrow-Prinzip wie bei den anderen Regeln.
- DickenachseDie dünnste Bounding-Box-Achse des Hosts gilt als seine Dicke - Z bei Decken, X oder Y bei Wänden - so braucht die Prüfung keinen Hinweis auf die Bauteilausrichtung.
- Zwei PrüfungenVolle Durchdringung heißt nur: openMin ≤ Nahfläche und openMax ≥ Fernfläche auf dieser Achse. Ein zweiter Durchlauf über alle drei Achsen findet den umgekehrten Fehler - eine Öffnung, die über den Host hinausragt - mit denselben Min/Max-Vergleichen.
Penetrationstiefen-Prüfung
Problem
Die Standard-Schnittprüfung von Solibri (SOL/234) übersieht durchdringende Bauteile mit sehr kleinem Volumen oder Querschnitt - eine Lücke, die die Solibri-Community seit Jahren meldet. Anker, Bewehrung und kleine Verbinder, die nicht tief genug in ihren Host reichen (oder zu weit hindurchragen), rutschen unbemerkt durch die Koordination.
Ansatz
Für jedes umschließende Bauteil sammelt die Regel die durchdringenden Bauteile, bestätigt eine echte Geometrie-Überschneidung und misst entlang der Durchdringungsachse. Sie meldet entweder die Penetrationstiefe (wie weit das Bauteil eingedrungen ist) oder die Restdistanz (von der Spitze des Bauteils bis zur Gegenfläche) und prüft diesen Wert gegen einen zulässigen Min/Max-Bereich.
Parameter
| Umschließende Bauteile | das durchdrungene Bauteil |
| Durchdringende Bauteile | das eindringende Bauteil |
| Prüfmodus | Restdistanz · Penetrationstiefe |
| Min / Max Distanz | zulässiger Bereich für den Messwert |
Ergebnis
Durchdringungen, deren Tiefe (oder Restdistanz) außerhalb des Bereichs liegt, werden mit Achse und Messwert gemeldet - z. B. „Component '(B) Anchor-12' penetrates '(B) Wand-2.6' along Z axis. Penetration depth: 12 mm (minimum required: 30 mm)."
Hintergrund Solibri Community - „Components inside component“ ↗
Wie der Code funktioniert
// Per axis: is the penetrating part partly in, partly out? If so, measure
// how far it entered (depth) and how far its tip is from the far face.
// Case 1 - enters from the min side:
if (penMin < encMin && penMax > encMin && penMax < encMax) {
depth = penMax - encMin; // how far it has entered
remaining = encMax - penMax; // tip -> far boundary
}
// Case 2 - enters from the max side:
else if (penMax > encMax && penMin < encMax && penMin > encMin) {
depth = encMax - penMin;
remaining = penMin - encMin;
}
// Keep the axis with the LARGEST depth, then range-check the chosen value.
double measured = depthMode ? depth : remaining;
if (measured < min - EPSILON || measured > max + EPSILON) { /* report */ }
- Echte ÜberschneidungVor dem Messen bestätigt getIntersections(enclosing), dass sich die Bauteile wirklich berühren - reine Bounding-Box-Überlappung erzeugt Fehlmeldungen bei Formen wie L-Profilen, deren Box in Nachbarn ragt, die die Geometrie nie berührt.
- Zwei EintrittsfälleEin Bauteil kann von beiden Seiten der umschließenden Box eindringen; jede der drei Achsen wird auf beide Fälle geprüft und liefert die Eindringtiefe sowie die Restdistanz der Spitze zur Gegenfläche.
- Tiefe vs. RestdistanzDieselbe Geometrie speist beide Modi - Penetrationstiefe (wie weit hinein) und Restdistanz (wie weit noch) - und genau die Bereichsprüfung des gewählten Werts findet die winzigen Durchdringungen, die Solibris Standardprüfung übersieht.

Interne Bauteilabstands-Prüfung
Problem
Abstandsprüfungen zwischen kleinen inneren Bauteilen - Schrauben, Bewehrung - sind nur innerhalb desselben Hosts sinnvoll. Die globale Abstandsprüfung von Solibri (SOL/222) vergleicht Bauteile über das ganze Modell, sodass zwei Schrauben in zwei verschiedenen, benachbarten Decken gegeneinander gemessen werden, obwohl sie zu getrennten Bauteilen gehören. Der Abstand muss je Elternbauteil bewertet werden, nicht global.
Ansatz
Für jedes umschließende Bauteil (z. B. eine Decke) sammelt die Regel die inneren Bauteile von Satz A (z. B. Schrauben) und Satz B (z. B. Bewehrung), deren Bounding-Box darin liegt. Für jedes A wird das nächste B im selben Elternbauteil gesucht - über den echten Flächen-zu-Flächen-Abstand der Bounding-Boxen - und Paare außerhalb des zulässigen Min/Max-Bereichs werden gemeldet.
Parameter
| Umschließende Bauteile | das Elternbauteil, das die Prüfung eingrenzt (z. B. Decke) |
| Innere Bauteile A | erster Satz innerer Teile (z. B. Schrauben) |
| Innere Bauteile B | zweiter Satz (z. B. Bewehrung); kann gleich A sein |
| Min / Max Distanz | zulässiger Abstandsbereich |
Ergebnis
Paare außerhalb des Bereichs werden gemeldet und auf ihren Host bezogen - z. B. „Inside '(B) Slab-3': distance between '(B) Bolt-7' and '(B) Bolt-9' is 42 mm (minimum required: 60 mm)." Teile in benachbarten Decken werden nie verglichen.
Wie der Code funktioniert
// Scope the search to THIS enclosing component: only inner parts whose
// bounding box sits inside it (this is what a global check does not do).
ComponentFilter innerA = AABBIntersectionFilter.ofComponentBounds(enclosing).and(filterA);
ComponentFilter innerB = AABBIntersectionFilter.ofComponentBounds(enclosing).and(filterB);
// For each A, keep its nearest B within the same parent:
for (Component a : model.getComponents(innerA)) {
Component nearestB = null;
double nearest = Double.MAX_VALUE;
for (Component b : model.getComponents(innerB)) {
if (b.equals(a) || b.equals(enclosing)) continue;
double d = aabbDistance(a.getBoundingBox(), b.getBoundingBox());
if (d < nearest) { nearest = d; nearestB = b; }
}
// report when the nearest distance is outside [min, max]
if (nearest < min - EPSILON || nearest > max + EPSILON) { /* report */ }
}
- Auf den Host begrenztBeide inneren Sätze werden mit AABBIntersectionFilter.ofComponentBounds(enclosing) gesammelt, sodass nur Teile innerhalb dieses umschließenden Bauteils betrachtet werden - genau das ist der Unterschied zu einem modellweiten Vergleich wie SOL/222.
- Nächster NachbarFür jedes A behält die Regel das einzige nächste B; die Meldung nennt beide Teile und ihren Host, sodass eine Abstandsverletzung direkt auf das betroffene Paar zeigt.
- Flächen-zu-Flächen-AbstandaabbDistance summiert die achsenweisen Lücken zwischen den beiden Bounding-Boxen (0 bei Überlappung) und liefert so den echten Abstand der Teile statt eines Wertes von Mittelpunkt zu Mittelpunkt.

