Download (as "donut.txt") donut
#!/usr/bin/perl -w
# GDSII generation for 10/5 um circle
use GDS2;
use strict;
use POSIX qw(floor ceil);
use Getopt::Std;
use Math::Trig;
require './text2gds.pm';
require './arc.pm'; # 円弧座標(の組)を計算して返す
# ---------------------------------
# arc::arc(中心 x, 中心 y, 開始角, 終了角, 半径, 頂点の数,
# 'not-used', 時計回り(-1) or 反時計回り(1) )
# ---------------------------------
our @ARGS;
our %opts;
my($VERSION);
$VERSION = "2018-09-07 11:40" ; # written by emacs time-stamp
# global variable, ここで宣言すると、 sub の中からも見える
my $pi = 3.141592;
sub rotate ($$$) {
my ($x) = shift;
my ($y) = shift;
my ($angle) = shift; # in degree
# ------------------------------------------------
# X cos(theta) -sin(theta) x
# =
# Y sin(theta) cos(theta) y
# ------------------------------------------------
my ($theta) = $angle * 3.14159265 /180;
## https://mathwords.net/heimenkaiten
my ($X) = $x * cos($theta) + $y * - sin($theta);
my ($Y) = $x * sin($theta) + $y * cos($theta);
return ($X, $Y);
}
# ------------------------------------------------
# CP のstructure を作る
# ------------------------------------------------
sub SqSIPHA ($$$$) {
my $S = shift; # nm
my $angle = shift;
my $policy = shift;
my $gds2File = shift;
my $name = sprintf("SqSIPHA%dW%dnm-L%02d", $angle, $S, $policy);
my $W = $S/1000; # --- nanometer to micron
my $H = $S/1000;
$gds2File -> printBgnstr (-name => $name);
$gds2File -> printBoundary (
-xy=> [
rotate(-$W/2, -$H/2, $angle),
rotate( $W/2, -$H/2, $angle),
rotate( $W/2, $H/2, $angle),
rotate(-$W/2, $H/2, $angle)],
-layer => $policy
);
$gds2File -> printEndstr();
return $name;
}
# ------------------------------------------------
# donut -h と入力した時の表示 (help)
# ------------------------------------------------
sub usage() {
print <<HELP;
$0:
Generate GDSII oblique
Usage
perl $0 [-h]
Where
-h show this help
HELP
}
# ------------------------------------------------------
# 幅 400nm, のドーナツ形状を作る、両側を 100nm の正方形でふちどり
# ------------------------------------------------------
sub donut ($$$ $$){
my $step = shift; # --- angle step
my $diameter = shift;
my $extra_count = shift; # --- 周囲に配置する CP の数に追加
my $policy = shift; # 切捨(1)、 四捨五入(2) の切替
my $gds2File = shift;
my $outer_length = ( $diameter /2 - 0.05) * $pi * 2;
my $inner_length = (($diameter-0.4)/2 + 0.05) * $pi * 2;
my $outer_count = int($outer_length/ 0.1) + $extra_count;
my $inner_count = int($inner_length/ 0.1) + $extra_count;
my $angle_pitch = 360/$outer_count;
# -------------------------------------------------------
# 円の内側と外側(から 0.05 だけ中に入った曲線)の座標を用意する
# -------------------------------------------------------
my @OUTER_COORDS = arc::arc(0, 0, 0, 360, ($diameter/2) - 0.05, $outer_count, 'not-used', -1 );
my @INNER_COORDS = arc::arc(0, 0, 0, 360, ($diameter/2) - 0.4 + 0.05, $inner_count, 'not-used', -1 );
# ------------------------------------------------------
# structure 開始, policy は切捨、四捨五入の切替
# ------------------------------------------------------
my $structure = sprintf("100nm-%ddeg-%dum-P%0d", $step, $diameter, $policy);
$gds2File -> printBgnstr( -name=> $structure);
# -----------------------------------
# 外側部分
# -----------------------------------
foreach my $i ( 0 .. $#OUTER_COORDS/2) { # $#variable は (@variable の個数 - 1) を表わす
my $structure;
# -------------------------------------------------------------------
# 座標は x1, y1, x2, y2 と並んでいるので、 x と y を一つおきに取出して組で使う
# -------------------------------------------------------------------
my ($x) = $OUTER_COORDS[$i * 2];
my ($y) = $OUTER_COORDS[$i * 2 + 1];
my $angle = atan($y/$x) * 180/$pi;
my $angle_round;
if ($policy == 1) {
$angle_round = int ( $angle %90/$step)* $step;
} else {
$angle_round = int (($angle+$step/2)%90/$step)* $step;
}
$gds2File -> printSref(
# layer = policy = 1 の方が切捨
# layer = policy = 2 の方が四捨五入
-name => sprintf("SqSIPHA%dW100nm-L%02d", $angle_round, $policy),
-xy => [$x, $y]);
}
# -----------------------------------
# 内側部分
# -----------------------------------
foreach my $i ( 0 .. $#INNER_COORDS/2) {
my $structure;
my ($x) = $INNER_COORDS[$i * 2];
my ($y) = $INNER_COORDS[$i * 2 + 1];
my $angle = atan($y/$x) * 180/$pi;
my $angle_round;
if ($policy == 1) {
$angle_round = int ( $angle %90/$step)* $step;
} else {
$angle_round = int (($angle+$step/2)%90/$step)* $step;
}
$gds2File -> printSref(
-name => sprintf("SqSIPHA%dW100nm-L%02d", $angle_round, $policy),
-xy => [$x, $y]);
}
# -----------------------------------
# 文字を描く
# -----------------------------------
my $title = sprintf("100nm by %d degree %d um +count(%d)",
$step, $diameter, $extra_count);
# -----------------------------------
# 文字を置くのに、適切な座標を計算
# -----------------------------------
my $text_x = - length($title) /3;
my $text_y = - $diameter * 0.8 ;
text2gds::text_flat($text_x, $text_y, 25, 0.1, , $title, $gds2File);
# -----------------------------------
# VSB 用の多角形(ドーナツ形)
# -----------------------------------
$gds2File -> printBoundary(
-xy => [
# 次の二つは回転方向(座標の並んでいる順)が逆 ↓
arc::arc(0, 0, 0, 180, $diameter/2 - 0.08, 72, 'not-used', -1 ), # 上半分の外側
arc::arc(0, 0, 0, 180, $diameter/2 - 0.4 + 0.08, 72, 'not-used', 1 ), # 上半分の内側
],
-layer => 0
);
$gds2File -> printBoundary(
-xy => [
arc::arc(0, 0, 180, 360, $diameter/2 - 0.08, 72, 'not-used', -1 ), # 下半分の外側
arc::arc(0, 0, 180, 360, $diameter/2 - 0.4 + 0.08, 72, 'not-used', 1 ), # 下半分の内側
],
-layer => 0
);
$gds2File -> printEndstr;
return $structure;
}
## --------------------------------------------
## M A I N R O U T I N E
## --------------------------------------------
my ($gds2File);
my ($X) = 0; # constant (MACRO)
my ($Y) = 1; # ditto
getopts('h', \%opts);
if ($opts{'h'} ) { usage() ; exit;}
my $filename = $0;
$filename =~ s/\.txt$//; # --- Strip '.txt' part
$filename .= '.gds';
print 'output name: '. $filename, "\n";
unlink $filename;
$gds2File = new GDS2(-fileName=> '>'. $filename );
$gds2File -> printInitLib(-name=>'LibraryName');
# ---------------------------------------------------------------------
# prepare CP structure ( by 1 degree step, with layer 1 and 2)
# ----------------------------------------------------------------------
foreach my $layer (1, 2) {
foreach my $angle ( 0..89 ) {
SqSIPHA(100, $angle, $layer, $gds2File);
};
}
# -----------------------------------------------------------------
# M A I N P A R T O F M A K I N G D O N U T S
# ----------------------------------------------------------------
my $extra_count = 10;
my @NAMES; # --- To collect structure names
foreach my $diameter ( 5, 10 ) {
foreach my $step (1, 5) { # --- angle step
foreach my $policy (1, 2) { # --- floor or round
push (@NAMES, donut($step, $diameter, $extra_count, $policy, $gds2File));
};
};
}
$gds2File -> printBgnstr( -name=> 'top');
# ------------------------------------------------------------------------
# place (make Strucure Reference of) above collected four
# ------------------------------------------------------------------------
foreach my $i ( 0..$#NAMES){
my $index = int($i/2); # --- place two at the same location
$gds2File -> printSref( -name=> $NAMES[$i], -xy => [0, $index * 15]);
}
text2gds::text_flat(-5, -10, 25, 0.1, , $VERSION, $gds2File);
$gds2File -> printEndstr;
$gds2File -> printEndlib();
__END__
(require 'time-stamp)
(add-hook 'write-file-hooks 'time-stamp)
(setq time-stamp-active t)
;; (setq time-stamp-time-zone "UTC")
(setq time-stamp-time-zone nil)
(setq time-stamp-format "%04y-%02m-%02d %02H:%02M");
(setq time-stamp-start "$VERSION = \"") ;
(setq time-stamp-end "\"") ;
(setq time-stamp-line-limit 20) ; ; default is 8
|