differt2d.geometry module

Geometrical objects to be placed in a differt2d.scene.Scene.

stack_leaves(pytrees, axis=0, is_leaf=None)[source]

Stacks the leaves of one or more Pytrees along a new axis.

Solution inspired from: https://github.com/google/jax/discussions/16882#discussioncomment-6638501.

Parameters:
Return type:

TypeVar(P, bound= PyTree)

Returns:

A new Pytree with leaves stacked along the new axis.

Raises:

ValueError – If the all PyTrees are not of the same type.

unstack_leaves(pytrees)[source]

Unstacks the leaves of a Pytree. Reciprocal of stack_leaves.

Parameters:

pytrees – A Pytree.

Return type:

list[PyTree]

Returns:

A list of Pytrees, where each Pytree has the same structure as the input Pytree, but each leaf contains only one part of the original leaf.

Raises:

ValueError – If the input is not the result of stacked PyTrees.

segments_intersect(P1, P2, P3, P4, tol=0.005, approx=None, **kwargs)[source]

Checks whether two line segments intersect.

The first segment is defined by points P1-P2, and the second by points P3-P4.

If they exist, the intersection coordinates can expressed as either:

\[P = \alpha \left(P_2 - P_1 \right) + P_1,\]

or,

\[P = \alpha \left(P_4 - P_3 \right) + P_3.\]

For \(P\) to exist, both \(\alpha\) and \(\beta\) must be in the range \([0;1]\).

Warning

Division by zero may occur if the two segments are colinear.

References:

“Graphics Gems III - 1st Edition”, section IV.6. Link to code.

Parameters:
  • P1 (Array, '2']) – The coordinates of the first point of the first segment.

  • P2 (Array, '2']) – The coordinates of the second point of the first segment.

  • P3 (Array, '2']) – The coordinates of the first point of the second segment.

  • P4 (Array, '2']) – The coordinates of the second point of the second segment.

  • tol (Union[Array, ''], float], default: 0.005) – Relaxes the condition to \([-\texttt{tol};1+\texttt{tol}]\).

  • approx (Optional[bool], default: None) – Whether approximation is enabled or not.

  • kwargs (Any) – Keyword arguments passed to activation.

Return type:

Union[Array, '*batch'], Array, '*batch']]

Returns:

Whether the two segments intersect.

Examples:

>>> from differt2d.geometry import segments_intersect
>>> from differt2d.logic import sigmoid
>>> import jax.numpy as jnp
>>> P1 = jnp.array([+0.0, +0.0])
>>> P2 = jnp.array([+1.0, +0.0])
>>> P3 = jnp.array([+0.5, -1.0])
>>> P4 = jnp.array([+0.5, +1.0])
>>> segments_intersect(P1, P2, P3, P4, approx=True)
Array(1., dtype=float32)
>>> segments_intersect(P1, P2, P3, P4, approx=False)
Array(True, dtype=bool)
>>> segments_intersect(P1, P2, P3, P4, approx=True, function=sigmoid)
Array(1., dtype=float32)
path_length(points)[source]

Returns the length of the given path, with N points.

Note

Currently, some epsilon value is added to each path segment to avoid division by zero in the gradient of this function. Hopefully, this should not be perceived by the user.

Parameters:

points (Array, 'N 2']) – An array of points.

Return type:

Array, '']

Returns:

The path length.

Examples:

>>> from differt2d.geometry import path_length
>>> import jax.numpy as jnp
>>> points = jnp.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 0.0]])
>>> path_length(points)  # 1 + 1 + sqrt(2)
Array(3.4142137, dtype=float32)
normalize(vector)[source]

Normalizes a vector, and also returns its length.

Parameters:

vector (Array, '2']) – A vector.

Return type:

tuple[Array, '2'], Array, '']]

Returns:

The normalized vector and its length.

Examples:

>>> from differt2d.geometry import normalize
>>> import jax.numpy as jnp
>>> vector = jnp.array([1.0, 1.0])
>>> normalize(vector)  # [1., 1.] / sqrt(2), sqrt(2)
(Array([0.70710677, 0.70710677], dtype=float32),
 Array(1.4142135, dtype=float32))
>>> zero = jnp.array([0.0, 0.0])
>>> normalize(zero)  # Special behavior at 0.
(Array([0., 0.], dtype=float32), Array(1., dtype=float32))
closest_point(points, target)[source]

Returns the index of the closest point to some target, and the actual distance.

Parameters:
  • points (Array, 'N 2']) – An array of 2D points.

  • target (Array, '2']) – A target point.

Return type:

tuple[Array, ''], Array, '']]

Returns:

The index of the closest point and the distance to the target.

Examples:

