Partilhar: WhatsApp
aulify · Sebenta
UC · Unidade de Competência · UC02915

Sebenta · Desenvolver algoritmos e rotinas de otimização para desenho automático (UC02915)

Do fluxograma à rotina em VBA, com otimização, exportação e importação entre CAD e ficheiros externos
25h · 2.25 pontos crédito Curso: T. Desenho e Projeto/Desig ↗ Referencial oficial SNQ
Índice

Introdução

Um técnico de desenho e projeto/design industrial passa boa parte do tempo a repetir operações: desenhar a mesma família de furos em dezenas de flanges, gerar a mesma vista em série, preencher a mesma lista de materiais peça a peça. Esta sebenta ensina a deixar de fazer isso à mão e a construir rotinas que o próprio software de CAD executa por nós, escritas sobretudo em VBA (Visual Basic for Applications), a linguagem de automação mais comum nos CAD do mercado (também referimos as macros e o AutoLISP de alguns ambientes CAD, como alternativas com a mesma lógica).

O percurso segue a ordem em que um técnico enfrenta o problema na prática: primeiro analisar se vale a pena automatizar e desenhar a lógica num fluxograma; depois dominar os tipos de variáveis, as operações e os ciclos que qualquer rotina usa; a seguir otimizar (por exemplo, o corte de material) e ligar o VBA ao CAD e ao Excel; por fim, montar rotinas de desenho automático, inquirir dados de modelos 2D e 3D, e exportar e importar informação entre o CAD e ficheiros externos, sempre com as normas de segurança presentes.

Objetivos de aprendizagem (referencial): analisar os requisitos e especificações do desenho a automatizar; preparar e executar algoritmos e rotinas de otimização; e transferir informações entre sistemas CAD e outros documentos.

Todo o código desta sebenta foi corrido de facto: os números que aparecem (poupanças, contagens, custos) são resultados reais de execução, não estimativas. Sempre que um exemplo depende da interface do CAD (que só existe dentro do próprio software), isso está identificado como referência, e a lógica de cálculo por trás dele foi isolada e testada à parte, em Python.

1. Analisar requisitos e avaliar a viabilidade de automatizar

Antes de escrever uma única linha de rotina, um técnico faz duas perguntas: o que o desenho tem de ter, e vale a pena automatizá-lo?

Requisitos e especificações

Sem esta distinção, a rotina automatiza depressa uma coisa errada. É por isso que a primeira realização do referencial desta UC é analisar os requisitos e especificações do desenho a automatizar, antes de "preparar e executar".

Exemplo resolvido: vale a pena automatizar esta tarefa?

O critério é comparar o tempo poupado ao longo de um ano com o custo de desenvolver a rotina, que só se paga uma vez:

def vale_a_pena_automatizar(frequencia_semana, tempo_manual_min, tempo_dev_min, semanas=52):
    """
    Decide se compensa desenvolver uma rotina para uma tarefa de desenho repetitiva.

    Otimiza: tempo total humano gasto num ano.
    Restrição: o tempo de desenvolvimento da rotina é um custo fixo, pago uma
    só vez; o tempo manual poupado escala com o número de ocorrências.
    Caso limite: sem ocorrências (frequência ou tempo manual a 0), nunca compensa.
    Como se sabe que é melhor: compara-se o tempo manual acumulado num ano
    contra o custo de desenvolver a rotina; só compensa se a poupança for positiva.
    """
    if frequencia_semana <= 0 or tempo_manual_min <= 0:
        return False, 0.0, 0, "sem ocorrências, nada para automatizar"
    ocorrencias = round(frequencia_semana * semanas)
    tempo_manual_total = ocorrencias * tempo_manual_min
    poupanca = tempo_manual_total - tempo_dev_min
    compensa = poupanca > 0
    motivo = "poupa tempo ao longo do ano" if compensa else "o desenvolvimento custa mais do que poupa"
    return compensa, poupanca, ocorrencias, motivo

Corrido com quatro casos:

Caso Frequência/semana Tempo à mão Tempo a programar Compensa? Poupança
Furos em série 3 8 min 90 min Sim 1158 min/ano
Tarefa rara (~1×/ano) 1/52 15 min 90 min Não −75 min
Tarefa que nunca acontece 0 10 min 90 min Não 0 min
Tarefa demorada e frequente 10 20 min 120 min Sim 10 280 min/ano

