geoclide.basic module#
Basic geometric objects used across geoclide.
This module implements the elementary objects on which the whole package is built: vectors, points, normals, rays and axis-aligned bounding boxes. All of them can represent either a single element or a set of elements (their components being ndarrays), allowing vectorized calculations.
Key Classes#
- Vector
A direction in the three-dimensional space, with the common operators (addition, subtraction, scaling, …).
- Point
A position in the three-dimensional space. The subtraction of two points gives a vector.
- Normal
A vector perpendicular to a surface at a particular position. It is not necessarily normalized and is transformed differently from a vector.
- Ray
A semi-infinite line described by an origin (Point), a direction (Vector) and the parametric range [mint, maxt].
- BBox
An axis-aligned bounding box described by its pmin and pmax corner points, supporting union operations and ray intersection tests.
- class geoclide.basic.BBox(p1: Point | None = None, p2: Point | None = None)[source]#
Bases:
objectBounding Box
- Parameters:
- p1Point, optional
Frist point(s) to use to create the bounding box(es)
- p2Point, optional
Second point(s) to use to create the bounding box(es)
Methods
common_face(b[, fill_value])Get the face index/indices which is/are common with one of the face(s) of bounding box(es) b2
Get a list of boolean checking which vertices (self) are common to the bounding box(es) b
intersect(...)Test if a ray/rays intersect(s) the bounding box(es)
is_inside(p)Test if point(s) p is/are included in the bounding box(es)
is_intersection(r[, diag_calc])Test if a ray/rays intersect(s) the bounding box(es)
union(b)Union with a point/set of points or a bounding box/set of bounding boxes
Examples
>>> import geoclide as gc >>> p1 = gc.Point(0., 0., 0.) >>> p2 = gc.Point(1., 1., 1.) >>> b1 = gc.BBox(p1, p2) >>> b1 pmin=Point(0.0, 0.0, 0.0), pmax=Point(1.0, 1.0, 1.0)
- common_face(b: BBox, fill_value: int | float | None = None) int | float | ndarray | None[source]#
Get the face index/indices which is/are common with one of the face(s) of bounding box(es) b2
The convention of index from face 0 to 5, for +X,-X,+Y,-Y,+Z,-Z:
|F2| |+Y| |F1|F4|F0|F5| where -> |-X|+Z|+X|-Z| |F3| |-Y|
- Parameters:
- bBBox
The secondary bounding box(es)
- fill_valueinteger, optional
In case there is no common face(s) returns fill_value
- Returns:
- int or ndarray
Returns the index/indices of the common face(s) or fill_value. In case of an ndarray, it is 1-D
Examples
>>> import geoclide as gc >>> b1 = gc.BBox(gc.Point(0., 0., 0.), gc.Point(1., 1., 1.)) >>> b2 = gc.BBox(gc.Point(1., 0., 0.), gc.Point(2., 1., 1.)) >>> gc.get_common_face(b1, b2) 0 >>> gc.get_common_face(b2, b1) 1
- common_vertices(b: BBox) ndarray[source]#
Get a list of boolean checking which vertices (self) are common to the bounding box(es) b
- Parameters:
- bBBox
The secondary bounding box(es)
- Returns:
- ndarray
Returns an array of boolean values indicating if the bounding box(es) vertices are common to the secondary b bounding box(es) vertices
Examples
>>> import geoclide as gc >>> b0 = gc.BBox(gc.Point(0., 0., 0.), gc.Point(1., 1., 1.)) >>> b1 = gc.BBox(gc.Point(1., 0., 0.), gc.Point(2., 1., 1.)) >>> b0.common_vertices(b1) array([False, True, True, False, False, True, True, False]) >>> b1.common_vertices(b0) array([ True, False, False, True, True, False, False, True])
- intersect(r: Ray, diag_calc: bool = False, *, ds_output: Literal[True] = True) Dataset[source]#
- intersect(r: Ray, diag_calc: bool = False, *, ds_output: Literal[False]) tuple[float | ndarray, float | ndarray, bool | ndarray]
- intersect(r: Ray, diag_calc: bool = False, *, ds_output: bool) Dataset | tuple
Test if a ray/rays intersect(s) the bounding box(es)
There are 3 possibilities:
no intersection
only 1 intersection (case of ray located initially inside the BBox)
2 intersections
- Parameters:
- rRay
The ray(s) to use for the intersection test(s)
- diag_calcbool, optional
Perform diagonal calculations in case of multiple bounding boxes and rays, the output is a 1-D array instead of a 2-D array where out[i] is calculated using r(i) and bbox(i). The same size for the BBox and Ray objects is required.
- ds_outputbool, optional
If True the output is a dataset, else returns a tuple with intersection information variables
- Returns:
- Dataset or tuple
Xarray dataset containing the intersection information if ds_output is True (see the get_bbox_intersect_dataset function for its variables), else a tuple. Form of the tuple:
- t0None or float or ndarray
-> The t ray variable of the first intersection. In case of only 1 intersection it represents nothing. An ndarray is 1-D, or 2-D for a set of rays and a set of bounding boxes.
- t1None or float or ndarray
-> The t ray variable of the second intersection. In case of only 1 intersection, t1 becomes the t ray variable of the first intersection. An ndarray is 1-D, or 2-D for a set of rays and a set of bounding boxes.
- is_intersectionbool or ndarray
-> If there is at least 1 intersection return True, else False. An ndarray is an ndarray of booleans, 1-D, or 2-D for a set of rays and a set of bounding boxes.
Examples
>>> import geoclide as gc >>> p1 = gc.Point(0., 0., 0.) >>> p2 = gc.Point(1., 1., 1.) >>> b1 = gc.BBox(p1, p2) >>> b1 pmin=Point(0.0, 0.0, 0.0), pmax=Point(1.0, 1.0, 1.0) >>> p3 = gc.Point(0.5, 0.5, 0.1) >>> v1 = gc.Vector(0., 0., 1.) >>> r1 = gc.Ray(p3, v1) >>> r1 r(t) = (0.5, 0.5, 0.1) + t*(0.0, 0.0, 1.0) with t ∈ [0,inf[ >>> t0, t1, is_intersection = b1.intersect(r1, ds_output=False) >>> t0, t1, is_intersection (0.0, np.float64(0.9000000000000006), True) >>> r1(t1) Point(0.5, 0.5, 1.0000000000000007)
- is_inside(p: Point) bool | ndarray[source]#
Test if point(s) p is/are included in the bounding box(es)
- is_intersection(r: Ray, diag_calc: bool = False) bool | ndarray[source]#
Test if a ray/rays intersect(s) the bounding box(es)
- Parameters:
- rRay
The ray(s) to use for the intersection test(s)
- diag_calcbool
Perform diagonal calculations in case of multiple bounding boxes and rays, the output is a 1-D array instead of a 2-D array where out[i] is calculated using r(i) and bbox(i). The same size for the BBox and Ray objects is required.
- Returns:
- bool or ndarray
If there is at least 1 intersection returns True, else False. In case of an ndarray, it is an ndarray of booleans, 1-D, or 2-D for a set of rays and a set of bounding boxes.
Examples
>>> import geoclide as gc >>> p1 = gc.Point(0., 0., 0.) >>> p2 = gc.Point(1., 1., 1.) >>> b1 = gc.BBox(p1, p2) >>> b1 pmin=Point(0.0, 0.0, 0.0), pmax=Point(1.0, 1.0, 1.0) >>> p3 = gc.Point(0.5, 0.5, 0.1) >>> v1 = gc.Vector(0., 0., 1.) >>> r1 = gc.Ray(p3, v1) >>> r1 r(t) = (0.5, 0.5, 0.1) + t*(0.0, 0.0, 1.0) with t ∈ [0,inf[ >>> b1.is_intersection(r1) True
- union(b: Point | BBox) BBox[source]#
Union with a point/set of points or a bounding box/set of bounding boxes
- Parameters:
- bPoint or BBox
The point(s) or bounding box(es) to use for the union
- Returns:
- BBox
The new bounding box(es) after the union
Examples
>>> import geoclide as gc >>> p1 = gc.Point(0., 0., 0.) >>> p2 = gc.Point(1., 1., 1.) >>> p3 = gc.Point(1., 1., 3.) >>> b1 = gc.BBox(p1, p2) >>> b1 pmin=Point(0.0, 0.0, 0.0), pmax=Point(1.0, 1.0, 1.0) >>> b2 = b1.union(p3) >>> b2 pmin=Point(0.0, 0.0, 0.0), pmax=Point(1.0, 1.0, 3.0)
- class geoclide.basic.Normal(x: float | ndarray | Vector | Point | Normal | None = None, y: float | ndarray | None = None, z: float | ndarray | None = None, copy: bool = False)[source]#
Bases:
object- Parameters:
- xfloat or ndarray or Point or Vector or Normal, optional
The x component(s) of the normal (see notes)
- yfloat or ndarray, optional
The y component(s) of the normal. In case of an ndarray, it must be 1-D
- zfloat or ndarray, optional
The z component(s) of the normal. In case of an ndarray, it must be 1-D
- copybool, optional
If True the given ndarrays are copied, else they are used as they are (see notes)
Methods
length
length_squared
to_numpy
Notes
if the parameter x is a 1-D ndarray of size 3 and y and z are None, the values of x, y and z will be equal to respectively x[0], x[1], and x[2]
if the parameter x is a 2-D ndarray of shape (n,3) and y and z are None, the values of x, y and z will be equal to respectively x[:,0], x[:,1], and x[:,2]
if the parameter x is a Point, Vector or Normal, it will circumvent the y and z parameters and take the components of the Point/Vector/Normal for x, y and z values
the x, y and z ndarrays given as parameters are not copied, modifying them afterwards modifies the normal. Use copy=True to get a normal with its own components
Examples
>>> import geoclide as gc >>> n1 = gc.Normal(0.,0.,1.) >>> n1 Normal(0.0, 0.0, 1.0)
- fmt = '.8f'#
- class geoclide.basic.Point(x: float | ndarray | Vector | Point | Normal | None = None, y: float | ndarray | None = None, z: float | ndarray | None = None, copy: bool = False)[source]#
Bases:
object- Parameters:
- xfloat or ndarray or Point or Vector or Normal, optional
The x component(s) of the point (see notes)
- yfloat or ndarray, optional
The y component(s) of the point. In case of an ndarray, it must be 1-D
- zfloat or ndarray, optional
The z component(s) of the point. In case of an ndarray, it must be 1-D
- copybool, optional
If True the given ndarrays are copied, else they are used as they are (see notes)
Methods
to_numpy
Notes
if the parameter x is a 1-D ndarray of size 3 and y and z are None, the values of x, y and z will be equal to respectively x[0], x[1], and x[2]
if the parameter x is a 2-D ndarray of shape (n,3) and y and z are None, the values of x, y and z will be equal to respectively x[:,0], x[:,1], and x[:,2]
if the parameter x is a Point, Vector or Normal, it will circumvent the y and z parameters and take the components of the Point/Vector/Normal for x, y and z values
the x, y and z ndarrays given as parameters are not copied, modifying them afterwards modifies the point. Use copy=True to get a point with its own components
Examples
>>> import geoclide as gc >>> p1 = gc.Point(0.,0.,1.) >>> p1 Point(0.0, 0.0, 1.0)
- fmt = '.8f'#
- class geoclide.basic.Ray(o: Point | Ray, d: Vector | None = None, mint: float = 0, maxt: float = inf)[source]#
Bases:
objectDefinition of ray:
r(t) = o + t*d, where:
o is/are the origin point(s) of the ray(s)
d is/are the direction(s) of the ray(s)
t belongs to stricly positive real numbers
- Parameters:
- oPoint or Ray
Origin point(s) of the ray(s). If the o parameter is a Ray -> circumvent all the parameters by the ray attributs
- dVector
Direction(s) of the ray(s)
- mintfloat, optional
The minimum t value
- maxtfloat, optional
The maximum t value
Methods
__call__(t)Solve ray(s) equation(s)
Examples
>>> import geoclide as gc >>> o = gc.Point(0., 50., 2.) >>> d = gc.Vector(0.,0.,1.) >>> r = gc.Ray(o, d, mint=20, maxt=100) >>> r r(t) = (0.0, 50.0, 2.0) + t*(0.0, 0.0, 1.0) with t ∈ [20,100[
- __call__(t: float | ndarray) Point[source]#
Solve ray(s) equation(s)
- Parameters:
- tfloat or ndarray
The t rays(s) values(s). The value(s) must lie between mint and maxt. In case of an ndarray, it must be 1-D
- Returns:
- Point
The result(s) of the equation r(t) = o + t*d
Examples
>>> import geoclide as gc >>> o = gc.Point(0., 0., 0.) >>> d = gc.Vector(1., 0., 0.) >>> r = gc.Ray(o, d) >>> t = 10. >>> r(t) Point(10.0, 0.0, 0.0)
- class geoclide.basic.Vector(x: float | ndarray | Vector | Point | Normal | None = None, y: float | ndarray | None = None, z: float | ndarray | None = None, copy: bool = False)[source]#
Bases:
object- Parameters:
- xfloat or ndarray or Point or Vector or Normal, optional
The x component(s) of the vector (see notes)
- yfloat or ndarray, optional
The y component(s) of the vector. In case of an ndarray, it must be 1-D
- zfloat or ndarray, optional
The z component(s) of the vector. In case of an ndarray, it must be 1-D
- copybool, optional
If True the given ndarrays are copied, else they are used as they are (see notes)
Methods
length
length_squared
to_numpy
Notes
if the parameter x is a 1-D ndarray of size 3 and y and z are None, the values of x, y and z will be equal to respectively x[0], x[1], and x[2]
if the parameter x is a 2-D ndarray of shape (n,3) and y and z are None, the values of x, y and z will be equal to respectively x[:,0], x[:,1], and x[:,2]
if the parameter x is a Point, Vector or Normal, it will circumvent the y and z parameters and take the components of the Point/Vector/Normal for x, y and z values
the x, y and z ndarrays given as parameters are not copied, modifying them afterwards modifies the vector. Use copy=True to get a vector with its own components
Examples
>>> import geoclide as gc >>> v1 = gc.Vector(0.,0.,1.) >>> v1 Vector(0.0, 0.0, 1.0)
- fmt = '.8f'#
- geoclide.basic.get_bbox_intersect_dataset(bbox: BBox, r: Ray, t0: float | ndarray | None = None, t1: float | ndarray | None = None, is_intersection: bool | ndarray = False, diag_calc: bool = False) Dataset[source]#
Create dataset containing the intersection test information
The intersect method return of BBox class gives the t0, t1 and is_intersection inputs of this function
- Parameters:
- bboxBBox
The bounding box(es) used for the intersection test
- rRay
The ray(s) used for the intersection test
- t0float or ndarray
The t ray variable of the first intersection. In case of an ndarray, it is 1-D, or 2-D for a set of rays and a set of bounding boxes
- t1float or ndarray
The t ray variable of the second intersection. In case of an ndarray, it is 1-D, or 2-D for a set of rays and a set of bounding boxes
- is_intersectionbool or ndarray, optional
If there is an intersection returns True, else False. In case of an ndarray, it is an ndarray of booleans, 1-D, or 2-D for a set of rays and a set of bounding boxes
- diag_calcbool, optional
This indicates whether diagonal calculations have been performed
- Returns:
- Dataset
Xarray dataset containing the intersection information.
Key variables included:
o: The origin(s) of the ray(s) [xyz]
d: The direction(s) of the ray(s) [xyz]
mint: The mint attribute of the ray(s)
maxt: The maxt attribute of the ray(s)
is_intersection: If there is an intersection -> True, else False
thit: The t ray variable(s) of the intersection point(s)
phit: The intersection point(s) [xyz]
In case of a set of rays and/or a set of bounding boxes, the variables get an extra nrays/nobj dimension.
- geoclide.basic.get_common_face(b1: BBox, b2: BBox, fill_value: int | float | None = None) int | float | ndarray | None[source]#
Get the face index/indices of the bounding box(es) b1 which is/are common to the bounding box(es) b2
The convention of index from face 0 to 5, for +X,-X,+Y,-Y,+Z,-Z:
|F2| |+Y| |F1|F4|F0|F5| where -> |-X|+Z|+X|-Z| |F3| |-Y|
- Parameters:
- b1BBox
The principal bounding box(es)
- b2BBox
The secondary bounding box(es)
- fill_valueinteger, optional
In case there is no common face(s) returns fill_value
- Returns:
- int or ndarray
Returns the index/indices of the common face(s) or fill_value. In case of an ndarray, it is 1-D
Examples
>>> import geoclide as gc >>> b1 = gc.BBox(gc.Point(0., 0., 0.), gc.Point(1., 1., 1.)) >>> b2 = gc.BBox(gc.Point(1., 0., 0.), gc.Point(2., 1., 1.)) >>> gc.get_common_face(b1, b2) 0 >>> gc.get_common_face(b2, b1) 1
- geoclide.basic.get_common_vertices(b1: BBox, b2: BBox) ndarray[source]#
Check which vertices of bounding box(es) b1 are common to the vectices of bounding box(es) b2
- Parameters:
- b1BBox
The principal bounding box(es)
- b2BBox
The secondary bounding box(es)
- Returns:
- ndarray
Returns an array of boolean values indicating whether the principal bounding box(es) b1 vertices are common to the secondary bounding box(es) b2 vertices. It is 1-D, or 2-D in case of a set of bounding boxes.
Examples
>>> import geoclide as gc >>> b1 = gc.BBox(gc.Point(0., 0., 0.), gc.Point(1., 1., 1.)) >>> b2 = gc.BBox(gc.Point(1., 0., 0.), gc.Point(2., 1., 1.)) >>> gc.get_common_vertices(b1, b2) array([False, True, True, False, False, True, True, False]) >>> gc.get_common_vertices(b2, b1) array([ True, False, False, True, True, False, False, True])