Ir para o conteúdo

← Blog

Automatizar desenhos DWG com Python (e com AutoLISP ou MCP)

· Guias

A interface do programa e a ajuda estão disponíveis em inglês e espanhol. Os comandos e as opções aparecem aqui como na versão em inglês do programa.

Desenhar a mesma malha de eixos em cada projeto, contar blocos em cem plantas ou colocar na camada certa o que alguém deixou na camada 0 são tarefas que se repetem. O LinceCAD pode ser controlado de fora com uma API local: um script Python abre desenhos, cria entidades, muda camadas, executa comandos e salva em DWG. Tudo passa por canais do próprio computador; nada sai para a internet.

Quatro caminhos, conforme o que você precisa

ViaO que éQuando usar
API local (JSON-RPC)Uma mensagem JSON por linha, por um pipe nomeado (Windows) ou um socket (Linux). Funciona a partir de qualquer linguagem.Controlar o LinceCAD, com a janela aberta ou sem ela, a partir dos seus próprios programas.
Cliente lince de PythonUma biblioteca sem dependências sobre essa API: dib.linea(…), dib.guardar_como(…)…Scripts Python mais curtos e legíveis.
Roda lince_nucleoUm módulo Python compilado que lê, modifica e salva DWG/DXF sem abrir o LinceCAD.Lotes de arquivos, servidores ou Jupyter.
AutoLISPO interpretador incorporado, com cerca de 200 funções.Comandos próprios dentro do programa, ou rotinas LISP que você já tenha.

Além disso, o LinceCAD traz um servidor MCP para conectar assistentes de IA, do qual falamos no final.

Passo 1: ativar a automação

A API vem desativada por padrão. Há duas formas de usá-la:

Os programas se identificam com um token (uma senha de 64 caracteres) que fica em api.toml, em %APPDATA%\lince no Windows ou ~/.config/lince no Linux. Só o seu usuário pode lê-lo.

Passo 2: um script com a biblioteca padrão

Este exemplo não precisa instalar nada além do Python. Inicie antes o lince --servidor --canal blogpy (ou use o canal da janela aberta). O script se apresenta com o token, cria um desenho, uma camada e um lote de 30 × 20 e o salva em DWG:

import json, os

# O token (a senha da API) fica em %APPDATA%\lince\api.toml
toml = os.path.join(os.environ["APPDATA"], "lince", "api.toml")
ficha = next(l.split("=", 1)[1].strip().strip('"')
             for l in open(toml, encoding="utf-8") if l.startswith("ficha"))

canal = open(r"\\.\pipe\blogpy", "r+b", buffering=0)  # lince --servidor --canal blogpy
n = 0

def llamar(metodo, **params):
    global n
    n += 1
    msg = {"jsonrpc": "2.0", "id": n, "method": metodo, "params": params}
    canal.write((json.dumps(msg) + "\n").encode("utf-8"))
    r = json.loads(canal.readline())
    if "error" in r:
        raise RuntimeError(r["error"]["message"])
    return r["result"]

llamar("session.hello", token=ficha)
llamar("document.new")
llamar("layer.create", name="PARCELA", color=1)
llamar("entity.create", entity={"type": "LWPOLYLINE", "layer": "PARCELA", "closed": True,
                                "vertices": [[0, 0], [30, 0], [30, 20], [0, 20]]})
print(llamar("document.summary")["byType"])         # {'LWPOLYLINE': 1}
print(llamar("document.saveAs", path=r"C:\planos\parcela.dwg"))

A primeira requisição de cada conexão tem de ser session.hello; caso contrário, a conexão é fechada. No Linux, em vez de open(), conecte um socket.AF_UNIX ao caminho do socket e use s.makefile("rwb", buffering=0); o resto é igual.

A API tem métodos para desenhos (document.open, save, saveAs, summary…), entidades (entity.query, get, create, set, delete, como objetos ou como listas DXF de entget), camadas, blocos, estilos, variáveis, seleção, desfazer, comandos (command.run), AutoLISP (lisp.eval), plotagem em PDF, PNG e SVG, captura da vista e eventos. O document.saveAs salva em DWG ou DXF conforme a extensão, na versão 2018 por padrão ou em 2013, 2010, 2007, 2004, 2000 e R14.

Passo 3: o mesmo com o cliente de Python

O cliente lince envolve essa API em objetos. Este script, com lince.iniciar(), inicia o LinceCAD sem janela, desenha uma malha de eixos com seus rótulos e doze pilares de 30 × 30 cm, e salva o DWG, um PDF e uma imagem:

import lince

ejes_x = [0, 5.0, 10.5, 16.0]      # posição dos eixos, em metros
ejes_y = [0, 4.5, 9.0]
h = 0.15                            # metade do lado de um pilar de 30 x 30 cm

