logo

Thread

logo
the fair gds editor

Introduction
Screenshots
License
Download
Userinterface
Function Index
White Papers
Community
Contact

Use your OpenID:

getopenID

mouse left
no help

Macro Programming: groupSimple() return value ?

by Toby Mangold - 9 Jul 2009, 16:08 CEST

Hi Jürgen,

at the moment I'm trying to set up a macro, which performs a multi-layer merge operation based on the boolean OR operation similar to the intrinsic merge command (is the merge working correclty in the latest release ? ... anyway ...)

Is there a protected, tmp working layer (e.g. 256) accessible from a macro, which will never contain elements ? At the moment I'm simply scanning for an invisible one starting from the back, 255. Is it possible to search for a disabled one from within a macro ?

One of my basic problems is related to the layout->drawing->groupSimple() command, which I need to put the current selection of elements subject to the merge operation into a temporary cell. (boolen APlusB cannot be called on a subgroup of the current selection without lossing the selection, right ?)
Now, how do I get a handle to the newly created cell ? There's no return value for groupSimple().

My current workaround walks to the end of the global cell list assuming any cell addition will go to the end of the list. It seems to work, but is this assumption valid in any case ?

There are a lot of performance issues with the macro partly due to the lack of array variables for caching. But the biggest issue at the moment
is a layout.exe crash after I've added the boolean AplusB operations and cleanup. I'm still
debugging and wondering weather this macro will run on the latest GPL release to double check for any layout.exe errors in my old 2008 GPL release .

Any comments or suggeststions in general which might help debugging or performance ?
Any kind of help is really appreciated.

Regards,
Toby

#!/usr/bin/layout
#name=boolean-merge
#help=performs a merge of selected elements (no cells) based on boolean tools

int main(){
int l;
int tmplay=255;
cell *myCell= layout->drawing->currentCell;
cell *myTmpCell;
string tmpA;
string tmpB;
cellList *lastCellEntry= layout->drawing->firstCell;
elementList *myElemL;

# we don't want to include any selected cells
layout->drawing->cDeselect();

# first of all, turn on all layers including selected elements
myElemL=myCell->firstElement;
while(myElemL!=NULL){
if(myElemL->thisElement!=NULL){
layers::num[myElemL->thisElement->layerNum].visible=true;
}
myElemL=myElemL->nextElement;
}

# try to find a non-visble, unused working layer
while(layers::num[tmplay].visible && ( tmplay > 0) ) { tmplay--; }
if ( (tmplay == 0) && layers::num[tmplay].visible ) {
layout->showMessage("ERROR","Cannot find an invisible working layer");
return;
}
#DEBUG
#layout->showMessage("working layer is","ID="+tmplay);

# grouping all elements we'd like to merge
layout->drawing->groupSimple();
layout->drawing->deselectAll();

# find last cell
while(lastCellEntry->nextCell != NULL) { lastCellEntry=lastCellEntry->nextCell ; }

# focus to newly added cell and flatten
#layout->drawing->setCell(lastCellEntry->thisCell->cellName);
layout->drawing->currentCell=lastCellEntry->thisCell;

#DEBUG
#layout->showMessage("temp. working cell is",lastCellEntry->thisCell->cellName);

lastCellEntry->thisCell->selectAll();
lastCellEntry->thisCell->flatSelect();

# Since the temp. cell contains only elements on visible layers,
# there's no need to clean the working layer. It has to be empty.

lastCellEntry->thisCell->deselectAll();
for (l=0;l<255;l++){
if (layers::num[l].visible){
# merge this visible layer
# layout->drawing->deselectAll();
layout->drawing->activeLayer=l;
layout->drawing->selectActiveLayer();

# How to check for the number of selected elements to conditionally skip the boolean operation ?

layout->drawing->currentCell->moveToLayerSelect(tmplay);
# boolean merge operation;
layout->booleanTool->setA();
# setA will deselect()
layout->booleanTool->setB();
layout->booleanTool->APlusB();
}
}
# Done with merge operations
#DEBUG
#layout->showMessage("DEBUG","done with merge");

#DEBUG
#layout->showMessage("DEBUG","go");

# need to find the cellref of my tmp. cell, which has been created by groupSimple()
myElemL=myCell->firstElement;
#DEBUG
#layout->showMessage("DEBUG","go2");
# Is there some way to break out of the while-loop without lossing info
# about the ciurrent element ? No ? ... for the moment we have to stick
# with a tmp flag pointer.
myTmpCell=NULL;
#DEBUG
#layout->showMessage("DEBUG","go3");
while( (myElemL !=NULL) && (myTmpCell==NULL)){
if(myElemL->thisElement!=NULL){
if(myElemL->thisElement->isCellref()){
myTmpCell=myElemL->thisElement->depend();
if( myTmpCell->cellName != lastCellEntry->thisCell->cellName ){
myTmpCell=NULL;
myElemL=myElemL->nextElement;
}
#DEBUG
#layout->showMessage("DEBUG","yes");
# keep myTmpCell, don't increment and exit loop
} else {
myElemL=myElemL->nextElement;
}
}
}
#DEBUG
#layout->showMessage("scan for cellref returned",myTmpCell->cellName);

if(myElemL->thisElement == NULL){
layout->showMessage("ERROR","cannot find automatically placed cellref ... strange ....");
return;
}
myElemL->thisElement->selectAll();
myCell->flatSelect();

#DEBUG
#layout->showMessage("DEBUG","cellref removed");
layout->drawing->currentCell=lastCellEntry->thisCell;
#layout->drawing->setCell(lastCellEntry->thisCell->cellName);
layout->drawing->deleteActuellCell();
layout->drawing->currentCell=myCell;
#layout->drawing->setCell(myCell->cellName);
#DEBUG
#layout->showMessage("DEBUG","finished");

}




