Metadata-Version: 2.4
Name: gemf_map
Version: 1.0.3
Summary: Python library for reading and writing GEMF map tile files.
Project-URL: Homepage, https://github.com/ColinMoldenhauer/GEMF
Project-URL: Documentation, https://gemf.readthedocs.io
Project-URL: Repository, https://github.com/ColinMoldenhauer/GEMF
Project-URL: Bug Tracker, https://github.com/ColinMoldenhauer/GEMF/issues
Author-email: Colin Moldenhauer <colin.moldenhauer@posteo.de>
License-Expression: GPL-3.0-only
License-File: LICENSE
Keywords: gemf,locus,map,mobile map,tiles
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.9
Requires-Dist: mercantile
Requires-Dist: numpy
Provides-Extra: all
Requires-Dist: folium; extra == 'all'
Requires-Dist: matplotlib; extra == 'all'
Requires-Dist: mkdocs-material; extra == 'all'
Requires-Dist: mkdocstrings[python]; extra == 'all'
Requires-Dist: pillow; extra == 'all'
Requires-Dist: pytest-cov; extra == 'all'
Requires-Dist: pytest>=8.0; extra == 'all'
Requires-Dist: shapely; extra == 'all'
Provides-Extra: docs
Requires-Dist: mkdocs-material; extra == 'docs'
Requires-Dist: mkdocstrings[python]; extra == 'docs'
Provides-Extra: geometry
Requires-Dist: shapely; extra == 'geometry'
Provides-Extra: plot
Requires-Dist: folium; extra == 'plot'
Requires-Dist: matplotlib; extra == 'plot'
Requires-Dist: pillow; extra == 'plot'
Provides-Extra: test
Requires-Dist: pytest-cov; extra == 'test'
Requires-Dist: pytest>=8.0; extra == 'test'
Description-Content-Type: text/markdown

# GEMF

Python package for the GEMF map format. From the format [specification](https://www.cgtk.co.uk/gemf):

> This tile store format is intended to provide a static (i.e. cannot be updated without regenerating from scratch) file containing a large number of tiles, stored
> in a manner that makes efficient use of SD cards and with which it is easy to access individual tiles very quickly. It is intended to overcome the existing issues
> with the way tiles are stored in most existing Android map applications as these are not very scalable.

`.gemf` files may be used in mobile mapping applications like [Locus](https://www.locusmap.app/)

# Installation
```cmd
pip install gemf-map
```


# Features
**Core features** are...
- reading `.gemf` map files via the `GEMF.from_file()` classmethod
- creating a GEMF object from PNG or JPG tiles via the `GEMF.from_tiles()` classmethod
- writing a newly created GEMF object to file via the `write()` method

**Further features** are...
- spatially subset (crop) a .gemf file
- extracting image tiles from binary `.gemf` files via the `save_tiles()` method
- adding tiles to an existing `.gemf` file (TODO)
- combining `GEMF` objects via `stack()`/`+`, `merge()`/`|`, `intersect()`/`&` and `difference()`/`-`

**Visualization features**:
- show the tiles of a .gemf file on a `folium` map
- show tile boundaries on a map

<!-- TODO: explain lazy laoding -->

# Usage

## Core
```python
from gemf import GEMF

# load an existing .gemf file
my_gemf = GEMF.from_file("MY_GEMF.gemf")

# extract the tiles
my_gemf.save_tiles("PATH/TO/TILEDIR")

# create a GEMF object from tiles on disk
new_gemf = GEMF.from_tiles("PATH/TO/TILEDIR")

# write GEMF object to .gemf file
new_gemf.write("PATH/TO/GEMF_FILE.gemf")
```

## Manipulation
```python
# crop to bounding box (all zoom levels will be cropped accordingly)
gemf_crop = my_gemf.crop(7, 60, 62, 36, 38)
```

## Combining GEMF objects
```python
# stack: add all sources of gemf2 onto gemf1 as new sources
combined = gemf1 + gemf2

# merge: union of tiles for sources present in both (matched by name)
# on conflicting tiles, "|" keeps gemf1's tile by default
merged = gemf1 | gemf2

# intersect: keep only tiles present in both, for shared sources
shared = gemf1 & gemf2

# difference: keep gemf1's tiles that are not present in gemf2's matching source
diff = gemf1 - gemf2
```


## Visualization
<!-- TODO: limitations for large gemf files -->
```python
from gemf.plot import GEMFPlot

# visualize tiles and tile boundaries
gemf_map = GEMFPlot(my_gemf)

# visualize tiles without boundaries
tile_map = GEMFPlot(my_gemf, show_tile_boundaries=False)

# visualize only boundaries (to avoid loading tile contents from disk)
boundary_map = GEMFPlot(my_gemf, show_tiles=False)
```

## Other
```python
# save the embedded tiles to image files
gemf_map.save_tiles("path/to/output/dir")
```