Skip to main content

Professional 2D and 3D geometry toolkit with shapes, vectors, conics, transformations, coordinate geometry, and analytic 3D formulas.

Project description

GeomLib Advanced

GeomLib Advanced is a pure-Python geometry toolkit for 2D and 3D mathematical work. It covers school-level geometry, coordinate geometry, conic sections, vectors, mensuration, and analytic 3D geometry.

Install from PyPI:

pip install geomlib-advanced

Import from the geomlib package:

from geomlib import Point, Circle, Triangle, Point3D, Sphere

Quick Start

from geomlib import Point, Circle, Triangle, Vector2D, Point3D, Vector3D, Line3D, Plane

circle = Circle(Point(0, 0), 5)
print(circle.area())
print(circle.perimeter())

triangle = Triangle(Point(0, 0), Point(3, 0), Point(0, 4))
print(triangle.area())
print(triangle.incenter())

vector = Vector2D(3, 4)
print(vector.magnitude())
print(vector.normalize())

line = Line3D(Point3D(0, 0, 0), Vector3D(1, 1, 1))
plane = Plane.from_point_normal(Point3D(0, 0, 2), Vector3D(0, 0, 1))
print(plane.line_intersection(line))

Complete Import List

from geomlib import (
    Point, Line, Circle, Rectangle, Square, Rhombus, Parallelogram,
    Triangle, Ellipse, Polygon, regular_polygon,
    Point3D, Sphere, Cube, Cuboid, Cylinder, Cone,
    Vector2D, Vector3D, Line3D, Plane,
    Parabola, Hyperbola,
    RelationResult,
    point_circle_relation, line_circle_relation, segment_circle_relation,
    circle_circle_relation, circle_intersection_points,
    line_rectangle_relation, line_sphere_relation, line_sphere_intersections,
    distance_between_points, section_formula,
    translate_points, rotate_points, scale_points,
    reflect_point_x, reflect_point_y, reflect_point_origin, translate_points3d,
    degrees_to_radians, radians_to_degrees,
    pythagorean_hypotenuse, pythagorean_leg, heron_area,
    distance_2d, distance_3d, midpoint_2d,
)

2D Points

Create a point with Point(x, y).

from geomlib import Point

p1 = Point(0, 0)
p2 = Point(3, 4)

print(p1.distance_to(p2))          # 5.0
print(p2.distance_to_origin())     # 5.0
print(p2.magnitude())              # 5.0
print(p1.midpoint(p2))             # Point halfway between p1 and p2
print(p1.slope_to(p2))             # slope of the line through p1 and p2
print(p2.translate(2, -1))         # move point by dx, dy
print(p2.rotate(90))               # rotate around origin
print(p2.rotate(90, Point(1, 1)))  # rotate around another point
print(p1.to_tuple())               # (0.0, 0.0)

Point also supports vector-like operators:

print(Point(1, 2) + Point(3, 4))
print(Point(3, 4) - Point(1, 2))
print(Point(2, 3) * 4)
print(Point(8, 6) / 2)
print(Point(1, 2).dot(Point(3, 4)))
print(Point(1, 2).cross(Point(3, 4)))

2D Vectors

Use Vector2D(x, y) for vector algebra.

from geomlib import Point, Vector2D

v = Vector2D(3, 4)
w = Vector2D(1, 0)

print(v.magnitude())          # 5.0
print(v.dot(w))               # dot product
print(v.cross(w))             # scalar 2D cross product
print(v.normalize())          # unit vector
print(v.angle_with(w))        # degrees
print(v.projection_on(w))     # vector projection
print(v.perpendicular())      # rotated 90 degrees
print(v.to_point())
print(v.to_tuple())

direction = Vector2D.from_points(Point(0, 0), Point(3, 4))
print(direction)

Vector2D supports +, -, * scalar, and / scalar.

Lines

Create a line from two points.

from geomlib import Point, Line, Circle

line1 = Line(Point(0, 0), Point(4, 4))
line2 = Line(Point(0, 4), Point(4, 0))