Estes quatro resultados vieram de correr mesmo a função, não de uma estimativa: é a prova de que o mesmo critério (poupança acumulada versus custo de desenvolvimento) muda de conclusão consoante a frequência real da tarefa.

Uma oficina de mobiliário técnico desenha, em média, 3 estantes por semana com o mesmo padrão de furos de fixação. Cada estante demora 8 minutos a furar manualmente no CAD. Desenvolver a rotina demorou 90 minutos. Ao fim de um ano, a rotina já poupou quase 20 horas de trabalho manual repetitivo.

2. Fluxogramas e algoritmia

Um fluxograma representa a lógica de uma rotina em símbolos normalizados, antes de se escrever uma única linha de código VBA. É o critério de desempenho "garantir a estrutura e a sequência de operações a automatizar com recurso a fluxogramas", aplicado.

Símbolos normalizados

Símbolo Significado
Oval início ou fim da rotina
Retângulo uma ação (calcular, desenhar, guardar)
Losango uma decisão (verdadeiro/falso)
Seta o sentido do fluxo de execução

Exemplo resolvido: fluxograma de uma rotina de furação

(Início)
   │
   ▼
[Ler N, diâmetro, x0, y0]
   │
   ▼
<N > 0?> ──não──► (Fim, sem furos)
   │ sim
   ▼
[i = 0]
   │
   ▼
<i < N?> ──não──► (Fim)
   │ sim
   ▼
[calcular ângulo, x, y]
   │
[desenhar furo em (x, y)]
   │
[i = i + 1] ──► volta a <i < N?>

O losango logo após a leitura dos dados é o caso limite: sem ele, N = 0 tentaria desenhar um furo que não devia existir. Este fluxograma é a base literal do código do capítulo 7.

Erro comum ao desenhar fluxogramas

Esquecer a condição de paragem de um ciclo (o losango "i < N?") é o erro mais frequente: sem ela, a rotina entra num ciclo infinito e trava o CAD. Todo o ciclo tem de ter, no fluxograma, uma seta que sai do losango de decisão para o "Fim".

3. Tipos de variáveis em VBA

Em VBA (Visual Basic for Applications), cada variável guarda um tipo de dado. O critério de desempenho "adequar os diferentes tipos de variáveis dinâmicas à tipologia de rotinas" exige escolher o tipo certo para cada uso.

Tipo VBA Guarda Exemplo de uso numa rotina de desenho
Integer inteiro pequeno (−32 768 a 32 767) número de furos de uma peça
Long inteiro grande contador de um ciclo com muitas iterações
Double número real, dupla precisão uma coordenada em milímetros
String texto a referência da peça, "PC-001"
Boolean verdadeiro ou falso "a peça está conforme?"
Variant qualquer tipo, decidido em execução um valor lido de uma célula Excel
Object referência a um objeto do CAD ou do Excel ThisDrawing, Worksheet
Dim nFuros As Integer
Dim diametro As Double
Dim referencia As String
Dim conforme As Boolean
Dim oDoc As Object          ' referência a um objeto do CAD

Variáveis dinâmicas e âmbito (scope)

Uma variável dinâmica é a que muda de valor ao longo da execução (um contador, uma coordenada atual), ao contrário de uma constante fixa.

Uma referência de peça como "007" tem de ser String, nunca um tipo numérico: como número, perderia o zero à esquerda e passaria a 7. É um erro comum em rotinas que leem códigos de peça de uma folha de cálculo.

4. Operações com variáveis e ciclos de programação

Divisão real vs divisão inteira

O erro clássico ao operar variáveis numa rotina de corte é confundir divisão real com divisão inteira ao contar quantas peças cabem num comprimento disponível.

comprimento_disponivel_mm = 2500
comprimento_peca_mm = 400
kerf_mm = 3

# ERRADO como contagem de peças (divisão real):
n_pecas_errado = comprimento_disponivel_mm / (comprimento_peca_mm + kerf_mm)
print(n_pecas_errado)
# → 6.20347394540943   (uma peça "meia" não existe fisicamente)

# CORRETO: divisão inteira (piso), o operador `\` em VBA
n_pecas_certo = comprimento_disponivel_mm // (comprimento_peca_mm + kerf_mm)
sobra_mm = comprimento_disponivel_mm - n_pecas_certo * (comprimento_peca_mm + kerf_mm)
print(n_pecas_certo, sobra_mm)
# → 6 82

