def bench_gdstk(output=None): r = 0.15 c1 = gdstk.Curve((1 / 2 - r, -(3**0.5) / 6), 1e-3) c1.arc(r, numpy.pi, numpy.pi * 2 / 3) c1.segment((1 - 2 * r) * numpy.exp(1j * numpy.pi * 2 / 3), relative=True) c1.arc(r, -numpy.pi / 3, -numpy.pi * 2 / 3) c1.segment((1 - 2 * r) * numpy.exp(-1j * numpy.pi * 2 / 3), relative=True) c1.arc(r, numpy.pi / 3, 0) p1 = gdstk.Polygon(c1.points()) c2 = gdstk.Curve((0, -r), 1e-3) c2.interpolation( [ 2 * r * numpy.exp(-1j * numpy.pi / 6), r * numpy.exp(1j * numpy.pi / 6), (0, 2 * r), r * numpy.exp(1j * numpy.pi * 5 / 6), 2 * r * numpy.exp(-1j * numpy.pi * 5 / 6), ], cycle=True, ) p2 = gdstk.Polygon(c2.points(), layer=1) if output: cell = gdstk.Cell("MAIN") cell.add(p1, p2) cell.write_svg(output, 300)
def test_scale(): poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.scale(0.5) assert_close(poly.points, [[0, 0], [0.5, 0], [0, 0.5]]) poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.scale(-2, 3, 1 + 0j) assert_close(poly.points, [[3, 0], [1, 0], [3, 3]])
def bezier_image(): points = [(4, 1), (4, 3), (0, 5), (-4, 3), (-4, -2), (0, -4), (0, 0)] curve = gdstk.Curve((0, 0)) curve.segment(points) control_poly = gdstk.Polygon(curve.points(), datatype=1) curve = gdstk.Curve((0, 0), tolerance=1e-3) curve.bezier(points) polygon = gdstk.Polygon(curve.points()) return gdstk.Cell("bezier").add(polygon, control_poly)
def test_bb(tree): c3, c2, c1 = tree assert_close(c3.bounding_box(), ((0, 0), (8, 4))) p2 = gdstk.Polygon(((-1, 2), (-1, 1), (0, 2)), 2, 2) c2.add(p2) assert_close(c3.bounding_box(), ((-1, 0), (8, 5))) p1 = gdstk.Polygon(((0, 3), (0, 2), (1, 3)), 3, 3) c1.add(p1) assert_close(c3.bounding_box(), ((-1, 0), (8, 6)))
def arc_image(): curve = gdstk.Curve((-0.6, 0), tolerance=1e-3) curve.segment((1, 0), True) curve.arc(1, 0, numpy.pi / 2) polygon_1 = gdstk.Polygon(curve.points()) curve = gdstk.Curve((0.6, 0), tolerance=1e-3) curve.segment((1, 0), True) curve.arc((2**-0.5, 0.4), -numpy.pi / 4, 3 * numpy.pi / 4, -numpy.pi / 4) polygon_2 = gdstk.Polygon(curve.points()) return gdstk.Cell("arc").add(polygon_1, polygon_2)
def tolerance_image(): curve = gdstk.Curve((-2.5, 0), tolerance=1e-1) curve.arc((2, 3), 0, numpy.pi) polygon_1 = gdstk.Polygon(curve.points()) # print(polygon_1.size) curve = gdstk.Curve((2.5, 0), tolerance=1e-3) curve.arc((2, 3), 0, numpy.pi) polygon_2 = gdstk.Polygon(curve.points()) # print(polygon_2.size) return gdstk.Cell("tolerance").add(polygon_1, polygon_2)
def flatten_image(): poly1 = gdstk.Polygon([(0, 0), (1, 0), (0.5, 1)]) cell1 = gdstk.Cell("CELL_1") cell1.add(poly1) poly2 = gdstk.Polygon([(1, 0), (1.5, 1), (0.5, 1)], layer=1) ref = gdstk.Reference(cell1, columns=2, rows=2, spacing=(1, 1)) cell2 = gdstk.Cell("CELL_2") cell2.add(poly2, ref) # print(len(cell2.polygons), len(cell2.references), len(cell2.dependencies(True))) cell2.flatten() # print(len(cell2.polygons), len(cell2.references), len(cell2.dependencies(True))) cell2.name = "flatten" return cell2
def tree(): p1 = gdstk.Polygon(((0, 0), (0, 1), (1, 0)), 0, 0) p2 = gdstk.Polygon(((2, 0), (2, 1), (1, 0)), 1, 1) l1 = gdstk.Label("label1", (0, 0), layer=11) l2 = gdstk.Label("label2", (2, 1), layer=12) c1 = gdstk.Cell("tree1") c1.add(p1) c1.add(l1) c2 = gdstk.Cell("tree2") c2.add(l2) c2.add(p2) c2.add(gdstk.Reference(c1)) c3 = gdstk.Cell("tree3") c3.add(gdstk.Reference(c2, (0, 0), columns=3, rows=2, spacing=(3, 3))) return c3, c2, c1
def test_properties(): for obj in [ gdstk.Polygon([-1 + 0j, -2j, 3 + 0j, 4j]), gdstk.FlexPath((0j, 1j), 0.1), gdstk.RobustPath(0j, 0.1), gdstk.Label("Label", 0j), gdstk.Reference("EMPTY"), gdstk.Cell("CELL"), gdstk.Library("Name"), ]: assert len(obj.properties) == 0 assert obj.get_property("None") is None obj.set_property("FIRST", 1) obj.set_property("SECOND", 2.0) obj.set_property("THIRD", -3) obj.set_property("FOURTH", [1, 2.0, -3, "FO", b"UR\x00TH\x00"]) obj.set_property("FIRST", -1) assert obj.get_property("FIRST") == [-1] obj.delete_property("THIRD") assert obj.properties == [ ["FIRST", -1], ["FOURTH", 1, 2.0, -3, b"FO", b"UR\x00TH\x00"], ["SECOND", 2.0], ["FIRST", 1], ] obj.properties = ( ("ONE", -1), ("TWO", -2.3e-4, "two"), ("Three", b"\xFF\xEE", 0), ) assert obj.properties == [ ["ONE", -1], ["TWO", -2.3e-4, b"two"], ["Three", b"\xFF\xEE", 0], ]
def segment_image(): curve = gdstk.Curve((1, 0)) curve.segment((0, 1)) curve.segment([0j, -1 + 0j]) curve.segment([(0, -1), (2, -1)], True) polygon = gdstk.Polygon(curve.points()) return gdstk.Cell("segment").add(polygon)
def convex_hull_image(): polygons = gdstk.text("F", 10, (0, 0)) f_cell = gdstk.Cell("F_CELL") f_cell.add(*polygons) array_ref = gdstk.Reference( f_cell, rotation=numpy.pi / 4, columns=3, rows=2, spacing=(8, 10) ) path = gdstk.FlexPath([(-5, 0), (0, -5), (5, 0)], 1, simple_path=True) main_cell = gdstk.Cell("MAIN") main_cell.add(array_ref, path) hull = main_cell.convex_hull() error = hull - numpy.array( [ [1.14904852, 27.66555281], [-12.81631041, 13.70019389], [-5.35355339, -0.35355339], [0.0, -5.70710678], [5.35355339, -0.35355339], [11.3137085, 13.96535893], [9.98788328, 17.94283457], [8.66205807, 20.15254326], ] ) assert numpy.abs(error).max() < 1e-8 polygon_hull = gdstk.Polygon(hull, datatype=1) main_cell.name = "convex_hull" return main_cell.add(polygon_hull)
def cubic_image(): curve = gdstk.Curve((0, 0), tolerance=1e-3) curve.cubic([(1, -2), (2, -2), (3, 0)]) curve.cubic([(2.7, 1), (1.8, 1), (1.5, 0), (1.3, -0.2), (0.3, -0.2), (0, 0)]) polygon = gdstk.Polygon(curve.points()) return gdstk.Cell("cubic").add(polygon)
def test_fillet(proof_cells): p1 = gdstk.Polygon([(0, 0), (1.2, 0), (1.2, 0.3), (1, 0.3), (1.5, 1), (0, 1.5)]) p2 = p1.copy().translate(2, 0) p1.fillet(0.3, tolerance=1e-3) p2.fillet([0.3, 0, 0.1, 0, 0.5, 10], tolerance=1e-3) assert_same_shape(proof_cells["Polygon.fillet"].polygons, [p1, p2], 2e-3)
def init_image(): curve = gdstk.Curve((3, 4), tolerance=1e-3) curve.segment((1, 1), True) curve.turn(1, -numpy.pi / 2) curve.segment((1, -1), True) polygon = gdstk.Polygon(curve.points()) return gdstk.Cell("init").add(polygon)
def poly_to_gds( poly: shpgm.Polygon, layer: int = 0 ) -> gdstk.Polygon : """ Create a gdstk polygon from a shapely Polygon Parameters ---------- poly : shapely polygon Polygon to be converted layer : int, optional GDS layer to put polygon on Returns ------- gds : gdstk polygon gds element that can be added to a gds cell """ gds_list = list( zip( *poly.exterior.xy ) ) for i in poly.interiors: p = gds_list[-1] gds_list.extend( list( zip( *i.xy ) ) ) gds_list.append( p ) gds = gdstk.Polygon( gds_list ) gds.layer = layer return( gds )
def main(filename, pixel_size, output): """Convert an image to a GDS file""" img = cv2.imread(filename, flags=cv2.IMREAD_GRAYSCALE) _, binaryImage = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY) binaryImage = cv2.flip( binaryImage, 0) # Flip image vertically since upper left corner is coordinate basis contours, hierarchy = cv2.findContours( binaryImage, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_TC89_KCOS) # Extract coordinates of contours hierarchy = np.squeeze(hierarchy) for i in range(len(contours)): contours[i] = np.squeeze(contours[i]).astype(float) * float( pixel_size) # Squeeze and correct dimensions lib = gdstk.Library() cell = gdstk.Cell("main") ld = {"layer": 0, "datatype": 1000} for i in np.where(hierarchy[:, 3] == -1)[0]: if hierarchy[i, 2] == -1 and len(contours[i]) > 2: cell.add(gdstk.Polygon(contours[i], **ld)) # Add a polygon without internals elif len(contours[i]) > 2 and hierarchy[i, 2] != -1: poly_p = gdstk.Polygon(contours[i], **ld) j = hierarchy[i, 2] while True: if len(contours[j]) > 2: poly_p = gdstk.boolean(poly_p, gdstk.Polygon(contours[j], **ld), "not", **ld) j = hierarchy[j, 0] if j == -1: break try: cell.add(*poly_p) except: cell.add(poly_p) lib.add(cell) lib.write_gds(output)
def interpolation_image(): points = [(4, 1), (4, 3), (0, 5), (-4, 3), (-4, -2), (0, -4)] curve = gdstk.Curve((0, 0)) curve.segment(points) control_poly_1 = gdstk.Polygon(curve.points(), datatype=1) curve = gdstk.Curve((0, 0), tolerance=1e-3) curve.interpolation(points, cycle=True) polygon_1 = gdstk.Polygon(curve.points()) half_pi = numpy.pi / 2 angles = [half_pi, None, None, None, -half_pi, -half_pi, None] curve = gdstk.Curve((4, -9)) curve.segment(points, relative=True) control_poly_2 = gdstk.Polygon(curve.points(), datatype=1) curve = gdstk.Curve((4, -9), tolerance=1e-3) curve.interpolation(points, angles, cycle=True, relative=True) polygon_2 = gdstk.Polygon(curve.points()) return gdstk.Cell("interpolation").add(polygon_1, control_poly_1, polygon_2, control_poly_2)
def test_area_size(): poly = gdstk.Polygon([(0, 0), (1, 0), 1j]) assert poly.layer == 0 assert poly.datatype == 0 assert poly.size == 3 assert poly.area() == 0.5 numpy.testing.assert_array_equal(poly.points, [[0, 0], [1, 0], [0, 1]]) poly = gdstk.Polygon([(0, 0), 1j, (1, 0)], 1, 2) assert poly.layer == 1 assert poly.datatype == 2 assert poly.size == 3 assert poly.area() == 0.5 numpy.testing.assert_array_equal(poly.points, [[0, 0], [0, 1], [1, 0]]) poly = gdstk.Polygon([(0, 0), (1, 0), 1 + 1j, 1j]) assert poly.size == 4 assert poly.area() == 1.0 numpy.testing.assert_array_equal(poly.points, [[0, 0], [1, 0], [1, 1], [0, 1]])
def test_copy(): points = [[-1, 0], [0, -2], [3, 0], [0, 4]] p1 = gdstk.Polygon(points, 5, 6) p2 = p1.copy() assert p1 is not p2 assert p1.layer == 5 assert p2.layer == 5 assert p1.datatype == 6 assert p2.datatype == 6 numpy.testing.assert_array_equal(p1.points, points) numpy.testing.assert_array_equal(p2.points, points)
def test_add_element(): p = gdstk.Polygon(((0, 0), (1, 0), (0, 1))) l = gdstk.Label("label", (0, 0)) c = gdstk.Cell("c_add_element") assert c.add(p) is c assert c.add(p, l) is c polygons = c.polygons assert len(polygons) == 2 assert polygons[0] is p assert polygons[1] is p assert len(c.labels) == 1 assert c.labels[0] is l
def parametric_image(): def top(u): x = 4 * u y = 1 - numpy.cos(4 * numpy.pi * u) return (x, y) curve = gdstk.Curve((-2, 0), tolerance=1e-3) curve.parametric(top) curve.parametric(lambda u: (4 - 2 * u**0.5) * numpy.exp(-1.5j * numpy.pi * u) - 4) polygon = gdstk.Polygon(curve.points()) return gdstk.Cell("parametric").add(polygon)
def bench_gdstk(output=None): p = gdstk.Polygon([(0, 0), (1, 0), (0, 1)]) fp = gdstk.FlexPath([(0, 0), (1, 0), (0.5, -0.5)], 0.1, ends="round") c1 = gdstk.Cell("REF") c1.add(p, fp) r = gdstk.Reference(c1, columns=3, rows=2, spacing=(2, 2), rotation=30 * numpy.pi / 180) c2 = gdstk.Cell("MAIN") c2.add(r) bb = c2.bounding_box() if output: c2.add(gdstk.rectangle(*bb, layer=1)) c2.write_svg(output, 100)
def test_properties(): for obj in [ gdstk.Polygon([-1 + 0j, -2j, 3 + 0j, 4j]), gdstk.FlexPath((0j, 1j), 0.1), gdstk.RobustPath(0j, 0.1), gdstk.Label("Label", 0j), gdstk.Reference("EMPTY"), ]: assert obj.get_property(12) is None assert obj.delete_property(12) is obj obj.set_property(13, "Property text") assert obj.get_property(12) is None assert obj.get_property(13) == "Property text" obj.delete_property(13) assert obj.get_property(13) is None obj.set_property(13, "Second text") obj.set_property(13, "Third text") assert obj.get_property(13) == "Third text"
def bench_gdstk(output=None): p = gdstk.Polygon([(0, 0), (1, 0), (0, 1)]) fp = gdstk.FlexPath([(-1, 0.5), (1, 0), (0.5, -0.5)], [0.1, 0.1], 0.3, ends="round") rp = gdstk.RobustPath((0, 0), [0.1, 0.1], 0.3).interpolation( [(2, 0.5), (2, 1), (-1, 4)] ) c1 = gdstk.Cell("REF") c1.add(p, fp, rp) r1 = gdstk.Reference( c1, columns=3, rows=2, spacing=(2, 2), rotation=30 * numpy.pi / 180 ) r2 = gdstk.Reference(c1, origin=(8, 0), columns=5, rows=4, spacing=(2, 2)) r3 = gdstk.Reference(c1, origin=(9, 1), columns=4, rows=3, spacing=(2, 2)) c2 = gdstk.Cell("MAIN") c2.add(r1, r2, r3) bb = c2.bounding_box() if output: c2.add(gdstk.rectangle(*bb, layer=1)) c2.write_svg(output, 100)
def convex_hull_image(): polygons = gdstk.text("F", 10, (0, 0)) f_cell = gdstk.Cell("F_CELL") f_cell.add(*polygons) array_ref = gdstk.Reference(f_cell, rotation=numpy.pi / 4, columns=3, rows=2, spacing=(8, 10)) hull = array_ref.convex_hull() error = hull - numpy.array([ [1.14904852, 27.66555281], [-12.81631041, 13.70019389], [-0.88388348, 1.76776695], [11.3137085, 13.96535893], [9.98788328, 17.94283457], [8.66205807, 20.15254326], ]) assert numpy.abs(error).max() < 1e-8 polygon_hull = gdstk.Polygon(hull, datatype=1) return gdstk.Cell("convex_hull").add(array_ref, polygon_hull)
def test_copy(): p = gdstk.Polygon(((0, 0), (1, 0), (0, 1))) lbl = gdstk.Label("label", (0, 0)) cref = gdstk.Cell("ref").add(gdstk.rectangle((-1, -1), (-2, -2))) ref = gdstk.Reference(cref) cell = gdstk.Cell("original") cell.add(p, lbl, ref) shallow_copy = cell.copy("copy_0", deep_copy=False) assert len(shallow_copy.polygons) == len(cell.polygons) assert p in shallow_copy.polygons assert len(shallow_copy.labels) == len(cell.labels) assert lbl in shallow_copy.labels assert len(shallow_copy.references) == len(cell.references) assert ref in shallow_copy.references deep_copy = cell.copy("copy_1") assert len(deep_copy.polygons) == len(cell.polygons) assert p not in deep_copy.polygons assert len(deep_copy.labels) == len(cell.labels) assert lbl not in deep_copy.labels assert len(deep_copy.references) == len(cell.references) assert ref not in deep_copy.references assert deep_copy.references[0].cell is ref.cell
def test_gds_properties(): for obj in [ gdstk.Polygon([-1 + 0j, -2j, 3 + 0j, 4j]), gdstk.FlexPath((0j, 1j), 0.1), gdstk.RobustPath(0j, 0.1), gdstk.Label("Label", 0j), gdstk.Reference("EMPTY"), ]: assert obj.get_gds_property(12) is None assert obj.delete_gds_property(12) is obj obj.set_gds_property(13, "Property text") assert obj.get_gds_property(12) is None assert obj.get_gds_property(13) == "Property text" obj.delete_gds_property(13) assert obj.get_gds_property(13) is None obj.set_gds_property(13, "Second text") obj.set_gds_property(13, "Third text") obj.set_gds_property(14, "Fourth text") assert obj.get_gds_property(13) == "Third text" assert obj.properties == [ ["S_GDS_PROPERTY", 14, b"Fourth text\x00"], ["S_GDS_PROPERTY", 13, b"Third text\x00"], ]
def render_text(text, size=None, position=(0, 0), font_prop=None, tolerance=0.1): precision = 0.1 * tolerance path = TextPath(position, text, size=size, prop=font_prop) polys = [] xmax = position[0] for points, code in path.iter_segments(): if code == path.MOVETO: c = gdstk.Curve(points, tolerance=tolerance) elif code == path.LINETO: c.segment(points.reshape(points.size // 2, 2)) elif code == path.CURVE3: c.quadratic(points.reshape(points.size // 2, 2)) elif code == path.CURVE4: c.cubic(points.reshape(points.size // 2, 2)) elif code == path.CLOSEPOLY: pts = c.points() if pts.size > 0: poly = gdstk.Polygon(pts) if pts[:, 0].min() < xmax: i = len(polys) - 1 while i >= 0: if polys[i].contain_any(*poly.points): p = polys.pop(i) poly = gdstk.boolean(p, poly, "xor", precision)[0] break elif poly.contain_any(*polys[i].points): p = polys.pop(i) poly = gdstk.boolean(p, poly, "xor", precision)[0] i -= 1 xmax = max(xmax, poly.points[:, 0].max()) polys.append(poly) return polys
def test_transform(): poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.transform() assert_close(poly.points, [[0, 0], [1, 0], [0, 1]]) poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.transform(2, True, numpy.pi / 2, -1j) assert_close(poly.points, [[0, -1], [0, 1], [2, -1]]) poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.transform(matrix=[[1, 2], [3, 4]]) assert_close(poly.points, [[0, 0], [1, 3], [2, 4]]) poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.transform(matrix=[[1, 2], [3, 4], [1, -0.5]]) assert_close(poly.points, [[0, 0], [0.5, 1.5], [4, 8]]) poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.transform(matrix=[[1, 2, 3], [4, 5, 6]]) assert_close(poly.points, [[3, 6], [4, 10], [5, 11]]) poly = gdstk.Polygon([0j, 1 + 0j, 1j]) poly.transform(matrix=[[1, 2, 3], [4, 5, 6], [3, 2, -1]]) assert_close(poly.points, [[-3, -6], [2, 5], [5, 11]])
def cubic_smooth_image(): curve = gdstk.Curve((0, 0), tolerance=1e-3) curve.cubic([1 + 0j, 1.5 + 0.5j, 1 + 1j]) curve.cubic_smooth([1j, 0j]) polygon = gdstk.Polygon(curve.points()) return gdstk.Cell("cubic_smooth").add(polygon)