print(line1.length())
print(line1.slope_angle())
print(line1.is_vertical())
print(line1.is_horizontal())
print(line1.is_parallel(line2))
print(line1.is_perpendicular(line2))
print(line1.intersection(line2))
print(line1.distance_to_point(Point(0, 2)))
print(line1.midpoint())
print(line1.contains_point(Point(2, 2)))
print(line1.contains_point(Point(5, 5), segment=True))
print(line1.equation_coefficients())  # (a, b, c) for ax + by + c = 0
print(line1.angle_with(line2))
print(line1.point_at_distance(2))

circle = Circle(Point(0, 0), 5)
print(line1.relation_to_circle(circle))
print(line1.is_tangent_to_circle(circle))
print(line1.is_secant_to_circle(circle))
print(line1.segment_relation_to_circle(circle))

Circles

from geomlib import Point, Line, Circle

c1 = Circle(Point(0, 0), 5)
c2 = Circle(Point(6, 0), 3)

print(c1.area())
print(c1.perimeter())              # circumference
print(c1.diameter())
print(c1.contains(Point(3, 4)))
print(c1.intersects(c2))
print(c1.relation_to_circle(c2))   # separate, tangent, intersecting, contained, coincident
print(c1.intersection_area(c2))
print(c1.tangent_points(Point(10, 0)))
print(c1.line_intersections(Line(Point(-10, 0), Point(10, 0))))
print(c1.relation_to_line(Line(Point(-10, 5), Point(10, 5))))
print(c1.relation_to_segment(Line(Point(0, 0), Point(10, 0))))
print(c1.is_tangent_to_line(Line(Point(-10, 5), Point(10, 5))))
print(c1.is_secant_to_line(Line(Point(-10, 0), Point(10, 0))))
print(c1.chord_length_from_line(Line(Point(-10, 0), Point(10, 0))))
print(c1.circle_intersections(Circle(Point(8, 0), 5)))
print(c1.relation(Circle(Point(8, 0), 5)))
print(c1.scale(2))
print(c1.translate(1, 2))

Geometric Relations

Relationship helpers return a RelationResult:

RelationResult(
    kind="tangent",
    intersections=(Point(0, 5),),
    distance=5.0,
    description="Line touches the circle at one point.",
)

Use these fields:

  • kind: relation name such as "outside", "tangent", "secant", "segment_crossing", "intersecting"
  • intersections: contact or intersection points
  • distance: useful separating distance when available
  • description: human-readable explanation
  • count: number of returned points
  • touches: True for tangent/touching relations
  • cuts: True for secant/crossing relations
  • disjoint: True when objects do not meet

Line and circle:

from geomlib import Point, Line, Circle, line_circle_relation, segment_circle_relation

circle = Circle(Point(0, 0), 5)
tangent = Line(Point(-10, 5), Point(10, 5))
secant = Line(Point(-10, 0), Point(10, 0))
outside = Line(Point(-10, 6), Point(10, 6))

print(line_circle_relation(tangent, circle).kind)  # tangent
print(line_circle_relation(secant, circle).kind)   # secant
print(line_circle_relation(outside, circle).kind)  # outside

relation = circle.relation_to_line(secant)
print(relation.kind)
print(relation.intersections)
print(relation.cuts)

segment = Line(Point(0, 0), Point(10, 0))
print(segment_circle_relation(segment, circle).kind)  # segment_crossing

Point and circle:

from geomlib import point_circle_relation

print(point_circle_relation(Point(0, 0), circle).kind)  # inside_circle
print(point_circle_relation(Point(5, 0), circle).kind)  # on_circle
print(point_circle_relation(Point(6, 0), circle).kind)  # outside_circle

Circle and circle:

from geomlib import circle_circle_relation, circle_intersection_points

c1 = Circle(Point(0, 0), 5)
c2 = Circle(Point(8, 0), 5)

relation = circle_circle_relation(c1, c2)
print(relation.kind)           # intersecting
print(relation.intersections)  # two common points
print(circle_intersection_points(c1, c2))

Line and rectangle:

from geomlib import Rectangle, line_rectangle_relation

rect = Rectangle(Point(0, 0), 4, 3)
line = Line(Point(-1, 1), Point(5, 1))

print(line_rectangle_relation(line, rect).kind)      # cutting
print(line.relation_to_rectangle(rect).intersections)

Rectangles and Squares

from geomlib import Point, Rectangle, Square