>>> from differt2d.geometry import closest_point
>>> import jax.numpy as jnp
>>> target = jnp.array([0.6, 0.3])
>>> points = jnp.array(
...     [
...         [0.0, 0.0],
...         [1.0, 0.0],  # This is the closest point
...         [1.0, 1.0],
...         [0.0, 1.0],
...     ]
... )
>>> closest_point(points, target)
(Array(1, dtype=int32), Array(0.49999997, dtype=float32))
>>> points[closest_point(points, target)[0]]
Array([1., 0.], dtype=float32)
class Point(xy=<factory>)[source]

Bases: Module, Plottable

A point object defined by its coordinates.

import matplotlib.pyplot as plt
import jax.numpy as jnp
from differt2d.geometry import Point

ax = plt.gca()
p1 = Point(xy=jnp.array([0., 0.]))
_ = p1.plot(ax)
p2 = Point(xy=jnp.array([1., 1.]))
_ = p2.plot(ax, color="b", annotate="$p_2$")
plt.show()  # doctest: +SKIP

(Source code, png, hires.png, pdf)

../_images/differt2d-geometry-1.png
Parameters:

xy (Float[jaxlib._jax.Array, '2'])

xy: Array, '2']

Cartesian coordinates.

plot(ax, *args, annotate=None, annotate_offset=(0.0, 0.0), annotate_kwargs=None, **kwargs)[source]

Plot this object on the given axes and returns the results.

Parameters:
Return type:

MutableSequence[Artist]

Returns:

The artist(s).

bounding_box()[source]
Return type:

Array, '2 2']

class Vertex(xy=<factory>)[source]

Bases: Point, Object

A vertex for corner diffraction.

import matplotlib.pyplot as plt
import jax.numpy as jnp
from differt2d.geometry import Wall

ax = plt.gca()
wall = Wall(xys=jnp.array([[0., 0.], [1., 0.]]))
_ = wall.plot(ax)
for vertex in wall.get_vertices():
    _ = vertex.plot(ax)
plt.show()  # doctest: +SKIP

(Source code, png, hires.png, pdf)

../_images/differt2d-geometry-2.png
Parameters:

xy (Float[jaxlib._jax.Array, '2'])

static parameters_count()[source]

Returns how many parameters (s, t, …) are needed to define an interaction point on this object.

Typically, this equals to one for 2D surfaces.

Return type:

int

Returns:

The number of parameters.

parametric_to_cartesian(param_coords)[source]
Return type:

Array, '2']

Parameters:

param_coords (Float[jaxlib._jax.Array, 'parameters_count'])

cartesian_to_parametric(carte_coords)[source]
Return type:

Array, 'parameters_count']

Parameters:

carte_coords (Float[jaxlib._jax.Array, '2'])

contains_parametric(param_coords, approx=None, **kwargs)[source]
Return type:

Union[Array, '*batch'], Array, '*batch']]

Parameters:
  • param_coords (Float[jaxlib._jax.Array, 'parameters_count'])

  • approx (bool | None)

  • kwargs (Any)

intersects_cartesian(ray, patch=0.0, approx=None, **kwargs)[source]
Return type:

Union[Array, '*batch'], Array, '*batch']]

Parameters:
  • ray (Float[jaxlib._jax.Array, '2 2'])

  • patch (Float[jaxlib._jax.Array, ''] | float)

  • approx (bool | None)

  • kwargs (Any)

evaluate_cartesian(ray_path)[source]
Return type:

Array, '']

Parameters:

ray_path (Float[jaxlib._jax.Array, '3 2'])

plot(ax, *args, **kwargs)[source]

Plot this object on the given axes and returns the results.

Parameters:
  • ax (Axes) – The axes to plot on.

  • args (Any) – Arguments passed to the plot function.

  • kwargs (Any) – Keyword arguments passed to the plot function.

  • annotate – Text to put next the the point.

  • annotate_offset

  • annotate_kwargs – Keyword arguments passed to matplotlib.axes.Axes.annotate.

Return type:

MutableSequence[Artist]

Returns:

The artist(s).

class Ray(xys=<factory>)[source]

Bases: Module

A ray object with origin and destination points.

import matplotlib.pyplot as plt
import jax.numpy as jnp
from differt2d.geometry import Ray

ax = plt.gca()
ray = Ray(xys=jnp.array([[0., 0.], [1., 1.]]))
_ = ray.plot(ax)
plt.show()  # doctest: +SKIP

(Source code, png, hires.png, pdf)

../_images/differt2d-geometry-3.png
Parameters:

xys (Float[jaxlib._jax.Array, '2 2'])

xys: Array, '2 2']

Cartesian coordinates (origin, dest).

origin()[source]

Returns the origin of this object.

Return type:

Array, '2']

Returns:

The origin.

dest()[source]

Returns the destination of this object.

Return type:

Array, '2']

Returns:

The destination.

