SOLIBRI SDK · JAVA

Eigene Solibri-Regeln

Eigene Prüfregeln, die Solibri nicht eingebaut hat - entwickelt mit dem Solibri Java SDK (Maven).

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-Filterwelche Bauteile ein Set bilden
Konnektivitäts-Toleranzmax. Spalt, der als „verbunden" gilt
Gruppierung nach EigenschaftMeldung 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.
Set-Connectivity-Prüfung

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-Filterwas enthält was
PrüfmodusGesamt · je Seite · gegenüber · alle Seiten
Min/Max-Anzahlzulässiger Bereich
Aktive Flächen & Zonewelche 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-BauteileWände / Decken, welche die Öffnungen tragen
Öffnungsbauteiledie zu prüfende Aussparungsgeometrie
Toleranzmax. 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 Bauteiledas durchdrungene Bauteil
Durchdringende Bauteiledas eindringende Bauteil
PrüfmodusRestdistanz · Penetrationstiefe
Min / Max Distanzzulä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.
Penetrationstiefen-Prüfung

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 Bauteiledas Elternbauteil, das die Prüfung eingrenzt (z. B. Decke)
Innere Bauteile Aerster Satz innerer Teile (z. B. Schrauben)
Innere Bauteile Bzweiter Satz (z. B. Bewehrung); kann gleich A sein
Min / Max Distanzzulä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.
Interne Bauteilabstands-PrüfungInterne Bauteilabstands-Prüfung