

from __future__ import annotations

from math import pi, pow







def _a					(			SCREAMING_SNAKE_CASE						:     int | float						)       ->       float:

 """simple docstring"""






 if side_length < 0:
  raise ValueError('vol_cube() only accepts non-negative values'						)
 return pow(SCREAMING_SNAKE_CASE       ,   3						)







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if height < 0 or radius < 0:
  raise ValueError('vol_spherical_cap() only accepts non-negative values'						)
 # Volume is 1/3 pi * height squared * (3 * radius - height)
 return 1 / 3 * pi * pow(SCREAMING_SNAKE_CASE       ,   2						) * (3 * radius - height)







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if radius_a < 0 or radius_a < 0 or centers_distance < 0:
  raise ValueError('vol_spheres_intersect() only accepts non-negative values'						)
 if centers_distance == 0:
  return vol_sphere(min(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)						)

 __lowerCAmelCase:  int        = (
     (radius_a - radius_a + centers_distance)
     * (radius_a + radius_a - centers_distance)
     / (2 * centers_distance)
 )
 __lowerCAmelCase:  List[str]        = (
     (radius_a - radius_a + centers_distance)
     * (radius_a + radius_a - centers_distance)
     / (2 * centers_distance)
 )

 return vol_spherical_cap(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						) + vol_spherical_cap(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if radius_a <= 0 or radius_a <= 0 or centers_distance < 0:
  raise ValueError(
      'vol_spheres_union() only accepts non-negative values, non-zero radius'						)

 if centers_distance == 0:
  return vol_sphere(max(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)						)

 return (
     vol_sphere(SCREAMING_SNAKE_CASE						)
     + vol_sphere(SCREAMING_SNAKE_CASE						)
     - vol_spheres_intersect(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)
 )







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if width < 0 or height < 0 or length < 0:
  raise ValueError('vol_cuboid() only accepts non-negative values'						)
 return float(width * height * length						)







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if height < 0 or area_of_base < 0:
  raise ValueError('vol_cone() only accepts non-negative values'						)
 return area_of_base * height / 3.0







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if height < 0 or radius < 0:
  raise ValueError('vol_right_circ_cone() only accepts non-negative values'						)
 return pi * pow(SCREAMING_SNAKE_CASE       ,   2						) * height / 3.0







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if height < 0 or area_of_base < 0:
  raise ValueError('vol_prism() only accepts non-negative values'						)
 return float(area_of_base * height						)







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if height < 0 or area_of_base < 0:
  raise ValueError('vol_pyramid() only accepts non-negative values'						)
 return area_of_base * height / 3.0







def _a					(			SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if radius < 0:
  raise ValueError('vol_sphere() only accepts non-negative values'						)
 # Volume is 4/3 * pi * radius cubed
 return 4 / 3 * pi * pow(SCREAMING_SNAKE_CASE       ,   3						)







def _a					(			SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if radius < 0:
  raise ValueError('vol_hemisphere() only accepts non-negative values'						)
 # Volume is radius cubed * pi * 2/3
 return pow(SCREAMING_SNAKE_CASE       ,   3						) * pi * 2 / 3







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if height < 0 or radius < 0:
  raise ValueError('vol_circular_cylinder() only accepts non-negative values'						)
 # Volume is radius squared * height * pi
 return pow(SCREAMING_SNAKE_CASE       ,   2						) * height * pi







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if inner_radius < 0 or outer_radius < 0 or height < 0:
  raise ValueError(
      'vol_hollow_circular_cylinder() only accepts non-negative values'						)
 if outer_radius <= inner_radius:
  raise ValueError('outer_radius must be greater than inner_radius'						)
 return pi * (pow(SCREAMING_SNAKE_CASE       ,   2						) - pow(SCREAMING_SNAKE_CASE       ,   2						)) * height







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if radius_a < 0 or radius_a < 0 or height < 0:
  raise ValueError('vol_conical_frustum() only accepts non-negative values'						)
 return (
     1
     / 3
     * pi
     * height
     * (pow(SCREAMING_SNAKE_CASE       ,   2						) + pow(SCREAMING_SNAKE_CASE       ,   2						) + radius_a * radius_a)
 )







def _a					(			SCREAMING_SNAKE_CASE						:     float       ,   SCREAMING_SNAKE_CASE						:     float						)       ->       float:

 """simple docstring"""






 if torus_radius < 0 or tube_radius < 0:
  raise ValueError('vol_torus() only accepts non-negative values'						)
 return 2 * pow(SCREAMING_SNAKE_CASE       ,   2						) * torus_radius * pow(SCREAMING_SNAKE_CASE       ,   2						)







def _a					(			)       ->       Any:

 """simple docstring"""






 print('Volumes:'						)
 print(f'''Cube: {vol_cube(2						) = }'''						)  # = 8
 print(f'''Cuboid: {vol_cuboid(2       ,   2       ,   2						) = }'''						)  # = 8
 print(f'''Cone: {vol_cone(2       ,   2						) = }'''						)  # ~= 1.33
 print(f'''Right Circular Cone: {vol_right_circ_cone(2       ,   2						) = }'''						)  # ~= 8.38
 print(f'''Prism: {vol_prism(2       ,   2						) = }'''						)  # = 4
 print(f'''Pyramid: {vol_pyramid(2       ,   2						) = }'''						)  # ~= 1.33
 print(f'''Sphere: {vol_sphere(2						) = }'''						)  # ~= 33.5
 print(f'''Hemisphere: {vol_hemisphere(2						) = }'''						)  # ~= 16.75
 print(f'''Circular Cylinder: {vol_circular_cylinder(2       ,   2						) = }'''						)  # ~= 25.1
 print(f'''Torus: {vol_torus(2       ,   2						) = }'''						)  # ~= 157.9
 print(f'''Conical Frustum: {vol_conical_frustum(2       ,   2       ,   4						) = }'''						)  # ~= 58.6
 print(f'''Spherical cap: {vol_spherical_cap(1       ,   2						) = }'''						)  # ~= 5.24
 print(f'''Spheres intersetion: {vol_spheres_intersect(2       ,   2       ,   1						) = }'''						)  # ~= 21.21
 print(f'''Spheres union: {vol_spheres_union(2       ,   2       ,   1						) = }'''						)  # ~= 45.81
 print(
     f'''Hollow Circular Cylinder: {vol_hollow_circular_cylinder(1       ,   2       ,   3						) = }'''						)  # ~= 28.3


if __name__ == "__main__":
  main()








from typing import SupportsIndex

import numpy as np
from scipy.ndimage import convolve







def _a					(			SCREAMING_SNAKE_CASE						:     np.ndarray       ,   SCREAMING_SNAKE_CASE						:     np.ndarray       ,   SCREAMING_SNAKE_CASE						:     np.ndarray						)       ->       np.ndarray:

 """simple docstring"""






 __lowerCAmelCase:  Any        = np.stack((horizontal_flow, vertical_flow)       ,   2						)

 # Create a grid of all pixel coordinates and subtract the flow to get the
 # target pixels coordinates
 __lowerCAmelCase:  List[str]        = np.stack(
     np.meshgrid(np.arange(0       ,   image.shape[1]						)       ,   np.arange(0       ,   image.shape[0]						)						)       ,   2						)
 __lowerCAmelCase:  int        = np.round(grid - flow						).astype(np.intaa						)

 # Find the locations outside of the original image
 __lowerCAmelCase:  Dict        = (grid < 0) | (grid >= np.array([image.shape[1], image.shape[0]]						))
 __lowerCAmelCase:  str        = 0

 __lowerCAmelCase:  List[str]        = image[grid[:, :, 1], grid[:, :, 0]]

 # Set pixels at invalid locations to 0
 __lowerCAmelCase:  List[str]        = 0

 return warped







def _a					(			SCREAMING_SNAKE_CASE						:     np.ndarray       ,   SCREAMING_SNAKE_CASE						:     np.ndarray       ,   SCREAMING_SNAKE_CASE						:     SupportsIndex       ,   SCREAMING_SNAKE_CASE						:     float | None = None       ,   )       ->       tuple[np.ndarray, np.ndarray]:

 """simple docstring"""






 if alpha is None:
  __lowerCAmelCase:  Tuple        = 0.1

 # Initialize flow
 __lowerCAmelCase:  Optional[int]        = np.zeros_like(SCREAMING_SNAKE_CASE						)
 __lowerCAmelCase:  Dict        = np.zeros_like(SCREAMING_SNAKE_CASE						)

 # Prepare kernels for the calculation of the derivatives and the average velocity
 __lowerCAmelCase:  List[Any]        = np.array([[-1, 1], [-1, 1]]						) * 0.2_5
 __lowerCAmelCase:  int        = np.array([[-1, -1], [1, 1]]						) * 0.2_5
 __lowerCAmelCase:  Tuple        = np.array([[1, 1], [1, 1]]						) * 0.2_5
 __lowerCAmelCase:  Dict        = np.array(
     [[1 / 12, 1 / 6, 1 / 12], [1 / 6, 0, 1 / 6], [1 / 12, 1 / 6, 1 / 12]]						)

 # Iteratively refine the flow
 for _ in range(SCREAMING_SNAKE_CASE						):
  __lowerCAmelCase:  Optional[int]        = warp(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)
  __lowerCAmelCase:  List[str]        = convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						) + convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)
  __lowerCAmelCase:  int        = convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						) + convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)
  __lowerCAmelCase:  List[Any]        = convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						) + convolve(SCREAMING_SNAKE_CASE       ,   -kernel_t						)

  __lowerCAmelCase:  Any        = convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)
  __lowerCAmelCase:  Dict        = convolve(SCREAMING_SNAKE_CASE       ,   SCREAMING_SNAKE_CASE						)

  # This updates the flow as proposed in the paper (Step 12)
  __lowerCAmelCase:  Tuple        = (
      derivative_x * avg_horizontal_velocity
      + derivative_y * avg_vertical_velocity
      + derivative_t
  )
  __lowerCAmelCase:  int        = update / (alpha**2 + derivative_x**2 + derivative_y**2)

  __lowerCAmelCase:  List[Any]        = avg_horizontal_velocity - derivative_x * update
  __lowerCAmelCase:  Union[str, Any]        = avg_vertical_velocity - derivative_y * update

 return horizontal_flow, vertical_flow


if __name__ == "__main__":
  import doctest

  doctest.testmod()





