Odio responder a mi propia pregunta, pero aquí voy. Espero no obtener puntos por responder, ¿sería extraño, solo por aceptar una respuesta? (Por cierto, no obtuve ninguna respuesta en el foro Element14).
La solución es usar el comando DIBUJAR, no RUTA. DIBUJO colocará un segmento de cable, exactamente donde lo especifique (a diferencia de ROUTE, que intenta conectarse a un cable de aire sin enrutar. ROUTE es esencialmente inútil en un script). El siguiente problema es a través de: No puedo (o no quiero) distinguir entre una vía manual y una salida automática, por lo que mantengo todas las vías que conectan dos (o más) segmentos de cables manuales. Se eliminan otras vías.
Entonces, lo que hace mi guión final es:
prepare a ripup command
for all copper segments that are not 0.01 wide (the width I use for autorouting)
check both endpoints for a via at that location
prepare the via to be resurrected when it is visited the 2nd time
prepare a command that resurrects the copper segment
execute the prepared commands
Tenga en cuenta que probablemente no funcionará para más de dos capas, ni para otras cosas que no sean segmentos de cable en la capa de cobre.
En mi humilde opinión, todo el concepto del águila ULP y los lenguajes de comando es problemático. Un ULP se ejecuta en un entorno de solo lectura, la única forma en que puede afectar el circuito, la placa o la biblioteca es mediante la creación de una lista de comandos. Esto elimina algunas técnicas de programación útiles, pero peor es que los comandos no fueron diseñados para ser creados fácilmente a partir de un ULP. Necesita todo tipo de transformaciones (en este caso: coordenadas, nombres de formas) para traducir del mundo ULP al mundo CMD.
(editar) Antes de ejecutar este ULP, configure la selección de 'doblado de alambre' para permitir ángulos arbitrarios, de lo contrario, Eagle intentará adaptar los cables resucitados a los ángulos permitidos, lo que puede resultar en un embarrado sangriento. En mi opinión, este es otro ejemplo del problema con ULP / SCR.
Este es el código ULP:
// gather the commands that must be run on exit
string RunOnExit = "";
void cmd( string s ) { RunOnExit += s + "\n"; }
// return an x or y position in the form that can be used in a command
real f( int x ){
board( B ) switch( B.grid.unit ) {
case 0: return u2mic(x);
case 1: return u2mm(x);
case 2: return u2mil(x);
case 3: return u2inch(x);
}
}
// return the string form of the a via's shape
string sn( int x ){
if( x == VIA_SHAPE_SQUARE ) return "square";
if( x == VIA_SHAPE_ROUND ) return "round";
if( x == VIA_SHAPE_OCTAGON ) return "octagon";
if( x == VIA_SHAPE_ANNULUS ) return "annulus";
if( x == VIA_SHAPE_THERMAL ) return "thermal";
return "unknown-via-shape";
}
// count the number of times x occurs in s
int n_ocurrences( string s, string x ){
int i, n = 0;
while( 1 ){
i = strstr( s, x );
if( i == -1 ) return n;
s = strsub( s, i + strlen( x ));
n++;
}
}
// add a via, but only when it is visited the second time
string via_list = "";
void add_via( int a, int b ){
// for all via's
board( B ) B.signals( S ) S.vias( V ){
// if the via is at the current location
if(( V.x == a ) && ( V.y == b )){
string s, coo;
// the coordinates of the via are used as its identification
sprintf( coo, "(%.6f %.6f)", f( V.x ), f( V.y ));
// if this is the second visit to this via
via_list += coo;
if( n_ocurrences( via_list, coo ) == 2 ){
// resurrect this via
sprintf( s, "VIA '%s' %f %s %s;",
S.name, f( V.drill ), sn( V.shape[ 1 ] ), coo );
cmd( s );
}
}
}
}
if( !board ){
dlgMessageBox("start this ULP in Board", "OK");
exit( 0 );
}
board( B ){
// first delete all coper segments,
// later we will resurrect what we want to keep
cmd( "RIPUP;" );
// for all wire segments in the top and bottom copper layers
B.signals(S) S.wires(W) {
if( ( W.layer == 1 ) || ( W.layer == 16 ) ){
// that are not 0.01 width (that is what the autorouter uses)
if( f( W.width ) != 0.01 ){
string s;
// resurrect via's adjacent to this wire segment
add_via( W.x1, W.y1 );
add_via( W.x2, W.y2 );
sprintf( s, "CHANGE LAYER %d;", W.layer );
cmd( s );
// resurrect this wire segment
sprintf(
s, "WIRE '%s' %f (%.6f %.6f) (%.6f %.6f);",
S.name, f( W.width),
f(W.x1), f(W.y1), f(W.x2), f(W.y2));
cmd( s );
}
}
}
// dlgMessageBox( RunOnExit, "OK");
exit( RunOnExit );
}