Esempio n. 1
0
 def constructors1(self,
                   pointc=pya.DPoint(0, 0),
                   angle=0,
                   widout=20000,
                   widin=10000,
                   bgn_ext=0):
     tr = pya.DCplxTrans(1, angle, False, pointc)
     self.edgeout = pya.DEdge(0, widout / 2, 0, -widout / 2).transformed(tr)
     self.edgein = pya.DEdge(bgn_ext, widin / 2, bgn_ext,
                             -widin / 2).transformed(tr)
Esempio n. 2
0
 def Narrow(self,widout,widin,length=6000):
     assert(self.end_ext==0)
     centerx,centery,angle=self.Getinfo()[0:3]
     tr=pya.DCplxTrans(1,angle,False,centerx,centery)
     edgeout=pya.DEdge(length,-widout/2,length,widout/2).transformed(tr)
     edgein=pya.DEdge(length,-widin/2,length,widin/2).transformed(tr)
     self.regionlistout.append(pya.DPolygon([self.painterout.pointl,self.painterout.pointr,edgeout.p1,edgeout.p2]))
     self.regionlistin.append(pya.DPolygon([self.painterin.pointl,self.painterin.pointr,edgein.p1,edgein.p2]))
     self.painterout.Setpoint(edgeout.p1,edgeout.p2)
     self.painterin.Setpoint(edgein.p1,edgein.p2)        
     return length   
Esempio n. 3
0
 def __init__(self,pointc=pya.DPoint(0,8000),angle=0,widout=20000,widin=10000,bgn_ext=0,end_ext=0):
     self.regionlistout=[]
     self.regionlistin=[]        
     self.path=lambda painter:None
     self.bgn_ext=bgn_ext
     self.end_ext=end_ext
     tr=pya.DCplxTrans(1,angle,False,pointc)
     edgeout=pya.DEdge(0,-widout/2,0,widout/2).transformed(tr)
     edgein=pya.DEdge(bgn_ext,-widin/2,bgn_ext,widin/2).transformed(tr)
     self.painterout=LinePainter(edgeout.p1,edgeout.p2)
     self.painterin=LinePainter(edgein.p1,edgein.p2)
     self.centerlineinfos=[]
Esempio n. 4
0
 def Narrow(self, widout, widin, length=6000):
     assert (self.end_ext == 0)
     tr = self.brush.DCplxTrans
     edgeout = pya.DEdge(length, widout / 2, length,
                         -widout / 2).transformed(tr)
     edgein = pya.DEdge(length, widin / 2, length,
                        -widin / 2).transformed(tr)
     self.regionlistout.append(
         pya.DPolygon([
             self.painterout.pointl, self.painterout.pointr, edgeout.p2,
             edgeout.p1
         ]))
     self.regionlistin.append(
         pya.DPolygon([
             self.painterin.pointl, self.painterin.pointr, edgein.p2,
             edgein.p1
         ]))
     self.painterout.Setpoint(edgeout.p1, edgeout.p2)
     self.painterin.Setpoint(edgein.p1, edgein.p2)
     return length
Esempio n. 5
0
    def _link_move_edges(angles, pts, edges, das, reverse=False):
        '''
        挪边
        '''
        deltaangle, maxlength, boundAngle, gridAngle, extendlength, turningr = Interactive._link_define_utils(
        )

        n = len(edges)
        if not reverse:
            argsArr = [0, 1, (lambda ii: ii < n - 2), 0, 1, 0, 1, 1, 1]
        else:
            argsArr = [n, -1, (lambda ii: ii > 2), -2, -1, -1, -2, -2, -2]
        initii, iid, condition, dad, dld, angle0d, angled, ptd, eid = argsArr

        ii = initii
        last = 0
        moved = False
        while condition(ii):
            da = das[ii + dad]
            sda = (da > 0) - (da < 0)
            da *= sda
            dl = turningr * tan(da / 180 * pi / 2)
            ll = pts[ii].distance(pts[ii + dld]) - last - dl
            last = dl
            if (ll < 0):
                # move pt
                angle0 = angles[ii + angle0d]
                angle = angles[ii + angled]
                pt = pts[ii + ptd]
                ei = ii + eid
                edges[ei] = pya.DEdge(
                    pt.x + maxlength * cos(angle / 180 * pi) +
                    (extendlength - ll) * cos(angle0 / 180 * pi),
                    pt.y + maxlength * sin(angle / 180 * pi) +
                    (extendlength - ll) * sin(angle0 / 180 * pi),
                    pt.x - maxlength * cos(angle / 180 * pi) +
                    (extendlength - ll) * cos(angle0 / 180 * pi),
                    pt.y - maxlength * sin(angle / 180 * pi) +
                    (extendlength - ll) * sin(angle0 / 180 * pi))
                if not all([
                        edges[ei].crossed_by(edges[ei - 1]),
                        edges[ei].crossed_by(edges[ei + 1])
                ]):
                    IO.warning.warning(
                        "paintlib.Interactive.link",
                        "Error : Invalid path leads to no crossing point when adjusting conflict",
                        pya.MessageBox.Ok)
                    return
                pts[ei] = edges[ei].crossing_point(edges[ei - 1])
                pts[ei + 1] = edges[ei].crossing_point(edges[ei + 1])
                moved = True
            ii += iid
        return moved, angles, pts, edges, das
