Skip to content

Commit

Permalink
[geom,vis] Add Geometry.corners property
Browse files Browse the repository at this point in the history
Now uses dual dimensions to list corners
Add unit test for Sphere
  • Loading branch information
holl- committed May 17, 2024
1 parent b081b21 commit aec269f
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 4 deletions.
3 changes: 2 additions & 1 deletion phi/geom/_box.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,10 @@ def face_areas(self) -> Tensor:
def face_shape(self) -> Shape:
return self.shape.without('vector') & dual(side='lower,upper') & dual(**self.shape['vector'].untyped_dict)

@property
def corners(self):
to_face = self.face_normals[{'~side': 'upper'}] * math.rename_dims(self.half_size, 'vector', dual)
lower_upper = math.meshgrid(math.instance, **{dim: [-1, 1] for dim in self.vector.item_names}, stack_dim=dual('vector')) # (x=2, y=2, ... vector=x,y,...)
lower_upper = math.meshgrid(math.dual, **{dim: [-1, 1] for dim in self.vector.item_names}, stack_dim=dual('vector')) # (x=2, y=2, ... vector=x,y,...)
to_corner = math.sum(lower_upper * to_face, '~vector')
return self.center + to_corner

Expand Down
14 changes: 14 additions & 0 deletions phi/geom/_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ def face_shape(self) -> Shape:
"""
raise NotImplementedError(self.__class__)

@property
def corners(self) -> Tensor:
"""
Returns:
Corner locations as `phiml.math.Tensor`.
Corners belonging to one object or cell are listed along dual dimensions.
If the object has no corners, a size-0 tensor with the correct vector and instance dims is returned.
"""
raise NotImplementedError(self.__class__)

def integrate_surface(self, face_values: Tensor, divide_volume=False) -> Tensor:
"""
Multiplies `values´ by the corresponding face area, computes the sum over all faces and divides by the cell volume.
Expand Down Expand Up @@ -716,6 +726,10 @@ def boundary_faces(self) -> Dict[str, Tuple[Dict[str, slice], Dict[str, slice]]]
def face_shape(self) -> Shape:
return self.shape

@property
def corners(self):
return self._location

def __getitem__(self, item):
return Point(self._location[_keep_vector(slicing_dict(self, item))])

Expand Down
4 changes: 4 additions & 0 deletions phi/geom/_sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,7 @@ def boundary_faces(self) -> Dict[str, Tuple[Dict[str, slice], Dict[str, slice]]]
@property
def face_shape(self) -> Shape:
return self.shape.without('vector') & dual(shell=0)

@property
def corners(self) -> Tensor:
return math.zeros(self.shape & dual(corners=0))
4 changes: 2 additions & 2 deletions phi/vis/_dash/_plotly_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ def plot(self, data: Field, figure, subplot, space: Box, min_val: float, max_val
for lxi, lyi, uxi, uyi, ci, a in zip(lower_x, lower_y, upper_x, upper_y, hex_color, alphas):
figure.add_shape(type="rect", xref="x", yref="y", x0=lxi, y0=lyi, x1=uxi, y1=uyi, fillcolor=ci, line_width=.5, line_color='#FFFFFF')
else:
corners = data.geometry.corners()
c4, c1, c3, c2 = reshaped_numpy(corners, [corners.shape.only(dims, reorder=True), non_channel(data), 'vector'])
corners = data.geometry.corners
c4, c1, c3, c2 = reshaped_numpy(corners, [corners.shape.only(['~'+d for d in dims], reorder=True), non_channel(data), 'vector'])
for c1i, c2i, c3i, c4i, ci, a in zip(c1, c2, c3, c4, hex_color, alphas):
path = f"M{c1i[0]},{c1i[1]} L{c2i[0]},{c2i[1]} L{c3i[0]},{c3i[1]} L{c4i[0]},{c4i[1]} Z"
figure.add_shape(type="path", xref="x", yref="y", path=path, fillcolor=ci, line_width=.5, line_color='#FFFFFF')
Expand Down
2 changes: 1 addition & 1 deletion phi/vis/_matplotlib/_matplotlib_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ def plot(self, data: Field, figure, subplot, space: Box, min_val: float, max_val
elif isinstance(data.geometry, BaseBox):
a = alphas[0]
c = mpl_colors[0]
cx, cy, cz = math.reshaped_numpy(data.geometry.corners(), ['vector', *dims])
cx, cy, cz = math.reshaped_numpy(data.geometry.corners, ['vector', *['~'+d for d in dims]])
plot_surface(subplot, cx[:, :, 1], cy[:, :, 1], cz[:, :, 1], alpha=a, color=c)
plot_surface(subplot, cx[:, :, 0], cy[:, :, 0], cz[:, :, 0], alpha=a, color=c)
plot_surface(subplot, cx[:, 1, :], cy[:, 1, :], cz[:, 1, :], alpha=a, color=c)
Expand Down
6 changes: 6 additions & 0 deletions tests/commit/geom/test__sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,9 @@ def test_reshaping_const_radius(self):
assert batch(bat=100) & instance(particles=50) & channel(vector='x,y') == s.shape
s = flatten(s)
assert batch(bat=100) & instance(flat=50) & channel(vector='x,y') == s.shape

def test_sphere_no_corners(self):
s = Sphere(x=0, y=0, radius=1)
corners = s.corners
self.assertIn('vector', corners.shape)
self.assertEqual(0, corners.shape.volume)

0 comments on commit aec269f

Please sign in to comment.