# dibuja

El esquema de un circuito de Simul como SVG, a partir del `.d`, del `.ds` o del `.dat`, con las formas que tenía en Simusol cuando se sabe cuáles eran.

Empezó el 08/10/2026, a pedido del autor: «hay algún software que permita
dibujar circuitos a partir de las descripciones que usamos en el .d o .ds o
directamente de nuestros dat»; eligió [netlistsvg](https://github.com/nturley/netlistsvg)
(«lo mejor para nosotros es netlistsvg, por ahora al menos») y pidió el
proyecto en siru («creemos en siru un proyecto dibuja»). Después, recuperar
las formas de Dia de Simusol (el tanque en lugar del capacitor) y sacar de
cada `.dia` un archivo aparte con lo que el `.d` no dice.

## Los programas

| programa | entra | sale |
|---|---|---|
| `dibuja` | un `.d`, `.ds` o `.dat` | `NOMBRE.svg` (o el netlist, con `--json`) |
| `dibuja-corpus` | directorios (por omisión el corpus de siru) | `NOMBRE.d.svg`, `NOMBRE.ds.svg` al lado de cada circuito |
| `junta-dias` | directorios (por omisión el corpus de siru) | `NOMBRE.dia` al lado de cada circuito, con `svn copy` |
| `dia2formas` | un `.dia` (o directorios con `-r`) | `NOMBRE.formas` al lado del `.dia` |
| `dia2paraplot` | un `.dia` (o directorios con `-r`) | `NOMBRE.paraplot` al lado, si el diagrama tiene cuadro `GRAFICOS` |
| `dia2piel` | las formas de Dia de Simusol | `pieles/simusol.svg`, la piel de netlistsvg |

El orden, para un corpus nuevo:

    junta-dias DIR          los .dia de Simusol al lado de cada circuito
    dia2formas -r DIR       un .formas por cada .dia
    dibuja-corpus DIR       un .svg por cada .d y .ds

(`dibuja-corpus --formas DIR` hace los dos últimos juntos.)

## Instalación

Descargar y ejecutar el instalador de SummaPack:

```sh
curl -fsSLO https://www.simusol.org/downloads/installsumma.sh
sh installsumma.sh dibuja/dibuja
```

El instalador permite elegir el formato adecuado para el sistema e instala las dependencias. Se usa la misma orden aunque SummaPack ya esté instalado. El paquete incluye netlistsvg, sus dependencias JavaScript y los símbolos; Dibuja funciona de manera independiente de Siru, Calcula y Dia.

| Uso | Requisitos |
|---|---|
| Dibujar desde `.dat` | Python 3 y Node.js 12 o posterior. |
| Dibujar desde `.d` o `.ds` | Además, `d2datdinc`; para `FORMAS`, versión 1.0-26 o posterior. |
| Extraer formas de un `.dia` | Python 3. |

Para instalar el lector de circuitos:

```sh
sh installsumma.sh slex/d2datdinc
```

Las instrucciones internas de construcción y empaquetado se encuentran en `doc/DESARROLLO.md` del árbol de fuentes.

## Revisar la conversión de Dia

Dibuja ayuda a comprobar visualmente si la conversión de un `.dia` a un `.ds` conservó el circuito. Reconstruye el esquema a partir de las ramas y conexiones del `.ds`, para compararlo con el diagrama original y detectar elementos faltantes o conexiones incorrectas. Cuando se conservaron las formas, también permite revisar los símbolos. La distribución del dibujo puede cambiar; las ecuaciones y los valores requieren su propia revisión.

## FORMAS dentro del circuito

Se puede copiar el contenido de un archivo `.formas` debajo del título `FORMAS` en un `.ds`, antes de `END`. La sección termina al encontrar otro título o `END`. Los campos de cada fila se separan con **tabuladores**, porque los nombres de las formas y las orientaciones contienen espacios. Se admiten comentarios con `#` y el formato antiguo `NOMBRE FORMA`, sin geometría.

```text
FORMAS
# nombre	forma	orientacion	x	y	ancho	alto
R1	Electrico - hresistor	horizontal	4	1	3	1.5
masa	Electrico - tierra	fija	8	6	2	2
nodo 1	Electrico - nodo	fija	3	1	1.5	1.5
END
```

| Campo | Contenido |
|---|---|
| `nombre` | Nombre de rama, `masa` o `nodo N` |
| `forma` | Nombre de la forma de Dia |
| `orientacion` | Texto de orientación y volteos |
| `x`, `y` | Esquina de la forma, en centímetros de Dia |
| `ancho`, `alto` | Tamaño, en centímetros de Dia |

Slex (`d2datdinc`) interpreta cada fila y escribe una lista de objetos en `GLOBAL.formas`, con esos siete campos; los últimos cuatro son números. Conserva el orden, las masas repetidas y los nodos. Las filas inválidas se informan como errores de `FORMAS` y no se publica un DAT parcial. El formato antiguo produce solo `nombre` y `forma`. Una sección vacía produce `"formas": []`; si no hay sección, la clave no aparece.

`dibuja` usa `GLOBAL.formas` tanto al leer un `.dat` como al traducir un `.ds`. Las formas internas tienen prioridad por nombre sobre el `.formas` externo; este puede completar las ramas restantes. Para la masa usa la primera entrada. `--electrico` ignora ambas fuentes. Las coordenadas, los tamaños y las orientaciones se conservan en el dato para usos posteriores: por ahora ELK sigue calculando la disposición del dibujo.

## Ejemplos y llamada desde Siru

Los ejemplos son autocontenidos: incluyen sus modelos de elementos, sin rutas al árbol de fuentes. Se entregan como `.ds`, `.dat` y `.svg` en `ejemplos/`, instalado como `PREFIX/share/dibuja/ejemplos`.

| Ejemplo | FORMAS | Resultado |
|---|---|---|
| [divisor.ds](ejemplos/divisor.ds) | Símbolos eléctricos explícitos | [Divisor de 10 V a 5 V](ejemplos/divisor.svg) |
| [termico.ds](ejemplos/termico.ds) | Símbolos térmicos y nodos | [Fuente de temperatura, resistencia y flujo](ejemplos/termico.svg) |
| [automatico.ds](ejemplos/automatico.ds) | Vacía | [Divisor con símbolos predeterminados](ejemplos/automatico.svg) |

```sh
dibuja ejemplos/divisor.dat -o /tmp/divisor.svg
dibuja ejemplos/termico.ds -o /tmp/termico.svg
siru ejemplos/automatico.ds
```

Siru comprueba la **presencia** de `GLOBAL.formas`, aunque sea una lista vacía. Si existe y encuentra `dibuja`, le entrega el dato ya leído y genera `NOMBRE.svg` al lado de la entrada, antes de simular. La misma regla vale para una entrada `.dat` y para `--continuar`. Sin `FORMAS` no pide un esquema automáticamente, aunque exista un `.formas` externo. Si `dibuja` no está instalado, continúa y deja constancia en `NOMBRE.log`; si falla, avisa y también continúa. El SVG se regenera con el mismo nombre en cada ejecución. Las entradas `.din` no llevan las ramas ni `FORMAS` y no activan esta llamada.

## dibuja

    dibuja circuito.d                  escribe circuito.svg
    dibuja circuito.dat -o otro.svg
    dibuja circuito.ds --json          solo el netlist para netlistsvg
    dibuja circuito.d --termico        sin .formas, con las formas térmicas
    dibuja circuito.d --electrico      con símbolos eléctricos aunque haya .formas

De un `.d` o un `.ds` el dato lo saca `d2datdinc` (corriendo en el
directorio del circuito, para que encuentre sus includes); un `.dat` ya es
el dato. Cada rama de `GLOBAL.ramas` (tipo, dos nodos, valor) pasa a una
celda del netlist de netlistsvg, que la dibuja y ubica todo sola (ELK, de
arriba hacia abajo).

Sin `.formas`, con los símbolos analógicos de netlistsvg:

| rama | símbolo | nodos |
|---|---|---|
| R… | resistencia | |
| C… | capacitor | |
| L… | bobina | |
| E… | fuente de tensión | `+` en el segundo nodo |
| J… | fuente de corriente | `+` en el segundo nodo |
| otra (S, T, modelos) | caja con el nombre y el tipo | |

La rama es del tipo que dice el dato (`RB`, `CB`, `EB`...): cuenta la
primera letra. Cada conexión a masa (`GND` o `0`) lleva su propio símbolo,
en lugar de un cable largo hasta un único nodo de masa. El valor va con
prefijo y unidad si es un número (`10 kΩ`, `100 µF`) y tal cual si es una
expresión (`2 * RP`). netlistsvg no cuenta los rótulos al calcular el
ancho del dibujo: `dibuja` lo agranda según el rótulo más largo.

Con `NOMBRE.formas` junto al circuito (el mismo nombre: `tanque.d` y
`tanque.formas`), cada rama va con la forma de Dia que tenía en Simusol, de
la piel `pieles/simusol.svg`:

- una forma de dos conexiones o más: la primera al primer nodo de la rama
  y la segunda al segundo;
- una forma de una sola conexión (el tanque, la fuente de temperatura):
  al nodo que no es masa; la masa la dibuja la forma;
- con una forma térmica el valor va en las unidades del circuito térmico:
  R en K/W, C en J/K, E en tempC y J en W;
- las ramas que no están en el `.formas` (un `.ds` armado a mano a partir
  de un diagrama tiene ramas que el diagrama no tiene) van con las formas
  del conjunto que predomina en el archivo, térmico, eléctrico o genérico
  (a pedido del autor: «a esas ramas hacerlas con el modelo predominante
  en formas»);
- la masa, con la forma de masa del `.formas` (la primera, si hay varias)
  o la del conjunto.

`--termico` dibuja con las formas térmicas un circuito sin formas: C el
tanque, R la conducción, E la fuente de temperatura, J el flujo, la masa a
0 °C. `--electrico` deja de lado `FORMAS` y el `.formas`.

## Las formas de Dia de Simusol

Simusol dibujaba los circuitos en Dia con formas propias, en cuatro
conjuntos: Térmico (el acumulador, que es un tanque; las resistencias de
conducción, convección y radiación; los flujos; la fuente de temperatura;
la masa a 0 °C), Eléctrico, Genérico y Modelos. Están en
`siru/dia-simusol/NOLOCALdia/share/dia/shapes` y en el paquete de Simusol
(`siru/pack/simusol/tar/share/data/shapes`); los dos juegos difieren un
poco y se usa la unión.

Cada forma trae su definición para Simusol (`share/data/elementos/*_ele.dia`):
el acumulador térmico es `C5 = C1,PCP,PMASA`, la resistencia convectiva
`R1 = V1,PAREA,PH`. El `.d` que Simusol sacaba del diagrama solo dice R, C,
E o J: qué forma llevaba cada rama queda en el `.dia`.

### dia2piel: la piel

    dia2piel                  escribe pieles/simusol.svg
    dia2piel -o otra.svg DIR...

Toma la piel analógica de netlistsvg y le agrega cada forma (51) como un
tipo de celda con el nombre de la forma sin blancos (`Termico-acumulador`):

- netlistsvg busca la celda por su `<s:alias>`, no por `s:type`, y toma
  todo `<g>` de adentro de una celda como un puerto: por eso la escala va
  en cada trazo y no en un grupo;
- el recuadro sale de lo que dibuja la forma y de sus conexiones (las
  formas de Dia no empiezan siempre en 0: las llaves van de x=19 a x=25),
  escalado para que lo más grande mida 50 px;
- un puerto `p0`, `p1`... por punto de conexión, del lado del recuadro más
  cercano;
- el trazo no se escala (`vector-effect`), y queda del grosor de los demás;
- las masas no llevan rótulos;
- el punto verde de algunas formas es la marca de Dia del primer terminal,
  y se deja.

`pieles/simusol.svg` se versiona; se rehace con `dia2piel` si cambian las
formas o netlistsvg.

### junta-dias: el .dia al lado del circuito

    junta-dias                     el corpus de siru
    junta-dias DIR...
    junta-dias --prueba            solo dice qué copiaría

Los `.d` que hizo Simusol dicen de qué diagrama salieron («a partir del
archivo-diagrama ../cprojects/tanque.dia»). Para cada `.d` y `.ds` busca ese
`.dia` junto al circuito y, si no está, uno con ese nombre en el árbol de
siru, fuera de los viejos (`siruviejo`, `viejos`, `ds2viejos`); de varios,
el que más ramas comparte con el circuito. Lo copia con `svn copy` (a
pedido del autor: «copialos no movelos»; el original queda donde estaba y
la copia conserva la historia) como `NOMBRE.dia`, junto a `NOMBRE.d` o
`NOMBRE.ds`. Si varios circuitos salieron del mismo diagrama, cada uno
lleva su copia.

Se copia aunque el diagrama tenga menos ramas que el circuito: muchos `.ds`
del corpus se armaron a mano a partir de `6elementos` y conservaron su
encabezado. En el corpus de siru (08/10/2026) se copiaron 97 diagramas para
100 circuitos (un `.d` y su `.ds` comparten el `.dia`): en 47 circuitos
coinciden todas las ramas, en 51 algunas y en 2 ninguna.

### dia2paraplot: el .paraplot

    dia2paraplot tanque_med.dia    escribe tanque_med.paraplot
    dia2paraplot -r DIR...         todos los .dia de esos directorios

Hace con los gráficos lo que `dia2formas` con las formas: saca del diagrama
lo que el `.d` no dice, que es su cuadro `GRAFICOS` —ejes, títulos, paneles,
qué guardar—, y lo escribe en el PARAPLOT de hoy, traduciendo los selectores
de columna (números o nombres propios) a los nombres de columna de la tabla.
Un `.dia` sin ese cuadro no da archivo: los gráficos de un circuito que sólo
declara `OUTPUTS` los prepara simplot solo. En el corpus son 6 de 97. De
dónde sale cada renglón y qué falta para que simplot los dibuje:
`doc/PARAPLOT.md`.

### dia2formas: el .formas

    dia2formas tanque.dia          escribe tanque.formas
    dia2formas -r DIR...           todos los .dia de esos directorios

En el diagrama cada forma lleva un texto, y Simusol nombraba la rama con la
letra de la forma más ese texto: en `tanque.dia`, la forma
`Termico - acumulador` con el texto `A` es la rama `CA` del `.d`
(`CA, 1-0 = 41860`). `dia2formas` hace lo mismo. La letra sale del nombre
de la forma:

| forma | letra |
|---|---|
| resistor, conductiva, convectiva, radiativa | R |
| capacitor, acumulador | C |
| inductor | L |
| fem, fuente | E |
| corriente, flujo | J |
| llave | S |
| transformador | T |
| 0gradosc, tierra, `Generico - 0` | masa |

Si al lado está el circuito (`NOMBRE.d` o `NOMBRE.ds`), usa sus ramas: para
reconocer un texto que ya es el nombre entero de una rama y para no anotar
formas de ramas que el circuito no tiene.

`NOMBRE.formas` tiene lo que el `.d` no dice y hace falta para dibujarlo
como estaba, en campos separados por tabulador:

    # formas de Dia de tanque.dia, de las ramas de tanque.d (dia2formas)
    # nombre  forma                 orientacion         x      y      ancho  alto
    CA        Termico - acumulador  fija                2.989  6.442  1.723  1.516
    E3        Termico - fuente      fija                ...
    J1        Termico - flujoi      hacia la izquierda  ...
    R5        Termico - hconductiva horizontal          ...
    masa      Termico - 0gradosc    fija                ...
    nodo 1    Termico - nodo        fija                ...
    nodo 2    Termico - nodo        fija                ...

- un renglón por rama, uno por cada símbolo de masa y uno por cada nodo,
  con el nombre que tiene en el diagrama;
- la forma, con su conjunto como primera palabra (Termico, Electrico,
  Generico, Modelos);
- la orientación: la del nombre de la forma (`h` horizontal, `v` vertical;
  en los flujos `d`, `i`, `D`, `U`, hacia la derecha, la izquierda, abajo
  o arriba) y si en Dia está volteada (`flip_horizontal`,
  `flip_vertical`): «horizontal, volteada horizontal». Las formas de
  Simusol no se rotan, solo se voltean (en todo el árbol: 23 volteadas
  horizontalmente y 9 verticalmente, de 3974). Las que se dibujan de una
  sola manera (el tanque, la fuente, la masa) dicen «fija»;
- el lugar en el diagrama: `x` e `y` de la esquina, `ancho` y `alto`, en
  las unidades de Dia (cm, con `y` creciendo hacia abajo).

`dibuja` usa la forma; la orientación y el lugar quedan para dibujar el
circuito como estaba en Dia, que todavía no se hace (netlistsvg ubica todo
por su cuenta). `dibuja` también lee el formato anterior, `RAMA FORMA`
separados por un blanco.

## dibuja-corpus

    dibuja-corpus                     el corpus de siru
    dibuja-corpus DIR...
    dibuja-corpus --todos             rehace también los que están al día
    dibuja-corpus --formas            antes, dia2formas -r

El corpus de siru es `siru/siru/corpus/corpus`. Al lado de cada `.d` y
`.ds` deja `NOMBRE.d.svg` o `NOMBRE.ds.svg` (con la extensión, porque hay
circuitos con las dos), y rehace solo los que no tienen dibujo o cuya fuente
es más nueva; varios a la vez. Al final dice cuántos dibujó, cuántos no son
circuitos (sistemas de ecuaciones sin ramas) y cuáles rechazó `d2datdinc`,
con el motivo.

En el corpus de siru (08/10/2026): 428 circuitos, 355 dibujados, 72
sistemas sin ramas y uno rechazado a propósito
(`inventados/tipo-sin-modelo.ds`); unos 20 s. De los 97 `.dia`, 95 dan su
`.formas` (414 ramas: 287 con formas eléctricas y 127 con térmicas); en los
otros 2 el diagrama no tiene formas de ninguna rama del circuito. Los
`.dia` del corpus están en svn; los `.formas` y los `.svg` no (se rehacen
con `dibuja-corpus --formas`).

En todo el árbol (789 `.d` y `.ds`, sin los viejos) dibuja 617; los demás
son sistemas de ecuaciones sin ramas (144) o circuitos que `d2datdinc`
rechaza (28: controles de rama viejos, includes que faltan).

## Pruebas

    pruebas/probar

- `dia2formas pruebas/tanque.dia` tiene que dar `pruebas/tanque.formas`;
- `dibuja --json` de `6elementos.d`, `unidades.d` y `tanque.d` (este con
  su `.formas`) tiene que dar los netlist de `pruebas/esperado/`;
- si está netlistsvg, cada uno tiene que salir como SVG.

## Límites

- Los circuitos chicos y medianos salen como un esquema prolijo. En uno muy
  grande (la grilla RC de 10×10 del corpus) el acomodo automático no
  respeta la forma de la cuadrícula.
- netlistsvg no reserva lugar para los rótulos: alguno se pisa con un
  símbolo vecino.
- Las ramas de más de dos nodos (transistores, transformadores de SCEPTRE)
  no llegan al dato como ramas y no se dibujan.
- El lugar y la orientación del `.formas` todavía no se usan para ubicar
  las formas.

Copyright (C) Diego Saravia. GPL 3 o posterior.
