[docs]@gf.celldefbend_euler(radius:float|None=None,angle:float=90.0,p:float=0.5,with_arc_floorplan:bool=True,npoints:int|None=None,direction:str="ccw",cross_section:CrossSectionSpec="xs_sc",**kwargs,)->Component:"""Euler bend with changing bend radius. By default, `radius` corresponds to the minimum radius of curvature of the bend. However, if `with_arc_floorplan` is True, `radius` corresponds to the effective radius of curvature (making the curve a drop-in replacement for an arc). If p < 1.0, will create a "partial euler" curve as described in Vogelbacher et. al. https://dx.doi.org/10.1364/oe.27.031394 default p = 0.5 based on this paper https://www.osapublishing.org/oe/fulltext.cfm?uri=oe-25-8-9150&id=362937 Args: radius: in um. Defaults to cross_section_radius. angle: total angle of the curve. p: Proportion of the curve that is an Euler curve. with_arc_floorplan: If False: `radius` is the minimum radius of curvature If True: The curve scales such that the endpoints match a bend_circular with parameters `radius` and `angle`. npoints: Number of points used per 360 degrees. direction: cw (clock-wise) or ccw (counter clock-wise). cross_section: specification (CrossSection, string, CrossSectionFactory dict). kwargs: additional cross_section arguments. .. code:: o2 | / / / o1_____/ """x=gf.get_cross_section(cross_section,**kwargs)radius=radiusorx.radiusifradiusisNone:returnwire_corner(cross_section=x)c=Component()p=euler(radius=radius,angle=angle,p=p,use_eff=with_arc_floorplan,npoints=npoints)ref=c<<p.extrude(x)ifdirection=="cw":ref.mirror(p1=[0,0],p2=[1,0])c.add_ports(ref.ports)c.info["length"]=float(np.round(p.length(),3))c.info["dy"]=float(np.round(abs(float(p.points[0][0]-p.points[-1][0])),3))c.info["radius_min"]=float(np.round(p.info["Rmin"],3))c.info["radius"]=radiusc.info["width"]=x.widthx.validate_radius(radius)c.absorb(ref)c.add_route_info(cross_section=x,length=c.info["length"],n_bend_90=abs(angle/90.0))returnc
bend_euler180=partial(bend_euler,angle=180)
[docs]@gf.celldefbend_euler_s(**kwargs)->Component:r"""Sbend made of 2 euler bends. Keyword Args: angle: total angle of the curve. p: Proportion of the curve that is an Euler curve. with_arc_floorplan: If False: `radius` is the minimum radius of curvature If True: The curve scales such that the endpoints match a bend_circular with parameters `radius` and `angle`. npoints: Number of points used per 360 degrees. direction: cw (clock-wise) or ccw (counter clock-wise). cross_section: specification (CrossSection, string, CrossSectionFactory dict). kwargs: cross_section settings. .. code:: _____ o2 / / / / | / / / o1_____/ """c=Component()b=bend_euler(**kwargs)b1=c.add_ref(b)b2=c.add_ref(b)b2.mirror()b2.connect("o1",b1.ports["o2"])c.add_port("o1",port=b1.ports["o1"])c.add_port("o2",port=b2.ports["o2"])c.info["length"]=2*b.info["length"]returnc
[docs]@gf.celldefbend_straight_bend(straight_length:float=10.0,angle:float=90,p:float=0.5,with_arc_floorplan:bool=True,npoints:int=720,direction:str="ccw",cross_section:CrossSectionSpec=strip,radius:float|None=None,**kwargs,)->Component:"""Sbend made of 2 euler bends and straight section in between. Args: straight_length: in um. angle: total angle of the curve. p: Proportion of the curve that is an Euler curve. with_arc_floorplan: If False: `radius` is the minimum radius of curvature If True: The curve scales such that the endpoints match a bend_circular with parameters `radius` and `angle`. npoints: Number of points used per 360 degrees. direction: cw (clock-wise) or ccw (counter clock-wise). cross_section: specification (CrossSection, string, CrossSectionFactory dict). radius: in um. Defaults to cross_section_radius. kwargs: additional cross_section arguments. """c=Component()b=bend_euler(angle=angle,p=p,with_arc_floorplan=with_arc_floorplan,npoints=npoints,direction="ccw",cross_section=cross_section,radius=radius,**kwargs,)b1=c.add_ref(b)ifdirection=="cw":b1.mirror_y()b2=c.add_ref(b)ifdirection=="cw":b2.mirror_y()s=c<<straight(length=straight_length,cross_section=cross_section,)s.connect("o1",b1.ports["o2"])b2.mirror()b2.connect("o1",s.ports["o2"])c.add_port("o2",port=b2.ports["o2"])c.add_port("o1",port=b1.ports["o1"])returnc
def_compare_bend_euler180()->None:"""Compare 180 bend euler with 2 90deg euler bends."""importgdsfactoryasgfp1=gf.Path()p1.append([gf.path.euler(angle=90),gf.path.euler(angle=90)])p2=gf.path.euler(angle=180)x=gf.cross_section.strip()c1=gf.path.extrude(p1,x)c1.name="two_90_euler"c2=gf.path.extrude(p2,x)c2.name="one_180_euler"c1.show()def_compare_bend_euler90():"""Compare bend euler with 90deg circular bend."""importgdsfactoryasgfc=gf.Component()radius=10b1=bend_euler(radius=radius)b2=gf.components.bend_circular(radius=radius)print(b1.info["length"])print(b2.info["length"])_=c<<b1_=c<<b2returncif__name__=="__main__":xs=gf.cross_section.strip(bbox_layers=[(111,0)],bbox_offsets=[3])c=bend_euler(cross_section=xs,angle=30)c.show(show_ports=True)