rect = Rectangle(Point(0, 0), width=10, height=5)
print(rect.bottom_left)
print(rect.top_left)
print(rect.bottom_right)
print(rect.top_right)
print(rect.center)
print(rect.area())
print(rect.perimeter())
print(rect.diagonal())
print(rect.contains(Point(2, 2)))
print(rect.intersects(Rectangle(Point(5, 2), 3, 3)))
print(rect.intersection(Rectangle(Point(5, 2), 3, 3)))
print(rect.scale(1.5))
print(rect.translate(2, 3))

square = Square(Point(0, 0), side=4)
print(square.area())                       # inherited from Rectangle
print(square.perimeter())                  # inherited from Rectangle
print(square.side_length)
print(square.diagonal())
print(square.inscribed_circle_radius())
print(square.circumscribed_circle_radius())

Triangles

from geomlib import Point, Triangle

t = Triangle(Point(0, 0), Point(6, 0), Point(0, 8))

print(t.side_lengths())
print(t.area())
print(t.perimeter())
print(t.angles())
print(t.is_equilateral())
print(t.is_isosceles())
print(t.is_right_angled())
print(t.centroid())
print(t.circumcenter())
print(t.incenter())
print(t.orthocenter())
print(t.circumradius())
print(t.inradius())
print(t.contains(Point(2, 2)))

Triangle points must form a non-degenerate triangle.

Quadrilaterals

from geomlib import Point, Rhombus, Parallelogram

rhombus = Rhombus(Point(0, 0), side=5, angle_deg=60)
print(rhombus.area())
print(rhombus.perimeter())
print(rhombus.height())
print(rhombus.vertices())
print(rhombus.contains(Point(1, 1)))
print(rhombus.inscribed_circle_radius())

para = Parallelogram(Point(0, 0), base_length=6, side_length=4, angle_deg=45)
print(para.area())
print(para.perimeter())
print(para.height())
print(para.vertices())
print(para.center())
print(para.contains(Point(2, 1)))

Ellipses, Parabolas, and Hyperbolas

from geomlib import Point, Ellipse, Parabola, Hyperbola

ellipse = Ellipse(Point(0, 0), a=5, b=3)
print(ellipse.area())
print(ellipse.perimeter())          # Ramanujan approximation
print(ellipse.eccentricity())
print(ellipse.foci())
print(ellipse.major_axis_length())
print(ellipse.minor_axis_length())
print(ellipse.directrices())
print(ellipse.contains(Point(1, 1)))
print(ellipse.scale(2))
print(ellipse.translate(3, 4))

parabola = Parabola(Point(0, 0), focal_length=2, orientation="up")
print(parabola.focus())
print(parabola.directrix())         # ("y", value) or ("x", value)
print(parabola.latus_rectum_length())
print(parabola.point_at(1))
print(parabola.contains(Point(4, 2)))

hyperbola = Hyperbola(Point(0, 0), a=3, b=4, transverse_axis="x")
print(hyperbola.eccentricity())
print(hyperbola.foci())
print(hyperbola.asymptotes())       # slope/intercept pairs
print(hyperbola.contains(Point(3, 0)))

Parabola orientation can be "right", "left", "up", or "down". Hyperbola transverse axis can be "x" or "y".

Polygons

from geomlib import Point, Polygon, regular_polygon

poly = Polygon([Point(0, 0), Point(4, 0), Point(4, 3), Point(0, 3)])

print(poly.signed_area())
print(poly.area())
print(poly.perimeter())
print(poly.edges())
print(poly.centroid())
print(poly.contains(Point(2, 2)))
print(poly.contains(Point(0, 1), include_boundary=False))
print(poly.is_convex())
print(poly.bounding_box())
print(poly.translate(1, 1))
print(poly.rotate(45))
print(poly.scale(2))

pentagon = regular_polygon(Point(0, 0), sides=5, radius=10)
print(pentagon.vertices)

Polygon vertices must be ordered around the boundary.

3D Points and Vectors

from geomlib import Point3D, Vector3D

p = Point3D(1, 2, 3)
q = Point3D(4, 6, 3)

print(p.distance_to(q))
print(p.distance_to_origin())
print(p.dot(q))
print(p.cross(q))
print(p.magnitude())
print(p.normalize())
print(p.translate(1, 1, 1))
print(p.rotate_x(90))
print(p.rotate_y(90))
print(p.rotate_z(90))
print(p.to_tuple())

