Geographic zone definitions with point-in-zone testing and database persistence.
ObjGeoZone defines an area in one of three shapes and answers the
question "does this coordinate fall inside the zone?".
| Shape | Definition method | contains() algorithm |
|---|---|---|
| Circle | define_circle(lat, lng, radius_km) |
Haversine distance |
| Polygon | define_polygon([(lat, lng), ...]) |
shapely / ray-casting |
| Bounding box | define_bbox(min_lat, min_lng, max_lat, max_lng) |
range comparison |
from ObjGeoZone import ObjGeoZone
zone = ObjGeoZone()
# ── Circle ────────────────────────────────────────────────────
zone.define_circle(center_lat=-33.9249, center_lng=18.4241, radius_km=25)
zone.contains(-33.92, 18.42) # True
zone.contains(-34.50, 19.00) # False
# ── Polygon ───────────────────────────────────────────────────
zone.define_polygon([
(-33.8, 18.3),
(-33.8, 18.6),
(-34.1, 18.6),
(-34.1, 18.3),
])
zone.contains(-33.95, 18.45) # True
# ── Bounding box ──────────────────────────────────────────────
zone.define_bbox(
min_lat=-34.1, min_lng=18.3,
max_lat=-33.8, max_lng=18.6,
)
zone.contains(-33.95, 18.45) # True
# ── Persist & reload ──────────────────────────────────────────
zone.define_circle(-33.9249, 18.4241, 25)
zone.save("CPT_METRO", "Cape Town Metro Area")
zone2 = ObjGeoZone()
zone2.load("CPT_METRO")
zone2.contains(-33.92, 18.42) # True
from ObjGeoLocation import ObjGeoLocation
from ObjGeoZone import ObjGeoZone
geo = ObjGeoLocation()
zone = ObjGeoZone()
zone.define_circle(-33.9249, 18.4241, radius_km=50)
point = geo.geocode("Observatory, Cape Town")
if point:
inside = zone.contains(point["lat"], point["lng"])
print(f"In zone: {inside}")
Defined in ObjGeoZone.yaml:
def_geo_zone| Column | Type | Notes |
|---|---|---|
| ZoneCode | VARCHAR(100) | Unique per Package |
| ZoneName | VARCHAR(255) | Human label |
| ZoneType | VARCHAR(50) | circle / polygon / bbox |
| CenterLat / CenterLng / RadiusKm | DECIMAL | Circle params |
| MinLat / MinLng / MaxLat / MaxLng | DECIMAL | Bbox params |
| Package | VARCHAR(255) | Axion package |
| Module | VARCHAR(255) | Always ObjGeoZone |
def_geo_zone_pointsPolygon vertices, one row per vertex ordered by PointOrder.
When shapely is installed, polygon containment uses shapely.geometry.Polygon
for correctness on concave shapes. Without shapely, a pure-Python ray-casting
(even-odd rule) implementation is used as fallback.
pip install shapely
shapely (optional but recommended for polygon accuracy)ObjGeoLocation — resolve addresses and IPs to coordinatesObjEnum.GeoZoneType — zone shape constantsObjTypes.GeoCoordType — tuple[float, float] alias for (lat, lng)