Automatiser des dessins DWG avec Python (et avec AutoLISP ou MCP)
L’interface du logiciel et son aide sont disponibles en anglais et en espagnol. Les commandes et les options sont données ici telles qu’elles apparaissent dans la version anglaise du logiciel.
Dessiner la même trame d’axes dans chaque projet, compter des blocs dans cent plans ou remettre sur le bon calque ce que quelqu’un a laissé sur le calque 0 sont des tâches répétitives. LinceCAD peut être piloté de l’extérieur par une API locale : un script Python ouvre des dessins, crée des entités, change des calques, exécute des commandes et enregistre en DWG. Tout passe par des canaux de l’ordinateur lui-même ; rien ne sort vers Internet.
Quatre voies, selon vos besoins
| Voie | Ce que c’est | Quand l’utiliser |
|---|---|---|
| API locale (JSON-RPC) | Un message JSON par ligne, via un tube nommé (Windows) ou un socket (Linux). Fonctionne depuis n’importe quel langage. | Piloter LinceCAD, fenêtre ouverte ou non, depuis vos propres programmes. |
Client lince pour Python | Une bibliothèque sans dépendances au-dessus de cette API : dib.linea(…), dib.guardar_como(…)… | Des scripts Python plus courts et plus lisibles. |
Roue lince_nucleo | Un module Python compilé qui lit, modifie et enregistre des DWG/DXF sans ouvrir LinceCAD. | Traitements par lots, serveurs ou Jupyter. |
| AutoLISP | L’interpréteur intégré, avec environ 200 fonctions. | Vos propres commandes dans le logiciel, ou des routines LISP que vous avez déjà. |
LinceCAD inclut aussi un serveur MCP pour connecter des assistants IA, dont nous parlons à la fin.
Étape 1 : activer l’automatisation
L’API est désactivée par défaut. Il y a deux façons de l’utiliser :
- Fenêtre ouverte : dans
OPTIONS, onglet Automation (automatisation), activez le canal local. Vous pouvez aussi y passer l’API en lecture seule et limiter les dossiers dans lesquels elle peut ouvrir, enregistrer et tracer. Le canal est\\.\pipe\lince-<utilisateur>sous Windows et$XDG_RUNTIME_DIR/lince.socksous Linux. - Sans fenêtre :
lince --servidorsert l’API sans rien afficher, pour les traitements par lots. Avec--canal NOM, vous choisissez le nom du tube. Sous Linux, il faut une session graphique (ouxvfb-run).
Les programmes s’identifient avec un jeton (un mot de passe de 64 caractères) qui se trouve dans
api.toml, dans %APPDATA%\lince sous Windows ou ~/.config/lince sous Linux.
Seul votre utilisateur peut le lire.
Étape 2 : un script avec la bibliothèque standard
Cet exemple ne demande rien d’autre que Python. Lancez d’abord lince --servidor --canal blogpy (ou
utilisez le canal de la fenêtre ouverte). Le script se présente avec le jeton, crée un dessin, un calque et une
parcelle de 30 × 20, puis l’enregistre en DWG :
import json, os
# Le jeton (mot de passe de l'API) se trouve dans %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"))
La première requête de chaque connexion doit être session.hello ; sinon, la connexion est fermée.
Sous Linux, au lieu de open(), connectez un socket.AF_UNIX au chemin du socket et
utilisez s.makefile("rwb", buffering=0) ; le reste est identique.
L’API dispose de méthodes pour les dessins (document.open, save, saveAs,
summary…), les entités (entity.query, get, create,
set, delete, sous forme d’objets ou de listes DXF d’entget), les calques, les
blocs, les styles, les variables, la sélection, l’annulation, les commandes (command.run), AutoLISP
(lisp.eval), le traçage en PDF, PNG et SVG, la capture de la vue et les événements.
document.saveAs enregistre en DWG ou DXF selon l’extension, en version 2018 par défaut ou en 2013,
2010, 2007, 2004, 2000 et R14.
Étape 3 : la même chose avec le client Python
Le client lince enveloppe cette API dans des objets. Ce script, avec lince.iniciar(),
lance LinceCAD sans fenêtre, dessine une trame d’axes avec leurs repères et douze poteaux de 30 × 30 cm, puis
enregistre le DWG, un PDF et une image :
import lince
ejes_x = [0, 5.0, 10.5, 16.0] # position des axes, en mètres
ejes_y = [0, 4.5, 9.0]
h = 0.15 # demi-côté d'un poteau de 30 x 30 cm
with lince.iniciar() as s: # lance LinceCAD sans fenêtre
dib = s.nuevo()
dib.crear_capa("EJES", color=1)
dib.crear_capa("PILARES", color=7)
dib.crear_capa("ROTULOS", color=3)
with dib.transaccion(): # le tout en une seule étape d'annulation
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)

