Download (as "inscribe_polygon.pm") inscribe_polygon.pm
#!/usr/pkg/bin/perl
package inscribe;
use GDS2;
use strict;
#require './text2gds.pm';
require './arc.pm';
my %DUPE_CHECK;
# -----------------------------------------------------
# generate structure circle
# -----------------------------------------------------
sub circle ($$$){
my $radius = shift;
my $polygon_count = shift;
my $gds2File = shift;
my $name = sprintf("circle-R%1.2f", $radius);
if ($DUPE_CHECK{$name}++) { return $name;}
$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;
my $y = sqrt( abs( $radius * $radius - $x * $x));
return $y;
}
# -----------------------------------------------------
# M A I N S U B R O U T I N E
# -----------------------------------------------------
sub inscribe_polygon($$$) {
my $size = shift; # size of circle (to inscribe)
my $pitch = shift; # segment length
my $gds2File = shift;
my $structure_name = sprintf("inscribe_polygon-S%1.2f-P%1.2f", $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 ; }
my $start_to_divide = $radius * $ratio;
my $end_to_divide = $radius * sqrt(2)/2;
my $pre_count = int($radius/$pitch); # from whole size
my $quadrant_count = int(($pre_count - 2)/ 2); # half after two extreme removed
if ($quadrant_count == 0 ) { $quadrant_count = 1;}
my $step = (- $end_to_divide + $start_to_divide) / $quadrant_count;
printf("%04d pre count/partial count/step: %4d / %4d / %4.3f\n", __LINE__, $pre_count, $quadrant_count, $step);
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
# ------------------------------------------------------
foreach my $i ( 0.. $quadrant_count -1) {
# print __LINE__ .' * ' . $index++. "\n";
my ($this_x, $this_y);
$this_x = $start_to_divide - $i * $step ; # decreasing at 1st quadrant
$this_y = get_other($this_x, $radius);
push(@part_pointer, [$this_x, $this_y]);
# ----------------------------------------
push(@COORDS_PTR, [$this_x, $this_y]);
push(@COORDS_PTR, [$this_x - $step, $this_y]);
# ----------------------------------------
}
my $E = $end_to_divide;
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.
# -------------------------------------------------------------------
# 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] - $step]);
push(@COORDS_PTR, [$part_pointer[$i] ->[$Y],
$part_pointer[$i] ->[$X]]);
# ----------------------------------------
}
push(@pointer, @rev_pointer); # copy the 45 .. 90 to whole
# ------------------------------
# start real structure
# ------------------------------
$gds2File -> printBgnstr(-name => $structure_name);
if (0) {
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]);
$gds2File -> printEndstr();
return $structure_name;
}
1;
__END__
|