Metadata-Version: 2.3
Name: hics
Version: 0.1.2
Summary: Python package for handling hierarchical coordinate systems.
Keywords: python
Author: Rob Scheeler
License: MIT License
         
         Copyright (c) 2025, Rob Scheeler
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
         
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Dist: loguru>=0.7.3
Requires-Dist: numpy>=2.0
Requires-Dist: pint>=0.25.2
Requires-Dist: platformdirs>=4.5.0
Requires-Dist: pyvista>=0.44
Requires-Dist: scipy>=1.16.3
Requires-Dist: xarray>=2025.10.1
Requires-Dist: xrench>=0.1.1
Requires-Dist: wget ; extra == 'geo'
Requires-Dist: cartopy ; extra == 'geo'
Requires-Dist: leafmap ; extra == 'geo'
Requires-Dist: geopandas ; extra == 'geo'
Requires-Dist: maplibre ; extra == 'geo'
Requires-Dist: dask[complete]>=2025.11.0 ; extra == 'geo'
Requires-Dist: python-dotenv>=1.2.1 ; extra == 'geo'
Requires-Dist: aiohttp>=3.13.2 ; extra == 'geo'
Requires-Dist: tqdm>=4.67.1 ; extra == 'geo'
Requires-Dist: rasterio>=1.4.3 ; extra == 'geo'
Requires-Dist: shapely>=2.1.2 ; extra == 'geo'
Requires-Dist: planetary-computer>=1.0.0 ; extra == 'geo'
Requires-Dist: requests>=2.32.5 ; extra == 'geo'
Requires-Dist: rtree>=1.4.1 ; extra == 'geo'
Requires-Dist: pyproj>=3.7.2 ; extra == 'geo'
Requires-Dist: rioxarray>=0.19.0 ; extra == 'geo'
Requires-Dist: aiofiles>=25.1.0 ; extra == 'geo'
Requires-Dist: gdal>=3.11.4 ; extra == 'geo'
Requires-Dist: nest-asyncio ; extra == 'geo'
Requires-Dist: odc-geo ; extra == 'geo'
Requires-Dist: skyfield ; extra == 'geo'
Requires-Python: >=3.11, <3.14
Project-URL: documentation, https://rscheeler.github.io/hics
Project-URL: homepage, https://github.com/rscheeler/hics
Project-URL: issues, https://github.com/rscheeler/hics/issues
Project-URL: repository, https://github.com/rscheeler/hics.git
Provides-Extra: geo
Description-Content-Type: text/markdown

# 🗺️ hics: Hierarchical Coordinate Systems
```hics``` is a Python package for handling hierarchical coordinate systems (HCS). It allows you to define relative transformations (translation and rotation) between frames and automatically resolves them to global positions (ECEF) or relative positions between any two frames in the tree.

## Core Concepts
### 1. Defining a Coordinate System
You can define a coordinate system using a position tuple and an optional reference frame. If no reference is provided, it defaults to the ```GLOBAL_CS```.

```python
from hics import HCS, ureg
import numpy as np

# A simple coordinate system 5 meters above the global origin
roof = HCS((0, 0, 5) * ureg.meter)

# A coordinate system relative to 'roof'
antenna = HCS((0, 0, 2) * ureg.meter, reference=roof)

# Resolves to [0, 0, 7]
print(antenna.global_position)
```
### 2. Rotations and Compound Transformations
```hics``` integrates with ```scipy.spatial.transform.Rotation```. Transformations are chained automatically down the hierarchy.

```python
from scipy.spatial.transform import Rotation

# Define a tower rotated 90 degrees on the roof
tower = HCS(
    (0, 4, 5) * ureg.meter,
    rotation=Rotation.from_euler("ZYZ", (0, 90, 0), degrees=True),
    reference=roof,
)

# Define an antenna on that rotated tower
local_ant = HCS(
    (0, 6, 5) * ureg.meter,
    reference=tower,
)
```
### 3. Relative Calculations
You can calculate the position or distance of one frame as seen from another, even if they are in different branches of the hierarchy.

```python
# How far is the antenna from the tower?
dist = local_ant.relative_distance(tower)

# What is the roof's position in the antenna's coordinate frame?
# This returns the roof's coordinates relative to local_ant's origin and rotation.
rel_pos = local_ant.relative_position(roof)
```
## Geospatial Integration
```hics``` includes powerful utilities for mapping coordinate systems to real-world paths using Digital Elevation Models (DEM) and Land Cover data.
### 1. Creating a CS from Lat/Lon/Alt
You can initialize a coordinate system directly from geographic coordinates. If ```hagl=True```, the altitude is treated as "Height Above Ground Level" and added to the terrain elevation at that point.

```python
# Initialize an HCS at a specific location in Boulder, CO
# 20 meters above the ground (HAGL)
cs_boulder = HCS.from_crs(
    (40.015 * ureg.degree, -105.270556 * ureg.degree, 20 * ureg.m), 
    hagl=True
)

# This resolves to a global ECEF position
print(cs_boulder.global_position)
```
### 2. Racetrack and Path Interpolation
You can generate a coordinate system that follows a trajectory (like a vehicle or aircraft) defined by latitude/longitude points.

```python
from hics.geo.scenarios import interp_llpnts2hcs, racetrack_latlon

# Generate a 10km altitude racetrack path
center = (40.037578, -105.228117) * ureg.degree
racetrack_pnts = racetrack_latlon(center[0], center[1], length=8.48*ureg.km, width=1.5*ureg.km)

racetrack = interp_llpnts2hcs(
    racetrack_pnts, 
    altitude=10*ureg.km, 
    speed=100*ureg.m/ureg.s, 
    bank_turns=True
)
```

### 3. Height Above Ground Level (HAGL)
If ```hagl=True``` is specified, hics uses the underlying DEM data to "pin" the coordinate system to the terrain height.

```python
# A car driving 2 meters above the ground following a path
drivecs = interp_llpnts2hcs(
    ll_path_points, 
    hagl=2*ureg.m, 
    speed=30*ureg.mph, 
    hagl=True
)
```

## Advanced Usage: Xarray and Lazy Loading
```hics``` leverages ```xarray``` and ```dask``` for performance.

* Lazy Merging: Large terrain datasets are merged lazily via VRT (Virtual Raster) files to save memory.
* Time-Series Support: Coordinate systems can be defined over time-indexed DataArrays, allowing for easy interpolation of moving objects.

## References

- [Cookiecutter Python Project](https://github.com/wyattferguson/pattern) - A modern cookiecutter template for your next Python project.