by Juergen Thies - 9 Jul 2009, 18:37 CEST

This macro should do want you want:

#!/usr/bin/layout
#name=boolean-merge
#help=performs a merge of selected elements (no cells) based on boolean tools

int unusedLayer(){
layers::hideUnusedLayers(layout->drawing);
int i,k=0;
for (i=0;i<=255;i++)
if (layers::num[i].visible==false) k=i;
return k;
}

int main(){
drawingField *d=layout->drawing;
cell *tempCell=d->addCell()->thisCell;
tempCell->cellName = "~myTempCell";
string cc=d->currentCell->cellName;
d->cDeselect();
d->currentCell->group(tempCell);
d->setCell("~myTempCell");
d->activeLayer=unusedLayer();
d->selectAll();
layout->booleanTool->setA();
layout->booleanTool->setB();
d->setCell(cc);
layout->booleanTool->aPlusB();
d->setCell("~myTempCell");
d->deleteActuellCell();
d->setCell(cc);
layers::hideUnusedLayers(layout->drawing);
}

Some comments to your questions:
- the merge command is aPlusB (not APlusB), the error message for that error was missing in the LayoutEditor.
- internal pointers like currentCell, firstcell are write protected, use setCell() instead.
- after groupSimple the new cell is always in firstCell->thisCell, cellname is noname_+unused number.
- in a boolean operation you can use multiply setA or setting multi layers in one operation,
- the boolean operation can be performed in an other cell than the source cell,
- the merge operation uses the same merge algorithm than the boolean tool, but will respect layers and will merge path elements different. In result the merge feature has a lower performance than the boolean tool.

by Toby Mangold - 10 Jul 2009, 10:18 CEST

Hi Jürgen,

Thanks a lot for all your comments and your macros. But I've to dissapoint you: I cannot test it, because the demo version of the latest download binaries seems to have expired, and the gpl version doesn't allow to run macros.

Furthermore, I cannot run it on the older sep 2008 gpl release, because hideUnusedLayers() isn't available there.

I'm going to try porting it back to a 2008 gpl release merging your suggestions into my own macro code. Are there any additional features used in your code, which are missing in the sep 2008 GPL version ?
Maybe I simply add the hideUnusedLayers() funciton to the code. I'm using a patched branch of the GPL code anyway (e.g. I've added an optional auto-enable of layers during file open/import). Wel'll see ...

Regarding the merge feature:
Did you improve it a lot in 2009 ? I've a very basic test file which gives very strange/poor results for all 2008 releases I'm able to check.
Could you please check the file or provide me a working demo version to test it on my own ?

(Since I canot attach data in this form, I've open a bug report on sourceforge and added the file there: ID: 2819440 , https://sourceforge.net/tracker/?func=detail&aid=2819440&group_id=121668&atid=691076)

Now, let's go try to backport your macro.

Regards,
Toby

by Juergen Thies - 10 Jul 2009, 10:43 CEST

To the merge feature:
Since the 2008 release i have change the algorithm for it. Now the same algorithm than for the boolean operations is used. This algorithm works more reliable than the old one.

Since the 2008 version more than 400 fixes and new feature have been added. Quite a lot of it affect the macro interface. (any new feature, some smaler bugs in the macro parsing, ...)

I will send you a evaluation license key, so you can test it on the newest release.

by Toby Mangold - 10 Jul 2009, 13:00 CEST

Thanks for getting me an eval license key.

Meanwhile it's working. The real basic problem was the layer_max in my old 2008 binary. 128!=256. This caused a lot of trouble. I was able to strip down a lot thanks to your tips. Make use of boolean tools working across cells made a big difference (no need for temp. layer). Further, I wish I had been aware of the fact that deleteActuellCell() automatically removes any cellrefs, too.

Now, here's the final macro:

#!/usr/bin/layout
#name=boolean-merge
#help=performs a layer-by-layer merge of selected elements (no cells) based on boolean tools

int main(){
int l;
drawingField *d=layout->drawing;
cell *myCell= d->currentCell;
cell *myTmpCell;
elementList *myElemL;

# we don't want to include any selected cells
d->cDeselect();

# first of all, turn on all layers including a selected element
myElemL=myCell->firstElement;
while(myElemL!=NULL){
if(myElemL->thisElement!=NULL){
layers::num[myElemL->thisElement->layerNum].visible=true;
}
myElemL=myElemL->nextElement;
}

# grouping all elements we'd like to merge
cell *myTmpCell=d->addCell()->thisCell;
myTmpCell->cellName = "~boolean-merge-tmp";
myCell->group(myTmpCell);
myTmpCell->deselectAll();

for (l=0;l<256;l++){
if (layers::num[l].visible ){
# merge this active layer back to the original cell
d->activeLayer=l;
# focus to newly added cell, otherwise either myTmpCell->selectLayer(l) or booleanTool->setA() cause trouble ... I don't care
d->setCell(myTmpCell->cellName);
d->selectActiveLayer();

layout->booleanTool->setA();
layout->booleanTool->setB();
d->setCell(myCell->cellName);
layout->booleanTool->aPlusB();
}
}
d->setCell(myTmpCell->cellName);
d->deleteActuellCell();
d->setCell(myCell->cellName);
}


Please log in to post!