From 99ea9c1c31b5aa458438ef21518dd2c531b3e2f3 Mon Sep 17 00:00:00 2001 From: Weiliang Jin Date: Tue, 19 Apr 2022 10:10:43 -0700 Subject: [PATCH] Treating one edge case of intersect_side in PolySlab --- tests/test_sidewall.py | 2 +- tidy3d/components/geometry.py | 54 ++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/tests/test_sidewall.py b/tests/test_sidewall.py index 58712d066f..6826635a5b 100644 --- a/tests/test_sidewall.py +++ b/tests/test_sidewall.py @@ -31,7 +31,7 @@ def convert_valid_polygon(vertices): """Given vertices that might have intersecting eduges, generate vertices of a valid polygon """ - poly = Polygon(vertices).buffer(1e-3) # make sure no intersecting edges + poly = Polygon(vertices).buffer(0) # make sure no intersecting edges if type(poly) is not Polygon: poly = poly[0] diff --git a/tidy3d/components/geometry.py b/tidy3d/components/geometry.py index 338d93faa0..4d0d103a79 100644 --- a/tidy3d/components/geometry.py +++ b/tidy3d/components/geometry.py @@ -1530,12 +1530,19 @@ def _intersections_side(self, position, axis) -> list: # pylint:disable=too-man polys = [] # looping through z_i to assemble the polygons - height = 0.0 height_list = np.append(height_list, self.length) - for h_local in height_list: - dist = -height * self._tanq + h_base = 0.0 + for h_top in height_list: + # length within between top and bottom + h_length = h_top - h_base + + # coordinate of each subsection + z_min, z_max = z_base + h_base, z_base + h_top + + # vertices for the base of each subsection + dist = -h_base * self._tanq vertices = self._shift_vertices(self.base_polygon, dist)[0] - z_min, z_max = z_base + height, z_base + height + h_local + # for vertical sidewall, no need for complications if np.isclose(self.sidewall_angle, 0): ints_y, ints_angle = self._find_intersecting_ys_angle_vertical( @@ -1562,8 +1569,8 @@ def _intersections_side(self, position, axis) -> list: # pylint:disable=too-man angle_min = np.arctan(np.tan(self.sidewall_angle) / np.sin(angle_min)) angle_max = np.arctan(np.tan(self.sidewall_angle) / np.sin(angle_max)) - dy_min = h_local * np.tan(angle_min) - dy_max = h_local * np.tan(angle_max) + dy_min = h_length * np.tan(angle_min) + dy_max = h_length * np.tan(angle_max) x1, y1 = self._order_by_axis(plane_val=y_min, axis_val=z_min, axis=axis) x2, y2 = self._order_by_axis(plane_val=y_max, axis_val=z_min, axis=axis) @@ -1571,9 +1578,9 @@ def _intersections_side(self, position, axis) -> list: # pylint:disable=too-man if y_max - y_min <= dy_min + dy_max: # intersect before reaching top of polygon # make triangle - h_mid = (y_max - y_min) / (dy_min + dy_max) * h_local + h_mid = (y_max - y_min) / (dy_min + dy_max) * h_length z_mid = z_min + h_mid - y_mid = y_min + dy_min / h_local * h_mid + y_mid = y_min + dy_min / h_length * h_mid x3, y3 = self._order_by_axis(plane_val=y_mid, axis_val=z_mid, axis=axis) vertices = ((x1, y1), (x2, y2), (x3, y3)) polys.append(Polygon(vertices)) @@ -1587,8 +1594,9 @@ def _intersections_side(self, position, axis) -> list: # pylint:disable=too-man vertices = ((x1, y1), (x2, y2), (x3, y3), (x4, y4)) polys.append(Polygon(vertices)) - - height += h_local + + # update the base coordinate for the next subsection + h_base = h_top return polys @@ -1631,7 +1639,7 @@ def _find_intersecting_height(self, position: float, axis: int) -> np.ndarray: return height def _find_intersecting_ys_angle_vertical( # pylint:disable=too-many-locals - self, vertices: np.ndarray, position: float, axis: int + self, vertices: np.ndarray, position: float, axis: int, exclude_on_vertices: bool = False ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: """Finds pairs of forward and backwards vertices where polygon intersects position at axis, Find intersection point (in y) assuming straight line,and intersecting angle between plane @@ -1646,6 +1654,8 @@ def _find_intersecting_ys_angle_vertical( # pylint:disable=too-many-locals position along axis. axis : int Integer index into 'xyz' (0,1,2). + exclude_on_vertices : bool = False + Whehter to exclude those intersecting directly with the vertices. Returns ------- @@ -1662,13 +1672,23 @@ def _find_intersecting_ys_angle_vertical( # pylint:disable=too-many-locals # get the forward vertices vertices_f = np.roll(vertices_axis, shift=-1, axis=0) + # x coordinate of the two sets of vertices + x_vertices_f = vertices_f[:, 0] + x_vertices_axis = vertices_axis[:, 0] + # find which segments intersect - intersects_b = np.logical_and( - (vertices_f[:, 0] <= position), (vertices_axis[:, 0] > position) + f_left_to_intersect = ( + x_vertices_f < position if exclude_on_vertices else x_vertices_f <= position ) - intersects_f = np.logical_and( - (vertices_axis[:, 0] <= position), (vertices_f[:, 0] > position) + orig_right_to_intersect = x_vertices_axis > position + intersects_b = np.logical_and(f_left_to_intersect, orig_right_to_intersect) + + f_right_to_intersect = x_vertices_f > position + orig_left_to_intersect = ( + x_vertices_axis < position if exclude_on_vertices else x_vertices_axis <= position ) + intersects_f = np.logical_and(f_right_to_intersect, orig_left_to_intersect) + intersects_segment = np.logical_or(intersects_b, intersects_f) iverts_b = vertices_axis[intersects_segment] iverts_f = vertices_f[intersects_segment] @@ -1728,7 +1748,9 @@ def _find_intersecting_ys_angle_slant( # pylint:disable=too-many-locals, too-ma vertices_b = np.roll(vertices_axis, shift=1, axis=0) ## First part, plane intersects with edges, same as vertical - ints_y, ints_angle = self._find_intersecting_ys_angle_vertical(vertices, position, axis) + ints_y, ints_angle = self._find_intersecting_ys_angle_vertical( + vertices, position, axis, exclude_on_vertices=True + ) ints_y = ints_y.tolist() ints_angle = ints_angle.tolist()