t()[source]

Returns the direction vector of this object.

Return type:

Array, '2']

Returns:

The direction vector.

rotate(angle, around=None)[source]

Returns a rotated copy of this ray.

Parameters:
  • angle (Union[Array, ''], float]) – The angle to rotate, in radian.

  • around (Union[Array, '2'], Point, None], default: None) – An optional point to rotate around.

Return type:

Self

Returns:

The rotated copy of this ray.

Examples:

>>> from differt2d.geometry import Ray
>>> import jax.numpy as jnp
>>> ray = Ray(xys=jnp.array([[0.0, 0.0], [1.0, 0.0]]))
>>> ray.rotate(angle=jnp.pi).xys
Array([[ 8.742278e-08,  0.000000e+00],
       [-1.000000e+00,  0.000000e+00]], dtype=float32)
class Wall(xys=<factory>)[source]

Bases: Ray, Object

A wall object defined by its corners.

import matplotlib.pyplot as plt
import jax.numpy as jnp
from differt2d.geometry import Wall

ax = plt.gca()
wall = Wall(xys=jnp.array([[0., 0.], [1., 0.]]))
_ = wall.plot(ax)
plt.show()  # doctest: +SKIP

(Source code, png, hires.png, pdf)

../_images/differt2d-geometry-4.png
Parameters:

xys (Float[jaxlib._jax.Array, '2 2'])

normal()[source]

Returns the normal to the current wall, expressed in cartesian coordinates and normalized.

Return type:

Array, '2']

Returns:

The normal.

static parameters_count()[source]

Returns how many parameters (s, t, …) are needed to define an interaction point on this object.

Typically, this equals to one for 2D surfaces.

Return type:

int

Returns:

The number of parameters.

parametric_to_cartesian(param_coords)[source]
Return type:

Array, '2']

Parameters:

param_coords (Float[jaxlib._jax.Array, 'parameters_count'])

cartesian_to_parametric(carte_coords)[source]
Return type:

Array, 'parameters_count']

Parameters:

carte_coords (Float[jaxlib._jax.Array, '2'])

contains_parametric(param_coords, approx=None, **kwargs)[source]
Return type:

Union[Array, '*batch'], Array, '*batch']]

Parameters:
  • param_coords (Float[jaxlib._jax.Array, 'parameters_count'])

  • approx (bool | None)

  • kwargs (Any)

intersects_cartesian(ray, patch=0.0, approx=None, **kwargs)[source]
Return type:

Union[Array, '*batch'], Array, '*batch']]

Parameters:
  • ray (Float[jaxlib._jax.Array, '2 2'])

  • patch (Float[jaxlib._jax.Array, ''] | float)

  • approx (bool | None)

  • kwargs (Any)

evaluate_cartesian(ray_path)[source]
Return type:

Array, '']

Parameters:

ray_path (Float[jaxlib._jax.Array, '3 2'])

image_of(point)[source]

Returns the image of a point with respect to this mirror (wall), using specular reflection.

Parameters:

point (Array, '2']) – The starting point.

Return type:

Array, '2']

Returns:

The image of the point.

Examples:

>>> from differt2d.geometry import Wall
>>> import jax.numpy as jnp
>>> wall = Wall(xys=jnp.array([[0.0, 0.0], [1.0, 0.0]]))
>>> wall.image_of(jnp.array([0.0, 1.0]))
Array([ 0., -1.], dtype=float32)
get_vertices()[source]

Returns the two vertices of this wall.

Return type:

tuple[Vertex, Vertex]

Returns:

The two vertices.

class RIS(xys=<factory>, phi=<factory>)[source]

Bases: Wall

A very basic Reflective Intelligent Surface (RIS) object.

Here, we model a RIS such that the angle of reflection is constant with respect to its normal, regardless of the incident vector.

Parameters:
  • xys (Float[jaxlib._jax.Array, '2 2'])

  • phi (Float[jaxlib._jax.Array, ''])

phi: Array, '']

The constant angle of reflection.

evaluate_cartesian(ray_path)[source]
Return type:

Array, '']

Parameters:

ray_path (Float[jaxlib._jax.Array, '3 2'])

plot(ax, *args, **kwargs)[source]
Return type:

MutableSequence[Artist]

Parameters:
class Path(xys, loss=<factory>)[source]

Bases: Module, Plottable

A path object with at least two points.

import matplotlib.pyplot as plt
import jax.numpy as jnp
from differt2d.geometry import Path

ax = plt.gca()
path = Path(xys=jnp.array([[0., 0.], [.8, .2], [1., 1.]]))
_ = path.plot(ax)
plt.show()  # doctest: +SKIP

(Source code, png, hires.png, pdf)