Esempio n. 6
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)
Esempio n. 7
0
 def TurningInterpolation(self, radius, angle=90):  #有待改进
     #radius非负向右,负是向左
     pass
     if angle < 0:
         angle = -angle
         radius = -radius
     angle = 90
     delta = self.pointr.distance(self.pointl)
     dx = (self.pointr.x - self.pointl.x) / delta
     dy = (self.pointr.y - self.pointl.y) / delta
     dtheta = atan2(dy, dx) * 180 / pi
     centerx = self.pointr.x + (radius - delta / 2) * dx
     centery = self.pointr.y + (radius - delta / 2) * dy
     n = int(
         ceil(1.3 * (abs(radius) + delta / 2) * angle * pi / 180 /
              IO.pointdistance) + 2)
     #
     rsgn = (radius > 0) - (radius < 0)
     pointr2 = pya.DPoint(centerx - rsgn * (radius - delta / 2) * dy,
                          centery + rsgn * (radius - delta / 2) * dx)
     pointl2 = pya.DPoint(centerx - rsgn * (radius + delta / 2) * dy,
                          centery + rsgn * (radius + delta / 2) * dx)
     pts1 = BasicPainter.arc_NewtonInterpolation(n, abs(radius) + delta / 2)
     pts2 = BasicPainter.arc_NewtonInterpolation(n, abs(radius) - delta / 2)
     pts1.extend(reversed(pts2))
     arc1 = pya.DPolygon(pts1)
     trans = pya.DCplxTrans(1, 180 + dtheta + 45 * rsgn, False, centerx,
                            centery)
     arc1.transform(trans)
     self.outputlist.append(arc1)
     self.pointr = pointr2
     self.pointl = pointl2
     pts3 = BasicPainter.arc_NewtonInterpolation(n, abs(radius))
     cpts = [
         pya.DEdge(pya.DPoint(), pt).transformed(trans).p2 for pt in pts3
     ]
     if abs(cpts[-1].distance(self.pointr) - delta / 2) < IO.pointdistance:
         if self.centerlinepts == []:
             self.centerlinepts = cpts
         else:
             self.centerlinepts.extend(cpts[1:])
     else:
         if self.centerlinepts == []:
             self.centerlinepts = cpts[::-1]
         else:
             self.centerlinepts.extend(cpts[-2::-1])
     return pi * 0.5 * abs(radius)
 def DrawText(self, cell, layer1, textstr, DCplxTrans1):
     #左下角坐标,每个字宽0.6*倍数高0.7*倍数线宽0.1*倍数
     #tr=pya.DCplxTrans(10,0,False,0,0)
     #倍数,逆时针度数,是否绕x翻转,平移x,平移y
     tr = pya.CplxTrans.from_dtrans(DCplxTrans1)
     textstr = "%s" % (textstr)
     param = {"text": textstr, "layer": layer1, "mag": 1}
     pv = []
     for p in self.TEXT_decl.get_parameters():
         if p.name in param:
             pv.append(param[p.name])
         else:
             pv.append(p.default)
     text_cell = IO.layout.create_cell("TEXT(\"%s\")" % (textstr))
     self.TEXT_decl.produce(IO.layout, [layer1], pv, text_cell)
     cell.insert(pya.CellInstArray(text_cell.cell_index(), tr))
     edge1 = pya.DEdge(len(textstr) * 0.6, 0,
                       len(textstr) * 0.6, 0.7).transformed(DCplxTrans1)
     return [edge1.p1, edge1.p2]
