Example #1
0
 def init_regions( self ):
     self.P0 = DPoint( 0,0 )
     self.P1 = self.P0 + DPoint( self.Z1.gap,0 )
     self.P2 = self.P1 + DPoint( self.Z1.width,0 )
     self.P3 = self.P2 + DPoint( 0,self.Z1.gap )
     self.P4 = self.P2 + DPoint( self.Z1.gap, self.Z2.gap )
     self.P5 = self.P4 + DPoint( 0,self.Z2.width )
     self.P6 = DPoint( 0, self.Z1.gap + self.Z1.width )
     self.P7 = DPoint( 0, self.Z1.gap )
     self.P8 = self.P7 + DPoint( self.Z1.gap,0 )
     self.P9 = self.P2 + DPoint( self.Z1.gap,0 )
     self.P10 = self.P5 + DPoint( 0, self.Z2.gap )
     self.P11 = self.P10 - DPoint( 2*self.Z1.gap + self.Z1.width, 0 )
     self.P12 = self.P6 + DPoint( 0, self.Z1.gap )
     
     self.connections = [(self.P6 + self.P7)*0.5,(self.P1 + self.P2)*0.5,(self.P5 + self.P4)*0.5]
     self.angle_connections = [0,3/2*pi,0]
             
     self.metal_polygon = DPolygon( [self.P1,self.P2,self.P3,self.P4,self.P5,self.P6,self.P7,self.P8] )
     self.empty1_polygon = DPolygon( [self.P0,self.P1,self.P8,self.P7] )
     self.empty2_polygon = DPolygon( [self.P2,self.P9,self.P4,self.P3]  )
     self.empty3_polygon = DPolygon( [self.P5,self.P10,self.P12,self.P6] )
     self.gnd_polygon = DPolygon( [self.P10,self.P11,self.P12] )
     self.metal_region = pya.Region( list(map(pya.Polygon().from_dpoly,[self.metal_polygon,self.gnd_polygon])) )
     self.empty_region = pya.Region( list(map(pya.Polygon().from_dpoly ,[self.empty1_polygon,self.empty2_polygon,self.empty3_polygon])) )
Example #2
0
    def produce_impl(self):

        # fetch the parameters
        dbu = self.layout.dbu
        tg = math.tan(math.radians(self.a / 2))

        # compute the bowtie
        pts = []
        pts.append(
            pya.Point(pya.DPoint((-self.lb / 2) / dbu, (self.wb / 2) / dbu)))
        pts.append(
            pya.Point(
                pya.DPoint((-self.lb / 2 - self.lw) / dbu,
                           (self.wb / 2 + self.lw * tg) / dbu)))
        pts.append(
            pya.Point(
                pya.DPoint((-self.lb / 2 - self.lw) / dbu,
                           (-self.wb / 2 - self.lw * tg) / dbu)))
        pts.append(
            pya.Point(pya.DPoint((-self.lb / 2) / dbu, -(self.wb / 2) / dbu)))
        self.cell.shapes(self.l_layer).insert(pya.Polygon(pts))
        pts = []
        pts.append(
            pya.Point(pya.DPoint((self.lb / 2) / dbu, -(self.wb / 2) / dbu)))
        pts.append(
            pya.Point(
                pya.DPoint((self.lb / 2 + self.lw) / dbu,
                           (-self.wb / 2 - self.lw * tg) / dbu)))
        pts.append(
            pya.Point(
                pya.DPoint((self.lb / 2 + self.lw) / dbu,
                           (self.wb / 2 + self.lw * tg) / dbu)))
        pts.append(
            pya.Point(pya.DPoint((self.lb / 2) / dbu, (self.wb / 2) / dbu)))
        self.cell.shapes(self.l_layer).insert(pya.Polygon(pts))
