④Layout Editor　マクロ入門

今回からはLayouteditorのマクロについて紹介していこうと思う。
LayoutEditorのマクロはC++、python、Rubyに対応している。
とりあえずC++を使ったマクロについて実例を交えながら紹介していく。

・円を繰り返しで描く
```
#!/usr/bin/layout
#name=circle array
#help=an array of circles with different parameter


int main(){
  int nx=10;                       //列の数
  int ny=9;                        //行の数
  int size=1000;                   //半径
  int stepX=4000;                  //円の中心間距離（ｘ方向）
  int stepY=3900;                  //円の中心間距離（ｙ方向）
  int x,y;
  for(x=0;x<nx;x++){
   for(y=0;y<ny;y++){
     int radius=size;
     layout->drawing->p(x*stepX,y*stepY);
     layout->drawing->p(x*stepX,y*stepY+radius);
     layout->drawing->circle();
     }
  }
  layout->drawing->scaleFull();
}
```
このコードを実行すると同じ円を繰り返して描くことができる。
各変数の値を変えてやれば、列と行の数、半径、ピッチも自由自在だ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039522/c3f027f3-7cfb-2ca4-a719-635099fdacf3.png)

・ドーナッツを繰り返しで描く
```
#!/usr/bin/layout
#name=donut array
#help=an array of donut with different parameter


int main(){
  int nx=5;                       //列の数
  int ny=5;                       //行の数
  int stepX=4000;                 //円の中心間距離（ｘ方向）
  int stepY=3900;                 //円の中心間距離（ｙ方向）
  int radiusouter=1000;           //外形
  int radiusinner=500;            //内径
  int x,y;
  for(x=0;x<nx;x++){
   for(y=0;y<ny;y++){
     // creating outer circle
     layout->drawing->point(x*stepX,y*stepY);
     layout->drawing->point(x*stepX,y*stepY+radiusouter);
     layout->drawing->point(x*stepX,y*stepY+radiusouter);
     layout->drawing->spiral();                                    //spiralは円弧のpathを描く
     layout->drawing->currentCell->firstElement->thisElement->selectAll();
     //creating inner cirlce
     layout->drawing->point(x*stepX,y*stepY);
     layout->drawing->point(x*stepX,y*stepY+radiusinner);
     layout->drawing->point(x*stepX,y*stepY+radiusinner);
     layout->drawing->spiral();                                    //spiralは円弧のpathを描く
     layout->drawing->currentCell->firstElement->thisElement->selectAll();
     //crating connection segment
     layout->drawing->point(x*stepX,y*stepY+radiusinner);
     layout->drawing->point(x*stepX,y*stepY+radiusouter);
     layout->drawing->path();                                      //内径と外形の間をつなぐ
     layout->drawing->currentCell->firstElement->thisElement->selectAll();
     // merge and convert path to a polygon
     layout->drawing->mergeSelect();
     layout->drawing->closeToPolygon();
     layout->drawing->deselectAll();
     }
  }
}
```
このコードを実行するとドーナツ状のポリゴンを繰り返して描くことができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039522/1cdc42ae-56b2-5cc2-634b-b53f85a3af39.png)

・Cellの参照をできるだけ多くウエハの中に敷き詰める
＊実行するとCurrentCellの要素は全て消えるため、注意！
事前準備
①baseCellという名前のCellを作成して、boxを用意しておく。
（長方形でも可、ウエハの大きさに比べてboxが小さすぎると描画に時間がかかるorフリーズするため注意）
②baseCell以外のCellに移動しておく
```
#!/usr/bin/layout
#name=Macro: roundCellArray.layout
#help=filling a wafer with cell references

bool insideCircle(point p, int radius){
 double x=p.x();
 double y=p.y();
 double r=radius;
 double d=x*x+y*y;
 if (d<r*r) return true;
 return false;
}

int main(){
string baseCell="baseCell";
int circleRadius=50000000;  //in databaseunits
int xCenter=0; // center of the circle
int yCenter=0;
layout->drawing->selectAll(); //uncomment these two line to delete design first
layout->drawing->deleteSelect();
string cellname=layout->drawing->currentCell->cellName;
cell *c=layout->drawing->findCell(baseCell);
if (c==NULL){
        layout->showMessage("Error","base cell not found");
       return 0;
}
point min=c->minimum();
point max=c->maximum();
point size=max-min;
point center; center.set(xCenter,yCenter);
int startX=min.x();
int startY=min.y();
while (startY>-circleRadius) startY-=size.y();
while (startX>-circleRadius) startX-=size.x();
int x=startX;
int y=-startY;
do {
   y=startY;
   do {
       point pc; pc.set(x-min.x()+xCenter,y-min.y()+yCenter);
       point p1,p2,p3,p4;
       p1.set(x,y); //lower left
       p2.set(x+size.x(),y); //lower right
       p3.set(x,y+size.y()); // upper left
       p4.set(x+size.x(),y+size.y()); // upper right
       if (insideCircle(p1,circleRadius)&&insideCircle(p2,circleRadius)
           &&insideCircle(p3,circleRadius)&&insideCircle(p4,circleRadius)){
              element *e=layout->drawing->currentCell->addCellref(c,pc);
       }
       y+= size.y();
  } while (y<circleRadius+size.y());
   x+= size.x();
} while (x<circleRadius+size.x());
layout->drawing->currentCell->addCircle(1,center,circleRadius,360); //uncomment to show circle
layout->drawing->scaleFull();
}
```
このコードを実行するとbaseCellのセル参照をウエハ内に敷き詰めることができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3039522/2dcd3fdf-fe08-9ed2-d6cc-ba0d4b4620f1.png)
正直なところ、コードの意味はまだ理解できていないので勉強しなければ、、、

今回はここまで！マクロは使いこなせれば強力なツールになりそうですね～
コードは以下のwebsiteを参考にしています。
http://www.layouteditor.net/wiki/CategoryMacro