Esempio n. 9
0
    def test_3_DTrans(self):

        c = pya.DCplxTrans(5.0, -7.0)
        self.assertEqual(str(c), "r0 *1 5,-7")

        c = pya.DCplxTrans(pya.DCplxTrans.M135)
        self.assertEqual(str(c), "m135 *1 0,0")
        self.assertEqual(c.is_unity(), False)
        self.assertEqual(c.is_ortho(), True)
        self.assertEqual(c.is_mag(), False)
        self.assertEqual(c.is_mirror(), True)
        self.assertEqual(c.rot(), pya.DCplxTrans.M135.rot())
        self.assertEqual(str(c.s_trans()), "m135 0,0")
        self.assertAlmostEqual(c.angle, 270)

        self.assertEqual(str(c.trans(pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str((c * pya.DEdge(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str(c.trans(pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str((c * pya.DBox(0, 1, 2, 3))), "(-3,-2;-1,0)")
        self.assertEqual(str(c.trans(pya.DText("text", pya.DVector(0, 1)))),
                         "('text',m135 -1,0)")
        self.assertEqual(str((c * pya.DText("text", pya.DVector(0, 1)))),
                         "('text',m135 -1,0)")
        self.assertEqual(
            str(
                c.trans(
                    pya.DPolygon([
                        pya.DPoint(0, 1),
                        pya.DPoint(2, -3),
                        pya.DPoint(4, 5)
                    ]))), "(-5,-4;-1,0;3,-2)")
        self.assertEqual(
            str((c * pya.DPolygon(
                [pya.DPoint(0, 1),
                 pya.DPoint(2, -3),
                 pya.DPoint(4, 5)]))), "(-5,-4;-1,0;3,-2)")
        self.assertEqual(
            str(c.trans(pya.DPath(
                [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))),
            "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false")
        self.assertEqual(
            str((c * pya.DPath(
                [pya.DPoint(0, 1), pya.DPoint(2, 3)], 10))),
            "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false")

        c = pya.DCplxTrans.from_itrans(pya.CplxTrans.M135)
        self.assertEqual(str(c), "m135 *1 0,0")

        c = pya.DCplxTrans(1.5)
        self.assertEqual(str(c), "r0 *1.5 0,0")
        self.assertEqual(c.is_unity(), False)
        self.assertEqual(c.is_ortho(), True)
        self.assertEqual(c.is_mag(), True)
        self.assertEqual(c.is_mirror(), False)
        self.assertEqual(c.rot(), pya.DCplxTrans.R0.rot())
        self.assertEqual(str(c.s_trans()), "r0 0,0")
        self.assertAlmostEqual(c.angle, 0)

        c = pya.DCplxTrans(0.75, 45, True, 2.5, -12.5)
        self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5")
        c = pya.DCplxTrans(0.75, 45, True, pya.DPoint(2.5, -12.5))
        self.assertEqual(str(c), "m22.5 *0.75 2.5,-12.5")
        self.assertEqual(c.is_unity(), False)
        self.assertEqual(c.is_ortho(), False)
        self.assertEqual(c.is_mag(), True)
        self.assertEqual(c.rot(), pya.DCplxTrans.M0.rot())
        self.assertEqual(str(c.s_trans()), "m0 2.5,-12.5")
        self.assertAlmostEqual(c.angle, 45)

        self.assertEqual(str(c.ctrans(5)), "3.75")
        self.assertEqual(str(c.trans(pya.DPoint(12, 16))),
                         "17.3492424049,-14.6213203436")

        self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0")
        self.assertEqual(pya.DCplxTrans().is_unity(), True)
        self.assertEqual((c * c.inverted()).is_unity(), True)

        c.mirror = False
        self.assertEqual(str(c), "r45 *0.75 2.5,-12.5")
        c.mag = 1.5
        self.assertEqual(str(c), "r45 *1.5 2.5,-12.5")
        c.disp = pya.DPoint(-1.0, 5.5)
        self.assertEqual(str(c), "r45 *1.5 -1,5.5")
        self.assertEqual(c.mag, 1.5)
        c.angle = 60
        self.assertEqual(str(c), "r60 *1.5 -1,5.5")
        self.assertEqual(("%g" % c.angle), "60")

        # Constructor variations
        self.assertEqual(str(pya.ICplxTrans()), "r0 *1 0,0")
        self.assertEqual(str(pya.ICplxTrans(1.5)), "r0 *1.5 0,0")
        self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20), 1.5)),
                         "r90 *1.5 10,20")
        self.assertEqual(str(pya.ICplxTrans(pya.Trans(1, False, 10, 20))),
                         "r90 *1 10,20")
        self.assertEqual(
            str(pya.ICplxTrans(1.5, 80, True, pya.Vector(100, 200))),
            "m40 *1.5 100,200")
        self.assertEqual(str(pya.ICplxTrans(1.5, 80, True, 100, 200)),
                         "m40 *1.5 100,200")
        self.assertEqual(str(pya.ICplxTrans(pya.Vector(100, 200))),
                         "r0 *1 100,200")
        self.assertEqual(str(pya.ICplxTrans(100, 200)), "r0 *1 100,200")
        self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200))),
                         "r0 *1 100,200")
        self.assertEqual(str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5)),
                         "r0 *1.5 150,300")
        self.assertEqual(
            str(
                pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5,
                               pya.Vector(10, 20))), "r0 *1.5 160,320")
        self.assertEqual(
            str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, 10, 20)),
            "r0 *1.5 160,320")

        self.assertEqual(str(pya.DCplxTrans()), "r0 *1 0,0")
        self.assertEqual(str(pya.DCplxTrans(1.5)), "r0 *1.5 0,0")
        self.assertEqual(
            str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02), 1.5)),
            "r90 *1.5 0.01,0.02")
        self.assertEqual(str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02))),
                         "r90 *1 0.01,0.02")
        self.assertEqual(
            str(pya.DCplxTrans(1.5, 80, True, pya.DVector(0.1, 0.2))),
            "m40 *1.5 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(1.5, 80, True, 0.1, 0.2)),
                         "m40 *1.5 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(pya.DVector(0.1, 0.2))),
                         "r0 *1 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(0.1, 0.2)), "r0 *1 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2))),
                         "r0 *1 0.1,0.2")
        self.assertEqual(str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5)),
                         "r0 *1.5 0.15,0.3")
        self.assertEqual(
            str(
                pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5,
                               pya.DVector(0.01, 0.02))), "r0 *1.5 0.16,0.32")
        self.assertEqual(
            str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, 0.01, 0.02)),
            "r0 *1.5 0.16,0.32")