Executado: o resultado correto é 6 peças inteiras, com 82 mm de sobra, confirmado por assert n_pecas_certo == 6 e assert sobra_mm == 82 no código de origem. Em VBA, a divisão inteira usa-se com n = disponivel \ (peca + kerf), com uma barra invertida, diferente de /.

Ciclos: For, Do While e Do Until

' For: usa-se quando se sabe à partida quantas vezes repetir
For i = 0 To nFuros - 1
    ' desenhar furo i
Next i

' Do While: repete enquanto a condição for verdadeira
i = 0
Do While i < nFuros
    i = i + 1
Loop

' Do Until: repete até a condição se tornar verdadeira
i = 0
Do Until i = nFuros
    i = i + 1
Loop

A mesma lógica, testada em Python, gerando furos alinhados com espaçamento fixo:

def furos_em_linha(n_furos, espaco_mm, x0=0.0):
    """Caso limite: n_furos <= 0 devolve lista vazia; n_furos == 1 fica só
    em x0 (não há espaçamento a aplicar a um único ponto)."""
    if n_furos <= 0:
        return []
    return [round(x0 + i * espaco_mm, 2) for i in range(n_furos)]

Executado: furos_em_linha(5, 40, x0=10) devolve [10, 50, 90, 130, 170]; furos_em_linha(0, 40) devolve []; furos_em_linha(1, 40, x0=10) devolve [10.0]. Os três casos foram confirmados por assert no ficheiro de origem.

5. Algoritmos de otimização para desenho automático

Otimizar é escolher, de entre várias soluções válidas, a que minimiza (ou maximiza) uma medida concreta, sob uma restrição, e provar que é de facto melhor comparando com uma alternativa nos mesmos dados.

Numa rotina de corte de barras de stock:

Exemplo resolvido: cortar barras de alumínio

Uma estrutura de mobiliário técnico precisa de 6 reforços horizontais de 831 mm e 4 reforços verticais de 1597 mm, cortados de barras de stock de 2500 mm, com folga de serra (kerf) de 3 mm.

def cortar_barras(pecas_mm, barra_mm, kerf_mm=3):
    """
    Algoritmo guloso (First Fit): percorre as peças pela ordem dada e
    coloca cada uma na primeira barra aberta onde caiba; se não couber
    em nenhuma, abre uma barra nova.

    Otimiza: número de barras de stock consumidas.
    Restrição: cada peça cortada consome ainda o kerf (folga de corte).
    Caso limite: uma peça maior do que a barra é impossível de cortar,
    e tem de ser sinalizada em vez de entrar num ciclo sem fim.
    """
    barras = []
    impossiveis = []
    for p in pecas_mm:
        if p > barra_mm:
            impossiveis.append(p)
            continue
        necessario = p + kerf_mm
        colocado = False
        for i, livre in enumerate(barras):
            if necessario <= livre:
                barras[i] -= necessario
                colocado = True
                break
        if not colocado:
            barras.append(barra_mm - necessario)
    return barras, impossiveis

Corrido com a mesma lista de peças, em duas ordens diferentes de entrada:

Ordem das peças à entrada Barras usadas Stock consumido Desperdício
Ordem de produção (as 6 prateleiras chegam primeiro, depois os 4 montantes) 7 17 500 mm 6096 mm
FFD, do maior para o menor 5 12 500 mm 1096 mm

Poupança real: (7 − 5) / 7 = 28,6% menos barras, calculada a partir dos números da execução (7 e 5 barras), no sentido correto da comparação: a base é a estratégia pior (ordem de produção), e o ganho é o que a FFD poupa sobre essa base.

O ganho da FFD não vem de "cortar melhor" cada peça, vem de decidir a ordem em que as peças entram no algoritmo guloso. Peças grandes colocadas primeiro deixam menos espaço morto do que peças pequenas que enchem uma barra e obrigam a próxima peça grande a abrir barra nova.

Testar e validar o algoritmo

Antes de confiar num algoritmo de otimização, testam-se os casos limite:

assert cortar_barras([], 2500) == ([], [])                       # lista vazia
assert cortar_barras([3000], 2500) == ([], [3000])                # peça maior que a barra
b_uma, _ = cortar_barras([100], 2500)
assert b_uma == [2500 - 100 - 3]                                  # uma só peça

Os três assert correram sem falhar: lista vazia devolve zero barras sem erro, uma peça maior do que o stock é sinalizada em vez de travar a rotina, e uma peça única ocupa uma barra com o desperdício esperado.

6. Interfaces VBA com softwares de CAD e folhas de cálculo

O VBA corre dentro do software de CAD e acede aos seus objetos através de uma interface de automação (a API do CAD). É pseudocódigo de referência, porque só corre com o CAD instalado:

' VBA (referência, depende da aplicação de CAD instalada)
Sub DesenharFuroExemplo()
    Dim oDoc As Object
    Set oDoc = ThisDrawing
    Dim centro(2) As Double
    centro(0) = 50: centro(1) = 0: centro(2) = 0
    oDoc.ModelSpace.AddCircle centro, 3   ' furo Ø6 mm
End Sub

A parte que é testável sem CAD é a lógica de cálculo (as coordenadas do centro), que já vimos nos capítulos 2 e 7; a chamada AddCircle é a única linha específica da API.

Funções de interface com o Excel

' VBA (referência)
Dim oExcel As Object
Set oExcel = CreateObject("Excel.Application")
oExcel.Workbooks.Open "C:\projeto\lista_materiais.xlsx"
Dim valor As Double
valor = oExcel.Sheets(1).Cells(2, 3).Value          ' ler a célula C2
oExcel.Sheets(1).Cells(2, 4).Value = valor * 1.23   ' escrever com IVA
oExcel.Quit

A parte de cálculo (aplicar o IVA) testa-se sem Excel nem CAD:

preco_sem_iva = 14.50
preco_com_iva = round(preco_sem_iva * 1.23, 2)
print(preco_com_iva)   # → 17.84

Executado: 17.84, confirmado por assert preco_com_iva == 17.84.

7. Rotinas para o desenho automático

Uma rotina de desenho automático junta os blocos anteriores num fluxo com seis passos:

1. Ler parâmetros de entrada (N, dimensões, material)
2. Validar (caso limite: N <= 0, dimensão negativa)
3. Calcular geometria em ciclo (For / Do)
4. Desenhar cada elemento via API do CAD
5. Aplicar regras de otimização, se aplicável (capítulo 5)
6. Confirmar (contagem de elementos criados)

Exemplo resolvido: furos num círculo de fixação

Uma tarefa muito comum em peças mecânicas e de mobiliário técnico é distribuir N furos uniformemente num círculo de fixação (bolt circle).

import math

def furos_em_circulo(n_furos, diametro_mm, x0=0.0, y0=0.0, angulo_inicial=0.0):
    """
    Caso limite: n_furos <= 0 devolve lista vazia; n_furos == 1 coloca o
    único furo no ângulo inicial, sem dividir 360°.
    """
    if n_furos <= 0:
        return []
    raio = diametro_mm / 2
    passo = 360 / n_furos if n_furos > 1 else 0
    pontos = []
    for i in range(n_furos):
        ang = math.radians(angulo_inicial + i * passo)
        x = round(x0 + raio * math.cos(ang), 2) + 0.0
        y = round(y0 + raio * math.sin(ang), 2) + 0.0
        pontos.append((x, y))
    return pontos

Corrido para uma flange com 8 furos e círculo de furação Ø100 mm (furos_em_circulo(8, 100)), a rotina devolveu, entre outros pontos:

Furo x (mm) y (mm)
1 (0°) 50,0 0,0
3 (90°) 0,0 50,0
5 (180°) −50,0 0,0
7 (270°) 0,0 −50,0

Estes valores foram confirmados por cálculo trigonométrico manual (assert pontos[0] == (50.0, 0.0) e assert pontos[2] == (0.0, 50.0)), e os casos limite furos_em_circulo(0, 100) == [] e furos_em_circulo(1, 100) == [(50.0, 0.0)] também passaram.

Verificação automática de regras de desenho

Depois de desenhar, uma boa rotina verifica o resultado contra as regras do gabinete de projeto, antes de o enviar para produção. Não otimiza nenhum valor: apenas classifica cada peça como conforme ou não conforme.

def verificar_regras(pecas, espessura_min_mm=2.0, furo_min_dist_borda_mm=5.0):
    """Rotina de verificação automática de regras de desenho (design rule
    check). Corre depois de gerar o desenho automático, antes de o enviar
    para produção."""
    problemas = []
    for peca in pecas:
        nome = peca["nome"]
        if peca["espessura_mm"] < espessura_min_mm:
            problemas.append(f"{nome}: espessura {peca['espessura_mm']} mm < mínimo {espessura_min_mm} mm")
        if peca["dist_furo_borda_mm"] < furo_min_dist_borda_mm:
            problemas.append(f"{nome}: furo a {peca['dist_furo_borda_mm']} mm da borda < mínimo {furo_min_dist_borda_mm} mm")
    return problemas

Corrido com duas peças, uma conforme e outra não: verificar_regras([{"nome": "Suporte A", "espessura_mm": 3.0, "dist_furo_borda_mm": 8.0}, {"nome": "Suporte B", "espessura_mm": 1.5, "dist_furo_borda_mm": 6.0}]) devolveu exatamente um problema, "Suporte B: espessura 1.5 mm < mínimo 2.0 mm", e nenhum para o Suporte A. Os casos limite verificar_regras([]) == [] (sem peças, sem problemas) e uma peça totalmente conforme sem nenhum problema assinalado também foram confirmados.

8. Rotinas para a inquirição de dados de modelos CAD 2D e 3D

Inquirir um modelo é ler as suas propriedades geométricas (área e perímetro em 2D; volume, massa e centro de gravidade em 3D) por rotina, em vez de as medir manualmente. Aplica-se diretamente a fabrico, orçamentação e planeamento da produção.

Em VBA, o volume vem das propriedades de massa do próprio CAD (referência):

' VBA (referência, depende do CAD instalado)
Dim volume As Double
volume = oPeca.MassProperties.Volume   ' em mm3

Exemplo resolvido: orçamentar uma peça a partir do volume inquirido

DENSIDADES_KG_M3 = {"aluminio": 2700, "aco": 7850, "pla": 1240}

def orcamentar_peca(volume_cm3, material, preco_kg_eur, tempo_maquina_min, custo_hora_maquina_eur):
    if material not in DENSIDADES_KG_M3:
        raise ValueError(f"material desconhecido: {material}")
    volume_m3 = volume_cm3 / 1_000_000
    massa_kg = volume_m3 * DENSIDADES_KG_M3[material]
    custo_material = massa_kg * preco_kg_eur
    custo_maquina = (tempo_maquina_min / 60) * custo_hora_maquina_eur
    return {
        "massa_kg": round(massa_kg, 3),
        "custo_material_eur": round(custo_material, 2),
        "custo_maquina_eur": round(custo_maquina, 2),
        "custo_total_eur": round(custo_material + custo_maquina, 2),
    }

Corrido com um suporte em alumínio, volume = 145 cm³ (o valor que a rotina inquiriria do modelo 3D):

Grandeza Valor obtido
Massa 0,392 kg
Custo de material (4,80 €/kg) 1,88 €
Custo de máquina (18 min a 35 €/h) 10,50 €
Custo total 12,38 €

Confirmado por cálculo manual: 0,000145 m³ × 2700 kg/m³ = 0,3915 kg ≈ 0,392 kg (arredondado a 3 casas). Testado também o caso limite de um material inexistente no dicionário ("titanio"): a rotina levanta ValueError em vez de devolver um número inventado.

9. Exportação de informação: de CAD para documentos texto ou folhas de cálculo

Exportar é escrever, a partir do CAD, um ficheiro que outra aplicação consegue ler. O formato mais universal é o CSV (valores separados por vírgula).

import csv

def exportar_bom(pecas, caminho):
    """Exporta a lista de materiais (BOM) extraída do modelo CAD para CSV."""
    with open(caminho, "w", newline="", encoding="utf-8") as f:
        campos = ["codigo", "descricao", "quantidade", "preco_unit_eur"]
        w = csv.DictWriter(f, fieldnames=campos)
        w.writeheader()
        for p in pecas:
            w.writerow(p)

Exemplo resolvido: a BOM de uma pequena estante.

Código Descrição Quantidade Preço unit. (€)
PC-001 Painel lateral MDF 18mm 2 14,50
PC-002 Prateleira MDF 18mm 4 9,20
PC-003 Dobradiça oculta 8 1,35
PC-004 Puxador alumínio 2 3,10

Custo total = 2×14,50 + 4×9,20 + 8×1,35 + 2×3,10 = 29,00 + 36,80 + 10,80 + 6,20 = 82,80 € (calculado por custo_total() e confirmado à mão). Esta lista, exportada para CSV, é o que o departamento de compras usa para encomendar os materiais, sem reescrever nada manualmente.

