Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Treating one edge case of intersect_side in PolySlab #323

Merged
merged 1 commit into from
Apr 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/test_sidewall.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down
52 changes: 37 additions & 15 deletions tidy3d/components/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -1562,18 +1569,18 @@ 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)

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))
Expand All @@ -1588,7 +1595,8 @@ 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

Expand Down Expand Up @@ -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
Expand All @@ -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
-------
Expand All @@ -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]
Expand Down Expand Up @@ -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()

Expand Down