Esempio n. 10
0
def layout_waveguide(cell, layer, points_list, width):
    """ Lays out a waveguide (or trace) with a certain width with along given points.

    This is very useful for laying out Bezier curves with or without adiabatic tapers.

    Args:
        cell: cell to place into
        layer: layer to place into. It is done with cell.shapes(layer).insert(pya.Polygon)
        points_list: list of pya.DPoint (at least 2 points)
        width (microns): constant or list. If list, then it has to have the same length as points

    """
    if len(points_list) < 2:
        raise NotImplemented("ERROR: points_list too short")
        return

    try:
        if len(width) == len(points_list):
            width_iterator = iter(width)
        else:
            width_iterator = repeat(width[0])
    except TypeError:
        width_iterator = repeat(width)
    finally:
        points_iterator = iter(points_list)

    dbu = cell.layout().dbu

    points_low = list()
    points_high = list()

    def norm(self):
        return sqrt(self.x**2 + self.y**2)

    def cos_angle(point1, point2):
        return point1 * point2 / norm(point1) / norm(point2)

    point_width_list = list(zip(points_iterator, width_iterator))
    N = len(point_width_list)

    first_point, first_width = point_width_list[0]
    next_point, next_width = point_width_list[1]

    delta = next_point - first_point
    theta = np.arctan2(delta.y, delta.x)
    first_high_point = first_point + 0.5 * first_width * \
        pya.DPoint(cos(theta + pi / 2), sin(theta + pi / 2))
    first_low_point = first_point + 0.5 * first_width * \
        pya.DPoint(cos(theta - pi / 2), sin(theta - pi / 2))
    points_high.append(first_high_point)
    points_low.append(first_low_point)

    for i in range(1, N - 1):
        prev_point, prev_width = point_width_list[i - 1]
        point, width = point_width_list[i]
        next_point, next_width = point_width_list[i + 1]

        delta_prev = point - prev_point
        delta_next = next_point - point
        theta_prev = np.arctan2(delta_prev.y, delta_prev.x)
        theta_next = np.arctan2(delta_next.y, delta_next.x)

        next_point_high = (next_point + 0.5 * next_width *
                           pya.DPoint(cos(theta_next + pi / 2), sin(theta_next + pi / 2)))
        next_point_low = (next_point + 0.5 * next_width *
                          pya.DPoint(cos(theta_next - pi / 2), sin(theta_next - pi / 2)))

        forward_point_high = (point + 0.5 * width *
                              pya.DPoint(cos(theta_next + pi / 2), sin(theta_next + pi / 2)))
        forward_point_low = (point + 0.5 * width *
                             pya.DPoint(cos(theta_next - pi / 2), sin(theta_next - pi / 2)))

        prev_point_high = (prev_point + 0.5 * prev_width *
                           pya.DPoint(cos(theta_prev + pi / 2), sin(theta_prev + pi / 2)))
        prev_point_low = (prev_point + 0.5 * prev_width *
                          pya.DPoint(cos(theta_prev - pi / 2), sin(theta_prev - pi / 2)))

        backward_point_high = (point + 0.5 * width *
                               pya.DPoint(cos(theta_prev + pi / 2), sin(theta_prev + pi / 2)))
        backward_point_low = (point + 0.5 * width *
                              pya.DPoint(cos(theta_prev - pi / 2), sin(theta_prev - pi / 2)))

        # High point decision
        next_high_edge = pya.DEdge(forward_point_high, next_point_high)
        prev_high_edge = pya.DEdge(backward_point_high, prev_point_high)

        if next_high_edge.crossed_by(prev_high_edge):
            intersect_point = next_high_edge.crossing_point(prev_high_edge)
            points_high.append(intersect_point)
        else:
            if width * (1 - cos_angle(delta_next, delta_prev)) > dbu:
                points_high.append(backward_point_high)
                points_high.append(forward_point_high)
            else:
                points_high.append((backward_point_high + forward_point_high) * 0.5)

        # Low point decision
        next_low_edge = pya.DEdge(forward_point_low, next_point_low)
        prev_low_edge = pya.DEdge(backward_point_low, prev_point_low)

        if next_low_edge.crossed_by(prev_low_edge):
            intersect_point = next_low_edge.crossing_point(prev_low_edge)
            points_low.append(intersect_point)
        else:
            if width * (1 - cos_angle(delta_next, delta_prev)) > dbu:
                points_low.append(backward_point_low)
                points_low.append(forward_point_low)
            else:
                points_low.append((backward_point_low + forward_point_low) * 0.5)

    last_point, last_width = point_width_list[-1]
    point, width = point_width_list[-2]
    delta = last_point - point
    theta = np.arctan2(delta.y, delta.x)
    final_high_point = last_point + 0.5 * last_width * \
        pya.DPoint(cos(theta + pi / 2), sin(theta + pi / 2))
    final_low_point = last_point + 0.5 * last_width * \
        pya.DPoint(cos(theta - pi / 2), sin(theta - pi / 2))
    if (final_high_point - points_high[-1]) * delta > 0:
        points_high.append(final_high_point)
    if (final_low_point - points_low[-1]) * delta > 0:
        points_low.append(final_low_point)

    # Append point only if change in direction is less than 120 degrees.
    def smooth_append(point_list, point):
        if point_list is None:
            print(point)
        if len(point_list) < 1:
            point_list.append(point)
            return point_list
        elif len(point_list) < 2:
            curr_edge = point - point_list[-1]
            if norm(curr_edge) > dbu:
                point_list.append(point)
                return point_list

        curr_edge = point - point_list[-1]
        if norm(curr_edge) > dbu:
            prev_edge = point_list[-1] - point_list[-2]
            if cos_angle(curr_edge, prev_edge) > cos(120 / 180 * pi):
                point_list.append(point)
        return point_list

    polygon_points = points_low + list(reversed(points_high))
    polygon_points = list(reduce(smooth_append, polygon_points, list()))

    poly = pya.DPolygon(polygon_points)
    cell.shapes(layer).insert(poly)