../_images/differt2d-geometry-5.png
Parameters:
  • xys (Float[jaxlib._jax.Array, 'num_points 2'])

  • loss (Float[jaxlib._jax.Array, ''])

xys: Array, 'num_points 2']

Array of cartesian coordinates.

loss: Array, '']

The loss value for the given path.

from_tx_objects_rx(*args, **kwargs) = Partial(   func=_JitWrapper(     fn='Path.from_tx_objects_rx',     filter_warning=False,     donate_first=False,     donate_rest=False   ),   args=(differt2d.geometry.Path,),   keywords={} )
Parameters:
Return type:

_Return

length()[source]

Returns the length of this path.

Return type:

Array, '']

Returns:

The path length.

on_objects(objects, approx=None, **kwargs)[source]

Returns whether the path correctly passes on the objects.

For each object i, it will check whether it contains the ith point in the path (start and end points are ignored).

Parameters:
  • objects (Sequence[Interactable]) – The list of objects to check against.

  • approx (Optional[bool], default: None) – Whether approximation is enabled or not.

  • kwargs – Keyword arguments passed to activation.

Return type:

Union[Array, '*batch'], Array, '*batch']]

Returns:

Whether this path passes on the objects.

intersects_with_objects(objects, path_candidate, patch=0.0, approx=None, **kwargs)[source]

Returns whether the path intersects with any of the objects.

The path_candidate argument is used to avoid checking for intersection on objects the path is allowed to pass on.

Parameters:
  • objects (Sequence[Interactable]) – The list of objects in the scene.

  • path_candidate (Array) – The object indices on which the path should pass.

  • patch (Union[Array, ''], float], default: 0.0) – The patch value for intersection check, see Interactable.intersects_cartesian.

  • approx (Optional[bool], default: None) – Whether approximation is enabled or not.

  • kwargs (Any) – Keyword arguments passed to activation.

Return type:

Union[Array, '*batch'], Array, '*batch']]

Returns:

Whether this path intersects any of the objects.

is_valid(objects, path_candidate, interacting_objects, tol=0.01, patch=0.0, approx=None, **kwargs)[source]

Returns whether the current path is valid, according to three requirements (see below).

The requirements are:

  1. the path loss is below some tolerance;

  2. the coordinate points are correctly placed inside the corresponding interacting objects;

  3. and the path does not intersect with any of the objects in the scene (except those concerned by 2.).

Parameters:
Return type:

Union[Array, '*batch'], Array, '*batch']]

Returns:

Whether this path is valid.

plot(ax, *args, **kwargs)[source]

Plot this object on the given axes and returns the results.

Parameters:
  • ax (Axes) – The axes to plot on.

  • args (Any) – Arguments passed to the plot function.

  • kwargs (Any) – Keyword arguments passed to the plot function.

Return type:

MutableSequence[Artist]

Returns:

The artist(s).

bounding_box()[source]

Returns the bounding box of this object.

This is: [[min_x, min_y], [max_x, max_y]].

Return type:

Array, '2 2']

Returns:

The min. and max. coordinates of this object.

class ImagePath(xys, loss=<factory>)[source]

Bases: Path

A path object that was obtained with the Image method.

Parameters:
  • xys (Float[jaxlib._jax.Array, 'num_points 2'])

  • loss (Float[jaxlib._jax.Array, ''])

from_tx_objects_rx(*args, **kwargs) = Partial(   func=_JitWrapper(     fn='ImagePath.from_tx_objects_rx',     filter_warning=False,     donate_first=False,     donate_rest=False   ),   args=(differt2d.geometry.ImagePath,),   keywords={} )
Parameters:
Return type:

_Return

class FermatPath(xys, loss=<factory>)[source]

Bases: Path

A path object that was obtained with the Fermat’s Principle Tracing method.

Parameters:
  • xys (Float[jaxlib._jax.Array, 'num_points 2'])

  • loss (Float[jaxlib._jax.Array, ''])

from_tx_objects_rx(*args, **kwargs) = Partial(   func=_JitWrapper(     fn='FermatPath.from_tx_objects_rx',     filter_warning=False,     donate_first=False,     donate_rest=False   ),   args=(differt2d.geometry.FermatPath,),   keywords={} )
Parameters:
Return type:

_Return

class MinPath(xys, loss=<factory>)[source]

Bases: Path

A path object that was obtained with the Min-Path-Tracing method [EOJ23].

Parameters:
  • xys (Float[jaxlib._jax.Array, 'num_points 2'])

  • loss (Float[jaxlib._jax.Array, ''])

from_tx_objects_rx(*args, **kwargs) = Partial(   func=_JitWrapper(     fn='MinPath.from_tx_objects_rx',     filter_warning=False,     donate_first=False,     donate_rest=False   ),   args=(differt2d.geometry.MinPath,),   keywords={} )
Parameters:
Return type:

_Return