v = Vector3D(1, 2, 3)
w = Vector3D(4, 5, 6)

print(Vector3D.from_points(p, q))
print(v.magnitude())
print(v.dot(w))
print(v.cross(w))
print(v.normalize())
print(v.angle_with(w))
print(v.projection_on(w))
print(v.scalar_triple(Vector3D(1, 0, 0), Vector3D(0, 1, 0)))
print(v.to_point3d())
print(v.to_tuple())

Point3D and Vector3D support +, -, * scalar, and / scalar.

3D Lines and Planes

from geomlib import Point3D, Vector3D, Line3D, Plane, Sphere

line1 = Line3D(Point3D(0, 0, 0), Vector3D(1, 1, 1))
line2 = Line3D.from_points(Point3D(0, 1, 0), Point3D(1, 2, 1))
secant_line = Line3D(Point3D(-10, 0, 0), Vector3D(1, 0, 0))
tangent_line = Line3D(Point3D(-10, 5, 0), Vector3D(1, 0, 0))
sphere = Sphere(Point3D(0, 0, 0), 5)

print(line1.point_at(2))
print(line1.distance_to_point(Point3D(1, 0, 0)))
print(line1.is_parallel(line2))
print(line1.angle_with(line2))
print(line1.shortest_distance_to_line(line2))
print(secant_line.relation_to_sphere(sphere).kind)   # secant
print(secant_line.sphere_intersections(sphere))
print(tangent_line.relation_to_sphere(sphere).kind)  # tangent
print(tangent_line.is_tangent_to_sphere(sphere))
print(secant_line.is_secant_to_sphere(sphere))

plane1 = Plane(0, 0, 1, -2)  # z - 2 = 0
plane2 = Plane.from_point_normal(Point3D(0, 0, 2), Vector3D(0, 0, 1))
plane3 = Plane.from_points(Point3D(0, 0, 0), Point3D(1, 0, 0), Point3D(0, 1, 0))

print(plane1.normal)
print(plane1.contains(Point3D(1, 1, 2)))
print(plane1.distance_to_point(Point3D(0, 0, 5)))
print(plane1.is_parallel(plane2))
print(plane1.angle_with(plane3))
print(plane1.line_intersection(line1))
print(plane1.coefficients())

3D Shapes

from geomlib import Point3D, Sphere, Cube, Cuboid, Cylinder, Cone

sphere = Sphere(Point3D(0, 0, 0), radius=3)
print(sphere.volume())
print(sphere.surface_area())
print(sphere.diameter())
print(sphere.contains(Point3D(1, 1, 1)))
print(sphere.intersects(Sphere(Point3D(4, 0, 0), 2)))
print(sphere.volume_intersection(Sphere(Point3D(4, 0, 0), 2)))
print(sphere.scale(2))
print(sphere.translate(1, 2, 3))

cube = Cube(Point3D(0, 0, 0), side=4)
print(cube.volume())
print(cube.surface_area())
print(cube.space_diagonal())
print(cube.vertices())
print(cube.contains(Point3D(1, 1, 1)))
print(cube.inscribed_sphere_radius())
print(cube.circumscribed_sphere_radius())
print(cube.scale(2))
print(cube.translate(1, 2, 3))

cuboid = Cuboid(Point3D(0, 0, 0), length=2, width=3, height=4)
print(cuboid.volume())
print(cuboid.surface_area())
print(cuboid.space_diagonal())
print(cuboid.vertices())
print(cuboid.contains(Point3D(0, 0, 1)))
print(cuboid.scale(2))
print(cuboid.translate(1, 2, 3))

cylinder = Cylinder(Point3D(0, 0, 0), radius=2, height=10)
print(cylinder.volume())
print(cylinder.surface_area())
print(cylinder.lateral_surface_area())
print(cylinder.contains(Point3D(1, 1, 0)))
print(cylinder.scale(2))
print(cylinder.translate(1, 2, 3))

cone = Cone(Point3D(0, 0, 0), radius=2, height=6)
print(cone.volume())
print(cone.surface_area())
print(cone.lateral_surface_area())
print(cone.slant_height())
print(cone.contains(Point3D(0, 0, -2)))
print(cone.scale(2))
print(cone.translate(1, 2, 3))