Esempio n. 11
0
def waveguide_dpolygon(points_list, width, dbu, smooth=True):
    """ Returns a polygon outlining a waveguide.

    This was updated over many iterations of failure. It can be used for both
    smooth optical waveguides or DC metal traces with corners. It is better
    than klayout's Path because it can have varying width.

    Args:
        points_list: list of pya.DPoint (at least 2 points)
        width (microns): constant or list. If list, then it has to have the same length as points
        dbu: dbu: typically 0.001, only used for accuracy calculations.
        smooth: tries to smooth final polygons to avoid very sharp edges (greater than 130 deg)
    Returns:
        polygon DPoints

    """
    if len(points_list) < 2:
        raise NotImplementedError("ERROR: points_list too short")
        return

    def norm(self):
        return sqrt(self.x**2 + self.y**2)

    try:
        if len(width) == len(points_list):
            width_iterator = iter(width)
        elif len(width) == 2:
            # assume width[0] is initial width and
            # width[1] is final width
            # interpolate with points_list
            L = curve_length(points_list)
            distance = 0
            widths_list = [width[0]]
            widths_func = lambda t: (1 - t) * width[0] + t * width[1]
            old_point = points_list[0]
            for point in points_list[1:]:
                distance += norm(point - old_point)
                old_point = point
                widths_list.append(widths_func(distance / L))
            width_iterator = iter(widths_list)
        else:
            width_iterator = repeat(width[0])
    except TypeError:
        width_iterator = repeat(width)
    finally:
        points_iterator = iter(points_list)

    points_low = list()
    points_high = list()

    def cos_angle(point1, point2):
        cos_angle = point1 * point2 / norm(point1) / norm(point2)

        # ensure it's between -1 and 1 (nontrivial numerically)
        if abs(cos_angle) > 1:
            return cos_angle / abs(cos_angle)
        else:
            return cos_angle

    def sin_angle(point1, point2):
        return sin(np.arccos(cos_angle(point1, point2)))

    point_width_list = list(zip(points_iterator, width_iterator))
    N = len(point_width_list)

    first_point, first_width = point_width_list[0]
    next_point, next_width = point_width_list[1]

    delta = next_point - first_point
    theta = np.arctan2(delta.y, delta.x)
    first_high_point = first_point + 0.5 * first_width * \
        pya.DPoint(cos(theta + pi / 2), sin(theta + pi / 2))
    first_low_point = first_point + 0.5 * first_width * \
        pya.DPoint(cos(theta - pi / 2), sin(theta - pi / 2))
    points_high.append(first_high_point)
    points_low.append(first_low_point)

    for i in range(1, N - 1):
        prev_point, prev_width = point_width_list[i - 1]
        point, width = point_width_list[i]
        next_point, next_width = point_width_list[i + 1]

        delta_prev = point - prev_point
        delta_next = next_point - point
        theta_prev = np.arctan2(delta_prev.y, delta_prev.x)
        theta_next = np.arctan2(delta_next.y, delta_next.x)

        next_point_high = (next_point + 0.5 * next_width *
                           pya.DPoint(cos(theta_next + pi / 2), sin(theta_next + pi / 2)))
        next_point_low = (next_point + 0.5 * next_width *
                          pya.DPoint(cos(theta_next - pi / 2), sin(theta_next - pi / 2)))

        forward_point_high = (point + 0.5 * width *
                              pya.DPoint(cos(theta_next + pi / 2), sin(theta_next + pi / 2)))
        forward_point_low = (point + 0.5 * width *
                             pya.DPoint(cos(theta_next - pi / 2), sin(theta_next - pi / 2)))

        prev_point_high = (prev_point + 0.5 * prev_width *
                           pya.DPoint(cos(theta_prev + pi / 2), sin(theta_prev + pi / 2)))
        prev_point_low = (prev_point + 0.5 * prev_width *
                          pya.DPoint(cos(theta_prev - pi / 2), sin(theta_prev - pi / 2)))

        backward_point_high = (point + 0.5 * width *
                               pya.DPoint(cos(theta_prev + pi / 2), sin(theta_prev + pi / 2)))
        backward_point_low = (point + 0.5 * width *
                              pya.DPoint(cos(theta_prev - pi / 2), sin(theta_prev - pi / 2)))

        fix_angle = lambda theta: ((theta + pi) % (2 * pi)) - pi

        # High point decision
        next_high_edge = pya.DEdge(forward_point_high, next_point_high)
        prev_high_edge = pya.DEdge(backward_point_high, prev_point_high)

        if next_high_edge.crossed_by(prev_high_edge):
            intersect_point = next_high_edge.crossing_point(prev_high_edge)
            points_high.append(intersect_point)
        else:
            cos_dd = cos_angle(delta_next, delta_prev)
            if width * (1 - cos_dd) > dbu and fix_angle(theta_next - theta_prev) < 0:
                points_high.append(backward_point_high)
                points_high.append(forward_point_high)
            else:
                points_high.append((backward_point_high + forward_point_high) * 0.5)

        # Low point decision
        next_low_edge = pya.DEdge(forward_point_low, next_point_low)
        prev_low_edge = pya.DEdge(backward_point_low, prev_point_low)

        if next_low_edge.crossed_by(prev_low_edge):
            intersect_point = next_low_edge.crossing_point(prev_low_edge)
            points_low.append(intersect_point)
        else:
            cos_dd = cos_angle(delta_next, delta_prev)
            if width * (1 - cos_dd) > dbu and fix_angle(theta_next - theta_prev) > 0:
                points_low.append(backward_point_low)
                points_low.append(forward_point_low)
            else:
                points_low.append((backward_point_low + forward_point_low) * 0.5)

    last_point, last_width = point_width_list[-1]
    point, width = point_width_list[-2]
    delta = last_point - point
    theta = np.arctan2(delta.y, delta.x)
    final_high_point = last_point + 0.5 * last_width * \
        pya.DPoint(cos(theta + pi / 2), sin(theta + pi / 2))
    final_low_point = last_point + 0.5 * last_width * \
        pya.DPoint(cos(theta - pi / 2), sin(theta - pi / 2))
    if (final_high_point - points_high[-1]) * delta > 0:
        points_high.append(final_high_point)
    if (final_low_point - points_low[-1]) * delta > 0:
        points_low.append(final_low_point)

    # Append point only if change in direction is less than 130 degrees.
    def smooth_append(point_list, point):
        if len(point_list) < 1:
            point_list.append(point)
            return point_list
        elif len(point_list) < 2:
            curr_edge = point - point_list[-1]
            if norm(curr_edge) >= dbu:
                point_list.append(point)
                return point_list

        curr_edge = point - point_list[-1]
        if norm(curr_edge) >= dbu:
            prev_edge = point_list[-1] - point_list[-2]

            if norm(prev_edge) * abs(sin_angle(curr_edge + prev_edge, prev_edge)) > dbu:
                if smooth:
                    # avoid corners when smoothing
                    if cos_angle(curr_edge, prev_edge) > cos(130 / 180 * pi):
                        point_list.append(point)
                    else:
                        # edge case when there is prev_edge is small and
                        # needs to be deleted to get rid of the corner
                        if norm(curr_edge) > norm(prev_edge):
                            point_list[-1] = point
                else:
                    point_list.append(point)
            # avoid unnecessary points
            else:
                point_list[-1] = point
        return point_list

    if debug and False:
        print("Points to be smoothed:")
        for point, width in point_width_list:
            print(point, width)

    smooth_points_high = list(reduce(smooth_append, points_high, list()))
    smooth_points_low = list(reduce(smooth_append, points_low, list()))
    # smooth_points_low = points_low
    # polygon_dpoints = points_high + list(reversed(points_low))
    # polygon_dpoints = list(reduce(smooth_append, polygon_dpoints, list()))
    polygon_dpoints = smooth_points_high + list(reversed(smooth_points_low))
    return DSimplePolygon(polygon_dpoints)
