plot-finder 0.3.2__tar.gz → 0.3.4__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.
Files changed (25) hide show
  1. {plot_finder-0.3.2 → plot_finder-0.3.4}/PKG-INFO +1 -1
  2. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/analyzer.py +94 -0
  3. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/plot.py +6 -0
  4. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/report.py +7 -6
  5. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder.egg-info/PKG-INFO +1 -1
  6. {plot_finder-0.3.2 → plot_finder-0.3.4}/pyproject.toml +1 -1
  7. {plot_finder-0.3.2 → plot_finder-0.3.4}/LICENSE +0 -0
  8. {plot_finder-0.3.2 → plot_finder-0.3.4}/README.md +0 -0
  9. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/__init__.py +0 -0
  10. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/ai.py +0 -0
  11. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/air.py +0 -0
  12. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/climate.py +0 -0
  13. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/exceptions.py +0 -0
  14. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/gugik.py +0 -0
  15. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/mpzp.py +0 -0
  16. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/noise.py +0 -0
  17. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/place.py +0 -0
  18. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/risks.py +0 -0
  19. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/sun.py +0 -0
  20. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder/visualizer.py +0 -0
  21. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder.egg-info/SOURCES.txt +0 -0
  22. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder.egg-info/dependency_links.txt +0 -0
  23. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder.egg-info/requires.txt +0 -0
  24. {plot_finder-0.3.2 → plot_finder-0.3.4}/plot_finder.egg-info/top_level.txt +0 -0
  25. {plot_finder-0.3.2 → plot_finder-0.3.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plot-finder
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Query Polish ULDK (GUGiK) API to find land parcels by TERYT ID or coordinates
5
5
  Author: Ernest Ilchenko
6
6
  License-Expression: MIT
@@ -61,6 +61,43 @@ _VOIVODESHIP_MAP = {
61
61
  }
62
62
 
63
63
 
64
+ _PLACE_CATEGORIES: dict[str, str] = {
65
+ # education
66
+ "school": "education", "kindergarten": "education",
67
+ "university": "education", "college": "education",
68
+ # finance
69
+ "atm": "finance", "bank": "finance",
70
+ # transport
71
+ "bus_stop": "transport", "bus_station": "transport",
72
+ "platform": "transport", "stop_position": "transport",
73
+ "tram_stop": "transport", "station": "transport", "halt": "transport",
74
+ "ferry_terminal": "transport", "aerodrome": "transport",
75
+ # infrastructure
76
+ "supermarket": "infrastructure", "convenience": "infrastructure",
77
+ "mall": "infrastructure", "pharmacy": "infrastructure",
78
+ "hospital": "infrastructure", "clinic": "infrastructure",
79
+ "doctors": "infrastructure", "dentist": "infrastructure",
80
+ "post_office": "infrastructure", "fuel": "infrastructure",
81
+ "police": "infrastructure", "fire_station": "infrastructure",
82
+ "place_of_worship": "infrastructure", "restaurant": "infrastructure",
83
+ "cafe": "infrastructure",
84
+ # green_areas
85
+ "park": "green_areas", "garden": "green_areas",
86
+ "nature_reserve": "green_areas", "playground": "green_areas",
87
+ "forest": "green_areas", "wood": "green_areas",
88
+ # water
89
+ "water": "water", "river": "water", "lake": "water",
90
+ "pond": "water", "reservoir": "water",
91
+ "stream": "water", "canal": "water",
92
+ # nuisances
93
+ "line": "nuisances", "transformer": "nuisances",
94
+ "plant": "nuisances", "generator": "nuisances",
95
+ "industrial": "nuisances", "landfill": "nuisances",
96
+ "quarry": "nuisances", "works": "nuisances",
97
+ "wastewater_plant": "nuisances", "sawmill": "nuisances",
98
+ }
99
+
100
+
64
101
  class PlotAnalyzer:
65
102
  def __init__(self, plot: Plot, *, radius: int = 1000, openweather_api_key: str | None = None) -> None:
66
103
  self.plot = plot
@@ -87,6 +124,63 @@ class PlotAnalyzer:
87
124
  lon, lat = _EPSG2180_TO_WGS84.transform(x, y)
88
125
  return lat, lon
89
126
 
127
+ # ------------------------------------------------------------------
128
+ # Bulk fetch — one Overpass request for all categories
129
+ # ------------------------------------------------------------------
130
+
131
+ def all_places(self, radius: int | None = None) -> dict[str, list[Place]]:
132
+ """Fetch all POI categories in a single Overpass request.
133
+
134
+ Returns a dict with keys: education, finance, transport,
135
+ infrastructure, green_areas, water, nuisances.
136
+ Also populates the cache so subsequent calls to individual
137
+ methods (e.g. education()) return instantly.
138
+ """
139
+ r = radius or self.radius
140
+ key = ("all_places", r)
141
+ if key in self._cache:
142
+ return self._cache[key]
143
+
144
+ query = f"""
145
+ [out:json][timeout:60];
146
+ (
147
+ nwr["amenity"~"school|kindergarten|university|college|atm|bank|bus_station|pharmacy|hospital|clinic|doctors|dentist|post_office|fuel|police|fire_station|place_of_worship|restaurant|cafe|ferry_terminal"](around:{r},{self._lat},{self._lon});
148
+ nwr["shop"~"supermarket|convenience|mall"](around:{r},{self._lat},{self._lon});
149
+ nwr["highway"="bus_stop"](around:{r},{self._lat},{self._lon});
150
+ nwr["public_transport"~"platform|stop_position"](around:{r},{self._lat},{self._lon});
151
+ nwr["railway"~"tram_stop|station|halt"](around:{r},{self._lat},{self._lon});
152
+ nwr["aeroway"="aerodrome"](around:{r},{self._lat},{self._lon});
153
+ nwr["leisure"~"park|garden|nature_reserve|playground"](around:{r},{self._lat},{self._lon});
154
+ nwr["landuse"~"forest|industrial|landfill|quarry"](around:{r},{self._lat},{self._lon});
155
+ nwr["natural"~"water|wood"](around:{r},{self._lat},{self._lon});
156
+ nwr["water"~"river|lake|pond|reservoir"](around:{r},{self._lat},{self._lon});
157
+ nwr["waterway"~"river|stream|canal"](around:{r},{self._lat},{self._lon});
158
+ nwr["power"~"line|transformer|plant|generator"](around:{r},{self._lat},{self._lon});
159
+ nwr["man_made"~"works|wastewater_plant"](around:{r},{self._lat},{self._lon});
160
+ nwr["craft"="sawmill"](around:{r},{self._lat},{self._lon});
161
+ );
162
+ out center;
163
+ """
164
+
165
+ all_results = self._run_overpass(query)
166
+
167
+ categories: dict[str, list[Place]] = {
168
+ "education": [], "finance": [], "transport": [],
169
+ "infrastructure": [], "green_areas": [], "water": [],
170
+ "nuisances": [],
171
+ }
172
+
173
+ for place in all_results:
174
+ cat = _PLACE_CATEGORIES.get(place.kind)
175
+ if cat:
176
+ categories[cat].append(place)
177
+
178
+ for cat_name, places in categories.items():
179
+ self._cache[(cat_name, r)] = places
180
+
181
+ self._cache[key] = categories
182
+ return categories
183
+
90
184
  # ------------------------------------------------------------------
91
185
  # Overpass-based place methods (cached)
92
186
  # ------------------------------------------------------------------
@@ -29,9 +29,15 @@ class Plot(BaseModel):
29
29
  @computed_field # type: ignore[prop-decorator]
30
30
  @property
31
31
  def area(self) -> float | None:
32
+ """Area in m². Transforms to EPSG:2180 if needed."""
32
33
  if not self.geom_wkt:
33
34
  return None
34
35
  geom = shapely.wkt.loads(self.geom_wkt)
36
+ if self.srid != 2180:
37
+ from pyproj import Transformer
38
+ from shapely.ops import transform
39
+ t = Transformer.from_crs(f"EPSG:{self.srid}", "EPSG:2180", always_xy=True)
40
+ geom = transform(t.transform, geom)
35
41
  return round(geom.area, 2)
36
42
 
37
43
  @computed_field # type: ignore[prop-decorator]
@@ -8,7 +8,6 @@ from pydantic import BaseModel
8
8
  from plot_finder.air import AirQuality
9
9
  from plot_finder.climate import Climate
10
10
  from plot_finder.exceptions import (
11
- NothingFoundError,
12
11
  OpenMeteoError,
13
12
  OSRMError,
14
13
  OpenWeatherAuthError,
@@ -64,11 +63,13 @@ class PlotReporter:
64
63
  if a.plot.geom_wkt:
65
64
  data["geometry"] = self._geometry_wgs84(a.plot.geom_wkt)
66
65
 
67
- for category in ("education", "finance", "transport", "infrastructure", "green_areas", "water", "nuisances"):
68
- try:
69
- data[category] = getattr(a, category)()
70
- except (NothingFoundError, OverpassError, OSRMError):
71
- pass
66
+ try:
67
+ places = a.all_places()
68
+ for category in ("education", "finance", "transport", "infrastructure", "green_areas", "water", "nuisances"):
69
+ if places.get(category):
70
+ data[category] = places[category]
71
+ except (OverpassError, OSRMError):
72
+ pass
72
73
 
73
74
  try:
74
75
  data["air_quality"] = a.air_quality()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plot-finder
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: Query Polish ULDK (GUGiK) API to find land parcels by TERYT ID or coordinates
5
5
  Author: Ernest Ilchenko
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "plot-finder"
7
- version = "0.3.2"
7
+ version = "0.3.4"
8
8
  description = "Query Polish ULDK (GUGiK) API to find land parcels by TERYT ID or coordinates"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes