smoothify 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smoothify-0.2.3/.github/workflows/ci.yml +40 -0
- smoothify-0.2.3/.github/workflows/publish.yml +75 -0
- smoothify-0.2.3/.gitignore +186 -0
- smoothify-0.2.3/.pre-commit-config.yaml +21 -0
- smoothify-0.2.3/.python-version +1 -0
- smoothify-0.2.3/.vscode/settings.json +42 -0
- smoothify-0.2.3/CHANGELOG.md +40 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/PKG-INFO +61 -7
- smoothify-0.2.1/smoothify.egg-info/PKG-INFO → smoothify-0.2.3/README.md +45 -24
- smoothify-0.2.3/RELEASING.md +50 -0
- smoothify-0.2.3/examples/Water.gpkg +0 -0
- smoothify-0.2.3/examples/Water_Smoothed.gpkg +0 -0
- smoothify-0.2.3/examples/real_world_water_example.ipynb +773 -0
- smoothify-0.2.3/examples/smoothify_vs_shapely_comparison.ipynb +683 -0
- smoothify-0.2.3/examples/usage_examples.ipynb +830 -0
- smoothify-0.2.3/images/example_1_polygon.png +0 -0
- smoothify-0.2.3/images/example_2_linestring.png +0 -0
- smoothify-0.2.3/images/example_3_iterations.png +0 -0
- smoothify-0.2.3/images/example_4_merging.png +0 -0
- smoothify-0.2.3/images/generate_example_images.ipynb +366 -0
- smoothify-0.2.3/images/generate_readme_image.ipynb +220 -0
- smoothify-0.2.3/images/smoothify_hero.png +0 -0
- smoothify-0.2.3/images/smoothify_logo.png +0 -0
- smoothify-0.2.3/pyproject.toml +80 -0
- smoothify-0.2.3/pytest.ini +16 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify/__init__.py +7 -1
- smoothify-0.2.3/smoothify/_version.py +24 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify/coordinator.py +23 -7
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify/geometry_ops.py +109 -17
- smoothify-0.2.3/smoothify/py.typed +0 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify/smoothify_core.py +32 -12
- smoothify-0.2.1/README.md → smoothify-0.2.3/smoothify.egg-info/PKG-INFO +78 -6
- smoothify-0.2.3/smoothify.egg-info/SOURCES.txt +51 -0
- smoothify-0.2.3/tests/README.md +26 -0
- smoothify-0.2.3/tests/__init__.py +1 -0
- smoothify-0.2.3/tests/conftest.py +42 -0
- smoothify-0.2.3/tests/test_all_geometry_types.py +988 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_area_tolerance.py +0 -1
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_auto_segment_length.py +122 -55
- smoothify-0.2.3/tests/test_data/naip_owm_water_bodies.geojson +121 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_edge_cases_coverage.py +12 -5
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_geometry_types.py +38 -24
- smoothify-0.2.3/tests/test_invalid_polygon.py +174 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_real_world_data.py +5 -1
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_smoothify_api.py +40 -33
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_smoothify_core.py +35 -4
- smoothify-0.2.3/tests/visual_tests.ipynb +1231 -0
- smoothify-0.2.1/pyproject.toml +0 -43
- smoothify-0.2.1/smoothify/__version__.py +0 -1
- smoothify-0.2.1/smoothify.egg-info/SOURCES.txt +0 -21
- {smoothify-0.2.1 → smoothify-0.2.3}/LICENSE +0 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/setup.cfg +0 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify.egg-info/dependency_links.txt +0 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify.egg-info/requires.txt +0 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/smoothify.egg-info/top_level.txt +0 -0
- {smoothify-0.2.1 → smoothify-0.2.3}/tests/test_chaikin.py +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
check:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
strategy:
|
|
11
|
+
fail-fast: false
|
|
12
|
+
matrix:
|
|
13
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v6
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0 # full history so setuptools-scm can read tags
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-python@v6
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- uses: astral-sh/setup-uv@v8.0.0
|
|
24
|
+
with:
|
|
25
|
+
cache-suffix: ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- run: uv sync --all-extras --dev
|
|
28
|
+
|
|
29
|
+
- name: Lint
|
|
30
|
+
run: uv run ruff check .
|
|
31
|
+
|
|
32
|
+
- name: Type check
|
|
33
|
+
run: uv run mypy smoothify/
|
|
34
|
+
|
|
35
|
+
- name: Test
|
|
36
|
+
run: uv run pytest tests/ -x -q
|
|
37
|
+
|
|
38
|
+
- name: Notebook smoke test
|
|
39
|
+
if: matrix.python-version == '3.11'
|
|
40
|
+
run: uv run pytest --nbmake examples/*.ipynb -q
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# Triggered by pushing a tag that looks like a version, e.g. `v1.0.0`.
|
|
4
|
+
# The version comes from the git tag itself (via setuptools-scm) — no file to bump.
|
|
5
|
+
# Publishing uses PyPI trusted publishing (OIDC) — no API tokens, no secrets.
|
|
6
|
+
# To enable: at https://pypi.org/manage/project/smoothify/settings/publishing/
|
|
7
|
+
# add a publisher with:
|
|
8
|
+
# Owner DPIRD-DMA
|
|
9
|
+
# Repository name Smoothify
|
|
10
|
+
# Workflow name publish.yml
|
|
11
|
+
# Environment pypi
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
tags:
|
|
16
|
+
- "v[0-9]+.[0-9]+.[0-9]+*"
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
name: Build distribution
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v6
|
|
24
|
+
with:
|
|
25
|
+
fetch-depth: 0 # full history so setuptools-scm can read tags
|
|
26
|
+
|
|
27
|
+
- uses: actions/setup-python@v6
|
|
28
|
+
with:
|
|
29
|
+
python-version: "3.11"
|
|
30
|
+
|
|
31
|
+
- uses: astral-sh/setup-uv@v8.0.0
|
|
32
|
+
|
|
33
|
+
- name: Build sdist + wheel
|
|
34
|
+
run: uv build
|
|
35
|
+
|
|
36
|
+
- uses: actions/upload-artifact@v4
|
|
37
|
+
with:
|
|
38
|
+
name: python-package-distributions
|
|
39
|
+
path: dist/
|
|
40
|
+
|
|
41
|
+
publish-to-pypi:
|
|
42
|
+
name: Publish to PyPI
|
|
43
|
+
needs: build
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
environment:
|
|
46
|
+
name: pypi
|
|
47
|
+
url: https://pypi.org/p/smoothify
|
|
48
|
+
permissions:
|
|
49
|
+
id-token: write # required for trusted publishing
|
|
50
|
+
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/download-artifact@v4
|
|
53
|
+
with:
|
|
54
|
+
name: python-package-distributions
|
|
55
|
+
path: dist/
|
|
56
|
+
|
|
57
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
58
|
+
|
|
59
|
+
github-release:
|
|
60
|
+
name: Create GitHub Release
|
|
61
|
+
needs: publish-to-pypi
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
permissions:
|
|
64
|
+
contents: write # required to create releases
|
|
65
|
+
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/download-artifact@v4
|
|
68
|
+
with:
|
|
69
|
+
name: python-package-distributions
|
|
70
|
+
path: dist/
|
|
71
|
+
|
|
72
|
+
- uses: softprops/action-gh-release@v2
|
|
73
|
+
with:
|
|
74
|
+
files: dist/*
|
|
75
|
+
generate_release_notes: true
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# Ruff stuff:
|
|
171
|
+
.ruff_cache/
|
|
172
|
+
|
|
173
|
+
# PyPI configuration file
|
|
174
|
+
.pypirc
|
|
175
|
+
private test data/*
|
|
176
|
+
*.gpkg-shm
|
|
177
|
+
*.gpkg-wal
|
|
178
|
+
*.DS_Store
|
|
179
|
+
test data/output/*
|
|
180
|
+
examples/Water_Smoothed.gpkg
|
|
181
|
+
|
|
182
|
+
# setuptools-scm generated version file
|
|
183
|
+
smoothify/_version.py
|
|
184
|
+
|
|
185
|
+
# uv lockfile (not tracked — library, resolve fresh)
|
|
186
|
+
uv.lock
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.15.8
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff-check
|
|
6
|
+
- id: ruff-format
|
|
7
|
+
- repo: local
|
|
8
|
+
hooks:
|
|
9
|
+
- id: mypy
|
|
10
|
+
name: mypy
|
|
11
|
+
entry: uv run mypy smoothify/
|
|
12
|
+
language: system
|
|
13
|
+
pass_filenames: false
|
|
14
|
+
always_run: true
|
|
15
|
+
- id: pytest
|
|
16
|
+
name: pytest
|
|
17
|
+
entry: uv run pytest tests/ -x -q -m "not slow"
|
|
18
|
+
language: system
|
|
19
|
+
pass_filenames: false
|
|
20
|
+
always_run: true
|
|
21
|
+
stages: [pre-push]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cSpell.words": [
|
|
3
|
+
"brentq",
|
|
4
|
+
"capstyle",
|
|
5
|
+
"chaikin",
|
|
6
|
+
"darkgreen",
|
|
7
|
+
"edgecolor",
|
|
8
|
+
"facecolor",
|
|
9
|
+
"figsize",
|
|
10
|
+
"fontsize",
|
|
11
|
+
"fontweight",
|
|
12
|
+
"geodataframe",
|
|
13
|
+
"geopandas",
|
|
14
|
+
"gpkg",
|
|
15
|
+
"ipykernel",
|
|
16
|
+
"joblib",
|
|
17
|
+
"lightgreen",
|
|
18
|
+
"linalg",
|
|
19
|
+
"linearing",
|
|
20
|
+
"linestrings",
|
|
21
|
+
"matplotlib",
|
|
22
|
+
"multipolygons",
|
|
23
|
+
"ndarray",
|
|
24
|
+
"numpy",
|
|
25
|
+
"polygonized",
|
|
26
|
+
"pytest",
|
|
27
|
+
"scipy",
|
|
28
|
+
"segmentize",
|
|
29
|
+
"setuptools",
|
|
30
|
+
"shapley",
|
|
31
|
+
"smoothify",
|
|
32
|
+
"soomthify",
|
|
33
|
+
"suptitle",
|
|
34
|
+
"xlabel",
|
|
35
|
+
"xlim",
|
|
36
|
+
"xticks",
|
|
37
|
+
"xtol",
|
|
38
|
+
"ylabel",
|
|
39
|
+
"ylim",
|
|
40
|
+
"yticks"
|
|
41
|
+
],
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.2.3] - 2026-06-02
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- The package now ships inline type hints and a `py.typed` marker, so type checkers (mypy, Pyright/Pylance) pick up `smoothify()`'s signatures and overloads in downstream code.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Invalid geometries (e.g. self-intersecting polygons) are now returned unchanged with a warning instead of crashing with a cryptic error or silently collapsing to an empty geometry. Behaviour is consistent across single geometries, lists/collections, and GeoDataFrames (and regardless of `merge_collection`). Repair them with shapely's `make_valid()` first if you want them smoothed.
|
|
14
|
+
|
|
15
|
+
## [0.2.2] - 2026-03-24
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Fixed LineString smoothing: self-intersecting lines are no longer run through the polygon-only `make_valid`/`unary_union` step, which could split them into a MultiLineString at crossing points
|
|
19
|
+
- Preserve coordinate dimensionality during Chaikin corner cutting instead of forcing 2D output, so smoothed geometries keep their original dimensions
|
|
20
|
+
|
|
21
|
+
## [0.2.1] - 2026-02-25
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- Fixed `TopologyException` crash on thin/elongated polygons by validating smoothed variants before union
|
|
25
|
+
- Fixed crash when hole subtraction splits a polygon into a MultiPolygon (e.g. tiny holes relative to segment length)
|
|
26
|
+
|
|
27
|
+
## [0.2.0] - 2026-02-25
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- `smooth_iterations=0` now returns the original input unchanged instead of running the geometry through segmentize/simplify pipeline without smoothing
|
|
31
|
+
|
|
32
|
+
## [0.1.0] - 2025-11-25
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- Initial public release
|
|
36
|
+
- Core smoothing functionality using Chaikin's corner-cutting algorithm
|
|
37
|
+
- Support for all Shapely geometry types (Polygon, LineString, MultiPolygon, etc.)
|
|
38
|
+
- Automatic segment length detection
|
|
39
|
+
- Parallel processing support
|
|
40
|
+
- Area preservation for polygons
|
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: smoothify
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Transform pixelated geometries from raster data into smooth natural looking features
|
|
5
5
|
Author-email: Nick Wright <nicholas.wright@dpird.wa.gov.au>
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/DPIRD-DMA/Smoothify
|
|
8
|
+
Project-URL: Repository, https://github.com/DPIRD-DMA/Smoothify
|
|
9
|
+
Project-URL: Issues, https://github.com/DPIRD-DMA/Smoothify/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/DPIRD-DMA/Smoothify/blob/main/CHANGELOG.md
|
|
8
11
|
Keywords: geometry,smoothing,smooth,GIS,raster,vector,chaikin,shapely,geopandas
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: GIS
|
|
23
|
+
Classifier: Topic :: Scientific/Engineering :: Image Processing
|
|
9
24
|
Requires-Python: >=3.10
|
|
10
25
|
Description-Content-Type: text/markdown
|
|
11
26
|
License-File: LICENSE
|
|
@@ -16,15 +31,18 @@ Requires-Dist: scipy>=1.11.0
|
|
|
16
31
|
Requires-Dist: shapely>=2.0.2
|
|
17
32
|
Dynamic: license-file
|
|
18
33
|
|
|
19
|
-
<p align="
|
|
34
|
+
<p align="center">
|
|
20
35
|
<img src="https://raw.githubusercontent.com/DPIRD-DMA/Smoothify/main/images/smoothify_logo.png" alt="Smoothify Text" width="600">
|
|
21
36
|
</p>
|
|
22
37
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
<p align="center">
|
|
39
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue" alt="Python Version"></a>
|
|
40
|
+
<a href="https://github.com/DPIRD-DMA/Smoothify/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License"></a>
|
|
41
|
+
<a href="https://pypi.org/project/smoothify/"><img src="https://img.shields.io/pypi/v/smoothify.svg" alt="PyPI version"></a>
|
|
42
|
+
<a href="https://pepy.tech/projects/smoothify"><img src="https://static.pepy.tech/badge/smoothify" alt="PyPI downloads"></a>
|
|
43
|
+
<a href="https://anaconda.org/conda-forge/smoothify"><img src="https://img.shields.io/conda/vn/conda-forge/smoothify.svg" alt="Conda version"></a>
|
|
44
|
+
<a href="https://github.com/DPIRD-DMA/Smoothify/tree/main/examples"><img src="https://img.shields.io/badge/Tutorials-Learn-brightgreen" alt="Tutorials"></a>
|
|
45
|
+
</p>
|
|
28
46
|
|
|
29
47
|
📋 [View Changelog](https://github.com/DPIRD-DMA/Smoothify/blob/main/CHANGELOG.md)
|
|
30
48
|
|
|
@@ -220,6 +238,22 @@ Smoothify uses an advanced multi-step smoothing pipeline:
|
|
|
220
238
|
6. Applies final smoothing pass
|
|
221
239
|
7. Optionally restores original area via buffering (for Polygons)
|
|
222
240
|
|
|
241
|
+
## Invalid Geometries
|
|
242
|
+
|
|
243
|
+
Smoothify does not repair invalid input. If it encounters an invalid geometry (e.g. a self-intersecting polygon), it returns that geometry **unchanged** and emits a warning, instead of crashing or silently producing an empty geometry. This is consistent whether you pass a single geometry, a list/collection, or a GeoDataFrame.
|
|
244
|
+
|
|
245
|
+
If you want invalid geometries smoothed, repair them first with shapely's `make_valid()`:
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
# GeoDataFrame
|
|
249
|
+
gdf.geometry = gdf.geometry.make_valid()
|
|
250
|
+
smoothed_gdf = smoothify(gdf, segment_length=10.0)
|
|
251
|
+
|
|
252
|
+
# Single geometry
|
|
253
|
+
from shapely import make_valid
|
|
254
|
+
smoothed = smoothify(make_valid(polygon), segment_length=1.0)
|
|
255
|
+
```
|
|
256
|
+
|
|
223
257
|
## Performance Considerations
|
|
224
258
|
|
|
225
259
|
- **Parallel Processing**: For large GeoDataFrames or collections, use `num_cores` = 0 to enable parallel processing
|
|
@@ -227,6 +261,26 @@ Smoothify uses an advanced multi-step smoothing pipeline:
|
|
|
227
261
|
- **Memory Usage**: Scales with geometry complexity. The algorithm creates multiple variants during smoothing
|
|
228
262
|
- **Optimal segment_length**: Should match the original raster cell size (pixel size) or be slightly larger for best results
|
|
229
263
|
|
|
264
|
+
## Running the Tests
|
|
265
|
+
|
|
266
|
+
Smoothify uses [pytest](https://pytest.org/). After cloning the repository, install the development dependencies and run the suite with [uv](https://docs.astral.sh/uv/):
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
# Install dependencies (including the dev group)
|
|
270
|
+
uv sync
|
|
271
|
+
|
|
272
|
+
# Run all tests
|
|
273
|
+
uv run pytest tests/
|
|
274
|
+
|
|
275
|
+
# Run with coverage
|
|
276
|
+
uv run pytest tests/ --cov=smoothify --cov-report=html
|
|
277
|
+
|
|
278
|
+
# Run a single test
|
|
279
|
+
uv run pytest tests/test_chaikin.py::TestChaikinCornerCutting::test_simple_square_polygon
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
If you prefer not to use uv, install the dev dependencies into your environment and run `pytest tests/` directly.
|
|
283
|
+
|
|
230
284
|
## Contributing
|
|
231
285
|
|
|
232
286
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -1,30 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
Name: smoothify
|
|
3
|
-
Version: 0.2.1
|
|
4
|
-
Summary: Transform pixelated geometries from raster data into smooth natural looking features
|
|
5
|
-
Author-email: Nick Wright <nicholas.wright@dpird.wa.gov.au>
|
|
6
|
-
License-Expression: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/DPIRD-DMA/Smoothify
|
|
8
|
-
Keywords: geometry,smoothing,smooth,GIS,raster,vector,chaikin,shapely,geopandas
|
|
9
|
-
Requires-Python: >=3.10
|
|
10
|
-
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Requires-Dist: geopandas>=1.0.0
|
|
13
|
-
Requires-Dist: joblib>=1.4.0
|
|
14
|
-
Requires-Dist: numpy>=1.27.0
|
|
15
|
-
Requires-Dist: scipy>=1.11.0
|
|
16
|
-
Requires-Dist: shapely>=2.0.2
|
|
17
|
-
Dynamic: license-file
|
|
18
|
-
|
|
19
|
-
<p align="left">
|
|
1
|
+
<p align="center">
|
|
20
2
|
<img src="https://raw.githubusercontent.com/DPIRD-DMA/Smoothify/main/images/smoothify_logo.png" alt="Smoothify Text" width="600">
|
|
21
3
|
</p>
|
|
22
4
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10%2B-blue" alt="Python Version"></a>
|
|
7
|
+
<a href="https://github.com/DPIRD-DMA/Smoothify/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License"></a>
|
|
8
|
+
<a href="https://pypi.org/project/smoothify/"><img src="https://img.shields.io/pypi/v/smoothify.svg" alt="PyPI version"></a>
|
|
9
|
+
<a href="https://pepy.tech/projects/smoothify"><img src="https://static.pepy.tech/badge/smoothify" alt="PyPI downloads"></a>
|
|
10
|
+
<a href="https://anaconda.org/conda-forge/smoothify"><img src="https://img.shields.io/conda/vn/conda-forge/smoothify.svg" alt="Conda version"></a>
|
|
11
|
+
<a href="https://github.com/DPIRD-DMA/Smoothify/tree/main/examples"><img src="https://img.shields.io/badge/Tutorials-Learn-brightgreen" alt="Tutorials"></a>
|
|
12
|
+
</p>
|
|
28
13
|
|
|
29
14
|
📋 [View Changelog](https://github.com/DPIRD-DMA/Smoothify/blob/main/CHANGELOG.md)
|
|
30
15
|
|
|
@@ -220,6 +205,22 @@ Smoothify uses an advanced multi-step smoothing pipeline:
|
|
|
220
205
|
6. Applies final smoothing pass
|
|
221
206
|
7. Optionally restores original area via buffering (for Polygons)
|
|
222
207
|
|
|
208
|
+
## Invalid Geometries
|
|
209
|
+
|
|
210
|
+
Smoothify does not repair invalid input. If it encounters an invalid geometry (e.g. a self-intersecting polygon), it returns that geometry **unchanged** and emits a warning, instead of crashing or silently producing an empty geometry. This is consistent whether you pass a single geometry, a list/collection, or a GeoDataFrame.
|
|
211
|
+
|
|
212
|
+
If you want invalid geometries smoothed, repair them first with shapely's `make_valid()`:
|
|
213
|
+
|
|
214
|
+
```python
|
|
215
|
+
# GeoDataFrame
|
|
216
|
+
gdf.geometry = gdf.geometry.make_valid()
|
|
217
|
+
smoothed_gdf = smoothify(gdf, segment_length=10.0)
|
|
218
|
+
|
|
219
|
+
# Single geometry
|
|
220
|
+
from shapely import make_valid
|
|
221
|
+
smoothed = smoothify(make_valid(polygon), segment_length=1.0)
|
|
222
|
+
```
|
|
223
|
+
|
|
223
224
|
## Performance Considerations
|
|
224
225
|
|
|
225
226
|
- **Parallel Processing**: For large GeoDataFrames or collections, use `num_cores` = 0 to enable parallel processing
|
|
@@ -227,6 +228,26 @@ Smoothify uses an advanced multi-step smoothing pipeline:
|
|
|
227
228
|
- **Memory Usage**: Scales with geometry complexity. The algorithm creates multiple variants during smoothing
|
|
228
229
|
- **Optimal segment_length**: Should match the original raster cell size (pixel size) or be slightly larger for best results
|
|
229
230
|
|
|
231
|
+
## Running the Tests
|
|
232
|
+
|
|
233
|
+
Smoothify uses [pytest](https://pytest.org/). After cloning the repository, install the development dependencies and run the suite with [uv](https://docs.astral.sh/uv/):
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Install dependencies (including the dev group)
|
|
237
|
+
uv sync
|
|
238
|
+
|
|
239
|
+
# Run all tests
|
|
240
|
+
uv run pytest tests/
|
|
241
|
+
|
|
242
|
+
# Run with coverage
|
|
243
|
+
uv run pytest tests/ --cov=smoothify --cov-report=html
|
|
244
|
+
|
|
245
|
+
# Run a single test
|
|
246
|
+
uv run pytest tests/test_chaikin.py::TestChaikinCornerCutting::test_simple_square_polygon
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
If you prefer not to use uv, install the dev dependencies into your environment and run `pytest tests/` directly.
|
|
250
|
+
|
|
230
251
|
## Contributing
|
|
231
252
|
|
|
232
253
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
Smoothify is published to PyPI by tag-push. The version comes from the git tag
|
|
4
|
+
itself (via `setuptools-scm`) — there is **no version file to bump**.
|
|
5
|
+
|
|
6
|
+
## Versioning
|
|
7
|
+
|
|
8
|
+
Follow [SemVer](https://semver.org/):
|
|
9
|
+
|
|
10
|
+
- **Major** (`v1.0.0` → `v2.0.0`): incompatible API change — removed args,
|
|
11
|
+
changed signatures, behavioural changes that break existing callers.
|
|
12
|
+
- **Minor** (`v1.0.0` → `v1.1.0`): backwards-compatible feature added.
|
|
13
|
+
- **Patch** (`v1.0.0` → `v1.0.1`): backwards-compatible bug fix.
|
|
14
|
+
|
|
15
|
+
Any commit that lands on `main` between releases shows up at install time as
|
|
16
|
+
a development version like `0.2.4.dev3+g1234abc`.
|
|
17
|
+
|
|
18
|
+
## Release checklist
|
|
19
|
+
|
|
20
|
+
1. **Sync `main`** locally:
|
|
21
|
+
```bash
|
|
22
|
+
git checkout main
|
|
23
|
+
git pull
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
2. **Update [`CHANGELOG.md`](CHANGELOG.md)**: move the `## [Unreleased]` entries to
|
|
27
|
+
`## [<version>] - <YYYY-MM-DD>` and add a fresh empty `[Unreleased]` block at the top.
|
|
28
|
+
Commit on `main`:
|
|
29
|
+
```bash
|
|
30
|
+
git commit -am "Prepare <version> changelog"
|
|
31
|
+
git push
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
3. **Tag and push**:
|
|
35
|
+
```bash
|
|
36
|
+
git tag v<version> # e.g. v0.3.0
|
|
37
|
+
git push origin v<version>
|
|
38
|
+
```
|
|
39
|
+
The tag must match `v<major>.<minor>.<patch>` (pre-release suffixes like
|
|
40
|
+
`v0.3.0rc1` also match the publish workflow's filter).
|
|
41
|
+
|
|
42
|
+
4. **Approve the deploy**: the [`Publish to PyPI`](.github/workflows/publish.yml)
|
|
43
|
+
workflow runs `uv build` and uploads to PyPI via OIDC trusted publishing.
|
|
44
|
+
The `pypi` GitHub environment is gated by a required reviewer — go to
|
|
45
|
+
**Actions → Publish to PyPI → Review deployments → Approve** to release.
|
|
46
|
+
|
|
47
|
+
5. **Verify**:
|
|
48
|
+
- PyPI page: <https://pypi.org/project/smoothify/>
|
|
49
|
+
- GitHub Releases: <https://github.com/DPIRD-DMA/Smoothify/releases>
|
|
50
|
+
(auto-generated release notes + wheel/sdist attached).
|
|
Binary file
|
|
Binary file
|