diff --git a/data-pipeline/scripts/extract-manifest.mjs b/data-pipeline/scripts/extract-manifest.mjs index 9a75b6d..05bb084 100644 --- a/data-pipeline/scripts/extract-manifest.mjs +++ b/data-pipeline/scripts/extract-manifest.mjs @@ -245,6 +245,19 @@ function stripLeaderLineComponentsUnsafe(mesh) { // Malha inteira é UM pedaço só conectado — nada pra separar/remover. if (facesByRoot.size <= 1) continue; + // Uma linha de chamada de verdade no app original é um segmento bem + // simples (poucos vértices) — bem menor que qualquer pedaço real de + // pele/estrutura. Sem esse limite de tamanho, uma faixa real só + // COMPRIDA (ex: a pele bem em cima da coluna, entre as costas + // esquerda e direita) também passa no teste de "reto e fino" e acaba + // sendo apagada por engano, abrindo um buraco de verdade na malha + // (foi exatamente o que aconteceu e o usuário reportou). Limitamos a + // remoção a pedaços pequenos em termos absolutos E relativos ao resto + // da malha. + const totalVerts = posAccessor.getCount(); + const MAX_LEADER_LINE_VERTS = 40; + const MAX_LEADER_LINE_SHARE = 0.15; + const keptFaces = []; let removedAny = false; for (const faceList of facesByRoot.values()) { @@ -254,7 +267,9 @@ function stripLeaderLineComponentsUnsafe(mesh) { vertSet.add(indices[f * 3 + 1]); vertSet.add(indices[f * 3 + 2]); } - if (isLeaderLinePointCloud([...vertSet].map(at))) { + const smallEnough = + vertSet.size <= MAX_LEADER_LINE_VERTS && vertSet.size <= totalVerts * MAX_LEADER_LINE_SHARE; + if (smallEnough && isLeaderLinePointCloud([...vertSet].map(at))) { removedAny = true; } else { keptFaces.push(...faceList);