Auto-Ajuste de Dobradiças em Colisão com Prateleiras (JavaScript)

Auto-Ajuste de Dobradiças em Colisão com Prateleiras (JavaScript)

Versão: CV2025.4

Descrição:

Este UCS tem a função de analisar a comparação dos diversos atributos entre os componentes de dobradiças (HNG) e calços de dobradiça (S_HNGPLT) e os três tipos de prateleiras existentes: prateleiras (SH), prateleiras fixas (FS) e prateleiras ajustáveis (AS) de forma a que quando a sua posição seja coincidente, dentro de uma zona de colisão definida, seja detectada a colisão e, de forma automática, decida mover a dobradiça para cima ou para baixo conforme seja mais próximo, dentro de uma margem de segurança em relação à caixa.

Existem zonas de colisão existem em altura (Y), em profundidade (Z) e margem à estrutura que vêm como padrão 50mm cada uma. No entanto, após a ativação da movimentação automática, podemos manipular estes valores para aumentar ou diminuir a nossa fronteira de colisão.


Instalação:

Opção 1

Download e Importação do Pacote com o UCS:

UCS_AUTOAJUSTE_DOB.pkg
pkg


Opção 2

Criar um novo UCS em JavaScript e configurar da seguinte maneira para funcionar, uma vez que trabalha ao nível do módulo (CAB):


Copiar o seguinte código para dentro do UCS criado (substituir tudo):

// UCS: AUTO-AJUSTE DE DOBRADIÇAS EM COLISÃO (DOBRADIÇAS VS PRATELEIRAS)
// Versão: 06012026
// Compatibilidade: CV2025.4

// --- 1. INICIALIZAÇÃO DE PARÂMETROS E ATRIBUTOS ---
// Define se o recurso está ativo e cria os campos na aba de Atributos do Gabinete.
if (_this.Evaluate('_MOVE_HNG_AUTO') == null) {
    _this.SetParameter('_MOVE_HNG_AUTO', 0, VAL_BOOL);
    _this.ModifyParameter('_MOVE_HNG_AUTO', PARMOD_STYLE, PARSTYLE_ATTRIBUTE);
    _this.ModifyParameter('_MOVE_HNG_AUTO', PARMOD_DESC, 'Auto-Ajustar Dobradiças em Colisão?');
}

// Cláusula de saída: Se desativado, remove os parâmetros auxiliares e para a execução.
if (_this.GetParameterValue('_MOVE_HNG_AUTO') == 0) {
    _this.RemoveParameter('_MOVE_HNG_ZONA_COLISAO_Y');
    _this.RemoveParameter('_MOVE_HNG_ZONA_COLISAO_Z');
    _this.RemoveParameter('_MOVE_HNG_MARGEM_LIMITE_ESTRUTURA');
    return;
}

var INCH_TO_MM = 25.4;

// Definição das distâncias de segurança (Zonas de Colisão)
if (_this.Evaluate('_MOVE_HNG_ZONA_COLISAO_Y') == null) {
    _this.SetParameter('_MOVE_HNG_ZONA_COLISAO_Y', (50/INCH_TO_MM), VAL_MEASUREMENT);
    _this.ModifyParameter('_MOVE_HNG_ZONA_COLISAO_Y', PARMOD_STYLE, PARSTYLE_ATTRIBUTE);
    _this.ModifyParameter('_MOVE_HNG_ZONA_COLISAO_Y', PARMOD_DESC, 'Auto-Ajustar Dobradiças.a - Zona de Colisao (Y)?');
}

if (_this.Evaluate('_MOVE_HNG_ZONA_COLISAO_Z') == null) {
    _this.SetParameter('_MOVE_HNG_ZONA_COLISAO_Z', (50/INCH_TO_MM), VAL_MEASUREMENT);
    _this.ModifyParameter('_MOVE_HNG_ZONA_COLISAO_Z', PARMOD_STYLE, PARSTYLE_ATTRIBUTE);
    _this.ModifyParameter('_MOVE_HNG_ZONA_COLISAO_Z', PARMOD_DESC, 'Auto-Ajustar Dobradiças.b - Zona de Colisao (Z)?');
}