dib.captura.Pour travailler avec la fenêtre déjà ouverte, on utilise lince.conectar() et s.dibujo
(le dessin actif). Il existe aussi .circulo, .arco, .mtexto,
.insertar (blocs), .consultar (par type, calque, boîte ou filtre), .comando,
.lisp et .trazar_png/.trazar_svg.
Sans ouvrir LinceCAD : la roue lince_nucleo
Pour traiter de nombreux fichiers, la roue lince_nucleo travaille dans le processus Python lui-même.
Cet extrait, tiré de la documentation, liste les cercles d’un plan et l’enregistre en 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")
L’alternative sans Python : AutoLISP
Si vous travaillez déjà en LISP, vous pouvez continuer. L’interpréteur de LinceCAD accepte defun C:,
ssget avec filtres, entget, entmod, entmake et
command, entre autres ; les routines se chargent avec APPLOAD ou automatiquement depuis
acaddoc.lsp. Cette commande compte les poteaux du plan précédent :
(defun C:CONTARPILARES (/ ss) (setq ss (ssget "X" '((0 . "LWPOLYLINE") (8 . "PILARES")))) (princ (strcat "\nPilares: " (itoa (if ss (sslength ss) 0)))) (princ) )
Sur ejes.dwg, elle répond « Pilares: 12 » (poteaux : 12). Pour des séquences fixes de commandes, il
y a aussi les scripts (SCRIPT).
Assistants IA avec MCP
lince --mcp est un serveur MCP (Model Context Protocol) sur l’entrée et la sortie
standard, pour les assistants qui le lancent eux-mêmes. Fenêtre ouverte, on peut en outre activer un serveur MCP
par HTTP, uniquement sur 127.0.0.1. L’assistant voit des outils pour ouvrir, interroger, créer, coter,
insérer des blocs, tracer en PDF, capturer la vue et annuler, ainsi que l’aide de LinceCAD comme documentation. Par
exemple, pour l’ajouter à Claude Code :
claude mcp add --scope project lince -- "C:\Program Files\lince\lince.exe" --mcp
Avec la confirmation activée, chaque modification demandée par l’assistant attend dans la palette
AIACTIONS jusqu’à ce que vous l’acceptiez ou la refusiez, et tout ce que fait un appel s’annule avec
un seul UNDO.
Limites
- Local uniquement. L’API sert les programmes du même ordinateur ; le tube refuse les clients
distants et le HTTP n’écoute pas en dehors de
127.0.0.1. - Une requête à la fois par connexion, sans lots JSON-RPC. Pour travailler en parallèle, ouvrez plusieurs connexions.
- Entités de l’espace objet. Les cotes sont en lecture seule via
entity.create: elles se créent aveccommand.runou avec l’outil MCPadd_dimension. La couleur vraie se lit mais ne s’écrit pas. - Aucune question à l’utilisateur.
lisp.evaléchoue si la routine demande des données (getpoint,entsel…), et le mode sans fenêtre n’ouvre pas de boîtes de dialogue. - La roue n’exécute ni commandes, ni AutoLISP, ni tracés, ni captures : c’est le rôle du client ou de la fenêtre.
- Paquets Python pendant la bêta. L’API et le serveur MCP sont fournis dans
lince.exe. Les paquetslinceetlince_nucleone sont pas encore publiés sur PyPI ni fournis avec l’installateur (le paquet qui s’appelle aujourd’huilincesur PyPI appartient à un autre projet) ; l’exemple de l’étape 2 fonctionne sans eux.
Questions fréquentes
Et si le plan de départ est un scan ? Il faut d’abord le convertir en vecteurs : nous l’expliquons dans vectoriser un plan scanné et le convertir en DWG.
Et sous Linux ? L’API fonctionne de la même façon, avec un socket Unix. Lisez ouvrir et modifier un DWG sous Linux.
Et pour la topographie ? La démarche avec l’onglet Topography est décrite dans courbes de niveau à partir d’un nuage de points LAS/LAZ.
L’API locale, AutoLISP et le serveur MCP sont fournis avec LinceCAD, avec une licence perpétuelle. Téléchargement · Voir les tarifs · AutoLISP, automatisation et toutes les autres fonctionnalités.