Download (as "inscribe_polygon-ellipsis.pm") inscribe_polygon-ellipsis.pm
#!/usr/pkg/bin/perl
package inscribe;
use GDS2;
use strict;
require './text2gds.pm';
require './4110.ellipsis.pm';
# -----------------------------------------------------
# generate structure ellipsis
# -----------------------------------------------------
sub ellipsis ($$$$){
my $radiusX = shift;
my $radiusY = shift;
my $polygon_count = shift;
my $gds2File = shift;
my $name = sprintf("ellipsys-X%3.3f-Y%3.3f", $radiusX, $radiusY);
$gds2File -> printBgnstr(-name => $name);
$gds2File -> printBoundary (
-xy => [ellipsis::ellipsis (0, 0, 0, 360, $radiusX, $radiusY, $polygon_count, ' ', 1)],
-layer => 56 );
$gds2File -> printEndstr();
return $name;
}
# calculate the X coordinate of the point where the slant = 1;
sub equilibrium($$) {
my $A = shift;
my $B = shift;
my $R = $A * $A / sqrt($A * $A + $B * $B);
return $R;
}
# -----------------------------------------------------
# calculate the coordinate on the ellipsis from x or y
# ----------------------------------------------------
sub get_otherY($$$) {
my $x = shift;
my $radiusX = shift;
my $radiusY = shift;
my $y = $radiusY * sqrt( abs( 1 - $x * $x / ($radiusX * $radiusX)));
return $y;
}
sub get_otherX($$$) {
my $y = shift;
my $radiusX = shift;
my $radiusY = shift;
my $x = $radiusX * sqrt( abs( 1 - $y * $y / ($radiusY * $radiusY)));
return $x;
}
# -----------------------------------------------------
# M A I N S U B R O U T I N E
# -----------------------------------------------------
sub ellipsis_polygon($$$$$) {
my $sizeX = shift; # size of ellipsis (to inscribe)
my $sizeY = shift;
my $pitch = shift; # segment length
my $gds2File = shift;
my $structure_name = sprintf("inscribe_polygon-X%03.3f-Y%03.3f-P%03.3f", $sizeX, $sizeY, $pitch);
my $radiusX = $sizeX/2 + $pitch/2;
my $radiusY = $sizeY/2 + $pitch/2;
# -------------------------------------
# make reference ellipsis
# -------------------------------------
my $polygon_count = int($sizeX * 8);
if ($polygon_count < 72) { $polygon_count = 72;}
my $ellipsis_name = ellipsis( $sizeX/2, $sizeY/2, $polygon_count, $gds2File);
# -------------------------------------
my $ratio = 0.97; # 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 ellipsis
if ($radiusX * ( 1 - $ratio) > $pitch/2) { $ratio = ($radiusX - $pitch/2)/$radiusX ; }
my $start_to_divide = $radiusX * $ratio;
my $end_to_divide = equilibrium($radiusX, $radiusY);
my $step = $pitch;
my $quadrant_count1 = int(($start_to_divide - $end_to_divide)/$step);
if ($quadrant_count1 == 0 ) { $quadrant_count1 = 1;}
# printf("%04d pre count/partial count/step: %4d / %4d / %4.3f\n", __LINE__, $pre_count, $quadrant_count1, $step);
my @part_pointer; # for 0 .. 45 degree, on the ellipsis 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 ellipsis (in between)
my $equillibrium = $end_to_divide;
# ------------------------------------------------------
# from 0 to equillibrium
# ------------------------------------------------------
my $step = $pitch;
my $lasty;
my $this_y;
# print __LINE__ . ' ' . $quadrant_count1. "\n";
foreach my $i ( 0.. $quadrant_count1 - 1) {
# print __LINE__ .' * ' . $index++. "\n";
my $this_x = $start_to_divide - $i * $step; # decreasing at 1st quadrant
$this_y = get_otherY($this_x, $radiusX, $radiusY);
$lasty = $this_y;
if ($ != $quadrant_count1 - 1) {
push(@pointer, [$this_x, $this_y]);
# ----------------------------------------
push(@COORDS_PTR, [$this_x, $this_y]);
push(@COORDS_PTR, [$this_x - $step, $this_y]);
# ----------------------------------------
} else {
}
}
# print __LINE__. ' ' . $lasty . "\n";
# -------------------------------------------------------------------
# from equillibrium to 90 degree,
# -------------------------------------------------------------------
$start_to_divide = get_otherY($equillibrium, $radiusX, $radiusY);
$end_to_divide = $radiusY + $step / 2;
my $quadrant_count2 = int(($end_to_divide - $start_to_divide)/$step);
if ($quadrant_count2 == 0 ) { $quadrant_count2 = 1;}
# print __LINE__ . ' ' . $start_to_divide. "\n";
# print __LINE__ . ' ' . $quadrant_count2. "\n";
# pop(@pointer);
# pop(@COORDS_PTR);
foreach my $i ( 0.. $quadrant_count2) {
# print __LINE__ .' * ' . $index++. "\n";
my $this_y = $start_to_divide + $i * $step;
my $this_x = get_otherX($this_y, $radiusX, $radiusY);
push(@pointer, [$this_x, $this_y]);
# ----------------------------------------
if ($i != 0) {
push(@COORDS_PTR, [$this_x, $this_y - $step]);
} else {
push(@COORDS_PTR, [$this_x, $lasty]);
}
if ($i != $quadrant_count2) {
push(@COORDS_PTR, [$this_x, $this_y ]);
} else {
push(@COORDS_PTR, [$this_x, $this_y - $step/2 ]);
}
# ----------------------------------------
}
# print __LINE__ . ' ' . $start_to_divide. "\n";
# ------------------------------
# start real structure
# ------------------------------
$gds2File -> printBgnstr(-name => $structure_name);
if (1) {
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 ellipsis
$gds2File -> printSref(
-name => $ellipsis_name,
-xy => [0, 0]);
$gds2File -> printEndstr();
return $structure_name;
}
1;
__END__
|