with lince.iniciar() as s:          # inicia o LinceCAD sem janela
    dib = s.nuevo()
    dib.crear_capa("EJES", color=1)
    dib.crear_capa("PILARES", color=7)
    dib.crear_capa("ROTULOS", color=3)
    with dib.transaccion():         # tudo fica em um só passo de desfazer
        for i, x in enumerate(ejes_x):
            dib.linea([x, -1.5], [x, ejes_y[-1] + 1.5], layer="EJES")
            dib.texto([x - 0.15, ejes_y[-1] + 2], str(i + 1), altura=0.4, layer="ROTULOS")
        for j, y in enumerate(ejes_y):
            dib.linea([-1.5, y], [ejes_x[-1] + 1.5, y], layer="EJES")
            dib.texto([-2.3, y - 0.2], "ABC"[j], altura=0.4, layer="ROTULOS")
        for x in ejes_x:
            for y in ejes_y:
                dib.polilinea([[x - h, y - h], [x + h, y - h], [x + h, y + h], [x - h, y + h]],
                              cerrada=True, layer="PILARES")
    print(dib.resumen()["byType"])  # {'LINE': 7, 'LWPOLYLINE': 12, 'TEXT': 7}
    dib.trazar_pdf(r"C:\planos\ejes.pdf")
    dib.guardar_como(r"C:\planos\ejes.dwg")
    dib.captura(r"C:\planos\ejes.png", ancho=1280)
Malha de quatro eixos verticais (1 a 4) e três horizontais (A a C) em vermelho, com doze pilares quadrados nos cruzamentos e os rótulos dos eixos em verde, sobre fundo branco.
A imagem que o script salva com dib.captura.

Para trabalhar com a janela já aberta, use lince.conectar() e s.dibujo (o desenho ativo). Há também .circulo, .arco, .mtexto, .insertar (blocos), .consultar (por tipo, camada, caixa ou filtro), .comando, .lisp e .trazar_png/.trazar_svg.

Sem abrir o LinceCAD: a roda lince_nucleo

Para processar muitos arquivos, a roda lince_nucleo trabalha dentro do próprio processo do Python. Este trecho, da documentação, lista os círculos de uma planta e a salva em DWG 2018:

import lince_nucleo as ln
dib = ln.abrir("plano.dwg")
for e in dib.consultar(tipo="CIRCLE"):
    print(e["handle"], e["radius"])
dib.guardar("salida.dwg", "2018")

A alternativa sem Python: AutoLISP

Se você já trabalha com LISP, pode continuar. O interpretador do LinceCAD aceita defun C:, ssget com filtros, entget, entmod, entmake e command, entre outras; as rotinas são carregadas com o APPLOAD ou automaticamente a partir do acaddoc.lsp. Este comando conta os pilares da planta anterior:

(defun C:CONTARPILARES (/ ss)
  (setq ss (ssget "X" '((0 . "LWPOLYLINE") (8 . "PILARES"))))
  (princ (strcat "\nPilares: " (itoa (if ss (sslength ss) 0))))
  (princ)
)

Sobre o ejes.dwg, ele responde «Pilares: 12». Para sequências fixas de comandos, também há os scripts (SCRIPT).

Assistentes de IA com MCP

O lince --mcp é um servidor MCP (Model Context Protocol) pela entrada e saída padrão, para os assistentes que o iniciam por conta própria. Com a janela aberta, também é possível ativar um servidor MCP por HTTP, só em 127.0.0.1. O assistente vê ferramentas para abrir, consultar, criar, cotar, inserir blocos, plotar em PDF, capturar a vista e desfazer, e a ajuda do LinceCAD como documentação. Por exemplo, para cadastrá-lo no Claude Code:

claude mcp add --scope project lince -- "C:\Program Files\lince\lince.exe" --mcp

Com a confirmação ativada, cada mudança que o assistente pede espera na paleta AIACTIONS até que você a aceite ou a rejeite, e tudo o que uma chamada faz é desfeito com um único UNDO.

Limitações

Perguntas frequentes

E se a planta de partida for um escaneamento? Primeiro é preciso passá-la para vetores: explicamos isso em como vetorizar uma planta escaneada e convertê-la em DWG.

E no Linux? A API funciona igual, com um socket Unix. Leia como abrir e editar DWG no Linux.

E para topografia? O processo com a guia Topography está em curvas de nível a partir de uma nuvem de pontos LAS/LAZ.

A API local, o AutoLISP e o servidor MCP vêm no LinceCAD, com licença perpétua. Downloads · Ver preços · AutoLISP, automação e os demais recursos.