Esempio n. 12
0
    def _get_region_cell_port(region,brush,layerlist,boxx,boxy,offsetx=0,offsety=0,deltaangle=0,absx=None,absy=None,portbrushs=None,transmissionlines=None,crossoverLayerList=False):#added crossoverLayerList
        '''先把图像逆时针转deltaangle角度后沿着平直截取'''
        # if deltaangle>46 or deltaangle<-46:raise RuntimeError('deltaangle more than 45 degree')
        if absx==None or absy==None:
            _pb=[region.bbox()]
            if type(brush)!=type(None):
                painter=CavityPainter(brush)
                painter.Run(lambda painter:painter._Straight(10)+painter._Straight(-10))
                _pb.append(painter.Output_Region().bbox())
            _pbr=pya.Region()
            for ii in _pb:_pbr.insert(ii)
            pc=_pbr.bbox().center()
        else:
            pc=pya.DPoint(absx,absy)
        pc=pya.DPoint(pc.x+offsetx,pc.y+offsety)
        
        def tr_to(obj,itr=False):
            trs=[pya.DCplxTrans(1,-deltaangle,False,pc.x,pc.y)]
            if itr:trs=[pya.ICplxTrans.from_dtrans(tr) for tr in trs]
            for tr in trs:
                obj=obj.transformed(tr)
            return obj
        def tr_back(obj,itr=False):
            trs=[pya.DCplxTrans(1,0,False,-pc.x,-pc.y),
                pya.DCplxTrans(1,deltaangle,False,0,0)]
            if itr:trs=[pya.ICplxTrans.from_dtrans(tr) for tr in trs]
            for tr in trs:
                obj=obj.transformed(tr)
            return obj

        box=tr_to(pya.Box(-boxx/2,-boxy/2,boxx/2,boxy/2),itr=True)
        #
        _,inregion=Interactive.cut(layerlist=layerlist,layermod='in',box=box,mergeanddraw=False)
        inregion=tr_back(inregion,itr=True)
        outregion=pya.Region(pya.Box(-boxx/2,-boxy/2,boxx/2,boxy/2))

        if type(brush)!=type(None):
            painter=CavityPainter(tr_back(brush))
            painter.Run(lambda painter:painter._Straight(-boxx-boxy))
            painter.Run(lambda painter:painter.Straight(2*boxx+2*boxy))
            inregion=inregion+painter.Output_Region()

        #计算端口
        ports=[]
        edges=[ #左,上,右,下
            pya.DEdge(-boxx/2,-boxy/2,-boxx/2,+boxy/2),
            pya.DEdge(-boxx/2,+boxy/2,+boxx/2,+boxy/2),
            pya.DEdge(+boxx/2,+boxy/2,+boxx/2,-boxy/2),
            pya.DEdge(+boxx/2,-boxy/2,-boxx/2,-boxy/2)
        ]
        #
        if type(brush)!=type(None):
            br=painter.brush
            pt=pya.DPoint(br.centerx,br.centery)
            angle=br.angle
            edge=pya.DEdge(pt.x,pt.y,pt.x-(2*boxx+2*boxy)*cos(angle/180*pi),pt.y-(2*boxx+2*boxy)*sin(angle/180*pi))
            ports.extend([ee.crossing_point(edge) for ee in edges if ee.crossed_by(edge)])
        if transmissionlines!=None:
            for transmissionline in transmissionlines:
                for info in transmissionline:
                    cpts=info[0]
                    pt0=cpts[0]
                    for pt in cpts[1:]:
                        edge=tr_back(pya.DEdge(pt0,pt))
                        pt0=pt
                        ports.extend([ee.crossing_point(edge) for ee in edges if ee.crossed_by(edge)])
        if portbrushs!=None:
            portbrushs=[tr_back(brush) for brush in portbrushs]
            ports.extend([pya.DPoint(brush.centerx,brush.centery) for brush in portbrushs])
        ports=[[pt.x,pt.y] for pt in ports if abs(pt.x)<boxx/2+10 and abs(pt.y)<boxy/2+10]
        
        
        final_region,cell=Interactive._merge_and_draw(outregion,inregion,pya.CplxTrans(1,-deltaangle,False,pc.x,pc.y))
        if crossoverLayerList!=False:
            final_region,cell=Interactive._merge_and_draw(outregion,inregion,pya.CplxTrans(1,-deltaangle,False,pc.x,pc.y),False)

