Download (as "sleeving-by-square.pm") sleeving-by-square.pm
#!/usr/pkg/bin/perl
package sleeving;
use GDS2;
use strict;
use POSIX qw(floor ceil);
require './text2gds.pm';
require './arc.pm';
require './rotate.pm';
# -----------------------------------------------------
# generate structure circle
# -----------------------------------------------------
sub circle ($$$){
my $radius = shift;
my $polygon_count = shift;
my $gds2File = shift;
my $name = sprintf("circle-R%3.2f", $radius);
$gds2File -> printBgnstr(-name => $name);
$gds2File -> printBoundary (
-xy => [arc::arc (0, 0, 0, 360, $radius, $polygon_count, ' ', 1)],
-layer => 56 );
$gds2File -> printEndstr();
return $name;
}
# -----------------------------------------------------
# calculate the coordinate on the circle from x or y
# ----------------------------------------------------
sub get_other($$) {
my $x = shift;
my $radius = shift;
$x *= 100;
$radius *= 100;
my $y = sqrt(abs ($radius * $radius - $x * $x));
return $y/100;
}
sub SqSIPHA {
my ($args) = @_;
my ($size) = $args -> {-size}; # nm
my ($angle) = $args -> {-angle};
my ($layer) = $args -> {-layer};
my ($gds2File) = $args -> { -gds2File};
my $name = sprintf("SqSIPHA%dW%dnm", $angle, $size);
my $W = $size/1000;
my $H = $size/1000;
$gds2File -> printBgnstr (-name => $name);
$gds2File -> printBoundary (
-xy=> [
rotate::rotate(-$W/2, -$H/2, $angle),
rotate::rotate( $W/2, -$H/2, $angle),
rotate::rotate( $W/2, $H/2, $angle),
rotate::rotate(-$W/2, $H/2, $angle)],
-layer=> $layer
);
$gds2File -> printEndstr();
return $name;
}
# -----------------------------------------------------
# M A I N S U B R O U T I N E
# -----------------------------------------------------
sub sleeving {
my ($args) = @_;
my ($size) = $args -> {-size};
my ($pitch) = $args -> {-pitch}; # segment length
my ($gds2File) = $args -> { -gds2File};
my $structure_name = sprintf("sleeving-S%5.3f-P%3.3f", $size, $pitch);
my $polygon =
inscribe_polygon ({
-size => $size - 0.15,
-pitch => $pitch,
-gds2File => $gds2File
});
$gds2File -> printBgnstr( -name => $structure_name);
my $radius_circle = $size/ 2 - 0.05;
my $peripheral = $size * 3.14159265;
my $count = int($peripheral/0.1) + 1;
my @COORDS = arc::arc(0,0, 0, 360, $radius_circle, $count, '', 1);
my $angle_step = 360/$count;
foreach my $i ( 0.. int($#COORDS/2)) {
my $angle = $i * $angle_step;
my $mod90 = $angle % 90;
my $proxy = int(($mod90 + 2.5)/5) * 5;;
# print __LINE__, $proxy,"\n";
if ($proxy == 90 ) { $proxy = 0;}
my $CP = sprintf("SqSIPHA%dW100nm", $proxy);
$gds2File -> printSref( -name => $CP, -xy => [ $COORDS[$i * 2], $COORDS[$i * 2 + 1]]);
}
$gds2File -> printSref( -name => $polygon, -xy => [0, 0]);
$gds2File -> printEndstr();
return $structure_name;
}
sub inscribe_polygon {
my ($args) = @_;
my ($size) = $args -> {-size};
my ($pitch) = $args -> {-pitch}; # segment length
my ($gds2File) = $args -> { -gds2File};
my $structure_name = sprintf("inscribe_polygon-S%5.3f-P%3.3f", $size, $pitch);
# -------------------------------------
# make reference cirlce
# -------------------------------------
my $polygon_count = int($size * 8);
if ($polygon_count < 72) { $polygon_count = 72;}
my $circle_name = circle( $size/2, $polygon_count, $gds2File);
# -------------------------------------
my $radius = $size /2;
my $ratio = 0.99; # start point ratio, set 1 makes the length of first segment equals to 0
# take care the case if the pitch is very small against the circle
if ($radius * ( 1 - $ratio) > $pitch/2) {
$ratio = ($radius - $pitch/2)/$radius ;
printf("%04d ******** %3.2f %3.2f\n", __LINE__, $ratio, $pitch);
}
my $start_to_divide = $radius * $ratio;
my $end_to_divide = $radius * sqrt(2)/2;
printf("%04d %3.2f %3.2f\n", __LINE__, $start_to_divide, $end_to_divide);
my $pre_count = floor($end_to_divide /$pitch); # from whole size
my $quadrant_count = $pre_count + 1; # half after two extreme removed
if ($quadrant_count <= 0 ) { $quadrant_count = 1;}
my $step = $end_to_divide / ($quadrant_count + 1) / 2;
printf(
"%04d radius / pitch / pre count / quadrant count / step / end to divide
%3.2f / %3.2f / %4d / %4d / %4.3f / %4.3f \n",
__LINE__, $radius, $pitch, $pre_count, $quadrant_count, $step, $end_to_divide);
my @part_pointer; # for 0 .. 45 degree, on the circle line
my @rev_pointer; # for 45 .. 90 degree, on the circle line
my @pointer; # for 0 .. 90
my $index = 0; # only for debug, not used for now
my $X = 0; # constant Macro
my $Y = 1; # ditto
my @COORDS_PTR; # coordinate pointer, x1, y1, x2, y2, ... xn, yn
# add the coordinate inside of the circle (in between)
# ------------------------------------------------------
# from 0 to 45 degree
# ------------------------------------------------------
my $prev_y = 0;
my $last_y;
foreach my $i ( 0.. ($quadrant_count * 2 + 2)) {
if ( ($i < ($quadrant_count * 2 + 1) * 0.9 ) &&
($i % 2 == 1 ) ) {next;} # every two step
my $this_y = $i * $step; # increasing at 1st quadrant
my $this_x = get_other($this_y, $radius);
# print __LINE__ .' * ' . $index++, ' ' , int ($step*100) / 100 , ' ' , $this_y, ' ' , $this_x. "\n";
push(@part_pointer, [$this_x, $this_y]);
# ----------------------------------------
push(@COORDS_PTR, [$this_x, $prev_y]);
push(@COORDS_PTR, [$this_x, $this_y]);
$prev_y = $this_y;
$last_y = $this_y;
# ----------------------------------------
}
my $E = $last_y;
push(@COORDS_PTR, [$last_y, $last_y]);
push(@pointer, @part_pointer); # copy the first 0 .. 45 to whole
#push(@pointer, [$E, $E]); # put the center point
#push(@COORDS_PTR, [$E, $E]); # also add on actual coordinate.
#push(@COORDS_PTR, [$E - $step/2, $E - $step/2]); # also add on actual coordinate.
# -------------------------------------------------------------------
# from 45 to 90 degree, copy 0 .. 45 data with reversed order
# -------------------------------------------------------------------
foreach my $i (reverse (0 .. $#part_pointer)) {
# print __LINE__ .' * ' . $index++. "\n";
push (@rev_pointer, [$part_pointer[$i] ->[$Y],
$part_pointer[$i] ->[$X]]);
# ----------------------------------------
# push(@COORDS_PTR, [$part_pointer[$i] ->[$Y],
# $part_pointer[$i] ->[$X]]);
# ----------------------------------------
}
my (@COPY);
@COPY = @COORDS_PTR;
foreach my $i (reverse (0.. $#COPY)) {
push(@COORDS_PTR, [$COPY[$i] ->[$Y], $COPY[$i] ->[$X]]);
# print __LINE__. ' ' . $i, ' ', $COPY[$i] ->[0]. ' ' . $COPY[$i] ->[1], "\n";
}
push(@pointer, @rev_pointer); # copy the 45 .. 90 to whole (important to digit mark)
# ------------------------------
# start real structure
# ------------------------------
$gds2File -> printBgnstr(-name => $structure_name);
for my $i ( 0..$#pointer){
text2gds::text_flat( $pointer[$i] -> [$X], $pointer[$i] -> [$Y],
15, $pitch/30, $i + 1, $gds2File);
}
my @COORDS; # This will finally be the printBoundary coordinates.
# ------------------------------
# pointer to vertex, one quadrant by one quadrant
# ------------------------------
for my $i ( 0..$#COORDS_PTR){
push (@COORDS, $COORDS_PTR[$i] -> [$X],
$COORDS_PTR[$i] -> [$Y]);}
for my $i ( reverse 0..$#COORDS_PTR){
push (@COORDS, - $COORDS_PTR[$i] -> [$X],
$COORDS_PTR[$i] -> [$Y]);}
for my $i ( 0..$#COORDS_PTR){
push (@COORDS, - $COORDS_PTR[$i] -> [$X],
- $COORDS_PTR[$i] -> [$Y]);}
for my $i ( reverse 0..$#COORDS_PTR){
push (@COORDS, $COORDS_PTR[$i] -> [$X],
- $COORDS_PTR[$i] -> [$Y]);}
$gds2File -> printBoundary (-xy=> [@COORDS], -layer=> 0);
# place reference circle
$gds2File -> printSref(
-name => $circle_name,
-xy => [0, 0]);
text2gds::text_flat ( 0, -0.5, 53, 0.005, $structure_name, $gds2File);
$gds2File -> printEndstr();
return $structure_name;
}
1;
__END__
|