if (_this.Evaluate('_MOVE_HNG_MARGEM_LIMITE_ESTRUTURA') == null) {
    _this.SetParameter('_MOVE_HNG_MARGEM_LIMITE_ESTRUTURA', (80/INCH_TO_MM), VAL_MEASUREMENT);
    _this.ModifyParameter('_MOVE_HNG_MARGEM_LIMITE_ESTRUTURA', PARMOD_STYLE, PARSTYLE_ATTRIBUTE);
    _this.ModifyParameter('_MOVE_HNG_MARGEM_LIMITE_ESTRUTURA', PARMOD_DESC, 'Auto-Ajustar Dobradiças.c - Margem Limite Caixa?');
}

// --- 2. CONFIGURAÇÕES EM MILÍMETROS (CONVERSÃO INICIAL) ---
// Criamos variáveis locais em MM para facilitar a leitura da lógica matemática abaixo.
var CONF_ZONA_Y_MM = _this.GetParameterValue('_MOVE_HNG_ZONA_COLISAO_Y') * INCH_TO_MM;
var CONF_ZONA_Z_MM = _this.GetParameterValue('_MOVE_HNG_ZONA_COLISAO_Z') * INCH_TO_MM;
var CONF_MARGEM_MM = _this.GetParameterValue('_MOVE_HNG_MARGEM_LIMITE_ESTRUTURA') * INCH_TO_MM;
var CONF_ALTURA_MAX_MM = _cab.DY * INCH_TO_MM;

var listaHng = [];
var listaPlt = [];
var listaShelves = [];
var prefixosShelves = ["FS", "SH", "AS"]; // Fixas, Soltas e Ajustáveis

// --- 3. COLETA DE DADOS (CONVERTENDO TUDO PARA MM NO MAPEAMENTO) ---
// Esta função recursiva varre o cab
function coletarTudo(pai) {
    var filhos = pai.GetChildren();
    if (filhos == null) return;
    for (var i = 0; i < filhos.Count; i++) {
        var obj = filhos(i);
        var nomeUpr = obj.NAME.toUpperCase();
       
        // Coleta de Dobradiças
        if ((nomeUpr.indexOf("HNG") === 0 || nomeUpr.indexOf(".HNG") !== -1) && nomeUpr.indexOf("PLT") === -1) {
            listaHng.push({
                obj: obj,
                x: Number(obj.GetParameterValue("PABSX")) * INCH_TO_MM,
                y: Number(obj.GetParameterValue("PABSY")) * INCH_TO_MM,
                z: Number(obj.GetParameterValue("PABSZ")) * INCH_TO_MM
            });
        }
       
        // Coleta de Calços
        if (nomeUpr.indexOf("PLT") !== -1) {
            listaPlt.push({
                obj: obj,
                x: Number(obj.GetParameterValue("PABSX")) * INCH_TO_MM,
                y: Number(obj.GetParameterValue("PABSY")) * INCH_TO_MM,
                z: Number(obj.GetParameterValue("PABSZ")) * INCH_TO_MM
            });
        }

        // Coleta de Prateleiras baseada nos prefixos definidos
        var eShelf = false;
        for (var p = 0; p < prefixosShelves.length; p++) {
            if (nomeUpr.indexOf(prefixosShelves[p]) === 0 || nomeUpr.indexOf("." + prefixosShelves[p]) !== -1) {
                eShelf = true; break;
            }
        }
        // IsShaped() filtra prateleiras com recortes complexos que poderiam invalidar a lógica
        if (eShelf && !obj.IsShaped()) {
            listaShelves.push({
                obj: obj,
                x: Number(obj.GetParameterValue("PABSX")) * INCH_TO_MM,
                y: Number(obj.GetParameterValue("PABSY")) * INCH_TO_MM,
                z: Number(obj.GetParameterValue("PABSZ")) * INCH_TO_MM,
                dy: Number(obj.GetParameterValue("DY")) * INCH_TO_MM,
                dx: Number(obj.GetParameterValue("DX")) * INCH_TO_MM,
                dz: Number(obj.GetParameterValue("DZ")) * INCH_TO_MM
            });
        }
       
        if (obj.GetChildren().Count > 0) { coletarTudo(obj); }
    }
}
coletarTudo(_cab);

