Skip to content

Commit 45c73ec

Browse files
committed
It's finally possible to plot PolySlab objects when transpose=True, finally. I tested the plot capability with the slice plane aligned with the polyslab plane, and perpendicular to it (which invokes and , respectively).
1 parent f51659c commit 45c73ec

File tree

4 files changed

+46
-20
lines changed

4 files changed

+46
-20
lines changed

tidy3d/components/geometry/base.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ def intersections_plane(
267267
if axis != 2:
268268
last, indices = self.pop_axis((0, 1, 2), axis, transpose=transpose)
269269
to_2D = to_2D[[*list(indices), last, 3]]
270+
print(f"Geometry.intersections_plane({transpose=}), {to_2D=}") # DEBUG
270271
return self.intersections_tilted_plane(normal, origin, to_2D)
271272

272273
def intersections_2dbox(self, plane: Box, transpose: bool = False) -> list[Shapely]:
@@ -533,10 +534,10 @@ def plot(
533534
matplotlib.axes._subplots.Axes
534535
The supplied or created matplotlib axes.
535536
"""
536-
537537
# find shapes that intersect self at plane
538538
axis, position = self.parse_xyz_kwargs(x=x, y=y, z=z)
539539
shapes_intersect = self.intersections_plane(x=x, y=y, z=z, transpose=transpose)
540+
print(f"Geometry.plot({transpose=}), {shapes_intersect=}") # DEBUG
540541

541542
plot_params = self.plot_params
542543
if viz_spec is not None:
@@ -1720,11 +1721,14 @@ def intersections_plane(
17201721
For more details refer to
17211722
`Shapely's Documentation <https://shapely.readthedocs.io/en/stable/project.html>`_.
17221723
"""
1724+
print(f"Planar.intersections_plane({transpose=})") # DEBUG
17231725
axis, position = self.parse_xyz_kwargs(x=x, y=y, z=z)
17241726
if not self.intersects_axis_position(axis, position):
17251727
return []
17261728
if axis == self.axis:
1727-
return self._intersections_normal(position)
1729+
# print(f"{self._intersections_normal=}") # DEBUG
1730+
return self._intersections_normal(position, transpose=transpose)
1731+
# print(f"{self._intersections_side=}") # DEBUG
17281732
return self._intersections_side(position, axis, transpose=transpose)
17291733

17301734
@abstractmethod
@@ -2105,6 +2109,7 @@ def intersections_plane(
21052109
For more details refer to
21062110
`Shapely's Documentation <https://shapely.readthedocs.io/en/stable/project.html>`_.
21072111
"""
2112+
print(f"Box.intersections_plane({transpose=})") # DEBUG
21082113
axis, position = self.parse_xyz_kwargs(x=x, y=y, z=z)
21092114
if not self.intersects_axis_position(axis, position):
21102115
return []
@@ -2181,6 +2186,7 @@ def intersections_with(self, other, transpose: bool = False):
21812186
dim = "xyz"[normal_ind]
21822187
pos = self.center[normal_ind]
21832188
xyz_kwargs = {dim: pos}
2189+
print(f"Box.intersects_with({transpose=}), {xyz_kwargs=}") # DEBUG
21842190
shapes_plane = other.intersections_plane(**xyz_kwargs, transpose=transpose)
21852191

21862192
# intersect all shapes with the input self
@@ -3009,6 +3015,7 @@ def intersections_plane(
30093015
For more details refer to
30103016
`Shapely's Documentaton <https://shapely.readthedocs.io/en/stable/project.html>`_.
30113017
"""
3018+
print(f"ClipOperation.intersections_plane({transpose=})") # DEBUG
30123019
a = self.geometry_a.intersections_plane(x, y, z, transpose=transpose)
30133020
b = self.geometry_b.intersections_plane(x, y, z, transpose=transpose)
30143021
geom_a = shapely.unary_union([Geometry.evaluate_inf_shape(g) for g in a])
@@ -3221,6 +3228,7 @@ def intersections_plane(
32213228
For more details refer to
32223229
`Shapely's Documentation <https://shapely.readthedocs.io/en/stable/project.html>`_.
32233230
"""
3231+
print(f"GeometryGroup.intersections_plane({transpose=})") # DEBUG
32243232
if not self.intersects_plane(x, y, z):
32253233
return []
32263234
return [

tidy3d/components/geometry/polyslab.py

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,8 @@ class PolySlab(base.Planar):
8787
)
8888

8989
@staticmethod
90-
def make_shapely_polygon(vertices: ArrayLike) -> shapely.Polygon:
90+
def make_shapely_polygon(vertices: ArrayLike, transpose: bool = False) -> shapely.Polygon:
9191
"""Make a shapely polygon from some vertices, first ensures they are untraced."""
92-
vertices = get_static(vertices)
9392
return shapely.Polygon(vertices)
9493

9594
@pydantic.validator("slab_bounds", always=True)
@@ -629,13 +628,15 @@ def _do_intersections_tilted_plane(
629628
path, _ = section.to_planar(to_2D=to_2D)
630629
return path.polygons_full
631630

632-
def _intersections_normal(self, z: float):
631+
def _intersections_normal(self, z: float, transpose: bool = False):
633632
"""Find shapely geometries intersecting planar geometry with axis normal to slab.
634633
635634
Parameters
636635
----------
637636
z : float
638637
Position along the axis normal to slab.
638+
transpose : bool = False
639+
Optional: Swap the planar (XY) coordinates?
639640
640641
Returns
641642
-------
@@ -644,16 +645,22 @@ def _intersections_normal(self, z: float):
644645
For more details refer to
645646
`Shapely's Documentation <https://shapely.readthedocs.io/en/stable/project.html>`_.
646647
"""
648+
print(f"PolySlab._intersections_normal({transpose=})") # DEBUG
647649
if math.isclose(self.sidewall_angle, 0):
648-
return [self.make_shapely_polygon(self.reference_polygon)]
649-
650+
vertices = self.reference_polygon
651+
if transpose:
652+
vertices = vertices[:, (1, 0)] # swap column 0 (x coords) with column 1 (y coords)
653+
return [self.make_shapely_polygon(vertices, transpose=transpose)]
650654
z0 = self.center_axis
651655
z_local = z - z0 # distance to the middle
652656
dist = -z_local * self._tanq
653657
vertices_z = self._shift_vertices(self.middle_polygon, dist)[0]
654-
return [self.make_shapely_polygon(vertices_z)]
658+
vertices = vertices_z
659+
if transpose:
660+
vertices = vertices[:, (1, 0)] # swap column 0 (x coords) with column 1 (y coords)
661+
return [self.make_shapely_polygon(vertices, transpose=transpose)]
655662

656-
def _intersections_side(self, position, axis) -> list:
663+
def _intersections_side(self, position, axis, transpose: bool = False) -> list:
657664
"""Find shapely geometries intersecting planar geometry with axis orthogonal to slab.
658665
659666
For slanted polyslab, the procedure is as follows,
@@ -678,6 +685,8 @@ def _intersections_side(self, position, axis) -> list:
678685
Position along ``axis``.
679686
axis : int
680687
Integer index into 'xyz' (0,1,2).
688+
transpose : bool = False
689+
Optional: Swap the coordinates in the plane orthogonal to the axis?
681690
682691
Returns
683692
-------
@@ -686,12 +695,14 @@ def _intersections_side(self, position, axis) -> list:
686695
For more details refer to
687696
`Shapely's Documentation <https://shapely.readthedocs.io/en/stable/project.html>`_.
688697
"""
698+
print(f"PolySlab._intersections_side({transpose=})") # DEBUG
689699

690700
# find out all z_i where the plane will intersect the vertex
691701
z0 = self.center_axis
692702
z_base = z0 - self.finite_length_axis / 2
693703

694704
axis_ordered = self._order_axis(axis)
705+
695706
height_list = self._find_intersecting_height(position, axis_ordered)
696707
polys = []
697708

@@ -723,8 +734,8 @@ def _intersections_side(self, position, axis) -> list:
723734
for y_index in range(len(ints_y) // 2):
724735
y_min = ints_y[2 * y_index]
725736
y_max = ints_y[2 * y_index + 1]
726-
minx, miny = self._order_by_axis(plane_val=y_min, axis_val=z_min, axis=axis)
727-
maxx, maxy = self._order_by_axis(plane_val=y_max, axis_val=z_max, axis=axis)
737+
minx, miny = self._order_by_axis(plane_val=y_min, axis_val=z_min, axis=axis, transpose=transpose)
738+
maxx, maxy = self._order_by_axis(plane_val=y_max, axis_val=z_max, axis=axis, transpose=transpose)
728739

729740
if math.isclose(self.sidewall_angle, 0):
730741
polys.append(self.make_shapely_box(minx, miny, maxx, maxy))
@@ -738,13 +749,13 @@ def _intersections_side(self, position, axis) -> list:
738749
dy_min = h_length * np.tan(angle_min)
739750
dy_max = h_length * np.tan(angle_max)
740751

741-
x1, y1 = self._order_by_axis(plane_val=y_min, axis_val=z_min, axis=axis)
742-
x2, y2 = self._order_by_axis(plane_val=y_max, axis_val=z_min, axis=axis)
752+
x1, y1 = self._order_by_axis(plane_val=y_min, axis_val=z_min, axis=axis, transpose=transpose)
753+
x2, y2 = self._order_by_axis(plane_val=y_max, axis_val=z_min, axis=axis, transpose=transpose)
743754
x3, y3 = self._order_by_axis(
744-
plane_val=y_max - dy_max, axis_val=z_max, axis=axis
755+
plane_val=y_max - dy_max, axis_val=z_max, axis=axis, transpose=transpose
745756
)
746757
x4, y4 = self._order_by_axis(
747-
plane_val=y_min + dy_min, axis_val=z_max, axis=axis
758+
plane_val=y_min + dy_min, axis_val=z_max, axis=axis, transpose=transpose
748759
)
749760
vertices = ((x1, y1), (x2, y2), (x3, y3), (x4, y4))
750761
polys.append(self.make_shapely_polygon(vertices).buffer(0))
@@ -984,11 +995,16 @@ def _find_intersecting_ys_angle_slant(
984995
return ints_y_sort, ints_angle_sort
985996

986997
@cached_property
987-
def bounds(self) -> Bound:
998+
def bounds(self, transpose: bool = False) -> Bound:
988999
"""Returns bounding box min and max coordinates. The dilation and slant angle are not
9891000
taken into account exactly for speed. Instead, the polygon may be slightly smaller than
9901001
the returned bounds, but it should always be fully contained.
9911002
1003+
Parameters
1004+
-------
1005+
transpose : bool = False
1006+
Optional: Swap the planar axes? (the axes perpendicular to self.axis)
1007+
9921008
Returns
9931009
-------
9941010
Tuple[float, float, float], Tuple[float, float float]
@@ -1021,8 +1037,8 @@ def bounds(self) -> Bound:
10211037
zmin, zmax = self.slab_bounds
10221038

10231039
# rearrange axes
1024-
coords_min = self.unpop_axis(zmin, (xmin, ymin), axis=self.axis)
1025-
coords_max = self.unpop_axis(zmax, (xmax, ymax), axis=self.axis)
1040+
coords_min = self.unpop_axis(zmin, (xmin, ymin), axis=self.axis, transpose=transpose)
1041+
coords_max = self.unpop_axis(zmax, (xmax, ymax), axis=self.axis, transpose=transpose)
10261042
return (tuple(coords_min), tuple(coords_max))
10271043

10281044
def _extrusion_length_to_offset_distance(self, extrusion: float) -> float:

tidy3d/components/scene.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ def plot_structures(
470470
matplotlib.axes._subplots.Axes
471471
The supplied or created matplotlib axes.
472472
"""
473-
473+
print(f"Scene.plot_structures({transpose=})") # DEBUG
474474
medium_shapes = self._get_structures_2dbox(
475475
structures=self.to_static().sorted_structures, x=x, y=y, z=z, hlim=hlim, vlim=vlim, transpose=transpose
476476
)

tidy3d/components/structure.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ def plot(
149149
y: Optional[float] = None,
150150
z: Optional[float] = None,
151151
ax: Ax = None,
152+
transpose: bool = False,
152153
**patch_kwargs,
153154
) -> Ax:
154155
"""Plot structure's geometric cross section at single (x,y,z) coordinate.
@@ -173,7 +174,8 @@ def plot(
173174
matplotlib.axes._subplots.Axes
174175
The supplied or created matplotlib axes.
175176
"""
176-
return self.geometry.plot(x=x, y=y, z=z, ax=ax, viz_spec=self.viz_spec, **patch_kwargs)
177+
print(f"AbstractStructure.plot({transpose=})") # DEBUG
178+
return self.geometry.plot(x=x, y=y, z=z, ax=ax, viz_spec=self.viz_spec, transpose=transpose, **patch_kwargs)
177179

178180

179181
class Structure(AbstractStructure):

0 commit comments

Comments
 (0)