######################added crossover_region_list###########
#        crossover_region_list=[]
#        if crossoverLayerList!=False:
            #for layerlist in crossoverLayerList:
#            _,crossover_inregion=Interactive.cut(layerlist=layerlist,layermod='in',box=box,mergeanddraw=False)#[1]
            #crossover_region_list.append(Interactive._merge_and_draw(outregion,crossover_inregion,None,False)[0])
#            final_region,cell=Interactive._merge_and_draw(outregion,crossover_inregion,None,False)

        #if crossoverLayerList!=False:
         #   final_region=[]
          #  final_region=crossover_region



        return final_region,cell,ports
Esempio n. 13
0
 def constructors3(self, pointoutl, pointinl, pointinr, pointoutr):
     self.edgeout = pya.DEdge(pointoutl, pointoutr)
     self.edgein = pya.DEdge(pointinl, pointinr)
Esempio n. 14
0
 def constructors2(self,
                   edgeout=pya.DEdge(0, 20000 / 2, 0, -20000 / 2),
                   edgein=pya.DEdge(0, 0, 0, 0)):
     self.edgeout = edgeout
     self.edgein = edgein
Esempio n. 15
0
    def _link_scan_angles(brush1, brush2, spts):
        '''
        扫角度
        '''
        deltaangle, maxlength, boundAngle, gridAngle, extendlength, turningr = Interactive._link_define_utils(
        )

        #起点
        angles = [boundAngle(brush1.angle)]
        pts = [pya.DPoint(brush1.centerx, brush1.centery)]
        edges = [
            pya.DEdge(pts[0].x, pts[0].y,
                      pts[0].x + maxlength * cos(angles[0] / 180 * pi),
                      pts[0].y + maxlength * sin(angles[0] / 180 * pi))
        ]
        das = []
        #这四个数组最终长度: n个角度, n+1个点, n条边, n-1个角度变化

        #经过的点
        for ii in range(1, len(spts)):
            pt = spts[ii]
            pt0 = spts[ii - 1]
            angle0 = angles[-1]
            edge0 = edges[-1]
            angle = gridAngle(atan2(pt.y - pt0.y, pt.x - pt0.x) / pi * 180)
            da = boundAngle(angle0 - angle)  # 默认的右转是顺时针, 计算出的逆时针的角度要取反
            if (da == 0):
                continue
            if (da == 180):
                IO.warning.warning("paintlib.Interactive.link",
                                   "Error : Turn 180 degrees",
                                   pya.MessageBox.Ok)
                return
            edge = pya.DEdge(pt.x + maxlength * cos(angle / 180 * pi),
                             pt.y + maxlength * sin(angle / 180 * pi),
                             pt.x - maxlength * cos(angle / 180 * pi),
                             pt.y - maxlength * sin(angle / 180 * pi))
            if not edge.crossed_by(edge0):
                if len(das) == 0:
                    continue
                print('point ', ii)
                print(angle)
                print(angle0)
                IO.warning.warning(
                    "paintlib.Interactive.link",
                    "Error : Invalid path leads to no crossing point",
                    pya.MessageBox.Ok)
                return
            angles.append(angle)
            das.append(da)
            pts.append(edge.crossing_point(edge0))
            edges.append(edge)

        #终点
        if True:
            angle0 = angles[-1]
            edge0 = edges[-1]
            angle = boundAngle(brush2.angle + 180)
            pt = pya.DPoint(brush2.centerx, brush2.centery)
            _angle = gridAngle(angle)
            if (_angle == angle0 and len(das) > 0):
                # 规整化后与终点平行, 放弃最后一个点, 从而不再平行
                angles.pop()
                das.pop()
                pts.pop()
                edges.pop()
                angle0 = angles[-1]
                edge0 = edges[-1]
            da = boundAngle(angle0 - angle)
            _da = boundAngle(angle0 - _angle)
            if (_da == 180):
                IO.warning.warning("paintlib.Interactive.link",
                                   "Error : Turn 180 degrees",
                                   pya.MessageBox.Ok)
                return
            lastpt = pt
            edge = pya.DEdge(pt.x, pt.y,
                             pt.x - maxlength * cos(angle / 180 * pi),
                             pt.y - maxlength * sin(angle / 180 * pi))
            if (angle == angle0 and len(das) == 0):
                # 只有起点和终点且平行
                dis = edge0.distance(pt)
                if abs(dis) < 10:
                    # 直连无需转弯
                    pass
                else:
                    # 需转弯, 此处多生成两个点和两个角度, 如果dis小于2-sqrt(2)的转弯半径, 生成路径时会报错
                    pt0 = pts[-1]
                    dse = pt0.distance(pt)
                    dp = sqrt(dse**2 - dis**2)
                    l1 = (dp - dis) / 2
                    if dis < 0:
                        das.extend([-45, 45])
                        angles.extend([angle + 45, angle])
                    else:
                        das.extend([45, -45])
                        angles.extend([angle - 45, angle])
                    pt1 = pya.DPoint(pt0.x + l1 * cos(angle / 180 * pi),
                                     pt0.y + l1 * sin(angle / 180 * pi))
                    pt2 = pya.DPoint(pt.x - l1 * cos(angle / 180 * pi),
                                     pt.y - l1 * sin(angle / 180 * pi))
                    pts.extend([pt1, pt2])
                    edges.extend([pya.DEdge(pt1, pt2), edge])
            else:
                angles.append(angle)
                das.append(da)
                if not edge.crossed_by(edge0):
                    print('brush2')
                    print(angle)
                    print(angle0)
                    IO.warning.warning(
                        "paintlib.Interactive.link",
                        "Error : Invalid path leads to no crossing point",
                        pya.MessageBox.Ok)
                    return
                pts.append(edge.crossing_point(edge0))
                edges.append(edge)
            pts.append(lastpt)
        return angles, pts, edges, das
