IFClite TypeScript API
    Preparing search index...

    Interface ClashRuleCoverage

    How many elements a rule's selectors actually matched in THIS model, before any geometry test ran. matchedB is null for a self-clash rule (no b selector). A rule with matchedA === 0 or matchedB === 0 never compared a single pair — its selector simply doesn't describe anything in this model (e.g. an MEP selector run against an infrastructure model).

    interface ClashRuleCoverage {
        candidatesExamined?: number;
        fromMembersA?: boolean;
        fromMembersB?: boolean;
        matchedA: number;
        matchedB: number | null;
        matchedKeysA?: readonly string[];
        matchedKeysB?: readonly string[] | null;
        rule: string;
    }
    Index
    candidatesExamined?: number

    Broad-phase candidate pairs the geometry kernel actually narrow-phase tested for THIS rule (RuleDetection.candidatesProcessed in engine-ts/kernel.ts), surfaced here so a caller can tell "matched elements on both sides AND compared some of them" apart from "matched elements on both sides but the broad phase found nothing worth testing". matchedA/matchedB alone cannot make that distinction — they are selector-match counts taken before any geometry runs, so they read as full coverage even when the broad phase (BVH margin query) ends up empty (#4244).

    0 here is NOT on its own evidence of a problem: two selected groups that are genuinely far apart (further than the rule's tolerance/ clearance margin) legitimately produce zero candidate pairs and a real 'clean' result — that is the ordinary, correct outcome for a rule whose matched elements never come close to touching. classifyRuleCoverage does not treat this field as a coverage signal for exactly that reason; it exists as a diagnostic a caller can inspect when a 'clean' result looks suspicious for other reasons (e.g. a much larger selector match count than expected), not as an automatic verdict. Absent on a result recorded before this field existed, or from a hand-built fixture.

    fromMembersA?: boolean

    Whether each side was resolved from explicit membership (membersA / membersB) rather than from its type selector. A caller explaining an empty side needs it and cannot recover it from rulesRun, which deliberately drops the resolved member lists. Absent on a result recorded before this existed — which is the same thing as "by selector".

    fromMembersB?: boolean
    matchedA: number
    matchedB: number | null
    matchedKeysA?: readonly string[]

    The durable key (IfcGUID / USD prim path) of every element THIS rule matched on each side, deduplicated and sorted for determinism — not just a count. compareClashRevisions (revision.ts) needs this to ask "was this SPECIFIC element re-examined?", which matchedA/matchedB (counts only) cannot answer: a narrowed selector that drops one previously- matched element while keeping the total count non-zero is invisible to a count-only check. matchedKeysB mirrors matchedB's null for a self-clash rule (no b side). Absent (not just empty) on a result recorded before this existed, or from a hand-built fixture — callers MUST treat an absent matchedKeysA as "cannot verify", never as "matched nothing".

    matchedKeysB?: readonly string[] | null
    rule: string