diff --git a/.bumpversion.toml b/.bumpversion.toml index 38351bb..a0385e1 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -1,5 +1,5 @@ [tool.bumpversion] -current_version = "1.7.0" +current_version = "1.8.0" parse = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)" serialize = ["{major}.{minor}.{patch}"] search = "{current_version}" diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c4de5a..a54f347 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ and the versioning aim to respect [Semantic Versioning](http://semver.org/spec/v Here is a template for new release sections +## [1.8.0] - 2024-05-23 +### Added +- docs for popups + +### Changed +- step size calculation rounds to 10, 100, 1000 etc. +- default choropleth legend entries to 5 + +### Fixed +- zero item in choropleth legend +- error in choropleths if value equals "1" + ## [1.7.0] - 2024-05-13 ### Added - Middleware to prevent 404 errors for missing MVTs diff --git a/README.md b/README.md index 837c5a2..755f9a0 100644 --- a/README.md +++ b/README.md @@ -116,4 +116,6 @@ Maplibre must be installed (i.e. via npm) and provided as JS framework # User Guides -- [Layers](docs/LAYERS.md) +- [How to define layers](docs/LAYERS.md) +- [How to enable popups](docs/POPUPS.md) +- [How to set up clusters](docs/CLUSTERS.md) diff --git a/django_mapengine/__init__.py b/django_mapengine/__init__.py index 538c037..db33187 100644 --- a/django_mapengine/__init__.py +++ b/django_mapengine/__init__.py @@ -1,3 +1,3 @@ """Map Engine init, holds version""" -__version__ = "1.7.0" +__version__ = "1.8.0" diff --git a/django_mapengine/choropleth.py b/django_mapengine/choropleth.py index f3a71d3..3e35a79 100644 --- a/django_mapengine/choropleth.py +++ b/django_mapengine/choropleth.py @@ -9,7 +9,7 @@ MAX_COLORBREWER_STEPS = 9 -DEFAULT_CHOROPLETH_CONFIG = {"color_palette": "YlGnBu", "num_colors": 6} +DEFAULT_CHOROPLETH_CONFIG = {"color_palette": "YlGnBu", "num_colors": 5} class ChoroplethError(Exception): @@ -101,8 +101,8 @@ def __calculate_steps(self, choropleth_config: dict, values: Optional[list] = No num = choropleth_config["num_colors"] else: num = 6 - step = (max_value - min_value) / (num - 1) - return [min_value + i * step for i in range(num - 1)] + [max_value] + step_size = self.__calculate_step_size(min_value, max_value, num) + return [min_value + i * step_size for i in range(num)] + [max_value] if "values" not in choropleth_config: error_msg = "Values have to be set in style file in order to composite choropleth colors." @@ -139,7 +139,7 @@ def get_fill_color(self, name: str, values: Optional[list] = None) -> list: if len(steps) > MAX_COLORBREWER_STEPS: error_msg = f"Too many choropleth values given for {name=}." raise IndexError(error_msg) - colors = colorbrewer.sequential["multihue"][choropleth_config["color_palette"]][len(steps)] + colors = colorbrewer.sequential["multihue"][choropleth_config["color_palette"]][len(steps) - 1] fill_color = [ "interpolate", ["linear"], @@ -151,6 +151,15 @@ def get_fill_color(self, name: str, values: Optional[list] = None) -> list: fill_color.append(rgb_color) return fill_color + @staticmethod + def __calculate_step_size(min_value: float, max_value: float, num: int) -> float: + """ + Calculate step size + + Algorithm tries to find nice step sizes instead of simply dividing range by number of steps. + """ + return (max_value - min_value) / num + @staticmethod def __calculate_lower_limit(number: float) -> int: """ @@ -164,7 +173,7 @@ def __calculate_lower_limit(number: float) -> int: Returns ------- int - rounded down value by meaningful amount, depending on the size of mini + rounded down value by meaningful amount Raises ------ @@ -172,12 +181,12 @@ def __calculate_lower_limit(number: float) -> int: if lower limit cannot be found """ if number == 0: - return number + return int(number) if number < 1: return int((number * 10) / 10) - if number > 1: - digits = int(math.log10(number)) - return int(number / pow(10, digits)) * 10**digits + if number >= 1: + digits = int(math.log10(number)) + 1 + return int(number / 10**digits) * 10**digits raise ValueError(f"Cannot find lower limit for {number=}") @staticmethod @@ -199,9 +208,9 @@ def __calculate_upper_limit(number: float) -> int: ValueError if upper limit cannot be found """ - if number < 1: + if number <= 1: return math.ceil((number * 10) / 10) if number > 1: - digits = int(math.log10(number)) + digits = int(math.log10(number)) + 1 return math.ceil(number / 10**digits) * 10**digits raise ValueError(f"Cannot find upper limit for {number=}") diff --git a/django_mapengine/static/django_mapengine/js/legend.js b/django_mapengine/static/django_mapengine/js/legend.js index aed4656..0edb2cb 100644 --- a/django_mapengine/static/django_mapengine/js/legend.js +++ b/django_mapengine/static/django_mapengine/js/legend.js @@ -24,10 +24,10 @@ const createLegend = (title, unit, colors, valueRanges, nextColumnStartIndex = 3
- ${valueRanges.filter((value, idx) => idx < nextColumnStartIndex).map((value, idx) => `
${value}
`).join(' ')} + ${valueRanges.filter((value, idx) => idx <= nextColumnStartIndex).map((value, idx) => `
${value}
`).join(' ')}
- ${valueRanges.filter((value, idx) => idx >= nextColumnStartIndex).map((value, idx) => `
${value}
`).join(' ')} + ${valueRanges.filter((value, idx) => idx > nextColumnStartIndex).map((value, idx) => `
${value}
`).join(' ')}