Metadata-Version: 2.4
Name: geokernel
Version: 1.5.36
Summary: Python bindings and samples for the GeoKernel GIS SDK.
Author-email: GeoKernel <sales@geokernel.io>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://geokernel.io
Project-URL: Documentation, https://geokernel.io/documentation
Keywords: gis,sdk,mapping,geokernel,shapefile
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: PySide6==6.11.0
Provides-Extra: formats
Requires-Dist: geokernel-formats==1.5.36; extra == "formats"
Provides-Extra: all
Requires-Dist: geokernel-formats==1.5.36; extra == "all"

# GeoKernel Python

Official Python package for the GeoKernel GIS SDK.

The package name is `geokernel`:

```powershell
pip install geokernel
```

Install extended GDAL formats, DuckDB and GeoParquet support when needed:

```powershell
pip install "geokernel[formats]"
```

`all` is the forward-compatible option for installing every optional GeoKernel runtime:

```powershell
pip install "geokernel[all]"
```

## Usage

```python
import sys

from PySide6.QtWidgets import QApplication, QMainWindow

from geokernel import Viewer, ViewerTool

app = QApplication(sys.argv)

window = QMainWindow()
window.setWindowTitle("HelloMap")
window.resize(1200, 800)

viewer = Viewer(width=1200, height=800)
viewer.set_tool(ViewerTool.PAN)
viewer.add_layer(r"D:\data\world_4326.shp")

window.setCentralWidget(viewer.qt_widget())
window.closeEvent = lambda event: (viewer.close(), event.accept())

window.show()
app.processEvents()
viewer.show()
viewer.resize(window.centralWidget().width(), window.centralWidget().height())
viewer.full_extent()
viewer.refresh_layers()
app.exec()
```

## Globe

The Globe API exposes all 56 native C ABI functions through `Globe`, typed request
and result dataclasses, and the PySide6 `GlobeWidget`. The matching **new native
runtime is required**: published SDK 1.5.34 predates this C API. These additions have
not yet been published to PyPI.

```python
from PySide6.QtWidgets import QApplication, QMainWindow
from geokernel import GlobeOptions, GlobeCamera
from geokernel.globe_qt import GlobeWidget

app = QApplication([])  # Create before the first Globe when using PySide6.
window = QMainWindow()
widget = GlobeWidget(
    options=GlobeOptions(network_enabled=True, atmosphere_enabled=True),
    camera=GlobeCamera(2.1744, 41.4036, 40, 2000, 50, 0),
)
window.setCentralWidget(widget)
window.resize(1100, 760)
window.show()
app.exec()
```

`widget.globe` provides camera/options, basemap discovery, layers, models, picking,
measurement and terrain analysis. The `ready`, `event_received` and `error` signals
report initialization, native notifications and pump failures. The widget pumps
native work on its Qt timer. `GlobeWidget` is imported separately so importing
`geokernel` does not load PySide6 or create a Qt application.

All calls, including `close()`, belong to the main thread. Use `Globe` as a context
manager when managing a native parent or standalone window yourself; call
`process_events()` to advance work and receive copied events. A native parent must
outlive its Globe. There is no GC-thread finalizer. `GlobeWidget` releases its host
on normal close, `deleteLater`, ancestor deletion, reparenting and application quit.
For low-level `shiboken6.delete`, call `close_globe()` before deleting the parent.
Reopening a closed widget creates a fresh session with its original settings.

```python
from geokernel import GlobeVectorRequest, GlobeVectorStyle

job = widget.globe.load_vector(GlobeVectorRequest(
    "buildings", building_path,
    style=GlobeVectorStyle(category_field="type"),
))
# In event_received, on jobFinished, inspect get_job_state(job).
# completed/failed/cancelled records remain until forget_job(job).
```

`wait_job(job, timeout=90)` is available for blocking workflows and pumps Qt while
waiting. Failed jobs raise `GlobeJobError`; cancelled jobs raise `CancelledError`.
A timeout requests cancellation and raises `TimeoutError`; poll until terminal
before forgetting that record. Failed/cancelled replacements keep the committed
layer. Job completion means CPU publication; GPU/network activity may still be
pending. Disposal cancels and joins work and can wait for provider I/O.

Use `dataclasses.replace` to update immutable options/camera values. Network access
is fixed at creation. Defaults leave basemap, terrain, atmosphere and lighting off;
choose a basemap from `get_basemaps()` and enable desired options explicitly.
Screen queries and widget dimensions use logical Qt pixels. IDs/counters preserve
all 64 bits. Dynamic layer settings/statistics and feature attributes are dictionaries.
Native errors retain their numeric `GlobeError.status` and UTF-8 message.

Terrain results use resident, unexaggerated DEM data. Check `available`, `status`
and `stale`: missing elevations remain `None`, and changing terrain invalidates
results. Visibility is terrain-only; it excludes buildings, vegetation and
refraction. Measurement distance/area use the native reference sphere. Viewshed
cells are typed `GlobeVisibilityCell` values in west-east, north-south row order.

### Globe verification

Run `python -m unittest discover -s tests -p "test_globe_contract.py" -v` for
ABI/codec checks without native libraries. For real integration tests set
`GEOKERNEL_GLOBE_INTEGRATION=1`, `GEOKERNEL_BIN` to the matching SDK bin directory,
and `GEOKERNEL_TEST_BUILDINGS`, `GEOKERNEL_TEST_MODEL`, `GEOKERNEL_TEST_RASTER`,
`GEOKERNEL_TEST_DEM` to the real Sagrada Familia files. On Windows, additional
test-only DLL directories can be listed in `GEOKERNEL_TEST_DLL_DIRS` using `;`.
On Linux, configure `LD_LIBRARY_PATH` for the SDK/Qt dependencies and use X11/xcb
(or Xvfb); foreign embedding on Wayland is unsupported by the native API.

Run `python -m unittest discover -s tests -p "test_globe_*.py" -v`. The Qt lifecycle
test runs in an isolated process. No example smoke-test or command-line modes are
introduced. Integration tests require a working Vulkan implementation.

## Development

```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e .
```

## Runtime Binaries

The PyPI package includes the universal, license-neutral GeoKernel runtime under:

```text
src/geokernel/bin/
```

The runtime should include `GeoKernel.Viewer.dll`, GeoKernel DLLs, Qt DLLs, Skia/GDAL/PROJ dependencies, Qt plugins, GDAL plugins, `gdal-data`, and `proj-data`.

For development builds, copy the current local SDK runtime into the package with:

```powershell
python tools\sync_runtime_binaries.py --source "D:\projects\GeoKernel\outputs\build\Release" --clean
```

If the package does not contain binaries yet, the wrapper also checks:

```text
GEOKERNEL_BIN
D:\projects\GeoKernel\outputs\build\Release
```

## Package Layout

```text
src/
  geokernel/
    __init__.py
    geometry.py
    layer.py
    dll.py
    viewer.py
    bin/
tools/
  sync_runtime_binaries.py
```
