API Reference

geo

A Python package for computational geometry. Provides primitives, operations, and utilities for 2D and 3D geometric tasks.

class geo.AABB(min_pt: Point3D, max_pt: Point3D)[source]

Bases: object

Axis-Aligned Bounding Box.

contains_point(point: Point3D) bool[source]

Check if point is inside or on boundary of AABB.

intersects_aabb(other: AABB) bool[source]

Check if this AABB intersects with another AABB.

intersects_sphere(sphere_center: Point3D, sphere_radius: float, epsilon: float = 1e-09) bool[source]

Check if AABB intersects a sphere. Finds closest point on AABB to sphere center, then checks distance.

max_pt: Point3D
min_pt: Point3D
class geo.BezierCurve(control_points: Sequence[Point2D])[source]

Bases: Curve2D

Arbitrary-degree 2-D Bezier curve.

Parameters:

control_points – Iterable of :class: geo.core.Point2D. At least two are required (a single point would be a degenerate curve; for that, use :class: geo.primitives_2d.curve.base.Curve2D directly or a degenerate curve subclass).

Notes

  • Degree = len(control_points) - 1

  • point_at uses Bernstein polynomials by default; can switch to De Casteljau for improved numerical stability on very high degrees via the use_casteljau flag.

derivative_curve() BezierCurve[source]

Returns the derivative of this Bezier curve as a new BezierCurve object. The resulting control points are vectors interpreted as new points.

point_at(t: float, *, use_casteljau: bool = False) Point2D[source]

Evaluate the curve at parameter t.

Parameters:
  • t (float) – Parameter value. 0 ≤ t ≤ 1 is the usual domain; other values extrapolate linearly.

  • use_casteljau (bool, default=False) – When True, uses the recursive De Casteljau algorithm, which is numerically stabler for high-degree curves.

Return type:

Point2D

tangent_at(t: float) Vector2D[source]

First derivative B’(t). Returns the zero vector for a degenerate (degree 0) curve.

The derivative of a Bezier curve is itself another Bezier curve of degree (n-1) whose control points are n·(Pᵢ₊₁ - Pᵢ).

class geo.Circle(center: Point2D, radius: float)[source]

Bases: object

Represents a circle in 2D space, defined by a center point and a radius.

property area: float

Calculates the area of the circle.

property circumference: float

Calculates the circumference (perimeter) of the circle.