// --- 4. LÓGICA DE DETECÇÃO EM MM ---
// Triplo loop comparativo: Dobradiça vs Prateleira -> Movimento -> Calço
for (var h = 0; h < listaHng.length; h++) {
    var hng = listaHng[h];

    for (var s = 0; s < listaShelves.length; s++) {
        var shf = listaShelves[s];

        // PASSO 1: Filtro X - Verifica se a dobradiça está montada no mesmo alinhamento da prateleira (lateral)
        if (hng.x >= (shf.x - 5) && hng.x <= (shf.x + shf.dy + 5)) {
            var centroShelfY = shf.y + (shf.dz / 2); // DZ em prateleiras horizontais refere-se à profundidade
            var difY = hng.y - centroShelfY;
           
            // PASSO 2: Filtro Y - Verifica se a dobradiça está dentro da zona de colisão vertical
            if (Math.abs(difY) < CONF_ZONA_Y_MM) {
                var frentePratZ = shf.z + shf.dx;
               
                // PASSO 3: Filtro Z - Verifica se a profundidade da prateleira atinge a ferragem
                if (frentePratZ > (hng.z - CONF_ZONA_Z_MM)) {
                   
                    // Cálculo de posições de escape (Acima ou Abaixo)
                    var posSeguraAcima = centroShelfY + CONF_ZONA_Y_MM + 2;
                    var posSeguraAbaixo = centroShelfY - CONF_ZONA_Y_MM - 2;
                   
                    // Validação de limites físicos (Não sair para fora do gabinete)
                    var podeSubir = (posSeguraAcima < (CONF_ALTURA_MAX_MM - CONF_MARGEM_MM));
                    var podeDescer = (posSeguraAbaixo > CONF_MARGEM_MM);
                   
                    var novoYAbs_MM;
                    // Lógica de desvio pelo caminho mais curto
                    if (Math.abs(hng.y - posSeguraAcima) <= Math.abs(hng.y - posSeguraAbaixo)) {
                        novoYAbs_MM = podeSubir ? posSeguraAcima : posSeguraAbaixo;
                    } else {
                        novoYAbs_MM = podeDescer ? posSeguraAbaixo : posSeguraAcima;
                    }

                    // ARREDONDAMENTO: Garante que o destino seja um número inteiro em milímetros
                    novoYAbs_MM = Math.round(novoYAbs_MM);

                    // Cálculo do deslocamento necessário (Delta)
                    var deltaY_MM = novoYAbs_MM - hng.y;

                    // Aplicação do movimento se o deslocamento for superior a 0.1mm
                    if (Math.abs(deltaY_MM) > 0.1) {
                        // Converte o delta de MM para Inch para o motor do Cabinet Vision
                        var deltaY_Inch = deltaY_MM / INCH_TO_MM;

                        // Move o objeto Dobradiça
                        hng.obj.Y += deltaY_Inch;

                        // BUSCA DO CALÇO: Localiza o calço que estava na mesma posição Y original
                        var menorDistX = 999;
                        var calcoAlvo = null;
                        for (var k = 0; k < listaPlt.length; k++) {
                            var plt = listaPlt[k];
                            // Critério: Mesmo Y (tolerância 2mm) e mesmo Z
                            if (Math.abs(plt.y - hng.y) < 2 && Math.abs(plt.z - hng.z) < 50) {
                                var dX = Math.abs(plt.x - hng.x);
                                if (dX < menorDistX) {
                                    menorDistX = dX;
                                    calcoAlvo = plt;
                                }
                            }
                        }

                        // Se o calço for encontrado, move-o na mesma proporção
                        if (calcoAlvo != null) {
                            calcoAlvo.obj.Y += deltaY_Inch;
                            calcoAlvo.y += deltaY_MM; // Atualiza cache para próxima prateleira no loop
                        }
                       
                        // Atualiza cache da dobradiça para o caso de múltiplas colisões na mesma peça
                        hng.y += deltaY_MM;
                    }
                }
            }
        }
    }
}