Perl で gdsii
実行環境
  Active Perl
     更新するには
ppm
  ppm
  DownLoad
  実行
Help
   perldoc GDS2
Examples
  basic-lines
  simple
  simple-sref
  aref
  circle
  circle-inverted
  sample-arc
  donut
  Inverted-Donuts
  Donuts_Combination
  Hello-World
  CP-array
  text2gds.pm
  rotate.pm
  rotate-rectangle
  arc.pm
  line-and-space-180
  triangle-array-nega
  sq_sleeve.pm
  TriangleGridStep
  triangle-array-nega-CP
  CirclesArray-SQ
  LargeCircles
  MA6-Alignment-mark.pm
  Alignment-Place
  Triangle-Grid
  Triangle-Grid-Wide
  ellipsis-polygons
  inscribe_polygon
  inscribe_polygon.pm
  inscribe_polygon-ellipsis.pm
  sleeving-by-square-sample
  sleeving-by-square.pm

Perl Perl/GDSII page
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

Last Update: Mon, 21 Feb 2022 10:13:01 GMT 1.66 2008/03/08