Je déteste répondre à ma propre question, mais c'est parti. J'espère que je ne reçois pas de points pour répondre, ce serait bizarre, seulement pour accepter une réponse? (BTW, je n'ai reçu aucune réponse sur le forum Element14.)
La solution consiste à utiliser la commande DRAW, pas ROUTE. DRAW placera un segment de fil, exactement là où vous le spécifiez (contrairement à ROUTE, qui essaie de se connecter à un fil aérien non acheminé. ROUTE est essentiellement inutile dans un script.). Le problème suivant est celui des via: je ne peux pas (ou je ne veux pas) faire la distinction entre un via manuel et un via autorouté, donc je garde tous les via qui connectent deux (ou plus) segments de fil manuels. Les autres via sont supprimés.
Alors, mon script final fait:
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
Notez qu'il ne fonctionnera probablement pas pour plus de deux couches, ni pour autre chose que des segments de fil au niveau de la couche de cuivre.
À mon humble avis, tout le concept des langages ULP et de commande eagle est gênant. Un ULP s'exécute dans un environnement en lecture seule, la seule façon dont il peut affecter le circuit, la carte ou la bibliothèque est de créer une liste de commandes. Cela élimine certaines techniques de programmation utiles, mais le pire est que les commandes n'ont pas été conçues pour être facilement créées à partir d'un ULP. Vous avez besoin de toutes sortes de transformations (dans ce cas: coordonnées, noms de forme) pour traduire du monde ULP au monde CMD.
(modifier) Avant d'exécuter cet ULP, définissez la sélection `` Wire Bend '' pour permettre des angles arbitraires, sinon Eagle tentera d'adapter les fils ressuscités aux angles autorisés, ce qui peut entraîner un désordre sanglant. À mon humble avis, c'est un autre exemple du problème avec ULP / SCR.
Voici le code 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 );
}