Esempio n. 16
0
    def link(brush1=None, brush2=None):
        '''
        输入两个CavityBrush作为参数, 并点击图中的一个路径, 生成一个连接两个brush的路径的函数  
        缺省时会在Interactive.searchr内搜索最近的brush
        第二个brush可为None, 此时取path的终点作为路径终点
        '''
        deltaangle = Interactive.deltaangle
        maxlength = Interactive.maxlength

        spts = Interactive._pts_path_selected()
        if spts == False: return
        if brush1 == None:
            brush1 = Interactive._get_nearest_brush(spts[0].x, spts[0].y)
        if brush2 == None:
            brush2 = Interactive._get_nearest_brush(spts[-1].x, spts[-1].y)

        if not isinstance(brush1, CavityBrush):
            pya.MessageBox.warning("paintlib.Interactive.link",
                                   "Argument 1 must be CavityBrush",
                                   pya.MessageBox.Ok)
            return
        if not isinstance(brush2, CavityBrush) and brush2 != None:
            pya.MessageBox.warning("paintlib.Interactive.link",
                                   "Argument 2 must be CavityBrush or None",
                                   pya.MessageBox.Ok)
            return
        angles = [brush1.angle]
        pts = [pya.DPoint(brush1.centerx, brush1.centery)]
        edges = [
            pya.DEdge(pts[0].x, pts[0].y,
                      pts[0].x + maxlength * cos(angles[0] / 180 * pi),
                      pts[0].y + maxlength * sin(angles[0] / 180 * pi))
        ]
        das = []
        lastpt = None

        for ii in range(1, len(spts)):
            pt = spts[ii]
            pt0 = spts[ii - 1]
            angle0 = angles[-1]
            edge0 = edges[-1]
            angle = atan2(pt.y - pt0.y, pt.x - pt0.x) / pi * 180
            angle = round(angle / deltaangle) * deltaangle
            angle = 0 if angle == 360.0 else angle
            if (angle == angle0): continue
            da = -((angle + 3600 - angle0) % 360)
            if (da == -180):
                pya.MessageBox.warning("paintlib.Interactive.link",
                                       "Error : Turn 180 degrees",
                                       pya.MessageBox.Ok)
                return
            if (da < -180): da = 360 + da
            lastpt = [pt.x, pt.y]
            angles.append(angle)
            edge = pya.DEdge(pt.x + maxlength * cos(angle / 180 * pi),
                             pt.y + maxlength * sin(angle / 180 * pi),
                             pt.x - maxlength * cos(angle / 180 * pi),
                             pt.y - maxlength * sin(angle / 180 * pi))
            das.append(da)
            if not edge.crossed_by(edge0):
                print('point ', ii)
                print(angle)
                print(angle0)
                pya.MessageBox.warning(
                    "paintlib.Interactive.link",
                    "Error : Invalid path leads to no crossing point",
                    pya.MessageBox.Ok)
                return
            pts.append(edge.crossing_point(edge0))
            edges.append(edge)

        if (brush2 != None):
            angle0 = angles[-1]
            edge0 = edges[-1]
            angle = brush2.angle + 180
            pt = pya.DPoint(brush2.centerx, brush2.centery)
            _angle = round(angle / deltaangle) * deltaangle
            _angle = 0 if _angle == 360.0 else _angle
            if (_angle == angle0):
                angles.pop()
                das.pop()
                pts.pop()
                edges.pop()
                angle0 = angles[-1]
                edge0 = edges[-1]
            da = -((angle + 3600 - angle0) % 360)
            _da = -((_angle + 3600 - angle0) % 360)
            if (_da == -180):
                pya.MessageBox.warning("paintlib.Interactive.link",
                                       "Error : Turn 180 degrees",
                                       pya.MessageBox.Ok)
                return
            if (da < -180): da = 360 + da
            lastpt = [pt.x, pt.y]
            edge = pya.DEdge(pt.x, pt.y,
                             pt.x - maxlength * cos(angle / 180 * pi),
                             pt.y - maxlength * sin(angle / 180 * pi))
            angles.append(angle)
            das.append(da)
            if not edge.crossed_by(edge0):
                print('brush2')
                print(angle)
                print(angle0)
                pya.MessageBox.warning(
                    "paintlib.Interactive.link",
                    "Error : Invalid path leads to no crossing point",
                    pya.MessageBox.Ok)
                return
            pts.append(edge.crossing_point(edge0))
            edges.append(edge)
        pts.append(pya.DPoint(lastpt[0], lastpt[1]))
        ss = Interactive._generatepath(pts, das)
        print('##################################')
        print(ss)
        print('##################################')
        Interactive._show_path(brush1, ss)