Skip to content

Commit

Permalink
Treating one edge case of intersect_side in PolySlab
Browse files Browse the repository at this point in the history
  • Loading branch information
weiliangjin2021 committed Apr 20, 2022
1 parent 8ee3f25 commit abd1efa
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 16 deletions.
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

0 comments on commit abd1efa

Please sign in to comment.