Coordinate Geometry Helpers

from geomlib import Point, distance_between_points, section_formula

p1 = Point(0, 0)
p2 = Point(6, 6)

print(distance_between_points(p1, p2))
print(section_formula(p1, p2, 1, 2))                  # internal division
print(section_formula(p1, p2, 3, 1, internal=False))  # external division

Formula Helpers

from geomlib import (
    degrees_to_radians,
    radians_to_degrees,
    pythagorean_hypotenuse,
    pythagorean_leg,
    heron_area,
    distance_2d,
    distance_3d,
    midpoint_2d,
)

print(degrees_to_radians(180))
print(radians_to_degrees(3.141592653589793))
print(pythagorean_hypotenuse(3, 4))
print(pythagorean_leg(5, 3))
print(heron_area(3, 4, 5))
print(distance_2d(0, 0, 3, 4))
print(distance_3d(0, 0, 0, 1, 2, 2))
print(midpoint_2d(0, 0, 4, 6))

Transformation Helpers

from geomlib import (
    Point,
    Point3D,
    translate_points,
    rotate_points,
    scale_points,
    reflect_point_x,
    reflect_point_y,
    reflect_point_origin,
    translate_points3d,
)

points = [Point(1, 0), Point(0, 1)]

print(translate_points(points, 2, 3))
print(rotate_points(points, 90))
print(scale_points(points, 2))
print(reflect_point_x(Point(2, 3)))
print(reflect_point_y(Point(2, 3)))
print(reflect_point_origin(Point(2, 3)))
print(translate_points3d([Point3D(1, 2, 3)], 1, 1, 1))

Validation Rules

  • Lengths, radii, dimensions, and axes must be positive.
  • Zero vectors cannot be normalized.
  • Lines need distinct points for meaningful geometry.
  • Triangles must be non-degenerate.
  • Polygon vertices must be ordered and must enclose non-zero area.
  • Division by zero raises the normal Python exception or a ValueError, depending on context.
  • Relation helpers use a small numeric tolerance, so tangent checks are stable for floating-point calculations.

Curriculum Coverage

GeomLib Advanced supports common CBSE, ICSE, and NCERT geometry topics:

  • Class 10 coordinate geometry: distance, midpoint, section formula, slope, line equations
  • Class 10 circle geometry: non-intersecting lines, tangents, secants, common points
  • Class 10 mensuration: triangle, quadrilateral, circle, cube, cuboid, cylinder, cone, sphere
  • Class 11 straight lines: slopes, angles, parallel/perpendicular checks, line equations
  • Class 11 conic sections: circle, ellipse, parabola, hyperbola
  • Class 11 introduction to 3D geometry: points and distance in 3D
  • Class 12 vectors and 3D geometry: vectors, dot/cross product, lines, planes, angles, distances

Development

Run tests:

python -m unittest discover -s tests

Build locally:

python -m build

Upload to PyPI after building and checking:

python -m twine check dist/*
python -m twine upload dist/*

License

This project is licensed under the MIT License.

Author

Arjun Singh Gangwar

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

geomlib_advanced-0.2.0.tar.gz (32.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

geomlib_advanced-0.2.0-py3-none-any.whl (33.6 kB view details)

Uploaded Python 3

File details

Details for the file geomlib_advanced-0.2.0.tar.gz.

File metadata

  • Download URL: geomlib_advanced-0.2.0.tar.gz
  • Upload date:
  • Size: 32.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for geomlib_advanced-0.2.0.tar.gz
Algorithm Hash digest
SHA256 81ab36cc17dde455ea167bf32d6f00d9a9d7044d31a0c0edb64fe03d6e531978
MD5 20ef28bf57f88c2527ffb348f41abad2
BLAKE2b-256 12d914b3c8d36135c930c37b899003cc1dbe30f96ece29aafddd6fca7ec33948

See more details on using hashes here.

File details

Details for the file geomlib_advanced-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for geomlib_advanced-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f98dcc7092472c954bc75fc7730178ce17773ebe9146c0647f894e2454e85962
MD5 598e696921f0c3900bb926d23986adca
BLAKE2b-256 6add58b17a321ca021f9d9cf977d1cf7ba732b5f5677937b1b48cebdef02cab1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page