Example #3
0
 def produce_impl(self):
     dbu = self.layout.dbu
     cross = []
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(self.w / (2 * dbu), self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(pya.DPoint(self.l1 / dbu,
                                          self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(self.l1 / dbu, -self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(self.w / (2 * dbu), -self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(self.w / (2 * dbu), -self.l2 / dbu)))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(-self.w / (2 * dbu), -self.l2 / dbu)))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(-self.w / (2 * dbu), -self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(-self.l1 / dbu, -self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(-self.l1 / dbu, self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(-self.w / (2 * dbu), self.w / (2 * dbu))))
     cross.append(
         pya.Point.from_dpoint(
             pya.DPoint(-self.w / (2 * dbu), self.l2 / dbu)))
     cross.append(
         pya.Point.from_dpoint(pya.DPoint(self.w / (2 * dbu),
                                          self.l2 / dbu)))
     if not self.inv:
         self.cell.shapes(self.l_layer).insert(pya.Polygon(cross))
     else:
         boundary = []
         boundary.append(
             pya.Point.from_dpoint(
                 pya.DPoint(-self.b1 / (2 * dbu), -self.b2 / (2 * dbu))))
         boundary.append(
             pya.Point.from_dpoint(
                 pya.DPoint(self.b1 / (2 * dbu), -self.b2 / (2 * dbu))))
         boundary.append(
             pya.Point.from_dpoint(
                 pya.DPoint(self.b1 / (2 * dbu), self.b2 / (2 * dbu))))
         boundary.append(
             pya.Point.from_dpoint(
                 pya.DPoint(-self.b1 / (2 * dbu), self.b2 / (2 * dbu))))
         poly = pya.Polygon(boundary)
         poly.insert_hole(cross)
         self.cell.shapes(self.l_layer).insert(poly)
Example #4
0
  def test_1_Trans(self):

    a = pya.Trans()
    b = pya.Trans( pya.Trans.M135, pya.Point( 17, 5 ))
    c = pya.Trans( 3, True, pya.Point( 17, 5 ))
    d = pya.Trans( pya.Point( 17, 5 ))
    e = pya.Trans( pya.Trans.M135 )
    e2 = pya.Trans.from_dtrans( pya.DTrans.M135 )
    f = pya.Trans( pya.DTrans( pya.DTrans.M135, pya.DPoint( 17, 5 )) )

    self.assertEqual( str(a), "r0 0,0" )
    self.assertEqual( str(pya.Trans.from_s(str(a))), str(a) )
    self.assertEqual( str(b), "m135 17,5" )
    self.assertEqual( str(c), "m135 17,5" )
    self.assertEqual( str(d), "r0 17,5" )
    self.assertEqual( str(e), "m135 0,0" )
    self.assertEqual( str(e2), "m135 0,0" )
    self.assertEqual( str(f), "m135 17,5" )
    self.assertEqual( str(pya.Trans.from_s(str(f))), str(f) )

    self.assertEqual( str(b.trans( pya.Point( 1, 0 ))), "17,4" )

    self.assertEqual( a == b, False )
    self.assertEqual( a == a, True )
    self.assertEqual( a != b, True )
    self.assertEqual( a != a, False )
    self.assertEqual( (d * e) == b, True )
    self.assertEqual( (e * d) == b, False )

    i = c.inverted()

    self.assertEqual( str(i), "m135 5,17" )
    self.assertEqual( (i * b) == a, True )
    self.assertEqual( (b * i) == a, True )

    c = pya.Trans( 3, True, pya.Point( 17, 5 ))
    self.assertEqual( str(c), "m135 17,5" )
    c.disp = pya.Point(1, 7)
    self.assertEqual( str(c), "m135 1,7" )
    c.angle = 1
    self.assertEqual( str(c), "m45 1,7" )
    c.rot = 3
    self.assertEqual( str(c), "r270 1,7" )
    c.mirror = True
    self.assertEqual( str(c), "m135 1,7" )

    self.assertEqual( str(e.trans( pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(( e * pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(e.trans( pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(( e * pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(e.trans( pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" )
    self.assertEqual( str(( e * pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" )
    self.assertEqual( str(e.trans( pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" )
    self.assertEqual( str(( e * pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" )
    self.assertEqual( str(e.trans( pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
    self.assertEqual( str(( e * pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
Example #5
0
 def vernier(self, width, length, pitch):
   '''
   vernier(width, length, pitch)
   
   Generates a vernier scale
   
   Parameters
   ---------
   width : integer
         The width of each tick marker
   length : integer
         The length of the central tick mark
         The major tick marks are 3/4 this length
         The minor tick marks are half this length
   pitch : integer
         The distance between each tick mark
   
   Returns
   ------
   region : [pya.Region]
        A region containing the vernier scale
   
   Description
   ---------
   A pair of vernier scale can be used to measure misalignment by eye.
   
   In photolithography the wafer will contain one vernier pattern (width = 4, length = 40, pitch = 8, units = micron)
   and the mask will contain a second vernier pattern (pitch = 8.2) providing an alignment measurement resolution of 0.2 micron.
   '''
   scaleM = 0.75
   scaleS = 0.5
   
   # Create the large tick mark
   polygons = []
   #tick = pya.Polygon([pya.Point(0,0), pya.Point(length,0), pya.Point(length,width), pya.Point(0,width)])
   tick = pya.Polygon([pya.Point(0,0), pya.Point(0,width), pya.Point(length,width), pya.Point(length,0)])
   tc = pya.ICplxTrans(int(-length/2),int(-width/2))
   polygons.append(tc.trans(tick))
   
   # Create the medium tick mark
   #tickm = pya.Polygon([pya.Point(0,0), pya.Point(length*scaleM,0), pya.Point(length*scaleM,width), pya.Point(0,width)])
   tickm = pya.Polygon([pya.Point(0,0), pya.Point(0,width), pya.Point(length*scaleM,width), pya.Point(length*scaleM,0)])
   pos = [-2, -1, 1, 2]
   for i in pos:
     tt = pya.ICplxTrans(0,int(i*pitch*5))
     polygons.append(tc.trans(tt.trans(tickm)))
   
   # Create the small tick mark
   #ticks = pya.Polygon([pya.Point(0,0), pya.Point(length*scaleS,0), pya.Point(length*scaleS,width), pya.Point(0,width)])
   ticks = pya.Polygon([pya.Point(0,0), pya.Point(0,width), pya.Point(length*scaleS,width), pya.Point(length*scaleS,0)])
   pos = [-9, -8, -7, -6, -4, -3, -2, -1, 1, 2, 3, 4, 6, 7, 8, 9]
   for i in pos:
     tt = pya.ICplxTrans(0,int(i*pitch))
     polygons.append(tc.trans(tt.trans(ticks)))
     
   return pya.Region(polygons)
Example #6
0
    def pieceHolderCassette(self, dbu=1):
        '''
      pieceHolderCassette()
      
      Generates the shape of the Jeol JBX-5500FS piece holder cassette
      
      Parameters
      ---------
      dbu : double
            The database unit
            
      Returns
      ------
      region : [pya.Region]
           A region containing the piece holder cassette shape
           
      Description
      ------
      The center of this piece holder shape (0,0) is at stage position (62.5mm, 37.5mm)
      
      Jeol Stage Y axis is reverse of KLayout Y axis
      '''
        # Create the quarter circle
        r = 36100 / dbu
        rx = 62500 / dbu
        ry = -37500 / dbu
        polygon = pya.Polygon([
            pya.Point(-r, -r),
            pya.Point(-r, r),
            pya.Point(r, r),
            pya.Point(r, -r)
        ])
        polygon = polygon.round_corners(0, r, 128)
        rectangle = pya.Polygon([
            pya.Point(-r, 0),
            pya.Point(-r, r),
            pya.Point(r, r),
            pya.Point(r, 0)
        ])
        tt = pya.ICplxTrans(1, 90, False, 0, 0)
        qCircle = pya.Region(polygon) - pya.Region(rectangle) - pya.Region(
            rectangle.transform(tt))

        # Create the trapezoid
        trapezoid = pya.Polygon([
            pya.Point(49500 / dbu, -70500 / dbu),
            pya.Point(40500 / dbu, -20500 / dbu),
            pya.Point(60500 / dbu, -20500 / dbu),
            pya.Point(51500 / dbu, -70500 / dbu)
        ])
        tt = pya.ICplxTrans(-rx, -ry)

        cassette = qCircle + pya.Region(trapezoid.transform(tt))

        return cassette
Example #7
0
    def ring(self, outerDiameter, innerDiameter, vertices=128, fracture=True):
        '''
      circle(outerDiameter, innerDiameter, vertices)
      
      Generates a circle shape
      
      Parameters
      ---------
      outerDiameter : integer
            The outer diameter of the ring
      innerDiameter : integer
            The inner diameter of the ring
      vertices : integer (128)
            Number of vertices in the circle (coerce to multiples of 4)
      fracture : boolean (True)
            Create the inner polygon with vertices that is optimal for fracturing horizontally
      
      Returns
      ------
      region : [pya.Region]
           A region containing the circle shape
      '''
        ro = int(outerDiameter / 2)
        ri = int(innerDiameter / 2)
        vertices = int(vertices / 4) * 4

        # Create a circle
        polygon = pya.Polygon([
            pya.Point(-ro, -ro),
            pya.Point(-ro, ro),
            pya.Point(ro, ro),
            pya.Point(ro, -ro)
        ])
        polygonOuter = polygon.round_corners(0, ro, vertices)
        polygon = pya.Polygon([
            pya.Point(-ri, -ri),
            pya.Point(-ri, ri),
            pya.Point(ri, ri),
            pya.Point(ri, -ri)
        ])

        if fracture:
            points = polygonOuter.each_point_hull()
            polygonInnerPoints = []
            r2 = np.power(ri, 2)
            for point in points:
                if (ri > np.absolute(point.y)):
                    x = np.sqrt(r2 - np.power(point.y, 2))
                    polygonInnerPoints.append(
                        pya.Point(np.sign(point.x) * x, point.y))
            polygonInner = pya.Polygon(polygonInnerPoints)
        else:
            polygonInner = polygon.round_corners(0, ri, vertices)

        return pya.Region(polygonOuter) - pya.Region(polygonInner)
Example #8
0
  def siWafer(self, diameter, primaryFlat, secondaryFlat, angle, vertices = 128):
      '''
      siWafer(diameter, secondaryFlatAngle)
      
      Generates a Silicon Wafer shape
      
      Parameters
      ---------
      diameter : integer
            The diameter of a standard silicon wafer
      primaryFlat : integer
            The length of the primary flat
      secondaryFlat : integer
            The length of the secondary flat
      angle : double
            The location of the secondary flat relative (counterclockwise) to primary flat
      vertices : integer (coerce to even number)
            The number of vertices used to generate the circle
      
      Returns
      ------
      region : [pya.Region]
           A region containing the Si Wafer shape
      
      Description
      ---------
      SEMI Wafer Flat M1-0302 Specification
      Wafer Size  = [2", 3", 100mm, 125mm, 150mm, 200mm, 300mm]
      Diameter [mm] = [50.8, 76.2, 100, 125, 150, 200, 300]
      Thickness [um] = [279, 381, 525 or 625, 625, 675 or 625, 725, 775]
      Primary Flat Length = [15.88, 22.22, 32.5, 42.5, 57.5, Notch, Notch]
      Secondary Flat Length = [8, 11.18, 18, 27.5, 37.5, NA, NA]
      '''
      dList = [50800, 76200, 10000, 12500, 15000]
      pFlatLengthList = [15.88, 22.22, 32.5, 42.5, 57.5]
      sFlatLengthList = [8, 11.18, 18, 27.5, 37.5]
      
      r = int(diameter/2)
      
      #Height of arc position (https://mathworld.wolfram.com/CircularSegment.html)
      pH = r- int(np.sqrt(4*np.power(r,2)-np.power(primaryFlat,2))/2)
      sH = r - int(np.sqrt(4*np.power(r,2)-np.power(secondaryFlat,2))/2)
      
      # Create a circle
      polygon = pya.Polygon([pya.Point(-r,-r), pya.Point(-r,r), pya.Point(r,r), pya.Point(r,-r)])
      polygon = polygon.round_corners(0,r,vertices)
      
      #Create a rectangle to produce the primary flat
      pRectangle = pya.Polygon([pya.Point(-r,r-pH), pya.Point(-r,r+pH), pya.Point(r,r+pH), pya.Point(r,r-pH)])
      
      #Create a rectangle to produce the secondary flat
      sRectangle = pya.Polygon([pya.Point(-r,r-sH), pya.Point(-r,r+sH), pya.Point(r,r+sH), pya.Point(r,r-sH)])
      tt = pya.ICplxTrans(1, angle, False, 0, 0)

      return pya.Region(polygon)-pya.Region(pRectangle)-pya.Region(sRectangle.transform(tt))
Example #9
0
 def produce_impl(self):
     dbu = self.layout.dbu
     path = pya.QPainterPath()
     font = pya.QFont(self.f, self.q, self.w, False)
     if self.s == 0:
         font.setStyle(pya.QFont.StyleNormal)
     elif self.s == 1:
         font.setStyle(pya.QFont.StyleItalic)
     else:
         font.setStyle(pya.QFont.StyleOblique)
     path.addText(0, 0, font, self.text)
     polygons = path.toSubpathPolygons()
     # gen polygon data
     source = []
     for polygon in polygons:
         points = []
         for point in polygon:
             points.append(
                 pya.Point.from_dpoint(
                     pya.DPoint(point.x / dbu / self.q,
                                -point.y / dbu / self.q)))
         source.append([points, []])
     # generate parent tree
     for polygon in source:
         for suspectedParent in source:
             if polygon != suspectedParent:
                 inside = True
                 for point in polygon[0]:
                     if not pya.Polygon(suspectedParent[0]).inside(point):
                         inside = False
                 if inside:
                     polygon[1].append(suspectedParent)
     # generate KLayout polygons
     outpoly = []
     i = 0
     while len(source):
         # find top
         for poly in source:
             if len(poly[1]) == 0:
                 source.remove(poly)
                 top = pya.Polygon(poly[0])
                 break
         remove = []
         # add corresponding holes
         for polygon in source:
             if poly in polygon[1]:
                 if len(polygon[1]) == 1:
                     remove.append(polygon)
                     top.insert_hole(polygon[0])
                 polygon[1].remove(poly)
         for polygon in remove:
             source.remove(polygon)
         self.cell.shapes(self.l_layer).insert(top)
Example #10
0
  def produce_impl(self):
  
    # This is the main part of the implementation: create the layout

    # fetch the parameters
    ru_dbu = self.ru / self.layout.dbu
    
    dist=0
    da = math.pi * 2 / self.n

    for i in range(0,self.taper):
    
      pts=[]
      
      rad_dbu=self.radius/self.layout.dbu
      
      # calculate the size of the hole
      rad=self.depth*rad_dbu+(i**2)/float(self.taper-1)**2*(1-self.depth)*rad_dbu
      
      print('rad: '+str(rad))
      print('i: '+str(i))
      # calculate the spacing between the last taper hole
      sp=self.depth*self.spacing+(i**2)/float(self.taper-1)**2*(1-self.depth)*self.spacing
      
      # add to the total distance along mirror
      dist+=sp
      
      # create a circle at the correct position
      # iterate through all the points on each circle
      for j in range(0,self.n):
        pts.append(pya.Point.from_dpoint(pya.DPoint((rad*math.cos(j*da)+dist/self.layout.dbu),(rad*math.sin(j*da)))))
    
      # create the shape for this circle
      self.cell.shapes(self.l_layer).insert(pya.Polygon(pts))
      
    print('self.normal: '+str(self.normal))
    
    # now create the untapered holes
    for i in range(0,int(self.normal)):
      pts=[]
      rad_dbu=self.radius/self.layout.dbu
      
      # add the total distance along mirror
      dist+=self.spacing
      
      # create a circle at the correct position
      # iterate through all the points on each circle
      for j in range(0,self.n):
        pts.append(pya.Point.from_dpoint(pya.DPoint((rad*math.cos(j*da)+dist/self.layout.dbu),(rad*math.sin(j*da)))))
        
      # create the shape for this circle
      self.cell.shapes(self.l_layer).insert(pya.Polygon(pts))
Example #11
0
    def produce_impl(self):
        from SiEPIC.utils import arc
        from SiEPIC.extend import to_itype

        dbu = self.layout.dbu

        layer = self.layout.layer(self.layer)
        radius = to_itype(self.radius, dbu)
        width = to_itype(self.width, dbu)

        poly = pya.Polygon(arc(radius + width / 2, 0, 360))
        hole = pya.Polygon(arc(radius - width / 2, 0, 360))
        poly.insert_hole(hole.get_points())
        self.cell.shapes(layer).insert(poly)
Example #12
0
  def test_extractRad(self):

    ex = pya.SimplePolygon().extract_rad()
    self.assertEqual(repr(ex), "[]")

    sp = pya.SimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)")

    sp = sp.round_corners(10000, 5000, 200)
    ex = sp.extract_rad()

    self.assertEqual(ex, [pya.SimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)"), 10000.0, 5000.0, 200])

    ex = pya.Polygon().extract_rad()
    self.assertEqual(ex, [])

    sp = pya.Polygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)")

    sp = sp.round_corners(10000, 5000, 200)
    ex = sp.extract_rad()

    self.assertEqual(ex, [pya.Polygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)"), 10000.0, 5000.0, 200])

    # double coords too ...

    ex = pya.DSimplePolygon().extract_rad()
    self.assertEqual(ex, [])

    sp = pya.DSimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)")

    sp = sp.round_corners(10000, 5000, 200)
    ex = sp.extract_rad()

    # round to integers for better comparison
    
    ex[0] = pya.SimplePolygon(ex[0])
    self.assertEqual(ex, [pya.SimplePolygon.from_s("(0,0;0,200000;300000,200000;300000,100000;100000,100000;100000,0)"), 10000.0, 5000.0, 200])

    ex = pya.DPolygon().extract_rad()
    self.assertEqual(ex, [])

    sp = pya.DPolygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)")

    sp = sp.round_corners(10000, 5000, 200)
    ex = sp.extract_rad()

    # round to integers for better comparison
    ex[0] = pya.Polygon(ex[0])

    self.assertEqual(ex, [pya.Polygon.from_s("(0,0;0,300000;300000,300000;300000,0/100000,100000;200000,100000;200000,200000;100000,200000)"), 10000.0, 5000.0, 200])
Example #13
0
  def test_selfRef(self):

    # p1 is a reference to the new'd object:
    p1 = pya.Polygon(pya.Box(10, 20, 30, 40)).move(10, 20)
    self.assertEqual(str(p1), "(20,40;20,60;40,60;40,40)")

    pp = pya.Polygon(pya.Box(10, 20, 30, 40))
    p1 = pp.move(10, 20)
    self.assertEqual(str(p1), "(20,40;20,60;40,60;40,40)")
    self.assertEqual(str(pp), "(20,40;20,60;40,60;40,40)")
    pp.move(1, 2)

    # p1 and pp are the same object
    self.assertEqual(str(p1), "(21,42;21,62;41,62;41,42)")
    self.assertEqual(str(pp), "(21,42;21,62;41,62;41,42)")
Example #14
0
def arc_wg_xy(x, y, r, w, theta_start, theta_stop, DevRec=None):
    # function to draw an arc of waveguide
    # x, y: location of the origin
    # r: radius
    # w: waveguide width
    # length units in dbu
    # theta_start, theta_stop: angles for the arc
    # angles in degrees

    from math import pi, cos, sin
    from . import points_per_circle

    circle_fraction = abs(theta_stop - theta_start) / 360.0
    npoints = int(points_per_circle(r) * circle_fraction)
    if DevRec:
        npoints = int(npoints / 10)
    if npoints == 0:
        npoints = 1
    da = 2 * pi / npoints * circle_fraction  # increment, in radians
    pts = []
    th = theta_start / 360.0 * 2 * pi
    for i in range(0, npoints + 1):
        pts.append(
            pya.Point.from_dpoint(
                pya.DPoint((x + (r + w / 2) * cos(i * da + th)) / 1,
                           (y + (r + w / 2) * sin(i * da + th)) / 1)))
    for i in range(npoints, -1, -1):
        pts.append(
            pya.Point.from_dpoint(
                pya.DPoint((x + (r - w / 2) * cos(i * da + th)) / 1,
                           (y + (r - w / 2) * sin(i * da + th)) / 1)))
    return pya.Polygon(pts)
Example #15
0
    def test_voidMethodsReturnSelf(self):

        hull = [
            pya.Point(0, 0),
            pya.Point(6000, 0),
            pya.Point(6000, 3000),
            pya.Point(0, 3000)
        ]
        hole1 = [
            pya.Point(1000, 1000),
            pya.Point(2000, 1000),
            pya.Point(2000, 2000),
            pya.Point(1000, 2000)
        ]
        hole2 = [
            pya.Point(3000, 1000),
            pya.Point(4000, 1000),
            pya.Point(4000, 2000),
            pya.Point(3000, 2000)
        ]
        poly = pya.Polygon(hull).insert_hole(hole1).insert_hole(hole2)
        self.assertEqual(
            str(poly),
            "(0,0;0,3000;6000,3000;6000,0/1000,1000;2000,1000;2000,2000;1000,2000/3000,1000;4000,1000;4000,2000;3000,2000)"
        )
Example #16
0
  def produce_impl(self):
  
    # fetch the parameters
    dbu = self.layout.dbu
    ly = self.layout

    LayerSi = self.layer
    LayerSiN = ly.layer(self.layer)
    LayerPinRecN = ly.layer(self.pinrec)
    LayerDevRecN = ly.layer(self.devrec)
    LayerTextN = ly.layer(self.textl)

    # Fetch all the parameters:
    a = self.a/dbu
    r = self.r/dbu

    # function to generate points to create a circle
    def hexagon_half(a): 
      theta_div = math.pi/3
      triangle_length = a/math.sqrt(3)
      pts = []
      for i in range(0,4):
        pts.append(Point.from_dpoint(pya.DPoint(triangle_length*math.cos(i*theta_div-math.pi/2), triangle_length*math.sin(i*theta_div-math.pi/2))))
      return pts      
 
    hexagon_pts = hexagon_half(a)
    hexagon_cell_poly_half = pya.Polygon(hexagon_pts)

    #hole_cell.insert(hole_cell_poly_0)
    
    self.cell.shapes(LayerSiN).insert(hexagon_cell_poly_half)
    
Example #17
0
def layout_taper(cell, layer, trans, w1, w2, length, insert=True):
    """ Lays out a taper

    Args:
        trans: pya.Trans: location and rotation
        w1: width of waveguide, float for DPoint type (microns); int for Point type (nm)
        w2: width of waveguide, float for DPoint type (microns); int for Point type (nm)
        length: length, float
        insert: flag to insert drawn waveguide or return shape, boolean

    """
    import pya
    if type(w1) == type(float()):
        pts = [
            pya.DPoint(0, -w1 / 2),
            pya.DPoint(0, w1 / 2),
            pya.DPoint(length, w2 / 2),
            pya.DPoint(length, -w2 / 2)
        ]
        shape_taper = pya.DPolygon(pts).transformed(trans)
    else:
        pts = [
            pya.Point(0, -w1 / 2),
            pya.Point(0, w1 / 2),
            pya.Point(length, w2 / 2),
            pya.Point(length, -w2 / 2)
        ]
        shape_taper = pya.Polygon(pts).transformed(trans)

    if insert == True:
        cell.shapes(layer).insert(shape_taper)
    else:
        return shape_taper
Example #18
0
def arc_wg(radius, w, theta_start, theta_stop, DevRec=None):
    # function to draw an arc of waveguide
    # radius: radius
    # w: waveguide width
    # length units in dbu
    # theta_start, theta_stop: angles for the arc
    # angles in degrees

    from math import pi, cos, sin
    from . import points_per_circle

    print("SiEPIC.utils arc_wg")
    circle_fraction = abs(theta_stop - theta_start) / 360.0
    npoints = int(points_per_circle(radius / 1000) * circle_fraction)
    if DevRec:
        npoints = int(npoints / 3)
    if npoints == 0:
        npoints = 1
    da = 2 * pi / npoints * circle_fraction  # increment, in radians
    pts = []
    th = theta_start / 360.0 * 2 * pi
    for i in range(0, npoints + 1):
        pts.append(
            pya.Point.from_dpoint(
                pya.DPoint(((radius + w / 2) * cos(i * da + th)) / 1,
                           ((radius + w / 2) * sin(i * da + th)) / 1)))
    for i in range(npoints, -1, -1):
        pts.append(
            pya.Point.from_dpoint(
                pya.DPoint(((radius - w / 2) * cos(i * da + th)) / 1,
                           ((radius - w / 2) * sin(i * da + th)) / 1)))
    return pya.Polygon(pts)
Example #19
0
    def circle(self, diameter, vertices=128):
        '''
      circle(diameter, vertices)
      
      Generates a circle shape
      
      Parameters
      ---------
      diameter : integer
            The diameter of a circle
      vertices : integer (128)
            Number of vertices in the circle (coerce to multiple of 4)
      
      Returns
      ------
      region : [pya.Region]
           A region containing the circle shape
      
      Description
      ------
      The number of vertices is coerced to even numbers to ensure good fracturing
      '''
        r = int(diameter / 2)
        vertices = int(vertices / 4) * 4

        # Create a circle
        polygon = pya.Polygon([
            pya.Point(-r, -r),
            pya.Point(-r, r),
            pya.Point(r, r),
            pya.Point(r, -r)
        ])
        polygon = polygon.round_corners(0, r, vertices)

        return pya.Region(polygon)
Example #20
0
 def produce_impl(self):
     dbu = self.layout.dbu
     # resolve path
     info = pya.QFileInfo(self.path)
     if info.isRelative():
         view = pya.Application.instance().main_window().current_view()
         designfile = view.active_cellview().filename()
         if designfile == "":
             self.error = "Error: In order to use relative file path, design must be saved first"
             return
         designdir = pya.QFileInfo(designfile).dir()
         path = designdir.absoluteFilePath(self.path)
     else:
         path = self.path
     # open image
     image = pya.QImage(path)
     if image.isNull():
         self.error = "Error opening image"
         return
     image = image.convertToFormat(pya.QImage.Format_Grayscale8)
     width = image.width()
     height = image.height()
     tilesx = math.ceil(width / self.t)
     tilesy = math.ceil(height / self.t)
     for tiley in range(tilesy):
         for tilex in range(tilesx):
             tile = image.copy(tilex * self.t, tiley * self.t, self.t,
                               self.t)
             polygons = []
             # generate pixels
             rangex = rangey = self.t
             if self.t * (tilex + 1) > width:
                 rangex = width % self.t
             if self.t * (tiley + 1) > height:
                 rangey = height % self.t
             for y in range(rangey):
                 for x in range(rangex):
                     color = pya.QColor(tile.pixel(x, y))
                     color = (color.red + color.green + color.blue) / 3
                     if (color > self.th
                             and not self.inv) or (color <= self.th
                                                   and self.inv):
                         x1 = (tilex * self.t + x) * self.px / dbu
                         y1 = -(tiley * self.t + y) * self.px / dbu
                         x2 = (tilex * self.t + x + 1) * self.px / dbu
                         y2 = -(tiley * self.t + y + 1) * self.px / dbu
                         polygons.append(
                             pya.Polygon(
                                 pya.Box(
                                     pya.Point.from_dpoint(
                                         pya.DPoint(x1, y1)),
                                     pya.Point.from_dpoint(
                                         pya.DPoint(x2, y2)))))
             # merge
             processor = pya.EdgeProcessor()
             merged = processor.simple_merge_p2p(polygons, False, False)
             for polygon in merged:
                 self.cell.shapes(self.l_layer).insert(polygon)
     self.error = None
Example #21
0
            def __init__(self, side, wall, dbu=1):

                self.a = side / 2 / dbu
                self.h = side / 2 / dbu - wall / dbu

                self.assign(
                    pya.Polygon(pya.Box(-self.a, -self.a, self.a, self.a)))
                self.insert_hole(pya.Box(-self.h, -self.h, self.h, self.h))
Example #22
0
  def produce_impl(self):
  
    # This is the main part of the implementation: create the layout

    # fetch the parameters
    dbu = self.layout.dbu;
    ly = self.layout
    shapes = self.cell.shapes
    spacing = self.spacing
    cwidth = self.cwidth
    amplitude = self.amplitude
    maxamplitude = cwidth/2+amplitude
    
    dist=0
    # spacing between each point
    dx=spacing/self.n
    dy=maxamplitude/self.n
    
    da = math.pi*2/self.n

    for i in range(0,self.period):
      pts=[]
         
      # add the total distance along mirror
      dist+=spacing
      
      #creat the left edge bottom part
      for j in range(0,self.n):
        pts.append(pya.Point.from_dpoint(pya.DPoint((0+dist)/dbu,-maxamplitude+j*dy/dbu)))   
      
      #creat the left edge upper part
      for j in range(0,self.n):
        pts.append(pya.Point.from_dpoint(pya.DPoint((0+dist)/dbu,j*dy/dbu)))
        
      # creat the top curve
      # iterate through all the points on each circle
      for j in range(0,self.n+1):
        pts.append(pya.Point.from_dpoint(pya.DPoint(((j*dx+dist)/dbu),(cwidth/2+amplitude/2+(amplitude/2)*math.cos(2*math.pi*j*dx/spacing))/dbu)))
        #pts.append(pya.Point.from_dpoint(pya.DPoint(0*dx/dbu,j*dy/dbu)))
           
      #creat the right edge upper part
      for j in range(0,self.n):
        pts.append(pya.Point.from_dpoint(pya.DPoint((spacing+dist)/dbu,maxamplitude-j*dy/dbu)))
      
      #creat the right edge bottom part
      for j in range(0,self.n):
        pts.append(pya.Point.from_dpoint(pya.DPoint((spacing+dist)/dbu,-j*dy/dbu)))
               
      #creat the bottom curve
      for j in range(0,self.n+1):
        pts.append(pya.Point.from_dpoint(pya.DPoint(((dist+spacing-j*dx)/dbu),(-1)*(cwidth/2+amplitude/2+(amplitude/2)*math.cos(2*math.pi*(dist+spacing-j*dx)/spacing))/dbu)))

     # pts.append(pya.Point.from_dpoint(pya.DPoint((0/dbu),dy*self.n/dbu)))
     
      # create the shape for this sine curve
      self.cell.shapes(self.l_layer).insert(pya.Polygon(pts))
Example #23
0
 def Border(leng=3050000,siz=3050000,wed=50000):
     polygons=[]        
     pts=[pya.Point(-siz,-siz),pya.Point(-siz+leng,-siz),pya.Point(-siz+leng,-siz+wed)]
     pts.extend([pya.Point(-siz+wed,-siz+wed),pya.Point(-siz+wed,-siz+leng),pya.Point(-siz,-siz+leng)])
     polygon1=pya.Polygon(pts)
     polygons.append(polygon1)
     polygons.append(polygon1.transformed(pya.Trans(pya.Trans.R90)))
     polygons.append(polygon1.transformed(pya.Trans(pya.Trans.R180)))
     polygons.append(polygon1.transformed(pya.Trans(pya.Trans.R270)))
     return pya.Region(polygons)
Example #24
0
  def test_touches(self):

    p1 = pya.Polygon(pya.Box(10, 20, 30, 40))
    self.assertEqual(p1.touches(pya.Polygon(pya.Box(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.Polygon(pya.Box(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.Polygon(pya.Box(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.Box(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.Box(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.Box(29, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.Edge(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.Edge(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.Edge(29, 20, 40, 50)), True)

    p1 = pya.SimplePolygon(pya.Box(10, 20, 30, 40))
    self.assertEqual(p1.touches(pya.Polygon(pya.Box(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.Polygon(pya.Box(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.Polygon(pya.Box(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.SimplePolygon(pya.Box(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.Box(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.Box(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.Box(29, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.Edge(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.Edge(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.Edge(29, 20, 40, 50)), True)

    p1 = pya.DPolygon(pya.DBox(10, 20, 30, 40))
    self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DBox(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.DBox(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.DBox(29, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.DEdge(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.DEdge(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.DEdge(29, 20, 40, 50)), True)

    p1 = pya.DSimplePolygon(pya.DBox(10, 20, 30, 40))
    self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.DPolygon(pya.DBox(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(30, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(31, 20, 40, 50))), False)
    self.assertEqual(p1.touches(pya.DSimplePolygon(pya.DBox(29, 20, 40, 50))), True)
    self.assertEqual(p1.touches(pya.DBox(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.DBox(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.DBox(29, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.DEdge(30, 20, 40, 50)), True)
    self.assertEqual(p1.touches(pya.DEdge(31, 20, 40, 50)), False)
    self.assertEqual(p1.touches(pya.DEdge(29, 20, 40, 50)), True)
Example #25
0
def layout_taper(cell, layer, trans, w1, w2, length):
    """ Lays out a taper

    Args:
        trans: pya.Trans: location and rotation
        w1: width of waveguide, float
        w2: width of waveguide, float
        length: length, float

    """
    import pya
    pts = [pya.Point(0,-w1/2), pya.Point(0,w1/2), pya.Point(length,w2/2), pya.Point(length,-w2/2)]
    cell.shapes(layer).insert(pya.Polygon(pts).transformed(trans))
Example #26
0
 def produce_impl(self):
     dbu = self.layout.dbu
     star = []
     anglestep = math.radians(360 / self.n)
     for i in range(self.n):
         angle = i * anglestep
         x = self.ri * math.cos(angle)
         y = self.ri * math.sin(angle)
         star.append(pya.Point.from_dpoint(pya.DPoint(x / dbu, y / dbu)))
         x = self.ro * math.cos(angle + anglestep / 2)
         y = self.ro * math.sin(angle + anglestep / 2)
         star.append(pya.Point.from_dpoint(pya.DPoint(x / dbu, y / dbu)))
     self.cell.shapes(self.l_layer).insert(pya.Polygon(star))
Example #27
0
 def produce_impl(self):
   dbu = self.layout.dbu
   arrow = []
   tg = math.tan(math.radians(self.a/2))
   hw = self.h * tg
   arrow.append(pya.Point.from_dpoint(pya.DPoint(self.w/(2*dbu), -self.b/dbu)))
   arrow.append(pya.Point.from_dpoint(pya.DPoint(self.w/(2*dbu), 0)))
   arrow.append(pya.Point.from_dpoint(pya.DPoint(hw/dbu, 0)))
   arrow.append(pya.Point.from_dpoint(pya.DPoint(0, self.h/dbu)))
   arrow.append(pya.Point.from_dpoint(pya.DPoint(-hw/dbu, 0)))
   arrow.append(pya.Point.from_dpoint(pya.DPoint(-self.w/(2*dbu), 0)))
   arrow.append(pya.Point.from_dpoint(pya.DPoint(-self.w/(2*dbu), -self.b/dbu)))
   self.cell.shapes(self.l_layer).insert(pya.Polygon(arrow))
Example #28
0
    def produce_impl(self):
        ru_dbu = self.w / self.layout.dbu

        # compute the circle
        pts = []
        da = math.pi * 2 / 4
        for i in range(0, 4):
            pts.append(
                pya.Point.from_dpoint(
                    pya.DPoint(ru_dbu * math.cos(i * da),
                               ru_dbu * math.sin(i * da))))

        # create the shape
        self.cell.shapes(self.ls_layer).insert(pya.Polygon(pts))
Example #29
0
  def produce_impl(self):

    # This is the main part of the implementation: create the layout

    # fetch the parameters
    ru_dbu = self.ru / self.layout.dbu

    # compute the circle
    pts = []
    #da = math.pi * 2 / self.n
    #for i in range(0, self.n):
      #pts.append(pya.Point.from_dpoint(pya.DPoint(ru_dbu * math.cos(i * da), ru_dbu * math.sin(i * da))))

    # create the shape
    self.cell.shapes(self.l_layer).insert(pya.Polygon(pts))
Example #30
0
    def test_2_DPolygon(self):

        pts = [pya.DPoint(0, 0)]
        p = pya.DPolygon(pts, True)
        self.assertEqual(str(p), "(0,0)")

        arr = []
        for e in p.each_edge():
            arr.append(str(e))
        self.assertEqual(arr, ["(0,0;0,0)"])

        p = pya.DPolygon(pya.DBox(0, 0, 100, 100))
        p.insert_hole([pya.DPoint(0, 0), pya.DPoint(10, 0)], True)
        self.assertEqual(str(p), "(0,0;0,100;100,100;100,0/0,0;10,0)")
        p.assign_hole(0, [pya.DPoint(0, 0), pya.DPoint(10, 0)])
        self.assertEqual(str(p), "(0,0;0,100;100,100;100,0/0,0;10,0)")
        p.assign_hole(0, [pya.DPoint(0, 0), pya.DPoint(10, 0)], True)
        self.assertEqual(str(p), "(0,0;0,100;100,100;100,0/0,0;10,0)")

        pts = [pya.DPoint(0, 0), pya.DPoint(10, 0)]
        p = pya.DPolygon(pts, True)
        self.assertEqual(str(p), "(0,0;10,0)")
        self.assertEqual(str(pya.Polygon(p)), "(0,0;10,0)")

        p.hull = []
        self.assertEqual(str(p), "()")

        p.hull = [pya.DPoint(0, 0), pya.DPoint(10, 0)]
        self.assertEqual(str(p), "(0,0;10,0)")

        p.assign_hull([pya.DPoint(0, 0), pya.DPoint(10, 0)], True)
        self.assertEqual(str(p), "(0,0;10,0)")

        arr = []
        for e in p.each_edge():
            arr.append(str(e))
        self.assertEqual(arr, ["(0,0;10,0)", "(10,0;0,0)"])

        self.assertEqual(str(p.moved(1, 2)), "(1,2;11,2)")
        self.assertEqual(str(p.sized(2)), "(0,-2;0,2;10,2;10,-2)")
        self.assertEqual(str(p * 2), "(0,0;20,0)")
        self.assertEqual(str(p.transformed(pya.DTrans(pya.DTrans.R90))),
                         "(0,0;0,10)")

        pp = p.dup()
        pp.transform(pya.DTrans(pya.DTrans.R90))
        self.assertEqual(str(pp), "(0,0;0,10)")