contains_point(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of the circle.

Parameters:
  • point – The Point2D to check.

  • epsilon – Tolerance for floating point comparisons (for boundary).

Returns:

True if the point is contained within or on the circle, False otherwise.

intersection_with_circle(other: Circle, epsilon: float = 1e-09) List[Point2D][source]

Calculates the intersection points of this circle with another circle.

Parameters:
  • other – The other Circle to intersect with.

  • epsilon – Tolerance for floating point comparisons.

Returns:

A list of intersection Point2Ds. - Empty list if no intersection (circles are separate or one contains another without touching). - One point if circles are tangent. - Two points if circles intersect at two distinct points. - Potentially infinite if circles are coincident (returns empty list for now).

intersection_with_line(line: Line2D, epsilon: float = 1e-09) List[Point2D][source]

Calculates the intersection points of this circle with a Line2D.

Parameters:
  • line – The Line2D to intersect with.

  • epsilon – Tolerance for floating point comparisons.

Returns:

A list of intersection Point2Ds. - Empty list if no intersection. - One point if the line is tangent to the circle. - Two points if the line secants the circle.

on_boundary(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point lies exactly on the boundary of the circle.

class geo.Circle3D(center: Point3D, radius: float, normal: Vector3D)[source]

Bases: object

Represents a circle in 3D space, defined by a center point, radius, and plane normal.

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Check if a point lies on the circumference of the circle (within epsilon tolerance).

class geo.Cone(apex: Point3D, base_center: Point3D, base_radius: float)[source]

Bases: object

Represents a finite right circular cone in 3D space. Defined by its apex point, the center of its circular base, and the radius of the base. The height and axis direction are derived from these.

property base_area: float

pi * r^2.

Type:

Calculates the area of the circular base

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of the cone. 1. Point must be between the base plane and a plane through the apex parallel to base. 2. For a point P, let its projection onto the cone’s axis be Q.

The distance from P to Q (radial_dist) must be <= R_at_Q, where R_at_Q is the radius of the cone’s cross-section at Q. R_at_Q = base_radius * (distance from apex to Q) / height.

get_base_plane() Plane[source]

Returns the plane of the cone’s base.

property lateral_surface_area: float

pi * r * slant_height.

Type:

Calculates the lateral surface area of the cone

property slant_height: float

Calculates the slant height of the cone.

property total_surface_area: float

base_area + lateral_surface_area.

Type:

Calculates the total surface area

property volume: float

(1/3) * pi * r^2 * h.

Type:

Calculates the volume of the cone

class geo.Cube(center: Point3D, side_length: float, axes: List[Vector3D] | None = None)[source]

Bases: object

Represents a cube in 3D space.

  • Axis-aligned cube defined by center and side_length.

  • Optionally, a rotation matrix (3 orthonormal Vector3D axes) can define a non-axis-aligned cube (oriented cube).

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of the cube.

For axis-aligned cubes (default axes), this is a simple bounding box check.

For oriented cubes, transform point into cube’s local axes coords, then check if within [-half_side, half_side] along each axis.

property faces_as_vertex_indices: List[List[int]]

Returns the 6 faces of the cube, each as a list of vertex indices. Vertices are ordered CCW when viewed from outside. Vertex order in self.vertices is:

index = (dx_index * 4) + (dy_index * 2) + dz_index with dx, dy, dz in (-hs, hs) ordering

The cube is built as a rectangular parallelepiped, but the order is consistent.

property surface_area: float

Calculates the surface area of the cube.

to_polyhedron() Polyhedron[source]

Converts this Cube to a Polyhedron object.

property vertices: List[Point3D]

Returns the precomputed vertices.

property volume: float

Calculates the volume of the cube.

class geo.Curve2D(control_points: Sequence[Point2D])[source]

Bases: ABC

Abstract base class for a 2D parametric curve. A curve is typically defined by C(t), where t is a parameter in [0, 1].

derivative_at(t: float) Vector2D[source]

Alias for tangent_at, representing the first derivative C’(t).

length(t0: float = 0.0, t1: float = 1.0, num_segments: int = 100) float[source]

Approximates the curve length from t0 to t1 using numerical integration.

Parameters:
  • t0 (float) – Starting parameter.

  • t1 (float) – Ending parameter.

  • num_segments (int) – Number of segments for numerical approximation.

Returns:

Approximate curve length.

Return type:

float

Raises:

ValueError – If num_segments is not positive.

abstract point_at(t: float) Point2D[source]

Calculates the point on the curve at parameter t. :param t: The parameter (typically in the range [0, 1]). :type t: float

Returns:

The point on the curve.

Return type:

Point2D

abstract tangent_at(t: float) Vector2D[source]

Calculates the (non-normalized) tangent vector to the curve at parameter t. If the tangent is undefined (e.g., cusp), a zero vector or exception may be returned/raised.

Parameters:

t (float) – The parameter.

Returns:

The tangent vector.

Return type:

Vector2D

class geo.Cylinder(base_center: Point3D, axis_direction: Vector3D, radius: float, height: float)[source]

Bases: object

Represents a finite right circular cylinder in 3D space. Defined by the center of its base, its axis direction, radius, and height.

property base_area: float

pi * r^2.

Type:

Calculates the area of one circular cap of the cylinder

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of the cylinder.

Steps: 1. Project point onto the cylinder’s axis. Check if projection is between base and top (with epsilon tolerance). 2. Calculate distance from point to the axis. Check if it’s within radius (with epsilon tolerance).

Parameters:
  • point – The point to test.

  • epsilon – Tolerance for boundary checks.

Returns:

True if point is inside or on the boundary, False otherwise.

distance_to_axis(point: Point3D) float[source]

Calculates the shortest distance from a given point to the cylinder’s axis line.

Parameters:

point – The point to measure distance from.

Returns:

The shortest distance from point to the axis line.

get_cap_planes() Tuple[Plane, Plane][source]

Returns the two planes of the cylinder caps.

The base cap’s normal points opposite to the axis direction (outward from volume), and the top cap’s normal points along the axis direction.

get_lateral_surface_point(angle_radians: float, height_fraction: float) Point3D[source]

Returns a point on the lateral surface of the cylinder given an angle around the axis and a height fraction along the axis.

Parameters:
  • angle_radians – Angle around the axis in radians (0 aligned with some reference).

  • height_fraction – Fraction between 0 (base) and 1 (top) along the axis height.

Returns:

A Point3D on the lateral surface of the cylinder.

property lateral_surface_area: float

2 * pi * r * h.

Type:

Calculates the lateral surface area (side) of the cylinder

project_point_onto_axis(point: Point3D) float[source]

Projects a point onto the cylinder’s axis and returns the scalar distance along the axis from the base_center.

Parameters:

point – The point to project.

Returns:

Scalar projection length along the axis from base_center.

property total_surface_area: float

2 * base_area + lateral_surface_area.

Type:

Calculates the total surface area

property volume: float

pi * r^2 * h.

Type:

Calculates the volume of the cylinder

class geo.Ellipse(center: Point2D, semi_major_axis: float, semi_minor_axis: float, angle_rad: float = 0.0)[source]

Bases: object

Represents an ellipse in 2D space. Defined by a center, semi-major axis length (a), semi-minor axis length (b), and a rotation angle for the major axis relative to the x-axis. We assume a >= b. If b > a, they are swapped.

property area: float

Calculates the area of the ellipse.

circumference() float[source]

Calculates the circumference (perimeter) of the ellipse. This uses Ramanujan’s approximation, which is quite accurate. C approx = pi * [3(a+b) - sqrt((3a+b)(a+3b))]

contains_point(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of the ellipse. The point is transformed to the ellipse’s local coordinate system (where it’s axis-aligned). Then, (x/a)^2 + (y/b)^2 <= 1 within a numerical tolerance.

property eccentricity: float

Calculates the eccentricity (e) of the ellipse. e = c / a = sqrt(1 - (b/a)^2) Returns 0 if a is zero.

get_foci() Tuple[Point2D, Point2D][source]

Calculates the two foci of the ellipse. Foci lie along the major axis, at distance c from the center.

property linear_eccentricity: float

Calculates the linear eccentricity (c), distance from center to each focus. c = sqrt(a^2 - b^2) Returns 0 if a < b (which shouldn’t happen if constructor enforces a>=b).

class geo.Line2D(p1: Point2D, p2_or_direction: Point2D | Vector2D)[source]

Bases: object

Represents an infinite line in 2D space. A line can be defined by two distinct points or by a point and a direction vector.

contains_point(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the line.

Parameters:
  • point – The Point2D to check.

  • epsilon – Tolerance for floating point comparisons.

Returns:

True if the point is on the line, False otherwise.

distance_to_point(point: Point2D) float[source]

Calculates the shortest distance from a point to this line. Distance = |(AP x d)| / |d|, where AP is vector from point on line to the given point, d is direction vector. For 2D, |(AP x d)| is |AP.x*d.y - AP.y*d.x|. Since d is normalized, |d|=1. So distance = |AP x d|.

intersection_with(other: Line2D, epsilon: float = 1e-09) Point2D | None[source]

Calculates the intersection point with another line.

Parameters:
  • other – The other Line2D.

  • epsilon – Tolerance for floating point comparisons.

Returns:

The intersection Point2D, or None if lines are parallel (or coincident). If lines are coincident, this method returns None as there isn’t a single intersection point.

is_parallel_to(other: Line2D, epsilon: float = 1e-09) bool[source]

Checks if this line is parallel to another line. Parallel lines have direction vectors that are scalar multiples of each other. Their 2D cross product (z-component) is zero.

is_perpendicular_to(other: Line2D, epsilon: float = 1e-09) bool[source]

Checks if this line is perpendicular to another line. Perpendicular lines have direction vectors whose dot product is zero.

point_at(t: float) Point2D[source]

Returns a point on the line at parameter t. P(t) = p1 + t * direction

Parameters:

t – The parameter.

Returns:

The Point2D on the line corresponding to t.

class geo.Line3D(origin: Point3D, direction_or_p2: Vector3D | Point3D)[source]

Bases: object

Represents an infinite line in 3D space. Defined by an origin point and a direction vector (normalized).

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the line.

distance_to_point(point: Point3D) float[source]

Calculates the shortest distance from a point to this line. Distance = |(P - origin) x direction| (direction is normalized).

point_at(t: float) Point3D[source]

Returns a point on the line at parameter t: P(t) = origin + t * direction.

project_point(point: Point3D) Point3D[source]

Projects a point orthogonally onto this line.

class geo.Plane(point_on_plane: Point3D, normal_or_p2: Vector3D | Point3D, p3: Point3D | None = None)[source]

Bases: object

Represents an infinite plane in 3D space.

A plane can be defined by a point on the plane and a normal vector, or by three non-collinear points.

The plane equation is: n · (P - P0) = 0, where n is the normal, P0 is a point on the plane, and P is any point (x,y,z) on the plane.

This can be written as:

Ax + By + Cz = D,

where (A, B, C) is the normal vector n, and D = n · P0 (note: this is the plane constant in this form).

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the plane.

This is true if the signed distance from the point to the plane is close to zero.

distance_to_point(point: Point3D, epsilon: float = 1e-09) float[source]

Calculates the shortest (unsigned) distance from a point to the plane.

get_coefficients() Tuple[float, float, float, float][source]
Returns the coefficients (A, B, C, D) of the plane equation:

Ax + By + Cz = D

intersection_with_line(line: Line3D) Point3D | None[source]

Calculates the intersection point of this plane with a Line3D.

Parameters:

line – The Line3D to intersect with.

Returns:

The intersection Point3D, or None if the line is parallel to the plane and not on the plane. If the line lies on the plane, it also returns None as there is no single intersection point (infinite intersections).

project_point(point: Point3D) Point3D[source]

Projects a point onto the plane.

P_proj = P - (n · (P - P0)) * n

signed_distance_to_point(point: Point3D) float[source]

Calculates the signed distance from a point to the plane.

Distance = n · (P - P0) / |n|. Since |n|=1, Distance = n · (P - P0). Positive if the point is on the side of the normal, negative otherwise.

class geo.Point(*coords: TCoord)[source]

Bases: Generic[TCoord]

A base class for a point in N-dimensional space. Not intended for direct instantiation for specific dimensions, but provides common functionality.

property coords: Sequence[TCoord]

Returns the coordinates of the point as a tuple.

property dimension: int

Returns the dimension of the point.

distance_to(other: Point[TCoord]) float[source]

Calculates the Euclidean distance to another point.

Parameters:

other – The other Point object.

Returns:

The Euclidean distance.

Raises:

ValueError – If the points have different dimensions.

midpoint(other: Point[TCoord]) Point[TCoord][source]

Calculates the midpoint between this point and another.

Parameters:

other – Another Point object of the same dimension.

Returns:

A new Point object representing the midpoint.

class geo.Point2D(x: float, y: float)[source]

Bases: Point[float]

Represents a point in 2D space.

classmethod from_polar(r: float, theta: float) Point2D[source]

Creates a Point2D from polar coordinates.

Parameters:
  • r – The radius.

  • theta – The angle in radians.

Returns:

A new Point2D object.

to_polar() tuple[float, float][source]

Converts Cartesian coordinates to polar coordinates.

Returns:

A tuple (r, theta) where r is the radius and theta is the angle in radians. Angle is in the range (-pi, pi].

property x: float

Returns the x-coordinate.

property y: float

Returns the y-coordinate.

class geo.Point3D(x: float, y: float, z: float)[source]

Bases: Point[float]

Represents a point in 3D space.

classmethod from_spherical(r: float, theta: float, phi: float) Point3D[source]

Creates a Point3D from spherical coordinates (ISO 80000-2:2019 convention).

Parameters:
  • r – Radial distance (must be non-negative).

  • theta – Inclination (polar angle from positive z-axis), in radians [0, pi].

  • phi – Azimuth (angle from positive x-axis in xy-plane), in radians.

Returns:

A new Point3D object.

to_spherical() tuple[float, float, float][source]

Converts Cartesian coordinates to spherical coordinates (ISO 80000-2:2019 convention). r: radial distance theta: inclination (polar angle, angle from positive z-axis), range [0, pi] phi: azimuth (angle from positive x-axis in xy-plane), range (-pi, pi]

Returns:

A tuple (r, theta, phi).

property x: float

Returns the x-coordinate.

property y: float

Returns the y-coordinate.

property z: float

Returns the z-coordinate.

class geo.Polygon(vertices: Sequence[Point2D])[source]

Bases: object

Represents a 2D polygon defined by a sequence of vertices. The vertices are assumed to be ordered (clockwise or counter-clockwise). This implementation primarily supports simple polygons (non-self-intersecting).

property area: float

Unsigned area of the polygon.

  • Simple polygon → abs(signed_area)

  • Self-intersecting → positive cross-term sum (net enclosed area)

centroid() Point2D[source]

Calculates the geometric centroid (center of mass) of a simple polygon. Formula: Cx = (1/6A) * sum_{i=0}^{n-1} (xi + x_{i+1}) * (xi*y_{i+1} - x_{i+1}*yi)

Cy = (1/6A) * sum_{i=0}^{n-1} (yi + y_{i+1}) * (xi*y_{i+1} - x_{i+1}*yi)

where A is the signed area.

contains_point(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point is inside, on the boundary, or outside the polygon. Uses the Ray Casting algorithm (even-odd rule) or Winding Number algorithm. This implementation uses the winding number algorithm. A point is inside if its winding number is non-zero. For simple polygons, winding number is +/-1 for inside, 0 for outside.

Parameters:
  • point – The Point2D to check.

  • epsilon – Tolerance for floating point comparisons.

Returns:

True if the point is inside or on the boundary, False otherwise.

property edges: List[Segment2D]

Returns a list of Segment2D objects representing the edges of the polygon.

is_clockwise() bool[source]

Checks if the polygon vertices are ordered clockwise.

is_convex(epsilon: float = 1e-09) bool[source]

Checks if the polygon is convex. A polygon is convex if all its internal angles are <= 180 degrees. This can be checked by looking at the sign of the cross product of consecutive edge vectors. All cross products should have the same sign (or be zero for collinear edges). Assumes vertices are ordered (e.g., CCW).

is_counter_clockwise() bool[source]

Checks if the polygon vertices are ordered counter-clockwise.

property num_vertices: int

Returns the number of vertices in the polygon.

property perimeter: float

Calculates the perimeter of the polygon.

signed_area() float[source]
class geo.Polyhedron(vertices: Sequence[Point3D], faces: Sequence[Sequence[int]])[source]

Bases: object

Represents a polyhedron defined by a list of vertices and a list of faces. Each face is a list of indices referencing the vertices list. Vertices of a face are assumed to be ordered CCW when viewed from outside.

contains_point(point: Point3D) bool[source]
get_face_normal(face_index: int) Vector3D[source]

Calculates the normal vector of a given face. Assumes face vertices are ordered CCW from outside. Uses a robust method by checking vertex triplets to find a non-collinear set.

Raises:

ValueError – If all triplets are collinear and face is degenerate.

get_face_points(face_index: int) List[Point3D][source]

Returns the Point3D objects for a given face index.

property num_edges: int

Calculates the number of unique edges in the polyhedron.

property num_faces: int
property num_vertices: int
surface_area() float[source]

Calculates the total surface area of the polyhedron. Sums the area of each face by triangulating polygonal faces from the first vertex.

volume() float[source]

Calculates the volume of the polyhedron. Uses the sum of signed volumes of tetrahedra formed by origin and each face triangle. Triangulates faces if needed.

Returns:

Absolute volume (non-negative).

Note

The reference origin (0,0,0) is assumed for signed volume calculations. If polyhedron does not contain origin, volume is still correct by absolute value.

class geo.Ray2D(origin: Point2D, direction: Vector2D)[source]

Bases: object

Represents a ray in 2D space, starting at an origin and extending infinitely in a given direction.

contains_point(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the ray. The point must be collinear with the ray’s line and on the positive side of the origin along the ray’s direction.

point_at(t: float) Point2D[source]

Returns a point on the ray at parameter t. P(t) = origin + t * direction. Note: For a ray, t must be non-negative.

Parameters:

t – The parameter (must be >= 0).

Returns:

The Point2D on the ray.

Raises:

ValueError – If t is negative.

to_line() Line2D[source]

Converts the ray to an infinite Line2D.

class geo.Ray3D(origin: Point3D, direction: Vector3D)[source]

Bases: object

Represents a ray in 3D space with origin and infinite direction.

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the ray.

Algorithm: 1. Check collinearity with the ray’s direction vector. 2. Ensure the point lies in the same direction as the ray (t >= 0).

point_at(t: float) Point3D[source]

Returns a point on the ray: P(t) = origin + t * direction with t >= 0.

project_point(point: Point3D) Point3D[source]

Projects a point orthogonally onto the ray. If projection parameter t < 0, returns the ray origin.

to_line() Line3D[source]

Converts the ray to an infinite Line3D.

class geo.Rectangle(p1: Point2D, p2_or_width: Point2D | float, height: float | None = None, angle_rad: float = 0.0)[source]

Bases: Polygon

Represents a rectangle in 2D space. Can be initialized with two opposite corner points, or with a corner, width, height, and angle. Inherits from Polygon. Vertices are ordered counter-clockwise by default.

property angle: float

Returns the rotation angle in radians from x-axis.

property area: float

Returns the area of the rectangle.

property diagonal_length: float

Returns the diagonal length of the rectangle.

property height: float

Returns the height of the rectangle.

is_square(epsilon: float = 1e-09) bool[source]

Checks if the rectangle is a square.

property width: float

Returns the width of the rectangle.

class geo.Segment2D(p1: Point2D, p2: Point2D)[source]

Bases: object

Represents a line segment in 2D space, defined by two distinct endpoints.

contains_point(point: Point2D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the segment within a given epsilon tolerance. Considers the point to be ‘on’ the segment if: - It lies approximately on the line (collinear within epsilon). - It projects within or near the segment bounds.

property direction_vector: Vector2D

Returns the direction vector from p1 to p2 (not necessarily normalized).

distance_to_point(point: Point2D) float[source]

Calculates the shortest distance from a point to this segment.

intersection_with_segment(other: Segment2D, epsilon: float = 1e-09) Point2D | None[source]

Calculates the intersection point with another segment.

Parameters:
  • other – The other Segment2D.

  • epsilon – Tolerance for floating point comparisons.

Returns:

The intersection Point2D, or None if they do not intersect or overlap. If segments overlap along a line, this method currently returns None. Handling of overlapping segments can be complex and is omitted for simplicity.

property length: float

Returns the length of the segment.

property midpoint: Point2D

Returns the midpoint of the segment.

to_line() Line2D[source]

Converts the segment to an infinite Line2D.

class geo.Segment3D(p1: Point3D, p2: Point3D)[source]

Bases: object

Represents a finite line segment in 3D space, defined by two distinct endpoints.

contains_point(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point lies on the segment.

Algorithm: 1. Check collinearity with the line defined by segment endpoints. 2. Verify if point lies between p1 and p2 by projection dot products.

Parameters:
  • point – Point3D to check.

  • epsilon – Tolerance for floating comparisons.

Returns:

True if point lies on or very close to the segment.

property direction_vector: Vector3D

Returns the vector from p1 to p2 (not normalized).

distance_to_point(point: Point3D) float[source]

Calculates the shortest distance from a point to the segment.

Uses clamped projection to find closest point on segment.

property length: float

Returns the Euclidean length of the segment.

property midpoint: Point3D

Returns the midpoint of the segment.

project_point(point: Point3D) Point3D[source]

Projects a point orthogonally onto the segment. If projection lies outside segment, clamps to nearest endpoint.

to_line() Line3D[source]

Converts the segment to an infinite Line3D defined by its endpoints.

class geo.Sphere(center: Point3D, radius: float)[source]

Bases: object

Represents a sphere in 3D space, defined by a center point and a radius.

contains_point(point: Point3D, on_surface_epsilon: float | None = None) bool[source]

Checks if a point is inside or on the boundary of the sphere.

Parameters:
  • point – The Point3D to check.

  • on_surface_epsilon – If provided, checks if the point is on the surface within this epsilon. Otherwise, checks if inside or on surface.

Returns:

True if condition met, False otherwise.

intersection_with_line(line: Line3D) List[Point3D][source]

Calculates intersection points of the sphere with a Line3D. Algorithm: Solve (X-C).(X-C) = r^2 where X = L0 + t*L_dir. This leads to a quadratic equation in t: at^2 + bt + c = 0.

intersection_with_plane(plane: Plane) Circle3D | None[source]

Calculates the intersection of the sphere with a Plane. Returns a Circle3D if intersection is a circle, or a Circle3D with radius 0 if tangent, or None if no intersection.

intersection_with_sphere(other: Sphere) Circle3D | None[source]

Calculates the intersection of this sphere with another sphere. Returns a Circle3D representing the circle of intersection, or None if no intersection or spheres are tangent at a point.

Reference: https://mathworld.wolfram.com/Sphere-SphereIntersection.html

on_surface(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point lies exactly on the surface of the sphere within epsilon.

point_from_spherical_coords(theta: float, phi: float) Point3D[source]

Returns a point on the sphere surface given spherical coordinates. theta: azimuthal angle in radians [0, 2*pi] phi: polar angle in radians [0, pi]

scale(factor: float) Sphere[source]

Returns a new Sphere scaled by the given factor relative to the origin.

strictly_inside(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point is strictly inside the sphere (excluding surface within epsilon).

strictly_outside(point: Point3D, epsilon: float = 1e-09) bool[source]

Checks if a point is strictly outside the sphere (excluding surface within epsilon).

property surface_area: float

4 * pi * r^2.

Type:

Calculates the surface area of the sphere

translate(offset: Vector3D) Sphere[source]

Returns a new Sphere translated by the given vector.

property volume: float

(4/3) * pi * r^3.

Type:

Calculates the volume of the sphere

class geo.SphereSphereIntersectionResult(type: str, point: Point3D | None = None, circle_center: Point3D | None = None, circle_radius: float | None = None, circle_normal: Vector3D | None = None)[source]

Bases: object

Result for sphere-sphere intersection.

circle_center: Point3D | None = None
circle_normal: Vector3D | None = None
circle_radius: float | None = None
point: Point3D | None = None
type: str
class geo.SplineCurve(control_points: Sequence[Point2D], degree: int = 3, knots: Sequence[float] | None = None)[source]

Bases: Curve2D

Open, clamped B-spline curve in 2D.

basis_function_derivatives(i: int, u: float, d: int = 1) List[List[float]][source]

Return derivatives up to order d (≤ p) of basis at u. Uses algorithm A2-3 (Piegl & Tiller).

basis_functions(i: int, u: float) List[float][source]

Compute p + 1 non-zero basis functions N_{i-p, …, i}(u).

elevate_degree() None[source]

Elevate degree by one (algorithm 5.3, Piegl & Tiller).

find_span(u: float) int[source]
insert_knot(u: float, r: int = 1) None[source]

Insert parameter u (p ≥ multiplicity + current mult.) up to r times.

point_at(t: float) Point2D[source]

Calculates the point on the curve at parameter t. :param t: The parameter (typically in the range [0, 1]). :type t: float

Returns:

The point on the curve.

Return type:

Point2D

tangent_at(t: float) Vector2D[source]

Calculates the (non-normalized) tangent vector to the curve at parameter t. If the tangent is undefined (e.g., cusp), a zero vector or exception may be returned/raised.

Parameters:

t (float) – The parameter.

Returns:

The tangent vector.

Return type:

Vector2D

to_bezier_segments() List[Tuple[Point2D, Point2D, Point2D, Point2D]][source]

Return a list of cubic Bezier segments equivalent to this B-spline. Works only for p == 3.

class geo.Triangle(p1: Point2D, p2: Point2D, p3: Point2D)[source]

Bases: Polygon

Represents a triangle in 2D space, defined by three vertices. Inherits from Polygon.

property angles_deg: Tuple[float, float, float]

Returns the three internal angles in degrees.

property angles_rad: Tuple[float, float, float]

Returns the three internal angles of the triangle in radians. (angle_at_p1, angle_at_p2, angle_at_p3) Uses the Law of Cosines: c^2 = a^2 + b^2 - 2ab*cos(C) => cos(C) = (a^2 + b^2 - c^2) / (2ab)

property area: float

Calculates the area of the triangle. Overrides Polygon.area for potential direct calculation, though Shoelace is fine. Area = 0.5 * |x1(y2−y3) + x2(y3−y1) + x3(y1−y2)|

property circumcircle: Circle | None

Calculates the circumcircle of the triangle (the circle passing through all three vertices). Returns None if the triangle is degenerate (vertices are collinear), though the constructor should prevent this.

property incircle: Circle | None

Calculates the incircle of the triangle (the largest circle contained within the triangle). Returns None if the triangle is degenerate. Incenter Ix = (a*x1 + b*x2 + c*x3) / (a+b+c) Incenter Iy = (a*y1 + b*y2 + c*y3) / (a+b+c) Inradius r = Area / s, where s is semi-perimeter (a+b+c)/2.

is_equilateral(epsilon: float = 1e-09) bool[source]

Checks if the triangle is equilateral.

is_isosceles(epsilon: float = 1e-09) bool[source]

Checks if the triangle is isosceles.

is_right(epsilon: float = 1e-09) bool[source]

Checks if the triangle is a right-angled triangle.

property side_lengths: Tuple[float, float, float]

Returns the lengths of the three sides (a, b, c). a: length of side opposite p1 (segment p2-p3) b: length of side opposite p2 (segment p1-p3) c: length of side opposite p3 (segment p1-p2)

class geo.Vector(*components: TComponent)[source]

Bases: Generic[TComponent]

A base class for a vector in N-dimensional space. Provides common vector operations.

angle_between(other: Vector[TComponent], in_degrees: bool = False) float[source]

Calculates the angle between this vector and another vector.

Parameters:
  • other – The other Vector object.

  • in_degrees – If True, returns the angle in degrees. Otherwise, in radians.

Returns:

The angle in radians or degrees.

Raises:

ValueError – If either vector is a zero vector or dimensions mismatch.

property components: Sequence[TComponent]

Returns the components of the vector as a tuple.

property dimension: int

Returns the dimension of the vector.

dot(other: Vector[TComponent]) float[source]

Calculates the dot product with another vector.

Parameters:

other – The other Vector object.

Returns:

The dot product.

Raises:

ValueError – If the vectors have different dimensions.

is_zero_vector(epsilon: float = 1e-09) bool[source]

Checks if the vector is a zero vector (all components are close to zero).

magnitude() float[source]

Calculates the magnitude (length) of the vector.

magnitude_squared() float[source]

Calculates the squared magnitude (length) of the vector.

normalize() Vector[float][source]

Returns a new unit vector in the same direction as this vector.

Returns:

A new Vector with magnitude 1.

Raises:

ValueError – If the vector is a zero vector (cannot normalize).

class geo.Vector2D(x: float, y: float)[source]

Bases: Vector[float]

Represents a vector in 2D space.

angle() float[source]

Calculates the angle of the vector with respect to the positive x-axis. The angle is in radians, in the range (-pi, pi].

cross(other: Vector2D) float[source]

Calculates the 2D cross product (magnitude of the 3D cross product’s z-component). This is a scalar value: self.x * other.y - self.y * other.x. It’s useful for determining orientation or signed area.

Parameters:

other – The other Vector2D object.

Returns:

The scalar result of the 2D cross product.

perpendicular(clockwise: bool = False) Vector2D[source]

Returns a 2D vector perpendicular to this one. By default, returns the counter-clockwise perpendicular vector (-y, x).

Parameters:

clockwise – If True, returns the clockwise perpendicular vector (y, -x).

Returns:

A new Vector2D perpendicular to this one.

property x: float

Returns the x-component.

property y: float

Returns the y-component.

class geo.Vector3D(x: float, y: float, z: float)[source]

Bases: Vector[float]

Represents a vector in 3D space.

cross(other: Vector3D) Vector3D[source]

Calculates the 3D cross product with another vector.

Parameters:

other – The other Vector3D object.

Returns:

A new Vector3D representing the cross product.

property x: float

Returns the x-component.

property y: float

Returns the y-component.

property z: float

Returns the z-component.

geo.check_point_left_of_line(point: Point2D, line_p1: Point2D, line_p2: Point2D) float[source]

Returns > 0 if point is left of the directed line from line_p1 to line_p2, < 0 if right, and 0 if collinear.

geo.clip_polygon_sutherland_hodgman(subject: Polygon, clip: Polygon) Polygon | None[source]

Clip subject (any polygon, CW or CCW) against convex clip (CCW).

Returns clipped polygon or None if empty.

geo.closest_point_on_segment_to_point(segment: Segment2D | Segment3D, point: Point2D | Point3D, *, epsilon: float = 1e-09) Point2D | Point3D[source]

Return the point on segment closest to point (inclusive ends).

geo.closest_points_segments_2d(seg1: Segment2D, seg2: Segment2D, *, epsilon: float = 1e-09) Tuple[Point2D, Point2D][source]

Pair of closest points (p_on_seg1, p_on_seg2) for two 2D segments.

geo.constrained_delaunay_triangulation(polygon: Polygon) List[Triangle][source]

Placeholder for Constrained Delaunay Triangulation that preserves polygon edges. Not implemented.

Parameters:

polygon – Polygon to triangulate.

Raises:

NotImplementedError

geo.convex_hull_2d_monotone_chain(points: Sequence[Point2D], *, keep_collinear: bool = False) List[Point2D][source]

Andrew monotone-chain convex hull.

Parameters:
  • points – The input point cloud (any iterable).

  • keep_collinear – False (default) removes collinear points on edges of the hull, returning the minimal vertex set. True keeps them.

geo.convex_hull_3d(points: Sequence[Point3D]) Polyhedron[source]

Compute the 3‑D convex hull using SciPy.

Returns a Polyhedron whose vertices are the unique points of points and faces given by the SciPy simplices (oriented CCW seen from outside).

geo.delaunay_triangulation_points_2d(points: Sequence[Point2D]) List[Triangle][source]

Computes the Delaunay triangulation of a set of 2D points.

Parameters:

points – Sequence of Point2D objects.

Returns:

List of Triangle objects forming the Delaunay triangulation.

Raises:

ValueError if fewer than 3 points are provided.

geo.distance_line_line_3d(line1: Line3D, line2: Line3D, *, epsilon: float = 1e-09) Tuple[float, Point3D | None, Point3D | None][source]

Shortest distance between two 3D infinite lines plus closest points.

  • Parallel lines - returns the perpendicular distance, points None.

  • Intersecting lines - distance 0, identical closest points.

  • Skew lines - distance > 0 and the unique closest points on each line.

geo.distance_point_line_3d(point: Point3D, line: Line3D) float[source]

Alias for line.distance_to_point(point) kept for API symmetry.

geo.distance_point_plane(point: Point3D, plane: Plane) float[source]

Alias for plane.distance_to_point(point) kept for API symmetry.

geo.distance_segment_segment_2d(seg1: Segment2D, seg2: Segment2D, *, epsilon: float = 1e-09) float[source]

Shortest distance between two closed 2D segments (0 if they touch).

geo.format_point_to_string(point: Point2D | Point3D, delimiter: str = ', ', precision: int = 6) str[source]

Formats a Point2D or Point3D object into a string.

geo.is_equal(a: float, b: float, epsilon: float = 1e-09) bool[source]

Checks if two floating-point numbers are equal within a specified tolerance.

Parameters:
  • a – The first float.

  • b – The second float.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if the absolute difference between a and b is less than epsilon, False otherwise.

geo.is_negative(a: float, epsilon: float = 1e-09) bool[source]

Checks if a floating-point number is definitively negative (less than -epsilon).

Parameters:
  • a – The float to check.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if a is less than -epsilon, False otherwise.

geo.is_polygon_simple(polygon: Polygon, epsilon: float = 1e-09) bool[source]

Checks if a polygon is simple (i.e., edges do not intersect except at shared vertices).

geo.is_positive(a: float, epsilon: float = 1e-09) bool[source]

Checks if a floating-point number is definitively positive (greater than epsilon).

Parameters:
  • a – The float to check.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if a is greater than epsilon, False otherwise.

geo.is_zero(a: float, epsilon: float = 1e-09) bool[source]

Checks if a floating-point number is close enough to zero.

Parameters:
  • a – The float to check.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if the absolute value of a is less than epsilon, False otherwise.

geo.line_polygon_intersections(line: Line2D, polygon: Polygon, epsilon: float = 1e-09) List[Point2D][source]

Finds all intersection points between an infinite line and a polygon’s edges.

Parameters:
  • line – The Line2D.

  • polygon – The Polygon.

  • epsilon – Tolerance for floating point comparisons.

Returns:

A list of unique Point2D intersection points.

geo.line_triangle_intersection_moller_trumbore(ray_origin: Point3D, ray_direction: Vector3D, tri_v0: Point3D, tri_v1: Point3D, tri_v2: Point3D, epsilon: float = 1e-09, cull_back_faces: bool = False) Tuple[Point3D, float] | None[source]

Möller-Trumbore ray-triangle intersection.

Parameters:
  • ray_origin – Ray or line origin.

  • ray_direction – Direction vector (not necessarily normalized).

  • tri_v0 – Triangle vertices.

  • tri_v1 – Triangle vertices.

  • tri_v2 – Triangle vertices.

  • epsilon – Numerical tolerance.

  • cull_back_faces – Ignore intersections with back faces if True.

Returns:

Tuple of (intersection_point, t_parameter) if intersection occurs. None otherwise.

geo.load_polygon2d_from_csv(file_path: str | PathLike, delimiter: str = ',', encoding: str = 'utf-8') Polygon[source]

Loads a 2D Polygon from a CSV file.

geo.load_polyhedron_from_obj_simple(file_path: str | PathLike, encoding: str = 'utf-8') Polyhedron[source]

Loads a Polyhedron from a simplified OBJ file (vertices and faces only).

geo.parse_points_from_string(data_string: str, delimiter: str = ',', point_dim: int = 2) list[Point2D | Point3D][source]

Parses a string of coordinates into a list of Point2D or Point3D objects. Supports 2D and 3D points; validates for supported dimensions.

geo.plane_plane_intersection(plane1: Plane, plane2: Plane, epsilon: float = 1e-09, debug: bool = False) Line3D | None[source]

Compute the intersection line of two planes.

Returns:

Line3D if planes intersect in a line. None if planes are parallel or coincident (no unique line).

If debug=True, logs warnings if numerical inconsistencies occur.

geo.plot_convex_hull_2d(points: Sequence[Point2D], hull: Sequence[Point2D] | None = None, *, ax=None, show: bool = True, point_kwargs=None, hull_kwargs=None)[source]

Quick matplotlib visualisation of a 2D hull.

geo.plot_convex_hull_3d(points: Sequence[Point3D], hull: Polyhedron | None = None, *, ax=None, show: bool = True)[source]

Matplotlib 3D plot of point cloud and its convex hull triangles.

geo.point_in_convex_polygon_2d(point: Point2D, polygon: Polygon, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of a convex polygon. Assumes vertices are ordered CCW.

The point must be left of or on every directed edge.

geo.point_in_polyhedron_convex(point: Point3D, polyhedron: Polyhedron, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of a convex polyhedron.

The point must lie on the non-positive side of all face planes (normals point outward).

geo.point_on_polygon_boundary(point: Point2D, polygon: Polygon, epsilon: float = 1e-09) bool[source]

Returns True if point lies exactly on any edge of the polygon.

geo.polygon_difference(a: Polygon, b: Polygon) List[Polygon][source]
geo.polygon_intersection(a: Polygon, b: Polygon) List[Polygon][source]
geo.polygon_union(a: Polygon, b: Polygon) List[Polygon][source]
geo.polyhedron_difference(a: Polyhedron, b: Polyhedron) List[Polyhedron][source]
geo.polyhedron_intersection(a: Polyhedron, b: Polyhedron) List[Polyhedron][source]
geo.polyhedron_union(a: Polyhedron, b: Polyhedron) List[Polyhedron][source]
geo.rotate_2d(entity: Point2D | Vector2D, angle_rad: float, origin: Point2D | None = None) Point2D | Vector2D[source]

Rotates a 2D Point or Vector counter-clockwise by a given angle around an origin.

Parameters:
  • entity – The Point2D or Vector2D to rotate.

  • angle_rad – The angle of rotation in radians.

  • origin – The Point2D about which to rotate. If None, rotation is performed about the coordinate system origin (0,0). For Vectors, origin is usually ignored if it’s a direction vector. If it’s a position vector, treat it like a point for rotation logic.

Returns:

A new Point2D or Vector2D, rotated.

Raises:

TypeError – If the entity is not a Point2D or Vector2D.

geo.rotate_3d(entity: Point3D | Vector3D, axis: Vector3D, angle_rad: float, origin: Point3D | None = None) Point3D | Vector3D[source]

Rotates a 3D Point or Vector by a given angle around an arbitrary axis. Uses Rodrigues’ rotation formula.

Parameters:
  • entity – The Point3D or Vector3D to rotate.

  • axis – The Vector3D representing the axis of rotation. Must be non-zero.

  • angle_rad – The angle of rotation in radians (counter-clockwise when looking down the axis vector towards the origin of the axis).

  • origin

    The Point3D about which to rotate. - If entity is Point3D: If None, rotation is about the coordinate

    system origin (0,0,0) along an axis passing through it.

    • If entity is Vector3D: This parameter is ignored; vectors are rotated

      about an axis passing through the coordinate system origin.

Returns:

A new Point3D or Vector3D, rotated.

Raises:
  • TypeError – If the entity is not Point3D/Vector3D, or axis is not Vector3D.

  • ValueError – If the rotation axis is a zero vector.

geo.save_polygon2d_to_csv(polygon: Polygon, file_path: str | PathLike, delimiter: str = ',', encoding: str = 'utf-8') None[source]

Saves a 2D Polygon’s vertices to a CSV file (x,y per line).

geo.save_polyhedron_to_obj_simple(polyhedron: Polyhedron, file_path: str | PathLike, precision: int = 6, encoding: str = 'utf-8') None[source]

Saves a Polyhedron object to a simple OBJ file format.

geo.scale(entity: GeomEntityType, factors: float | Vector, origin: Point | None = None) GeomEntityType[source]

Scales a geometric entity (Point or Vector) by given factors.

Parameters:
  • entity – The Point or Vector to scale.

  • factors

    • A single float for uniform scaling across all dimensions.

    • A Vector of the same dimension as the entity for non-uniform scaling.

  • origin

    • The Point about which to scale. If None, scaling is done about the

      coordinate system origin (0,0) or (0,0,0).

    • For Vectors, origin is typically ignored unless the vector is treated as a

      position vector relative to an origin. If scaling a direction vector, origin is usually not applicable. This implementation scales components directly.

Returns:

A new Point or Vector of the same type as the input entity, scaled.

Raises:
  • TypeError – If the entity is not a Point or Vector, or if factors type is invalid.

  • ValueError – If dimensions mismatch or factors are invalid.

geo.segment_circle_intersections(segment: Segment2D, circle: Circle, epsilon: float = 1e-09) List[Point2D][source]

Finds intersection points between a line segment and a circle.

Parameters:
  • segment – The Segment2D.

  • circle – The Circle.

  • epsilon – Tolerance for floating point comparisons.

Returns:

A list of unique Point2D intersection points.

geo.segment_contains_point_collinear(line_origin: Point2D, line_dir: Vector2D, pt_to_check: Point2D, seg_p1: Point2D, seg_p2: Point2D, epsilon: float) bool[source]

Helper for line_polygon_intersections: checks if pt_to_check (known collinear with line) is on segment.

Parameters:
  • line_origin – Origin point of the line.

  • line_dir – Direction vector of the line.

  • pt_to_check – The point to check.

  • seg_p1 – Segment endpoint 1.

  • seg_p2 – Segment endpoint 2.

  • epsilon – Tolerance for floating point comparisons.

Returns:

True if pt_to_check lies on the segment, False otherwise.

geo.segment_segment_intersection_detail(seg1: Segment2D, seg2: Segment2D, epsilon: float = 1e-09) Tuple[Literal['none', 'point', 'overlap', 'collinear_no_overlap'], Point2D | Tuple[Point2D, Point2D] | None][source]

Determines the intersection of two 2D line segments with more detail.

Parameters:
  • seg1 – The first Segment2D.

  • seg2 – The second Segment2D.

  • epsilon – Tolerance for floating point comparisons.

Returns:

  • IntersectionType: “none”, “point”, “overlap”, “collinear_no_overlap”.

  • Optional[Union[Point2D, Tuple[Point2D, Point2D]]]:
    • If “point”, the intersection Point2D.

    • If “overlap”, a tuple of two Point2Ds representing the overlapping segment.

    • None otherwise.

Return type:

A tuple

geo.signed_angle_between_vectors_2d(v1: Vector2D, v2: Vector2D) float[source]

Signed angle v1 → v2 in radians (CCW positive, range (-π, π]).

geo.sphere_sphere_intersection(s1: Sphere, s2: Sphere, epsilon: float = 1e-09) SphereSphereIntersectionResult[source]

Calculate intersection between two spheres.

Returns:

  • type ‘none’ if no intersection.

  • type ‘point’ with point attribute if tangent.

  • type ‘circle’ with center, radius, and normal if intersect in circle.

  • type ‘coincident’ if spheres are coincident.

Return type:

SphereSphereIntersectionResult

geo.tetrahedralise(points: Sequence[Point3D]) List[Tuple[Point3D, Point3D, Point3D, Point3D]][source]

Computes the 3D Delaunay tetrahedralization of a set of 3D points.

Parameters:

points – Sequence of Point3D objects.

Returns:

List of tetrahedra, each represented by a tuple of four Point3D vertices.

Raises:

ValueError if fewer than 4 points are provided.

geo.translate(entity: GeomEntityType, offset: Vector) GeomEntityType[source]

Translates a geometric entity (Point or Vector) by an offset vector.

Parameters:
  • entity – The Point or Vector to translate.

  • offset – The Vector representing the translation.

Returns:

A new Point or Vector of the same type as the input entity, translated.

Raises:
  • TypeError – If the entity is not a Point or Vector, or if dimensions mismatch.

  • ValueError – If dimensions of entity and offset vector do not match.

geo.triangulate_simple_polygon_ear_clipping(polygon: Polygon, ensure_ccw: bool = True) List[Triangle][source]

Triangulates a simple 2D polygon using the Ear Clipping (Ear Cutting) method. Assumes the polygon is simple (no self-intersections). Vertices should be ordered (e.g., counter-clockwise for this implementation).

Parameters:
  • polygon – The simple Polygon to triangulate.

  • ensure_ccw – If True, ensures polygon vertices are CCW. If False, assumes they are.

Returns:

A list of Triangle objects that form the triangulation. Returns empty list if polygon has < 3 vertices or is degenerate.

geo.validate_list_of_points(points: Sequence[Any], min_points: int = 0, point_type: Type[Point2D] | Type[Point3D] | None = None, name: str = 'Point list') None[source]

Validates if the input is a sequence of Point2D or Point3D objects.

Parameters:
  • points – The sequence to validate.

  • min_points – Minimum number of points required in the sequence.

  • point_type – Expected type of points (Point2D or Point3D). If None, allows either.

  • name – Name of the list (for error messages).

Raises:
  • TypeError – If points is not a sequence or contains non-Point objects.

  • ValueError – If the number of points is less than min_points.

geo.validate_non_negative(value: int | float, name: str = 'Value') None[source]

Validates if a numeric value is non-negative.

Parameters:
  • value – The numeric value to check.

  • name – The name of the value (for error messages).

Raises:
  • ValueError – If the value is negative.

  • TypeError – If the value is not numeric.

geo.validate_polygon_vertices(vertices: ~typing.Sequence[~typing.Any], point_type: ~typing.Type[~geo.core.point.Point2D] = <class 'geo.core.point.Point2D'>, name: str = 'Polygon vertices') None[source]

Validates vertices for a Polygon. Specifically for 2D polygons.

Parameters:
  • vertices – Sequence of potential vertices.

  • point_type – Expected type of point (default Point2D).

  • name – Name for error messages.

Raises:
  • TypeError – If vertices is not a sequence or elements are not of point_type.

  • ValueError – If fewer than 3 vertices are provided.

geo.validate_positive(value: int | float, name: str = 'Value') None[source]

Validates if a numeric value is strictly positive.

Parameters:
  • value – The numeric value to check.

  • name – The name of the value (for error messages).

Raises:
  • ValueError – If the value is not positive.

  • TypeError – If the value is not numeric.

Core module for the geo package. This module aggregates the fundamental classes and functions from its submodules, making them easily accessible from the ‘core’ namespace.

class geo.core.Point(*coords: TCoord)[source]

Bases: Generic[TCoord]

A base class for a point in N-dimensional space. Not intended for direct instantiation for specific dimensions, but provides common functionality.

property coords: Sequence[TCoord]

Returns the coordinates of the point as a tuple.

property dimension: int

Returns the dimension of the point.

distance_to(other: Point[TCoord]) float[source]

Calculates the Euclidean distance to another point.

Parameters:

other – The other Point object.

Returns:

The Euclidean distance.

Raises:

ValueError – If the points have different dimensions.

midpoint(other: Point[TCoord]) Point[TCoord][source]

Calculates the midpoint between this point and another.

Parameters:

other – Another Point object of the same dimension.

Returns:

A new Point object representing the midpoint.

class geo.core.Point2D(x: float, y: float)[source]

Bases: Point[float]

Represents a point in 2D space.

classmethod from_polar(r: float, theta: float) Point2D[source]

Creates a Point2D from polar coordinates.

Parameters:
  • r – The radius.

  • theta – The angle in radians.

Returns:

A new Point2D object.

to_polar() tuple[float, float][source]

Converts Cartesian coordinates to polar coordinates.

Returns:

A tuple (r, theta) where r is the radius and theta is the angle in radians. Angle is in the range (-pi, pi].

property x: float

Returns the x-coordinate.

property y: float

Returns the y-coordinate.

class geo.core.Point3D(x: float, y: float, z: float)[source]

Bases: Point[float]

Represents a point in 3D space.

classmethod from_spherical(r: float, theta: float, phi: float) Point3D[source]

Creates a Point3D from spherical coordinates (ISO 80000-2:2019 convention).

Parameters:
  • r – Radial distance (must be non-negative).

  • theta – Inclination (polar angle from positive z-axis), in radians [0, pi].

  • phi – Azimuth (angle from positive x-axis in xy-plane), in radians.

Returns:

A new Point3D object.

to_spherical() tuple[float, float, float][source]

Converts Cartesian coordinates to spherical coordinates (ISO 80000-2:2019 convention). r: radial distance theta: inclination (polar angle, angle from positive z-axis), range [0, pi] phi: azimuth (angle from positive x-axis in xy-plane), range (-pi, pi]

Returns:

A tuple (r, theta, phi).

property x: float

Returns the x-coordinate.

property y: float

Returns the y-coordinate.

property z: float

Returns the z-coordinate.

class geo.core.Vector(*components: TComponent)[source]

Bases: Generic[TComponent]

A base class for a vector in N-dimensional space. Provides common vector operations.

angle_between(other: Vector[TComponent], in_degrees: bool = False) float[source]

Calculates the angle between this vector and another vector.

Parameters:
  • other – The other Vector object.

  • in_degrees – If True, returns the angle in degrees. Otherwise, in radians.

Returns:

The angle in radians or degrees.

Raises:

ValueError – If either vector is a zero vector or dimensions mismatch.

property components: Sequence[TComponent]

Returns the components of the vector as a tuple.

property dimension: int

Returns the dimension of the vector.

dot(other: Vector[TComponent]) float[source]

Calculates the dot product with another vector.

Parameters:

other – The other Vector object.

Returns:

The dot product.

Raises:

ValueError – If the vectors have different dimensions.

is_zero_vector(epsilon: float = 1e-09) bool[source]

Checks if the vector is a zero vector (all components are close to zero).

magnitude() float[source]

Calculates the magnitude (length) of the vector.

magnitude_squared() float[source]

Calculates the squared magnitude (length) of the vector.

normalize() Vector[float][source]

Returns a new unit vector in the same direction as this vector.

Returns:

A new Vector with magnitude 1.

Raises:

ValueError – If the vector is a zero vector (cannot normalize).

class geo.core.Vector2D(x: float, y: float)[source]

Bases: Vector[float]

Represents a vector in 2D space.

angle() float[source]

Calculates the angle of the vector with respect to the positive x-axis. The angle is in radians, in the range (-pi, pi].

cross(other: Vector2D) float[source]

Calculates the 2D cross product (magnitude of the 3D cross product’s z-component). This is a scalar value: self.x * other.y - self.y * other.x. It’s useful for determining orientation or signed area.

Parameters:

other – The other Vector2D object.

Returns:

The scalar result of the 2D cross product.

perpendicular(clockwise: bool = False) Vector2D[source]

Returns a 2D vector perpendicular to this one. By default, returns the counter-clockwise perpendicular vector (-y, x).

Parameters:

clockwise – If True, returns the clockwise perpendicular vector (y, -x).

Returns:

A new Vector2D perpendicular to this one.

property x: float

Returns the x-component.

property y: float

Returns the y-component.

class geo.core.Vector3D(x: float, y: float, z: float)[source]

Bases: Vector[float]

Represents a vector in 3D space.

cross(other: Vector3D) Vector3D[source]

Calculates the 3D cross product with another vector.

Parameters:

other – The other Vector3D object.

Returns:

A new Vector3D representing the cross product.

property x: float

Returns the x-component.

property y: float

Returns the y-component.

property z: float

Returns the z-component.

geo.core.is_equal(a: float, b: float, epsilon: float = 1e-09) bool[source]

Checks if two floating-point numbers are equal within a specified tolerance.

Parameters:
  • a – The first float.

  • b – The second float.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if the absolute difference between a and b is less than epsilon, False otherwise.

geo.core.is_negative(a: float, epsilon: float = 1e-09) bool[source]

Checks if a floating-point number is definitively negative (less than -epsilon).

Parameters:
  • a – The float to check.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if a is less than -epsilon, False otherwise.

geo.core.is_positive(a: float, epsilon: float = 1e-09) bool[source]

Checks if a floating-point number is definitively positive (greater than epsilon).

Parameters:
  • a – The float to check.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if a is greater than epsilon, False otherwise.

geo.core.is_zero(a: float, epsilon: float = 1e-09) bool[source]

Checks if a floating-point number is close enough to zero.

Parameters:
  • a – The float to check.

  • epsilon – The tolerance. Defaults to DEFAULT_EPSILON.

Returns:

True if the absolute value of a is less than epsilon, False otherwise.

geo.core.rotate_2d(entity: Point2D | Vector2D, angle_rad: float, origin: Point2D | None = None) Point2D | Vector2D[source]

Rotates a 2D Point or Vector counter-clockwise by a given angle around an origin.

Parameters:
  • entity – The Point2D or Vector2D to rotate.

  • angle_rad – The angle of rotation in radians.

  • origin – The Point2D about which to rotate. If None, rotation is performed about the coordinate system origin (0,0). For Vectors, origin is usually ignored if it’s a direction vector. If it’s a position vector, treat it like a point for rotation logic.

Returns:

A new Point2D or Vector2D, rotated.

Raises:

TypeError – If the entity is not a Point2D or Vector2D.

geo.core.rotate_3d(entity: Point3D | Vector3D, axis: Vector3D, angle_rad: float, origin: Point3D | None = None) Point3D | Vector3D[source]

Rotates a 3D Point or Vector by a given angle around an arbitrary axis. Uses Rodrigues’ rotation formula.

Parameters:
  • entity – The Point3D or Vector3D to rotate.

  • axis – The Vector3D representing the axis of rotation. Must be non-zero.

  • angle_rad – The angle of rotation in radians (counter-clockwise when looking down the axis vector towards the origin of the axis).

  • origin

    The Point3D about which to rotate. - If entity is Point3D: If None, rotation is about the coordinate

    system origin (0,0,0) along an axis passing through it.

    • If entity is Vector3D: This parameter is ignored; vectors are rotated

      about an axis passing through the coordinate system origin.

Returns:

A new Point3D or Vector3D, rotated.

Raises:
  • TypeError – If the entity is not Point3D/Vector3D, or axis is not Vector3D.

  • ValueError – If the rotation axis is a zero vector.

geo.core.scale(entity: GeomEntityType, factors: float | Vector, origin: Point | None = None) GeomEntityType[source]

Scales a geometric entity (Point or Vector) by given factors.

Parameters:
  • entity – The Point or Vector to scale.

  • factors

    • A single float for uniform scaling across all dimensions.

    • A Vector of the same dimension as the entity for non-uniform scaling.

  • origin

    • The Point about which to scale. If None, scaling is done about the

      coordinate system origin (0,0) or (0,0,0).

    • For Vectors, origin is typically ignored unless the vector is treated as a

      position vector relative to an origin. If scaling a direction vector, origin is usually not applicable. This implementation scales components directly.

Returns:

A new Point or Vector of the same type as the input entity, scaled.

Raises:
  • TypeError – If the entity is not a Point or Vector, or if factors type is invalid.

  • ValueError – If dimensions mismatch or factors are invalid.

geo.core.translate(entity: GeomEntityType, offset: Vector) GeomEntityType[source]

Translates a geometric entity (Point or Vector) by an offset vector.

Parameters:
  • entity – The Point or Vector to translate.

  • offset – The Vector representing the translation.

Returns:

A new Point or Vector of the same type as the input entity, translated.

Raises:
  • TypeError – If the entity is not a Point or Vector, or if dimensions mismatch.

  • ValueError – If dimensions of entity and offset vector do not match.

Operations module for the geometry package.

This module provides functions for various geometric operations and algorithms, such as intersection detection, measurements, containment checks, etc.

class geo.operations.AABB(min_pt: Point3D, max_pt: Point3D)[source]

Bases: object

Axis-Aligned Bounding Box.

contains_point(point: Point3D) bool[source]

Check if point is inside or on boundary of AABB.

intersects_aabb(other: AABB) bool[source]

Check if this AABB intersects with another AABB.

intersects_sphere(sphere_center: Point3D, sphere_radius: float, epsilon: float = 1e-09) bool[source]

Check if AABB intersects a sphere. Finds closest point on AABB to sphere center, then checks distance.

max_pt: Point3D
min_pt: Point3D
class geo.operations.SphereSphereIntersectionResult(type: str, point: Point3D | None = None, circle_center: Point3D | None = None, circle_radius: float | None = None, circle_normal: Vector3D | None = None)[source]

Bases: object

Result for sphere-sphere intersection.

circle_center: Point3D | None = None
circle_normal: Vector3D | None = None
circle_radius: float | None = None
point: Point3D | None = None
type: str
geo.operations.check_point_left_of_line(point: Point2D, line_p1: Point2D, line_p2: Point2D) float[source]

Returns > 0 if point is left of the directed line from line_p1 to line_p2, < 0 if right, and 0 if collinear.

geo.operations.clip_polygon_sutherland_hodgman(subject: Polygon, clip: Polygon) Polygon | None[source]

Clip subject (any polygon, CW or CCW) against convex clip (CCW).

Returns clipped polygon or None if empty.

geo.operations.closest_point_on_segment_to_point(segment: Segment2D | Segment3D, point: Point2D | Point3D, *, epsilon: float = 1e-09) Point2D | Point3D[source]

Return the point on segment closest to point (inclusive ends).

geo.operations.closest_points_segments_2d(seg1: Segment2D, seg2: Segment2D, *, epsilon: float = 1e-09) Tuple[Point2D, Point2D][source]

Pair of closest points (p_on_seg1, p_on_seg2) for two 2D segments.

geo.operations.constrained_delaunay_triangulation(polygon: Polygon) List[Triangle][source]

Placeholder for Constrained Delaunay Triangulation that preserves polygon edges. Not implemented.

Parameters:

polygon – Polygon to triangulate.

Raises:

NotImplementedError

geo.operations.convex_hull_2d_monotone_chain(points: Sequence[Point2D], *, keep_collinear: bool = False) List[Point2D][source]

Andrew monotone-chain convex hull.

Parameters:
  • points – The input point cloud (any iterable).

  • keep_collinear – False (default) removes collinear points on edges of the hull, returning the minimal vertex set. True keeps them.

geo.operations.convex_hull_3d(points: Sequence[Point3D]) Polyhedron[source]

Compute the 3‑D convex hull using SciPy.

Returns a Polyhedron whose vertices are the unique points of points and faces given by the SciPy simplices (oriented CCW seen from outside).

geo.operations.delaunay_triangulation_points_2d(points: Sequence[Point2D]) List[Triangle][source]

Computes the Delaunay triangulation of a set of 2D points.

Parameters:

points – Sequence of Point2D objects.

Returns:

List of Triangle objects forming the Delaunay triangulation.

Raises:

ValueError if fewer than 3 points are provided.

geo.operations.distance_line_line_3d(line1: Line3D, line2: Line3D, *, epsilon: float = 1e-09) Tuple[float, Point3D | None, Point3D | None][source]

Shortest distance between two 3D infinite lines plus closest points.

  • Parallel lines - returns the perpendicular distance, points None.

  • Intersecting lines - distance 0, identical closest points.

  • Skew lines - distance > 0 and the unique closest points on each line.

geo.operations.distance_point_line_3d(point: Point3D, line: Line3D) float[source]

Alias for line.distance_to_point(point) kept for API symmetry.

geo.operations.distance_point_plane(point: Point3D, plane: Plane) float[source]

Alias for plane.distance_to_point(point) kept for API symmetry.

geo.operations.distance_segment_segment_2d(seg1: Segment2D, seg2: Segment2D, *, epsilon: float = 1e-09) float[source]

Shortest distance between two closed 2D segments (0 if they touch).

geo.operations.is_polygon_simple(polygon: Polygon, epsilon: float = 1e-09) bool[source]

Checks if a polygon is simple (i.e., edges do not intersect except at shared vertices).

geo.operations.line_polygon_intersections(line: Line2D, polygon: Polygon, epsilon: float = 1e-09) List[Point2D][source]

Finds all intersection points between an infinite line and a polygon’s edges.

Parameters:
  • line – The Line2D.

  • polygon – The Polygon.

  • epsilon – Tolerance for floating point comparisons.

Returns:

A list of unique Point2D intersection points.

geo.operations.line_triangle_intersection_moller_trumbore(ray_origin: Point3D, ray_direction: Vector3D, tri_v0: Point3D, tri_v1: Point3D, tri_v2: Point3D, epsilon: float = 1e-09, cull_back_faces: bool = False) Tuple[Point3D, float] | None[source]

Möller-Trumbore ray-triangle intersection.

Parameters:
  • ray_origin – Ray or line origin.

  • ray_direction – Direction vector (not necessarily normalized).

  • tri_v0 – Triangle vertices.

  • tri_v1 – Triangle vertices.

  • tri_v2 – Triangle vertices.

  • epsilon – Numerical tolerance.

  • cull_back_faces – Ignore intersections with back faces if True.

Returns:

Tuple of (intersection_point, t_parameter) if intersection occurs. None otherwise.

geo.operations.plane_plane_intersection(plane1: Plane, plane2: Plane, epsilon: float = 1e-09, debug: bool = False) Line3D | None[source]

Compute the intersection line of two planes.

Returns:

Line3D if planes intersect in a line. None if planes are parallel or coincident (no unique line).

If debug=True, logs warnings if numerical inconsistencies occur.

geo.operations.plot_convex_hull_2d(points: Sequence[Point2D], hull: Sequence[Point2D] | None = None, *, ax=None, show: bool = True, point_kwargs=None, hull_kwargs=None)[source]

Quick matplotlib visualisation of a 2D hull.

geo.operations.plot_convex_hull_3d(points: Sequence[Point3D], hull: Polyhedron | None = None, *, ax=None, show: bool = True)[source]

Matplotlib 3D plot of point cloud and its convex hull triangles.

geo.operations.point_in_convex_polygon_2d(point: Point2D, polygon: Polygon, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of a convex polygon. Assumes vertices are ordered CCW.

The point must be left of or on every directed edge.

geo.operations.point_in_polyhedron_convex(point: Point3D, polyhedron: Polyhedron, epsilon: float = 1e-09) bool[source]

Checks if a point is inside or on the boundary of a convex polyhedron.

The point must lie on the non-positive side of all face planes (normals point outward).

geo.operations.point_on_polygon_boundary(point: Point2D, polygon: Polygon, epsilon: float = 1e-09) bool[source]

Returns True if point lies exactly on any edge of the polygon.

geo.operations.polygon_difference(a: Polygon, b: Polygon) List[Polygon][source]
geo.operations.polygon_intersection(a: Polygon, b: Polygon) List[Polygon][source]
geo.operations.polygon_union(a: Polygon, b: Polygon) List[Polygon][source]
geo.operations.polyhedron_difference(a: Polyhedron, b: Polyhedron) List[Polyhedron][source]
geo.operations.polyhedron_intersection(a: Polyhedron, b: Polyhedron) List[Polyhedron][source]
geo.operations.polyhedron_union(a: Polyhedron, b: Polyhedron) List[Polyhedron][source]
geo.operations.segment_circle_intersections(segment: Segment2D, circle: Circle, epsilon: float = 1e-09) List[Point2D][source]

Finds intersection points between a line segment and a circle.

Parameters:
  • segment – The Segment2D.

  • circle – The Circle.

  • epsilon – Tolerance for floating point comparisons.

Returns:

A list of unique Point2D intersection points.

geo.operations.segment_contains_point_collinear(line_origin: Point2D, line_dir: Vector2D, pt_to_check: Point2D, seg_p1: Point2D, seg_p2: Point2D, epsilon: float) bool[source]

Helper for line_polygon_intersections: checks if pt_to_check (known collinear with line) is on segment.

Parameters:
  • line_origin – Origin point of the line.

  • line_dir – Direction vector of the line.

  • pt_to_check – The point to check.

  • seg_p1 – Segment endpoint 1.

  • seg_p2 – Segment endpoint 2.

  • epsilon – Tolerance for floating point comparisons.

Returns:

True if pt_to_check lies on the segment, False otherwise.

geo.operations.segment_segment_intersection_detail(seg1: Segment2D, seg2: Segment2D, epsilon: float = 1e-09) Tuple[Literal['none', 'point', 'overlap', 'collinear_no_overlap'], Point2D | Tuple[Point2D, Point2D] | None][source]

Determines the intersection of two 2D line segments with more detail.

Parameters:
  • seg1 – The first Segment2D.

  • seg2 – The second Segment2D.

  • epsilon – Tolerance for floating point comparisons.

Returns:

  • IntersectionType: “none”, “point”, “overlap”, “collinear_no_overlap”.

  • Optional[Union[Point2D, Tuple[Point2D, Point2D]]]:
    • If “point”, the intersection Point2D.

    • If “overlap”, a tuple of two Point2Ds representing the overlapping segment.

    • None otherwise.

Return type:

A tuple

geo.operations.signed_angle_between_vectors_2d(v1: Vector2D, v2: Vector2D) float[source]

Signed angle v1 → v2 in radians (CCW positive, range (-π, π]).

geo.operations.sphere_sphere_intersection(s1: Sphere, s2: Sphere, epsilon: float = 1e-09) SphereSphereIntersectionResult[source]

Calculate intersection between two spheres.

Returns:

  • type ‘none’ if no intersection.

  • type ‘point’ with point attribute if tangent.

  • type ‘circle’ with center, radius, and normal if intersect in circle.

  • type ‘coincident’ if spheres are coincident.

Return type:

SphereSphereIntersectionResult

geo.operations.tetrahedralise(points: Sequence[Point3D]) List[Tuple[Point3D, Point3D, Point3D, Point3D]][source]

Computes the 3D Delaunay tetrahedralization of a set of 3D points.

Parameters:

points – Sequence of Point3D objects.

Returns:

List of tetrahedra, each represented by a tuple of four Point3D vertices.

Raises:

ValueError if fewer than 4 points are provided.

geo.operations.triangulate_simple_polygon_ear_clipping(polygon: Polygon, ensure_ccw: bool = True) List[Triangle][source]

Triangulates a simple 2D polygon using the Ear Clipping (Ear Cutting) method. Assumes the polygon is simple (no self-intersections). Vertices should be ordered (e.g., counter-clockwise for this implementation).

Parameters:
  • polygon – The simple Polygon to triangulate.

  • ensure_ccw – If True, ensures polygon vertices are CCW. If False, assumes they are.

Returns:

A list of Triangle objects that form the triangulation. Returns empty list if polygon has < 3 vertices or is degenerate.

Utilities sub-package for the geometry library.

Contains helper functions for validation, I/O, and other miscellaneous tasks that are not core geometric primitives or operations but support the library.

geo.utils.format_point_to_string(point: Point2D | Point3D, delimiter: str = ', ', precision: int = 6) str[source]

Formats a Point2D or Point3D object into a string.

geo.utils.load_polygon2d_from_csv(file_path: str | PathLike, delimiter: str = ',', encoding: str = 'utf-8') Polygon[source]

Loads a 2D Polygon from a CSV file.

geo.utils.load_polygon2d_from_json(file_path: str | PathLike, encoding: str = 'utf-8') Polygon[source]

Loads a 2D Polygon from a JSON file containing a list of point dictionaries.

geo.utils.load_polyhedron_from_obj_simple(file_path: str | PathLike, encoding: str = 'utf-8') Polyhedron[source]

Loads a Polyhedron from a simplified OBJ file (vertices and faces only).

geo.utils.parse_points_from_string(data_string: str, delimiter: str = ',', point_dim: int = 2) list[Point2D | Point3D][source]

Parses a string of coordinates into a list of Point2D or Point3D objects. Supports 2D and 3D points; validates for supported dimensions.

geo.utils.save_polygon2d_to_csv(polygon: Polygon, file_path: str | PathLike, delimiter: str = ',', encoding: str = 'utf-8') None[source]

Saves a 2D Polygon’s vertices to a CSV file (x,y per line).

geo.utils.save_polygon2d_to_json(polygon: Polygon, file_path: str | PathLike, encoding: str = 'utf-8') None[source]

Saves a 2D Polygon to a JSON file with a list of point dictionaries.

geo.utils.save_polyhedron_to_obj_simple(polyhedron: Polyhedron, file_path: str | PathLike, precision: int = 6, encoding: str = 'utf-8') None[source]

Saves a Polyhedron object to a simple OBJ file format.

geo.utils.validate_list_of_points(points: Sequence[Any], min_points: int = 0, point_type: Type[Point2D] | Type[Point3D] | None = None, name: str = 'Point list') None[source]

Validates if the input is a sequence of Point2D or Point3D objects.

Parameters:
  • points – The sequence to validate.

  • min_points – Minimum number of points required in the sequence.

  • point_type – Expected type of points (Point2D or Point3D). If None, allows either.

  • name – Name of the list (for error messages).

Raises:
  • TypeError – If points is not a sequence or contains non-Point objects.

  • ValueError – If the number of points is less than min_points.

geo.utils.validate_non_negative(value: int | float, name: str = 'Value') None[source]

Validates if a numeric value is non-negative.

Parameters:
  • value – The numeric value to check.

  • name – The name of the value (for error messages).

Raises:
  • ValueError – If the value is negative.

  • TypeError – If the value is not numeric.

geo.utils.validate_polygon_vertices(vertices: ~typing.Sequence[~typing.Any], point_type: ~typing.Type[~geo.core.point.Point2D] = <class 'geo.core.point.Point2D'>, name: str = 'Polygon vertices') None[source]

Validates vertices for a Polygon. Specifically for 2D polygons.

Parameters:
  • vertices – Sequence of potential vertices.

  • point_type – Expected type of point (default Point2D).

  • name – Name for error messages.

Raises:
  • TypeError – If vertices is not a sequence or elements are not of point_type.

  • ValueError – If fewer than 3 vertices are provided.

geo.utils.validate_positive(value: int | float, name: str = 'Value') None[source]

Validates if a numeric value is strictly positive.

Parameters:
  • value – The numeric value to check.

  • name – The name of the value (for error messages).

Raises:
  • ValueError – If the value is not positive.

  • TypeError – If the value is not numeric.