10. Importação de informação: de documentos de texto e folhas de cálculo para documentos de CAD

Importar é o caminho inverso: ler um ficheiro externo e usar os dados para gerar ou atualizar o desenho, cumprindo o critério de desempenho "garantir a transferência bidirecional de informação entre documentos CAD e ficheiros externos".

def importar_bom(caminho):
    """Importa de volta um CSV para uma lista de dicionários, com os tipos corretos."""
    pecas = []
    with open(caminho, encoding="utf-8") as f:
        for linha in csv.DictReader(f):
            linha["quantidade"] = int(linha["quantidade"])
            linha["preco_unit_eur"] = float(linha["preco_unit_eur"])
            pecas.append(linha)
    return pecas

Corrido em conjunto com o capítulo 9 (exportar a BOM e importá-la de volta): os 4 artigos e o custo total de 82,80 € vieram idênticos ao original, confirmado por assert abs(custo_orig - custo_lida) < 0.001. É esta viagem de ida e volta, exportar depois importar, que prova que nenhum dado se perde ou corrompe na transferência.

Sem converter explicitamente "4" (texto, como vem do CSV) para 4 (número), as contas seguintes falhariam ou dariam resultados errados. Todo o CSV chega como texto; a rotina de importação é responsável por converter cada campo para o tipo certo.

11. Normas de segurança e saúde no trabalho

Automatizar não dispensa as normas de segurança e saúde no trabalho, uma aptidão avaliada nesta UC tal como as de programação:

Antes de mandar produzir com uma rotina nova, valida sempre o resultado numa peça isolada. Um erro numa rotina de desenho automático replica-se por todas as peças de uma série de uma só vez, ao contrário de um erro manual, que fica confinado a uma peça.

Erros comuns

Glossário

Síntese

Uma rotina de desenho automático nasce de uma análise de requisitos e de uma avaliação de viabilidade, ganha forma num fluxograma, e materializa-se em VBA com os tipos de variáveis, as operações e os ciclos certos. Quando o objetivo é reduzir desperdício, aplica-se um algoritmo de otimização testado e comparado com uma alternativa, nunca "por adivinhação". As interfaces ligam o VBA ao CAD e ao Excel, permitindo rotinas de desenho automático completas, inquirição de dados de modelos 2D e 3D para fabrico e orçamentação, e a exportação e importação de informação entre o CAD e ficheiros externos, sempre validada e sempre com as normas de segurança em mente, porque um erro numa rotina se replica por toda uma série de peças de uma só vez.

Exercícios resolvidos

1. Uma tarefa repete-se 5 vezes por semana, demora 6 minutos à mão, e a rotina levaria 200 minutos a desenvolver. Compensa automatizar?

Resolução: ocorrências/ano = 5 × 52 = 260; tempo manual total = 260 × 6 = 1560 min; poupança = 1560 − 200 = 1360 min. Como a poupança é positiva, compensa, com uma folga considerável.

2. Uma peça de 2800 mm tem de ser cortada de barras de stock de 2500 mm. O que deve fazer a rotina de corte?

Resolução: a peça é maior do que a barra, é um caso impossível, não um caso a "forçar". A rotina deve sinalizar a peça como impossível de cortar (como faz cortar_barras, acrescentando-a à lista impossiveis) e nunca tentar encaixá-la num ciclo sem fim.

3. Qual o tipo de variável VBA correto para guardar o código de uma peça, "A007", e porquê?

Resolução: String. Um tipo numérico perderia o "A" e o zero à esquerda; como texto, o código mantém-se exatamente como foi definido pelo gabinete de projeto.

4. Calcula, por divisão inteira, quantas peças de 350 mm (mais 2 mm de kerf) cabem numa barra de 3000 mm, e qual a sobra.

Resolução: 3000 // (350 + 2) = 3000 // 352 = 8 peças; sobra = 3000 − 8×352 = 3000 − 2816 = 184 mm.

5. Uma rotina lê o volume de uma peça em aço, 60 cm³, ao preço de 1,20 €/kg. Qual a massa e o custo do material (sem custo de máquina)?

Resolução: volume_m3 = 60/1 000 000 = 0,00006 m³; massa = 0,00006 × 7850 = 0,471 kg; custo = 0,471 × 1,20 = 0,57 € (arredondado a 2 casas).