Coverage for klayout_pex/klayout/shapes_pb2_converter.py: 81%
67 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-31 20:14 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-31 20:14 +0000
1#
2# --------------------------------------------------------------------------------
3# SPDX-FileCopyrightText: 2024-2025 Martin Jan Köhler and Harald Pretl
4# Johannes Kepler University, Institute for Integrated Circuits.
5#
6# This file is part of KPEX
7# (see https://github.com/iic-jku/klayout-pex).
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
21# SPDX-License-Identifier: GPL-3.0-or-later
22# --------------------------------------------------------------------------------
23#
25import klayout.db as kdb
26import klayout_pex_protobuf.kpex.geometry.shapes_pb2 as shapes_pb2
29class ShapesConverter:
30 def __init__(self, dbu: float):
31 self.dbu = dbu
33 def klayout_point(self, point: shapes_pb2.Point) -> kdb.Point:
34 # FIXME: there is no PointWithProperties yet
35 return kdb.Point(point.x, point.y)
37 def klayout_point_to_pb(self,
38 point_kly: kdb.Point,
39 point_pb: shapes_pb2.Point):
40 point_pb.x = point_kly.x
41 point_pb.y = point_kly.y
43 def klayout_box(self, box: shapes_pb2.Box) -> kdb.Box:
44 box_kly = kdb.Box(box.lower_left.x,
45 box.lower_left.y,
46 box.upper_right.x,
47 box.upper_right.y)
48 if box.net:
49 box_kly = kdb.BoxWithProperties(box_kly, {'net': box.net})
50 return box_kly
52 def klayout_box_to_pb(self,
53 box_kly: kdb.Box,
54 shape_pb: shapes_pb2.Shape):
55 shape_pb.kind = shapes_pb2.Shape.Kind.SHAPE_KIND_BOX
56 box_pb = shape_pb.box
57 if isinstance(box_kly, kdb.BoxWithProperties):
58 net_name = box_kly.property('net')
59 if net_name:
60 box_pb.net = net_name
61 box_pb.lower_left.x = box_kly.left
62 box_pb.lower_left.y = box_kly.bottom
63 box_pb.upper_right.x = box_kly.right
64 box_pb.upper_right.y = box_kly.top
66 def klayout_polygon(self, polygon: shapes_pb2.Polygon) -> kdb.Polygon:
67 points_kly = [self.klayout_point(pt) for pt in polygon.hull_points]
68 polygon_kly = kdb.Polygon(points_kly)
69 if len(polygon.net) >= 1:
70 polygon_kly = kdb.PolygonWithProperties(polygon_kly, {'net': polygon.net})
71 return polygon_kly
73 def klayout_polygon_to_pb(self,
74 polygon_kly: kdb.Polygon,
75 shape_pb: shapes_pb2.Shape):
76 shape_pb.kind = shapes_pb2.Shape.Kind.SHAPE_KIND_POLYGON
77 net_name = polygon_kly.property('net')
78 if net_name:
79 shape_pb.polygon.net = net_name
80 for p_kly in polygon_kly.each_point_hull():
81 self.klayout_point_to_pb(p_kly, shape_pb.polygon.hull_points.add())
83 def klayout_shape(self, shape: shapes_pb2.Shape) -> kdb.Shape:
84 match shape.kind:
85 case shapes_pb2.Shape.Kind.SHAPE_KIND_BOX:
86 return self.klayout_box(shape.box)
87 case shapes_pb2.Shape.Kind.SHAPE_KIND_POLYGON:
88 return self.klayout_polygon(shape.polygon)
89 case _:
90 raise NotImplementedError()
92 def klayout_shape_to_pb(self,
93 shape_kly: kdb.Shape,
94 shape_pb: shapes_pb2.Shape):
95 if shape_kly.is_box():
96 self.klayout_box_to_pb(shape_kly.bbox(), shape_pb)
97 elif shape_kly.is_polygon():
98 self.klayout_polygon_to_pb(shape_kly.polygon(), shape_pb)
99 else:
100 raise NotImplementedError()
102 def klayout_region(self, region: shapes_pb2.Region) -> kdb.Region:
103 region_kly = kdb.Region()
104 for shape in region.shapes:
105 match shape.kind:
106 case shapes_pb2.Shape.Kind.SHAPE_KIND_POLYGON:
107 region_kly.insert(self.klayout_polygon(shape.polygon))
108 case shapes_pb2.Shape.Kind.SHAPE_KIND_BOX:
109 region_kly.insert(self.klayout_box(shape.box))
110 case _:
111 raise NotImplementedError()
112 return region_kly
114 def klayout_region_to_pb(self,
115 region_kly: kdb.Region,
116 region_pb: shapes_pb2.Region):
117 for sh_kly in region_kly:
118 self.klayout_polygon_to_pb(sh_kly, region_pb.shapes.add())