diff options
author | Ruben Undheim <ruben.undheim@gmail.com> | 2019-10-18 21:46:49 +0200 |
---|---|---|
committer | Ruben Undheim <ruben.undheim@gmail.com> | 2019-10-18 21:46:49 +0200 |
commit | 0fd6ff7ea7c1cfb4f53b2f79e5afac228e283f0f (patch) | |
tree | 335cce98269b0a462d1d58ba8b95deb677e2186d | |
parent | 34ba80aa541f0e7960d02e31f70cb37c64169f53 (diff) |
New upstream version 0.2+ds.1
-rw-r--r-- | COPYRIGHT | 18 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | applications/DumpGDSIIFile.cc | 36 | ||||
-rw-r--r-- | applications/DumpGDSIIRecords.cc | 47 | ||||
-rw-r--r-- | applications/GDSII2GMSH.cc | 418 | ||||
-rw-r--r-- | applications/GDSIIConvert.cc | 27 | ||||
-rw-r--r-- | lib/Flatten.cc | 26 | ||||
-rw-r--r-- | lib/ReadGDSIIFile.cc | 9 | ||||
-rw-r--r-- | lib/libGDSII.cc | 5 | ||||
-rw-r--r-- | lib/libGDSII.h | 24 |
10 files changed, 75 insertions, 537 deletions
diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..bbaa3b9 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,18 @@ +/* Copyright (C) 2018 M. T. Homer Reid + * + * This file is part of LIBGDSII. + * + * LIBGDSII is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LIBGDSII is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ diff --git a/Makefile.am b/Makefile.am index f12cfd2..cf3853a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,3 +4,5 @@ AM_CFLAGS = -O3 AM_CXXFLAGS = -O3 SUBDIRS = lib applications examples EXTRA_DIST = COPYRIGHT + + diff --git a/applications/DumpGDSIIFile.cc b/applications/DumpGDSIIFile.cc deleted file mode 100644 index 253f1f4..0000000 --- a/applications/DumpGDSIIFile.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 2005-2017 Massachusetts Institute of Technology -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2, or (at your option) -% any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software Foundation, -% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* - * DumpGDSIIFile -- simple test/demo program for libGDSII library - * -- for working with GDSII files - * Homer Reid 11/2017 - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> -#include <string> - -#include "libGDSII.h" -#include "GDSIIOptions.h" - -int main(int argc, char *argv[]) -{ - GDSIIOptions *Options = ProcessGDSIIOptions(argc, argv); -} diff --git a/applications/DumpGDSIIRecords.cc b/applications/DumpGDSIIRecords.cc deleted file mode 100644 index afd6c74..0000000 --- a/applications/DumpGDSIIRecords.cc +++ /dev/null @@ -1,47 +0,0 @@ - -/* Copyright (C) 2005-2017 Massachusetts Institute of Technology -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2, or (at your option) -% any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software Foundation, -% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* - * DumpGDSIIRecords -- utility for writing text descriptions - * -- of data records in a GDS II file - * - * Homer Reid 11/2017 - */ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string> - -#include "libGDSII.h" - -using namespace std; -using namespace libGDSII; - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -int main(int argc, char *argv[]) -{ - if ( argc!=2 ) - { printf("usage: DumpGDSIIRecords File.gds\n"); - exit(1); - }; - - DumpGDSIIFile(argv[1]); -} diff --git a/applications/GDSII2GMSH.cc b/applications/GDSII2GMSH.cc deleted file mode 100644 index e998659..0000000 --- a/applications/GDSII2GMSH.cc +++ /dev/null @@ -1,418 +0,0 @@ -/* Copyright (C) 2005-2017 Massachusetts Institute of Technology -% -% This program is free software; you can redistribute it and/or modify -% it under the terms of the GNU General Public License as published by -% the Free Software Foundation; either version 2, or (at your option) -% any later version. -% -% This program is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You should have received a copy of the GNU General Public License -% along with this program; if not, write to the Free Software Foundation, -% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*/ - -/* - * GDSII2GMSH.cc -- convert GDSII file to GMSH geometry file - * Homer Reid 12/2017 - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <math.h> -#include <string> -#include <sstream> - -#include "libGDSII.h" -#include "GDSIIOptions.h" - -using namespace std; -using namespace libGDSII; - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -typedef struct GTransform - { double X0, Y0; - double CosTheta, SinTheta; - double Mag; - bool Refl; - } GTransform; - -typedef vector<GTransform> GTVec; - -void ApplyGTransform(GTransform GT, double X, double Y, double *XP, double *YP) -{ - X *= GT.Mag; - Y *= (GT.Refl ? -1.0 : 1.0)*GT.Mag; - *XP = GT.X0 + GT.CosTheta*X - GT.SinTheta*Y; - *YP = GT.Y0 + GT.SinTheta*X + GT.CosTheta*Y; -} - -/***************************************************************/ -/* data structure that keeps track of the status of the GMSH */ -/* file output process */ -/***************************************************************/ -typedef struct StatusData -{ - int NumNodes, NumLines, NumSurfaces, RefDepth; - bool PPFormat; - double UnitInMM, LayerThickness; - string GeoFileName, PPFileName; - FILE *GeoFile, *PPFile; - int CurrentLayer; - GTVec GTStack; -} StatusData; - -void InitStatusData(StatusData *SD) -{ - SD->NumNodes=0; - SD->NumLines=0; - SD->NumSurfaces=0; - SD->RefDepth=0; - SD->PPFormat=false; - SD->UnitInMM=1.0; - SD->LayerThickness=0.0; - SD->GeoFile = 0; - SD->PPFile = 0; - SD->CurrentLayer = -1; - SD->GTStack.clear(); -} - -void OpenGeoFile(StatusData *SD) -{ if (SD->GeoFile) return; - SD->GeoFile=fopen(SD->GeoFileName.c_str(),"w"); - if (!SD->GeoFile) - GDSIIData::ErrExit("could not open file %s",SD->GeoFileName.c_str()); -} - -void OpenPPFile(StatusData *SD) -{ if (SD->PPFile) return; - SD->PPFile=fopen(SD->PPFileName.c_str(),"w"); - if (!SD->PPFile) - GDSIIData::ErrExit("could not open file %s",SD->PPFileName.c_str()); -} - -void GetPhysicalXY(StatusData *SD, double X, double Y, double *pXP, double *pYP) -{ - double XP=X, YP=Y; - for(unsigned n=SD->GTStack.size(); n>0; n--) - { ApplyGTransform(SD->GTStack[n-1],X,Y,&XP,&YP); - X=XP; - Y=YP; - } - *pXP = SD->UnitInMM * XP; - *pYP = SD->UnitInMM * YP; -} - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -void WriteBoundary(StatusData *SD, GDSIIData *Data, int ns, int ne) -{ - GDSIIStruct *s = Data->Structs[ns]; - GDSIIElement *e = s->Elements[ne]; - vector<int> XY = e->XY; - int NXY = XY.size() / 2; - - double Z0 = e->Layer * SD->LayerThickness; - double Unit = SD->UnitInMM; - - if (SD->CurrentLayer!=-1 && SD->CurrentLayer!=e->Layer) return; - OpenGeoFile(SD); - - fprintf(SD->GeoFile,"// Struct %s element #%i (boundary)\n",s->Name->c_str(),ne); - - int Node0=SD->NumNodes; - for(int n=0; n<NXY-1; n++) - { double X, Y; - GetPhysicalXY(SD, XY[2*n+0], XY[2*n+1], &X, &Y); - fprintf(SD->GeoFile,"Point(%i)={%e,%e,%e};\n",++(SD->NumNodes),X,Y,Z0); - } - - int Line0=SD->NumLines; - for(int n=0; n<NXY-2; n++) - fprintf(SD->GeoFile,"Line(%i)={%i,%i}; \n",++(SD->NumLines),Node0+1+n,Node0+n+2); - fprintf(SD->GeoFile,"Line(%i)={%i,%i}; \n",++(SD->NumLines),Node0+NXY-1,Node0+1); - - fprintf(SD->GeoFile,"Line Loop(%i)={",(SD->NumSurfaces)++); - for(int n=0; n<NXY-2; n++) - fprintf(SD->GeoFile,"%i,",Line0+n+1); - fprintf(SD->GeoFile,"%i};\n",Line0+NXY-1); - fprintf(SD->GeoFile,"Plane Surface(%i)={%i};\n",SD->NumSurfaces-1,SD->NumSurfaces-1); - - //fprintf(SD->GeoFile,"Extrude{ 0, 0, %e } { Surface{%i}; }\n",LayerThickness,NumSurfaces-1); - fprintf(SD->GeoFile,"\n"); -} - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -void WritePath(StatusData *SD, GDSIIData *Data, int ns, int ne) -{ - GDSIIStruct *s = Data->Structs[ns]; - GDSIIElement *e = s->Elements[ne]; - vector<int> XY = e->XY; - int NXY = XY.size() / 2; - - double Z0 = SD->LayerThickness; - double Unit = SD->UnitInMM; - double DeltaZ = 1.0*Unit; - double W = e->Width*Unit; - - if (SD->CurrentLayer!=-1 && SD->CurrentLayer!=e->Layer) return; - OpenGeoFile(SD); - - fprintf(SD->GeoFile,"// Struct %s element #%i (path)\n",s->Name->c_str(),ne); - - int Line0 = SD->NumLines; - - for(int n=0; n<NXY; n++) - { - // coordinates of center point - double X1, Y1; - GetPhysicalXY(SD, XY[2*n+0], XY[2*n+1], &X1, &Y1); - - if (W==0.0) - { - fprintf(SD->GeoFile,"Point(%i)={%e,%e,%e}; \n",(SD->NumNodes)++,X1,Y1,Z0); - if (n>0) fprintf(SD->GeoFile,"Line(%i)={%i,%i};\n",(SD->NumLines)++,SD->NumNodes-2,SD->NumNodes-1); - } - else if (n<(NXY-1)) - { - int np1 = (n+1)%NXY; - double X2, Y2; - GetPhysicalXY(SD, XY[2*np1+0], XY[2*np1+1], &X2, &Y2); - - // unit vector in width direction - double DX = X2-X1, DY=Y2-Y1, DNorm = sqrt(DX*DX + DY*DY); - if (DNorm==0.0) DNorm=1.0; - double XHat = +1.0*DY / DNorm; - double YHat = -1.0*DX / DNorm; - - fprintf(SD->GeoFile,"Point(%i)={%e,%e,%e};\n",SD->NumNodes++,X1-0.5*W*XHat,Y1-0.5*W*YHat,Z0); - fprintf(SD->GeoFile,"Point(%i)={%e,%e,%e};\n",SD->NumNodes++,X2-0.5*W*XHat,Y2-0.5*W*YHat,Z0); - fprintf(SD->GeoFile,"Point(%i)={%e,%e,%e};\n",SD->NumNodes++,X2+0.5*W*XHat,Y2+0.5*W*YHat,Z0); - fprintf(SD->GeoFile,"Point(%i)={%e,%e,%e};\n",SD->NumNodes++,X1+0.5*W*XHat,Y1+0.5*W*YHat,Z0); - - fprintf(SD->GeoFile,"Line(%i)={%i,%i};\n",SD->NumLines++,SD->NumNodes-4,SD->NumNodes-3); - fprintf(SD->GeoFile,"Line(%i)={%i,%i};\n",SD->NumLines++,SD->NumNodes-3,SD->NumNodes-2); - fprintf(SD->GeoFile,"Line(%i)={%i,%i};\n",SD->NumLines++,SD->NumNodes-2,SD->NumNodes-1); - fprintf(SD->GeoFile,"Line(%i)={%i,%i};\n",SD->NumLines++,SD->NumNodes-1,SD->NumNodes-4); - - if (n<(NXY-2)) continue; - - fprintf(SD->GeoFile,"Line Loop(%i)={",SD->NumSurfaces++); - for(int m=0; m<NXY-2; m++) - fprintf(SD->GeoFile,"%i,",Line0+m+1); - fprintf(SD->GeoFile,"%i};\n",Line0+NXY-1); - fprintf(SD->GeoFile,"Plane Surface(%i)={%i};\n",SD->NumSurfaces-1,SD->NumSurfaces-1); - } - } -} - -void WriteStruct(StatusData *SD, GDSIIData *Data, int ns, bool ASRef=false); - -void WriteASRef(StatusData *SD, GDSIIData *Data, int ns, int ne) -{ - SD->RefDepth++; - - GDSIIStruct *s = Data->Structs[ns]; - GDSIIElement *e = s->Elements[ne]; - vector<int> XY = e->XY; - - int nsRef = e->nsRef; - if ( nsRef==-1 || nsRef>=((int)(Data->Structs.size())) ) - GDSIIData::ErrExit("structure %s, element %i: REF to unknown structure %s",s->Name,ne,e->SName); - - double Mag = (e->Type==SREF) ? e->Mag : 1.0; - double Angle = (e->Type==SREF) ? e->Angle : 0.0; - bool Refl = (e->Type==SREF) ? e->Refl : false; - - GTransform GT; - GT.CosTheta=cos(Angle*M_PI/180.0); - GT.SinTheta=sin(Angle*M_PI/180.0); - GT.Mag=Mag; - GT.Refl=Refl; - SD->GTStack.push_back(GT); - GTransform *CurrentTransform = &(SD->GTStack[SD->GTStack.size()-1]); - - double Unit = SD->UnitInMM; - - int NC=1, NR=1; - double XYCenter[2], DeltaXYC[2]={0,0}, DeltaXYR[2]={0,0}; - XYCenter[0] = (double)XY[0]; - XYCenter[1] = (double)XY[1]; - if (e->Type == AREF) - { - NC = e->Columns; - NR = e->Rows; - DeltaXYC[0] = (XY[2] - XYCenter[0]) / NC; - DeltaXYC[1] = (XY[3] - XYCenter[1]) / NC; - DeltaXYR[0] = (XY[4] - XYCenter[0]) / NR; - DeltaXYR[1] = (XY[5] - XYCenter[1]) / NR; - } - - for(int nc=0; nc<NC; nc++) - for(int nr=0; nr<NR; nr++) - { - CurrentTransform->X0 = XYCenter[0] + nc*DeltaXYC[0] + nr*DeltaXYR[0]; - CurrentTransform->Y0 = XYCenter[1] + nc*DeltaXYC[1] + nr*DeltaXYR[1]; - WriteStruct(SD, Data, nsRef, true); - } - - SD->GTStack.pop_back(); - SD->RefDepth--; -} - -void WriteText(StatusData *SD, GDSIIData *Data, int ns, int ne) -{ - GDSIIStruct *s = Data->Structs[ns]; - GDSIIElement *e = s->Elements[ne]; - vector<int> XY = e->XY; - - if (SD->CurrentLayer!=-1 && SD->CurrentLayer!=e->Layer) return; - - double X, Y; - GetPhysicalXY(SD, e->XY[0], e->XY[1], &X, &Y); - - double Z = e->Layer * SD->LayerThickness; - - OpenPPFile(SD); - fprintf(SD->PPFile,"View \"Layer %i, TextType %i\" {\n",e->Layer,e->TextType); - fprintf(SD->PPFile,"T3 (%e,%e,%e,0) {\"%s\"};\n",X,Y,Z,e->Text->c_str()); - fprintf(SD->PPFile,"};\n"); - - // TODO handle magnigification and reflection - if (e->Angle!=0.0) - { double CosTheta=cos(e->Angle*M_PI/180.0); - double SinTheta=sin(e->Angle*M_PI/180.0); - fprintf(SD->PPFile,"v0=PostProcessing.NbViews-1;\n"); - fprintf(SD->PPFile,"View[v0].TransformXX=%e;\n",CosTheta); - fprintf(SD->PPFile,"View[v0].TransformXY=%e;\n",-1.0*SinTheta); - fprintf(SD->PPFile,"View[v0].TransformYX=%e;\n",1.0*SinTheta); - fprintf(SD->PPFile,"View[v0].TransformYY=%e;\n",CosTheta); - } -} - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -void WriteElement(StatusData *SD, GDSIIData *Data, int ns, int ne) -{ - GDSIIStruct *s = Data->Structs[ns]; - GDSIIElement *e = s->Elements[ne]; - - switch(e->Type) - { - /*--------------------------------------------------------------*/ - /*--------------------------------------------------------------*/ - /*--------------------------------------------------------------*/ - case BOUNDARY: - WriteBoundary(SD, Data, ns, ne); - break; - - case PATH: - WritePath(SD, Data, ns, ne); - break; - - case SREF: - case AREF: - WriteASRef(SD, Data, ns, ne); - break; - - case TEXT: - WriteText(SD, Data, ns, ne); - break; - - default: - ; // all other element types ignored for now - }; -} - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -void WriteStruct(StatusData *SD, GDSIIData *Data, int ns, bool ASRef) -{ - GDSIIStruct *s=Data->Structs[ns]; - - if (s->IsPCell) return; - if (ASRef==false && s->IsReferenced) return; - - if (SD->PPFormat) - fprintf(SD->GeoFile,"View \"{%s}\" {\n",s->Name->c_str()); - - for(size_t ne=0; ne<s->Elements.size(); ne++) - WriteElement(SD, Data, ns, ne); - - if (SD->PPFormat) - fprintf(SD->GeoFile,"};\n"); -} - -/***************************************************************/ -/***************************************************************/ -/***************************************************************/ -int main(int argc, char *argv[]) -{ - /***************************************************************/ - /* parse command-line options **********************************/ - /***************************************************************/ - GDSIIOptions *Options = ProcessGDSIIOptions(argc, argv); - - GDSIIData *gdsIIData = Options->gdsIIData; - Options->gdsIIData->WriteDescription(); - - StatusData SD; - InitStatusData(&SD); - - SD.UnitInMM = Options->UnitInMM * gdsIIData->UnitInMeters; - - if (Options->SeparateLayers) - SD.LayerThickness=0.0; - else - SD.LayerThickness = SD.UnitInMM; - - string FileBase(Options->FileBase); - SD.GeoFileName = FileBase + ".geo"; - SD.PPFileName = FileBase + ".pp"; - - /***************************************************************/ - /***************************************************************/ - /***************************************************************/ - iVec LayerNames; - EntityTable ETable = gdsIIData->Flatten(LayerNames); - char FlatFileBase[100]; - snprintf(FlatFileBase,100,"%s.flat",FileBase.c_str()); - WriteGMSHFile(ETable, LayerNames, FlatFileBase, Options->SeparateLayers); - - /***************************************************************/ - /***************************************************************/ - /***************************************************************/ - int LList[1]={-1}; - set<int> LayersToWrite = (Options->SeparateLayers ? gdsIIData->Layers : set<int>(LList,LList+1)); - for(set<int>::iterator it=LayersToWrite.begin(); it!=LayersToWrite.end(); it++) - { int Layer = SD.CurrentLayer = *it; - char LayerStr[20]=""; - if (Layer!=-1) snprintf(LayerStr,20,".Layer%i",Layer); - SD.GeoFileName = FileBase + LayerStr + ".geo"; - for(size_t ns=0; ns<gdsIIData->Structs.size(); ns++) - WriteStruct(&SD,gdsIIData,ns,false); - if (SD.GeoFile) - { printf("Wrote GMSH geometry file %s.\n",SD.GeoFileName.c_str()); - fclose(SD.GeoFile); - SD.GeoFile=0; - } - } - if (SD.PPFile) - { printf("Wrote GMSH post-processing file %s.\n",SD.PPFileName.c_str()); - fclose(SD.PPFile); - } - printf("Thank you for your support.\n"); - -} diff --git a/applications/GDSIIConvert.cc b/applications/GDSIIConvert.cc index 8bf3af3..0335000 100644 --- a/applications/GDSIIConvert.cc +++ b/applications/GDSIIConvert.cc @@ -58,7 +58,7 @@ void Usage(const char *ErrorMessage, ...) printf("\n"); printf(" ** Other flags: **\n"); printf(" --MetalLayer 12 define layer 12 as a metal layer (may be specified multiple times)\n"); - printf(" --LengthUnit xx set output length unit in mm (default = 1)\n"); + printf(" --LengthUnit xx set output length unit in meters (default = 1e-6)\n"); printf(" --FileBase xx set base name for output files\n"); printf(" --verbose produce more output\n"); printf(" --SeparateLayers write separate output files for objects on each layer\n"); @@ -68,7 +68,7 @@ void Usage(const char *ErrorMessage, ...) typedef struct GDSIIOptions { char *GDSIIFile; bool Raw, Analyze, WriteGMSH, WritePorts; - double UnitInMM; + double CoordinateLengthUnit; char *FileBase; bool Verbose; bool SeparateLayers; @@ -86,16 +86,16 @@ GDSIIOptions *ProcessGDSIIOptions(int argc, char *argv[]) /***************************************************************/ /* process command-line options *******************************/ /***************************************************************/ - GDSIIOptions *Options = new GDSIIOptions; - Options->GDSIIFile = 0; - Options->Raw = false; - Options->Analyze = false; - Options->WriteGMSH = false; - Options->WritePorts = false; - Options->UnitInMM = 1.0; - Options->FileBase = 0; - Options->Verbose = false; - Options->SeparateLayers = false; + GDSIIOptions *Options = new GDSIIOptions; + Options->GDSIIFile = 0; + Options->Raw = false; + Options->Analyze = false; + Options->WriteGMSH = false; + Options->WritePorts = false; + Options->CoordinateLengthUnit = 1.0e-6; + Options->FileBase = 0; + Options->Verbose = false; + Options->SeparateLayers = false; int narg=1; for(; narg<argc; narg++) @@ -142,7 +142,7 @@ GDSIIOptions *ProcessGDSIIOptions(int argc, char *argv[]) else if (!strcasecmp(argv[narg],"--LogFile")) GDSIIData::LogFileName=strdup(argv[++narg]); else if (!strcasecmp(argv[narg],"--LengthUnit")) - sscanf(argv[++narg],"%le",&Options->UnitInMM); + sscanf(argv[++narg],"%le",&Options->CoordinateLengthUnit); else if (!strcasecmp(argv[narg],"--MetalLayer")) { int nml; if (1==sscanf(argv[++narg],"%i",&nml)) Options->MetalLayers.push_back(nml); } @@ -441,7 +441,6 @@ n,MemBefore[n],MemDuring[n],MemAfter[n],MemAfter[n]-MemBefore[n]); if (Options->WriteGMSH) WriteGeometryAndPorts(gdsIIData, Options); - printf("Thank you for your support.\n"); } diff --git a/lib/Flatten.cc b/lib/Flatten.cc index 6a884c3..44a6bc7 100644 --- a/lib/Flatten.cc +++ b/lib/Flatten.cc @@ -62,15 +62,15 @@ static void ApplyGTransform(GTransform GT, double X, double Y, double *XP, doubl /***************************************************************/ typedef struct StatusData { int CurrentLayer; - double UnitInMM; + double IJ2XY; // scale factor converting GDSII integer-value vertex indices to real-valued coordinates in the chosen length units EntityList EntitiesThisLayer; GTVec GTStack; int RefDepth; } StatusData; -static void InitStatusData(StatusData *SD) +static void InitStatusData(StatusData *SD, double CoordinateLengthUnit, double PixelLengthUnit) { SD->CurrentLayer=-1; - SD->UnitInMM = 1.0e-6; + SD->IJ2XY = PixelLengthUnit / CoordinateLengthUnit; SD->RefDepth=0; } @@ -83,8 +83,8 @@ static void GetPhysicalXY(StatusData *SD, double X, double Y, double *pXP, doubl X=XP; Y=YP; } - *pXP = SD->UnitInMM * XP; - *pYP = SD->UnitInMM * YP; + *pXP = SD->IJ2XY * XP; + *pYP = SD->IJ2XY * YP; } /***************************************************************/ @@ -128,8 +128,8 @@ void AddPath(StatusData *SD, GDSIIData *Data, int ns, int ne) vector<int> IXY = e->XY; int NXY = IXY.size() / 2; - double Unit = SD->UnitInMM; - double W = e->Width*Unit; + double IJ2XY = SD->IJ2XY; + double W = e->Width*IJ2XY; Entity E; E.Text = 0; @@ -297,11 +297,17 @@ void AddStruct(StatusData *SD, GDSIIData *Data, int ns, bool ASRef) /***************************************************************/ /***************************************************************/ /***************************************************************/ -void GDSIIData::Flatten(double UnitInMM) +void GDSIIData::Flatten(double CoordinateLengthUnit) { + if (CoordinateLengthUnit==0.0) + { CoordinateLengthUnit = 1.0e-6; + char *s=getenv("LIBGDSII_LENGTH_UNIT"); + if (s && 1==sscanf(s,"%le",&CoordinateLengthUnit)) + Log("Setting libGDSII length unit to %g meters.\n",CoordinateLengthUnit); + } + StatusData SD; - InitStatusData(&SD); - SD.UnitInMM = UnitInMM * this->UnitInMeters; + InitStatusData(&SD, CoordinateLengthUnit, FileUnits[1]); for(size_t nl=0; nl<Layers.size(); nl++) { SD.CurrentLayer = Layers[nl]; diff --git a/lib/ReadGDSIIFile.cc b/lib/ReadGDSIIFile.cc index dbfdd48..308b984 100644 --- a/lib/ReadGDSIIFile.cc +++ b/lib/ReadGDSIIFile.cc @@ -727,9 +727,10 @@ void InitializeParseState(ParseState *PState, GDSIIData *Data) } /*--------------------------------------------------------------*/ +/*- If CoordinateLengthUnit is nonzero, it sets the desired */ +/*- output unit (in meters) for vertex coordinates. */ /*--------------------------------------------------------------*/ -/*--------------------------------------------------------------*/ -void GDSIIData::ReadGDSIIFile(const string FileName) +void GDSIIData::ReadGDSIIFile(const string FileName, double CoordinateLengthUnit) { ErrMsg=0; @@ -789,9 +790,7 @@ void GDSIIData::ReadGDSIIFile(const string FileName) /*- Flatten hierarchy to obtain simple unstructured lists */ /*- of polygons and text labels on each layer. */ /*--------------------------------------------------------------*/ - Flatten(); - - //printf("Read %i data records from file %s.\n", PState.NumRecords,FileName.c_str()); + Flatten(CoordinateLengthUnit); } /***************************************************************/ diff --git a/lib/libGDSII.cc b/lib/libGDSII.cc index 8101f25..4cbd397 100644 --- a/lib/libGDSII.cc +++ b/lib/libGDSII.cc @@ -7,7 +7,7 @@ % % This program is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAh PURPOSE. See the +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License @@ -40,8 +40,9 @@ GDSIIData::GDSIIData(const string FileName) { // initialize class data LibName = 0; + FileUnits[0] = 1.0e-3; // these seem to be the default for GDSII files + FileUnits[1] = 1.0e-9; UnitInMeters = 1.0e-6; - FileUnits[0] = FileUnits[1]=0.0; GDSIIFileName = new string(FileName); ReadGDSIIFile(FileName); diff --git a/lib/libGDSII.h b/lib/libGDSII.h index d520c86..d30d7e7 100644 --- a/lib/libGDSII.h +++ b/lib/libGDSII.h @@ -65,10 +65,10 @@ typedef struct { char *Text; dVec XY; int Layer; } TextString; typedef vector<TextString> TextStringList; /***************************************************************/ -/* Data structures used to process GDSII files: */ +/* Data structures used to process GDSII files. */ /* (a) GDSIIElement and GDSIIStruct are used to store info */ /* on the geometry as described in the GDSII file, with */ -/* nesting hierarchy intact */ +/* nesting hierarchy intact. */ /* (b) Flattening the hierarchy (i.e. eliminating all SREFS */ /* and AREFS to instantiate all objects and text directly)*/ /* yields a table of Entity structures, organized by the */ @@ -78,7 +78,21 @@ typedef vector<TextString> TextStringList; /* reference point/location). An EntityList is a */ /* collection of Entities, in no particular order, all on */ /* the same layer. An EntityTable is a collection of */ -/* (LayerIndex, EntityList) pairs. */ +/* (LayerIndex, EntityList) pairs. */ +/* */ +/* Note that, whereas GDSIIElements and GDSIIStructs */ +/* represent vertices as pairs of integers (multiples of */ +/* the GDSII database unit), Entities represent vertices */ +/* by pairs of doubles (real-valued, continuous physical */ +/* coordinates). The default length unit for the */ +/* coordinates of Entity vertices is 1 micron, but this */ +/* may be changed by specifying a nonzero value for the */ +/* CoordinateLengthUnit argument to Flatten(), or by */ +/* setting the environment variable LIBGDSII_LENGTH_UNIT, */ +/* to the desired length unit in meters (default=1e-6). */ +/* Thus, to output vertex coordinates in units of */ +/* millimeters, set LengthUnit or LIBGDSII_LENGTH_UNIT to */ +/* 1.0e-3. */ /***************************************************************/ enum ElementType { BOUNDARY, PATH, SREF, AREF, TEXT, NODE, BOX }; @@ -158,9 +172,9 @@ namespace libGDSII /*--------------------------------------------------------*/ // private: // constructor helper methods - void ReadGDSIIFile(const std::string FileName); + void ReadGDSIIFile(const std::string FileName, double CoordinateLengthUnit=0.0); int GetStructByName(std::string Name); - void Flatten(double UnitInMM=1.0); + void Flatten(double CoordinateLengthUnit=0.0); /*--------------------------------------------------------*/ /* variables intended for internal use */ |