networkforge 1.4.1__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.
- networkforge-1.4.1/.gitignore +14 -0
- networkforge-1.4.1/CHANGELOG.md +666 -0
- networkforge-1.4.1/LICENSE +674 -0
- networkforge-1.4.1/PKG-INFO +336 -0
- networkforge-1.4.1/README.md +306 -0
- networkforge-1.4.1/docs/network-analyst.md +273 -0
- networkforge-1.4.1/docs/network-rules.md +610 -0
- networkforge-1.4.1/docs/osm-data.md +89 -0
- networkforge-1.4.1/docs/tagging-guide.md +11 -0
- networkforge-1.4.1/docs/traffic.md +240 -0
- networkforge-1.4.1/pyproject.toml +116 -0
- networkforge-1.4.1/src/networkforge/__init__.py +48 -0
- networkforge-1.4.1/src/networkforge/__main__.py +7 -0
- networkforge-1.4.1/src/networkforge/cli.py +681 -0
- networkforge-1.4.1/src/networkforge/coverage.py +176 -0
- networkforge-1.4.1/src/networkforge/edits.py +460 -0
- networkforge-1.4.1/src/networkforge/errors.py +87 -0
- networkforge-1.4.1/src/networkforge/export.py +1056 -0
- networkforge-1.4.1/src/networkforge/inputs.py +256 -0
- networkforge-1.4.1/src/networkforge/modes.py +336 -0
- networkforge-1.4.1/src/networkforge/network.py +703 -0
- networkforge-1.4.1/src/networkforge/osm.py +450 -0
- networkforge-1.4.1/src/networkforge/paths.py +113 -0
- networkforge-1.4.1/src/networkforge/points.py +290 -0
- networkforge-1.4.1/src/networkforge/presets.py +50 -0
- networkforge-1.4.1/src/networkforge/projection.py +81 -0
- networkforge-1.4.1/src/networkforge/tags.py +132 -0
- networkforge-1.4.1/src/networkforge/topology.py +1086 -0
- networkforge-1.4.1/src/networkforge/traffic.py +905 -0
- networkforge-1.4.1/src/networkforge/turns.py +308 -0
- networkforge-1.4.1/src/networkforge/validation.py +642 -0
- networkforge-1.4.1/tests/__init__.py +0 -0
- networkforge-1.4.1/tests/conftest.py +12 -0
- networkforge-1.4.1/tests/data/custom_road_test.geojson +11 -0
- networkforge-1.4.1/tests/data/custom_road_test.qmd +27 -0
- networkforge-1.4.1/tests/data/extent.geojson +8 -0
- networkforge-1.4.1/tests/data/extent.qmd +27 -0
- networkforge-1.4.1/tests/helpers.py +132 -0
- networkforge-1.4.1/tests/integration/__init__.py +0 -0
- networkforge-1.4.1/tests/integration/conftest.py +43 -0
- networkforge-1.4.1/tests/integration/grid.py +314 -0
- networkforge-1.4.1/tests/integration/test_build_options.py +148 -0
- networkforge-1.4.1/tests/integration/test_cli_build.py +167 -0
- networkforge-1.4.1/tests/integration/test_coverage.py +148 -0
- networkforge-1.4.1/tests/integration/test_custom_ferries.py +74 -0
- networkforge-1.4.1/tests/integration/test_edge_cases.py +249 -0
- networkforge-1.4.1/tests/integration/test_edits.py +679 -0
- networkforge-1.4.1/tests/integration/test_export.py +422 -0
- networkforge-1.4.1/tests/integration/test_file_names.py +172 -0
- networkforge-1.4.1/tests/integration/test_gpkg.py +190 -0
- networkforge-1.4.1/tests/integration/test_gpkg_layers.py +187 -0
- networkforge-1.4.1/tests/integration/test_osm_source.py +138 -0
- networkforge-1.4.1/tests/integration/test_points.py +151 -0
- networkforge-1.4.1/tests/integration/test_properties.py +158 -0
- networkforge-1.4.1/tests/integration/test_standalone.py +374 -0
- networkforge-1.4.1/tests/integration/test_synthetic_grid.py +470 -0
- networkforge-1.4.1/tests/integration/test_traffic_build.py +157 -0
- networkforge-1.4.1/tests/integration/test_turns.py +284 -0
- networkforge-1.4.1/tests/live/__init__.py +0 -0
- networkforge-1.4.1/tests/live/conftest.py +30 -0
- networkforge-1.4.1/tests/live/test_cities.py +230 -0
- networkforge-1.4.1/tests/live/test_local_extract.py +96 -0
- networkforge-1.4.1/tests/live/test_structural_invariants.py +70 -0
- networkforge-1.4.1/tests/live/test_valhalla_islands.py +107 -0
- networkforge-1.4.1/tests/live/test_valhalla_real_data.py +341 -0
- networkforge-1.4.1/tests/qgis/__init__.py +0 -0
- networkforge-1.4.1/tests/qgis/check_with_qgis.py +108 -0
- networkforge-1.4.1/tests/qgis/make_fixture.py +105 -0
- networkforge-1.4.1/tests/r5/__init__.py +5 -0
- networkforge-1.4.1/tests/r5/conftest.py +221 -0
- networkforge-1.4.1/tests/r5/test_before_and_after.py +36 -0
- networkforge-1.4.1/tests/r5/test_cycling.py +43 -0
- networkforge-1.4.1/tests/r5/test_edits.py +60 -0
- networkforge-1.4.1/tests/r5/test_transit.py +28 -0
- networkforge-1.4.1/tests/r5/worker.py +49 -0
- networkforge-1.4.1/tests/unit/__init__.py +0 -0
- networkforge-1.4.1/tests/unit/test_access_rules.py +79 -0
- networkforge-1.4.1/tests/unit/test_cli.py +284 -0
- networkforge-1.4.1/tests/unit/test_custom_tags.py +296 -0
- networkforge-1.4.1/tests/unit/test_grade_separation.py +38 -0
- networkforge-1.4.1/tests/unit/test_inputs.py +225 -0
- networkforge-1.4.1/tests/unit/test_presets.py +57 -0
- networkforge-1.4.1/tests/unit/test_projection.py +69 -0
- networkforge-1.4.1/tests/unit/test_speeds.py +39 -0
- networkforge-1.4.1/tests/unit/test_traffic.py +296 -0
- networkforge-1.4.1/tests/valhalla/__init__.py +0 -0
- networkforge-1.4.1/tests/valhalla/conftest.py +132 -0
- networkforge-1.4.1/tests/valhalla/harness.py +252 -0
- networkforge-1.4.1/tests/valhalla/test_before_and_after.py +219 -0
- networkforge-1.4.1/tests/valhalla/test_cli_outputs.py +91 -0
- networkforge-1.4.1/tests/valhalla/test_cycling.py +157 -0
- networkforge-1.4.1/tests/valhalla/test_edits.py +254 -0
- networkforge-1.4.1/tests/valhalla/test_esri_network_dataset.py +319 -0
- networkforge-1.4.1/tests/valhalla/test_ferries.py +88 -0
- networkforge-1.4.1/tests/valhalla/test_joins.py +369 -0
- networkforge-1.4.1/tests/valhalla/test_less_common_tags.py +139 -0
- networkforge-1.4.1/tests/valhalla/test_multipart.py +69 -0
- networkforge-1.4.1/tests/valhalla/test_points.py +96 -0
- networkforge-1.4.1/tests/valhalla/test_random_lines.py +129 -0
- networkforge-1.4.1/tests/valhalla/test_standalone.py +135 -0
- networkforge-1.4.1/tests/valhalla/test_tags_as_valhalla_reads_them.py +173 -0
- networkforge-1.4.1/tests/valhalla/test_traffic.py +315 -0
- networkforge-1.4.1/tests/valhalla/test_turns.py +126 -0
- networkforge-1.4.1/tests/valhalla/test_wheelchair.py +110 -0
- networkforge-1.4.1/uv.lock +1314 -0
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to NetworkForge. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions
|
|
5
|
+
follow [Semantic Versioning](https://semver.org/). From 1.0 the command
|
|
6
|
+
line (flags, exit codes, `--json` events) and the Python API are stable:
|
|
7
|
+
a breaking change means a new major version.
|
|
8
|
+
|
|
9
|
+
## [Unreleased]
|
|
10
|
+
|
|
11
|
+
## [1.4.1] - 2026-11-13
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Published on PyPI: `pip install networkforge`. Each release tag now
|
|
15
|
+
uploads the built package to PyPI as well as to GitHub Releases.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- README links point to GitHub, so they work on the PyPI page too.
|
|
19
|
+
|
|
20
|
+
## [1.4.0] - 2026-10-28
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- A `restrictions` layer in every GeoPackage (`write_gpkg`): one line
|
|
24
|
+
per turn restriction in the OSM file written from the same network,
|
|
25
|
+
OpenStreetMap's and the user's, drawn 20 m along the from street,
|
|
26
|
+
through the junction or along the via way(s), and 20 m along the to
|
|
27
|
+
street. Columns `relation_id`, `from_way`, `via_node`, `via_ways`,
|
|
28
|
+
`to_way`, `custom` (`yes` on the user's) and the relation's tags. Always
|
|
29
|
+
written, empty when there are none. `info` has `gpkg_layers` and
|
|
30
|
+
`gpkg_restriction_columns`.
|
|
31
|
+
- The nodes a custom layer's points tag are marked in the GeoPackage's
|
|
32
|
+
`nodes` layer: `modified` = `yes` on an OpenStreetMap node, `custom` =
|
|
33
|
+
`yes` on a new node or one on a custom line.
|
|
34
|
+
- More node columns: `bus`, `psv`, `hgv`, `wheelchair`, `toll`,
|
|
35
|
+
`maxheight`, `maxwidth`, `maxweight`, `entrance` (in the OSM file
|
|
36
|
+
already; now in the GeoPackage too).
|
|
37
|
+
- Custom features and single streets (`traffic --streets`) whose
|
|
38
|
+
coordinates can't be longitude / latitude in their CRS (metres in a
|
|
39
|
+
layer that says degrees) are refused, naming the features. Single
|
|
40
|
+
streets in a wrong CRS used to match no street, with only a warning.
|
|
41
|
+
|
|
42
|
+
### Changed
|
|
43
|
+
- `write_osm` and `write_gpkg` take the result of `prepare_osm_data`
|
|
44
|
+
(`data=` / `osm_data=`); the CLI makes it once for each network.
|
|
45
|
+
|
|
46
|
+
## [1.3.0] - 2026-10-21
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
- Measured speeds for traffic: `speed_kph` (km/h) wherever a `factor`
|
|
50
|
+
could be given, in road-class bands and on single streets; where a
|
|
51
|
+
factor and a speed overlap, the slower wins.
|
|
52
|
+
- A speed table by OpenStreetMap way id (`--speed-table FILE`, a CSV or
|
|
53
|
+
a GeoPackage table; Python: `speed_table`): rows of `osm_id` / `osmid`,
|
|
54
|
+
`days`, `time`, `speed_kph` or `factor`, `direction`. The form measured
|
|
55
|
+
speeds usually come in. Rows that match nothing are named by row
|
|
56
|
+
(`--speed-table-id-field`, or the row number) in a warning (`rows`)
|
|
57
|
+
and in the done event's `unmatched_rows`; `table_rows` counts the rows
|
|
58
|
+
used.
|
|
59
|
+
- `direction = backward` for single streets and the speed table: only
|
|
60
|
+
the direction opposite the drawn line, or the way's own direction.
|
|
61
|
+
- A warning when Valhalla can only approximate a band (short and much
|
|
62
|
+
slower than normal: its compact week of speeds can't hold the dip).
|
|
63
|
+
- docs/traffic.md: what uses traffic in the Network Analyst plugin
|
|
64
|
+
(routes and isochrones in its panel do; matrices and its Processing
|
|
65
|
+
tools don't).
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
- A short, deep band (e.g. 64 down to 12 km/h for 90 minutes) unpacked in
|
|
69
|
+
Valhalla with speeds near or below zero in its middle, so a trip took
|
|
70
|
+
many times longer than given (a 238 m slip road took 14 minutes). Speeds
|
|
71
|
+
that would unpack below half of those asked for are now raised before
|
|
72
|
+
packing.
|
|
73
|
+
|
|
74
|
+
## [1.2.1] - 2026-10-20
|
|
75
|
+
|
|
76
|
+
### Fixed
|
|
77
|
+
- `networkforge traffic` failed on Windows ("Valhalla could not build a
|
|
78
|
+
graph from the OSM file", with no detail): pyvalhalla's programs only
|
|
79
|
+
find their libraries there when `pyvalhalla.libs` is on PATH, which
|
|
80
|
+
the engine now sets for them. Its error messages now give Valhalla's
|
|
81
|
+
exit code. The Windows CI job runs the traffic tests in Valhalla.
|
|
82
|
+
|
|
83
|
+
## [1.2.0] - 2026-10-20
|
|
84
|
+
|
|
85
|
+
### Added
|
|
86
|
+
- `networkforge traffic` (Python: `add_traffic`, `read_traffic_settings`):
|
|
87
|
+
time-of-day speeds for Valhalla. A settings file of time bands by road
|
|
88
|
+
class ("primary roads at 60% on weekdays from 07:00 to 09:30") is put on
|
|
89
|
+
a network as Valhalla's predicted traffic, and Valhalla's graph is
|
|
90
|
+
written as a `.tar` file (the Network Analyst plugin's "From Tar").
|
|
91
|
+
Only routes with a departure or arrival time use it; without a time
|
|
92
|
+
every street keeps its normal speed. Needs the new `traffic` extra
|
|
93
|
+
(`pip install "networkforge[traffic]"`, pyvalhalla 3.9.0). See
|
|
94
|
+
docs/traffic.md. `networkforge info` lists the settings' days, road
|
|
95
|
+
classes and factor range under `traffic`.
|
|
96
|
+
- Single streets for traffic (`--streets FILE`, Python: `street_bands`):
|
|
97
|
+
a line layer, one row per street and time band (`days`, `time`,
|
|
98
|
+
`factor`, optional `direction` both/forward and `osm_id` / `osmid`).
|
|
99
|
+
A line without a way id is matched onto the stretches it runs along,
|
|
100
|
+
so it can be part of a long street or a new one. A street with rows of
|
|
101
|
+
its own ignores the road-class bands. Lines that match nothing are
|
|
102
|
+
named in a warning (`--id-field`) and in the done event's `unmatched`.
|
|
103
|
+
|
|
104
|
+
## [1.1.0] - 2026-10-16
|
|
105
|
+
|
|
106
|
+
### Added
|
|
107
|
+
- `ramp`, `ramp:wheelchair`, `ramp:stroller` and `ramp:bicycle` are
|
|
108
|
+
written for your own lines and for changes to existing streets (they
|
|
109
|
+
were dropped), and their values are checked. Valhalla tests record
|
|
110
|
+
what 3.9 does with them and with kerbs: nothing yet. Steps with a
|
|
111
|
+
ramp still stop a wheelchair, and no kerb does.
|
|
112
|
+
- A warning names fields that look like OpenStreetMap tags
|
|
113
|
+
(`tactile_paving`, `cycleway:surface` ...) but that NetworkForge
|
|
114
|
+
doesn't write, so routers won't see them. Names, sources, notes and
|
|
115
|
+
addresses (`name:en`, `source:maxspeed` ...) aren't warned about.
|
|
116
|
+
- A warning when a local OSM file (`osm_source=` / `--osm-source`)
|
|
117
|
+
doesn't cover the whole area. A region's extract stops at its
|
|
118
|
+
boundary, so a box reaching across it quietly lost streets: built from
|
|
119
|
+
Geofabrik's Berkshire file, a box around Reading lost about 1,800
|
|
120
|
+
streets north of the Thames, with no warning. The build now finds the
|
|
121
|
+
part of the area where the file has no streets at all, reaching the
|
|
122
|
+
area's edge and covering at least 5% of it, and says where it is.
|
|
123
|
+
The sea side of a coastline doesn't count. With `--json` the warning
|
|
124
|
+
event carries `gaps`, a `[west, south, east, north]` box for each part.
|
|
125
|
+
|
|
126
|
+
### Fixed
|
|
127
|
+
Found by probing the build with shapes the tests didn't draw
|
|
128
|
+
(`tests/integration/test_edge_cases.py`; the first four changed routes
|
|
129
|
+
in Valhalla).
|
|
130
|
+
|
|
131
|
+
- A custom bridge, tunnel, ferry or line on another `layer` was joined
|
|
132
|
+
to a custom road it crosses wherever either had a vertex within
|
|
133
|
+
`snap_tolerance` of the crossing. A vertex of a bridge drawn exactly
|
|
134
|
+
on a junction (or of a road on a motorway's node) joined it too. Only
|
|
135
|
+
ends join now, as documented.
|
|
136
|
+
- A line crossing or ending on a street right beside the dead end of
|
|
137
|
+
another way (within `snap_tolerance`) was pulled onto the dead end and
|
|
138
|
+
never joined the street.
|
|
139
|
+
- Making a street one-way when its OSM way closes on itself (a loop, a
|
|
140
|
+
crescent): drawn against the way's direction it was written the wrong
|
|
141
|
+
way round, and the closing stretch was reversed in the GeoPackage
|
|
142
|
+
either way.
|
|
143
|
+
- An existing turn restriction over a via way was dropped, silently,
|
|
144
|
+
when any part of one of its ways was changed. It now follows the
|
|
145
|
+
pieces, as restrictions with a via node did. (It still goes, rightly,
|
|
146
|
+
if part of the via way is removed.)
|
|
147
|
+
- About one line end in ten moved onto a street mid-block became two
|
|
148
|
+
nodes in one place joined by an edge of no length; so did three lines
|
|
149
|
+
crossing at one point.
|
|
150
|
+
- `--gpkg` (or another output) naming the `--custom` file overwrote the
|
|
151
|
+
custom data and reported success. Outputs that would replace an input
|
|
152
|
+
or each other are refused, and a missing output folder is reported
|
|
153
|
+
before the build rather than after it.
|
|
154
|
+
- An extent or custom layer in a projection measured in feet (US State
|
|
155
|
+
Plane) was built in feet: `length_m` and travel times 3.28 times too
|
|
156
|
+
large. Such projections are replaced by the UTM zone.
|
|
157
|
+
- Attributes named `index_right` / `index_left` crashed the build; `fid`,
|
|
158
|
+
a name differing from another only in capitals, or a GeoPackage
|
|
159
|
+
analysis column name (`car`, `length_m` ...) stopped the GeoPackage
|
|
160
|
+
being written. The first and last are set aside with the other
|
|
161
|
+
internal names; the others get a trailing underscore in the
|
|
162
|
+
GeoPackage.
|
|
163
|
+
- `--json`: a feature whose `--id-field` is empty was written as `NaN`,
|
|
164
|
+
which is not JSON; it is `null`.
|
|
165
|
+
- Control characters in a tag value made OSM XML that could not be read;
|
|
166
|
+
an extent file without features and an infinite `--snap-tolerance` are
|
|
167
|
+
input errors (exit 3), not crashes.
|
|
168
|
+
- A new line drawn to the pier of an existing ferry that no street
|
|
169
|
+
reaches got a node of its own beside the ferry's, so the ferry stayed
|
|
170
|
+
out of reach in Valhalla. Its end now joins the ferry.
|
|
171
|
+
- `maxspeed=0` gave endless travel times (GeoPackage minutes, OSMnx
|
|
172
|
+
routing): a speed of 0 is ignored, as routers do, and on a custom
|
|
173
|
+
feature it is an error.
|
|
174
|
+
- `bridge=0` / `bridge=false` (and the same for `tunnel`) counted as a
|
|
175
|
+
bridge, so the line didn't join the streets it crossed. They mean no.
|
|
176
|
+
- A change to an existing street drawn ACROSS a block (through the
|
|
177
|
+
middle of it) was applied to that block. A feature must now run along
|
|
178
|
+
the stretch, within 45 degrees.
|
|
179
|
+
|
|
180
|
+
### Tests
|
|
181
|
+
- Cycling infrastructure is now tested in Valhalla
|
|
182
|
+
(`tests/valhalla/test_cycling.py`): a cycle lane, a track or a
|
|
183
|
+
cycleway draws cyclists off a shorter street and nobody else; a lane
|
|
184
|
+
added to an existing street makes it cheaper to cycle; unpaved
|
|
185
|
+
surfaces close a street to the bicycles that can't take them.
|
|
186
|
+
|
|
187
|
+
- Wheelchair routing (`tests/valhalla/test_wheelchair.py`): steps,
|
|
188
|
+
`wheelchair=no` and gravel turn a wheelchair back and nobody else.
|
|
189
|
+
- Less common tags (`tests/valhalla/test_less_common_tags.py`):
|
|
190
|
+
motorcycles, mopeds and taxis, buses against a one-way street,
|
|
191
|
+
roundabouts, `maxspeed:hgv`, rough surfaces and mountain paths.
|
|
192
|
+
|
|
193
|
+
### Documentation
|
|
194
|
+
- [network-analyst.md](docs/network-analyst.md#cycling-infrastructure)
|
|
195
|
+
says which cycling tags Valhalla routes by and which it ignores
|
|
196
|
+
(`cycleway:both`, `bicycle_road`, `cyclestreet`).
|
|
197
|
+
- The tagging guide is now [network-rules.md](docs/network-rules.md),
|
|
198
|
+
"Network rules: how your lines become a network", written for people
|
|
199
|
+
using the QGIS plugin. It opens with a short summary of the rules
|
|
200
|
+
instead of code, names each setting as the QGIS form does, and ends
|
|
201
|
+
with a table of each setting in QGIS, on the command line and in
|
|
202
|
+
Python. The code examples are in the README. `docs/tagging-guide.md`
|
|
203
|
+
is now a short page pointing to the new one. Errors' `guide` (in
|
|
204
|
+
`--json` error events too) now names the file:
|
|
205
|
+
`network-rules.md#presets`, not `presets`.
|
|
206
|
+
- The guide brought up to date. The
|
|
207
|
+
quick start shows the command line, the PBF and the GeoPackage, plus
|
|
208
|
+
a table of Python options with their CLI flags. Points are allowed in
|
|
209
|
+
the layer, and lines that join nothing are kept with a warning (the
|
|
210
|
+
guide said both were refused). Attributes that aren't tags are kept in
|
|
211
|
+
the GeoPackage. The reserved names list is complete. New: `wheelchair`,
|
|
212
|
+
`maxspeed:hgv`, time-of-day access, line ends that nearly meet, loops,
|
|
213
|
+
an error table for points, and a list of the warnings and what to do
|
|
214
|
+
about each.
|
|
215
|
+
|
|
216
|
+
## [1.0.1] - 2026-10-11
|
|
217
|
+
|
|
218
|
+
### Fixed
|
|
219
|
+
- On Windows, an OSM file in a folder with accented or other non-English
|
|
220
|
+
letters in its name (`C:\Users\Zoë\Documents\...`) could not be read
|
|
221
|
+
("Open failed ... The system cannot find the file specified"), and
|
|
222
|
+
`.osm.pbf`, `.osm.gz` and `.osm.bz2` output could not be written to
|
|
223
|
+
one. The same went for such letters in the file's own name.
|
|
224
|
+
|
|
225
|
+
### Tests
|
|
226
|
+
- The offline tests now also run on Windows on every push.
|
|
227
|
+
|
|
228
|
+
## [1.0.0] - 2026-10-06
|
|
229
|
+
|
|
230
|
+
The first stable release: every OSM feature a network build needs -
|
|
231
|
+
new lines, changed and removed streets, turn restrictions, points on
|
|
232
|
+
the network, ferries - tested against Valhalla.
|
|
233
|
+
|
|
234
|
+
### Stability
|
|
235
|
+
- The command line (`build`, `check`, `presets`, `info`), its exit codes
|
|
236
|
+
and its `--json` events, and the Python API (`build_network`,
|
|
237
|
+
`write_osm`, `write_gpkg`, the errors) are now stable. New fields may
|
|
238
|
+
be added to the JSON events; none is removed or changes meaning
|
|
239
|
+
without a new major version.
|
|
240
|
+
|
|
241
|
+
### Added
|
|
242
|
+
- **New ferries.** A custom line with `route=ferry` (or
|
|
243
|
+
`route=shuttle_train`) and no `highway` tag is a ferry, as in
|
|
244
|
+
OpenStreetMap. It joins the streets only at its ends, passing over
|
|
245
|
+
streets it crosses. Everyone may use it unless an access tag closes
|
|
246
|
+
it (`motor_vehicle=no` for a foot ferry); `duration=hh:mm` sets the
|
|
247
|
+
crossing time, else 10 km/h - both as Valhalla reads them. In the
|
|
248
|
+
GeoPackage every mode takes the ferry's time. `info --json` lists
|
|
249
|
+
`tag_values.route` and `tag_patterns.duration`.
|
|
250
|
+
- **Warnings for values routers don't know** on `surface`, `smoothness`,
|
|
251
|
+
`tracktype`, `sac_scale`, `sidewalk`, `cycleway*`, `segregated`, `lit`,
|
|
252
|
+
`toll`, `junction`, `bridge`, `tunnel` and `incline`, for new lines and
|
|
253
|
+
edits alike, with the likely spelling (`surface='asphault' ... did you
|
|
254
|
+
mean 'asphalt'?`). OSM allows any value, so the build carries on.
|
|
255
|
+
`info --json` lists the known values in `tag_values` (and
|
|
256
|
+
`tag_patterns.incline`).
|
|
257
|
+
- **Deleting tags from an existing street.** On a feature with an OSM
|
|
258
|
+
id, `remove_tags=maxspeed;motor_vehicle` deletes those tags from the
|
|
259
|
+
stretch (an empty attribute still means "no change"). Deleting
|
|
260
|
+
`oneway` makes the street two-way. `info --json` has
|
|
261
|
+
`remove_tags_field`.
|
|
262
|
+
- **Points: barriers, signals, crossings.** A point in the custom layer
|
|
263
|
+
with node tags (`barrier=bollard`, `highway=traffic_signals`,
|
|
264
|
+
`crossing=zebra`, ...) tags the node it is on (within snap_tolerance)
|
|
265
|
+
or cuts the nearest street there with a new node - on new lines,
|
|
266
|
+
existing and changed streets alike. `remove_tags` on a point deletes
|
|
267
|
+
an existing node's tags (take out a bollard). `layer` picks the street
|
|
268
|
+
where a bridge crosses one. `check` / `build --json` report `points` /
|
|
269
|
+
`tagged_nodes`.
|
|
270
|
+
- **Via-way turn restrictions.** A turn line through two junctions
|
|
271
|
+
joined by a street becomes a restriction over that stretch (from way,
|
|
272
|
+
via way, to way), e.g. no U-turn across a dual carriageway. Valhalla
|
|
273
|
+
obeys it.
|
|
274
|
+
- Tests for multi-part custom lines: offline (parts that share an end,
|
|
275
|
+
cross, nearly meet, stray from the network or collapse; random
|
|
276
|
+
multi-part lines in the property tests) and in Valhalla (each part
|
|
277
|
+
routable, crossing parts joined, per-part edits and removals,
|
|
278
|
+
standalone networks).
|
|
279
|
+
|
|
280
|
+
### Changed
|
|
281
|
+
- **Point features are accepted** in the custom layer (they tag nodes,
|
|
282
|
+
see above); only other geometry types are refused, now as "not a line
|
|
283
|
+
or point".
|
|
284
|
+
|
|
285
|
+
### Fixed
|
|
286
|
+
- **A multi-part feature that changes an existing street** (`osm_id`)
|
|
287
|
+
now applies to each part on its own: `oneway` follows the direction
|
|
288
|
+
each part is drawn in (all parts took the first part's), and a problem
|
|
289
|
+
or an unchanged feature is reported once, not once per part.
|
|
290
|
+
- **A new roundabout without `oneway`** is one-way in the GeoPackage's
|
|
291
|
+
`car_direction` / `bike_direction`, as OSM and Valhalla treat it. It
|
|
292
|
+
was marked two-way there (the PBF was already right).
|
|
293
|
+
- **A line that crosses itself within 1 m of a motorway** (or another
|
|
294
|
+
grade-separated way) no longer joins it there. The line was cut at the
|
|
295
|
+
crossing before snapping, and the cut ends counted as line ends, which
|
|
296
|
+
may join a motorway (as slip roads do). Now only the ends you drew do.
|
|
297
|
+
Found by the new multi-part property tests; single lines were affected
|
|
298
|
+
too.
|
|
299
|
+
|
|
300
|
+
## [0.12.0] - 2026-10-06
|
|
301
|
+
|
|
302
|
+
### Added
|
|
303
|
+
- **Turn restrictions.** A line in the custom layer drawn from one street,
|
|
304
|
+
through a junction, onto another, with OSM's `restriction` tag
|
|
305
|
+
(`no_left_turn`, `only_straight_on`, ...), becomes an OSM turn
|
|
306
|
+
restriction relation. `restriction:hgv` / `:bus` / `:motorcar` /
|
|
307
|
+
`:bicycle` limit it to one kind of vehicle, and `except` exempts some.
|
|
308
|
+
It works between existing streets, new lines and changed streets, and
|
|
309
|
+
in standalone networks. Streets that run through the junction are cut
|
|
310
|
+
there, as OSM requires. Lines that pass through no junction or more
|
|
311
|
+
than one are refused with the feature named; a value that disagrees
|
|
312
|
+
with the drawn turn (no_right_turn drawn as a left turn) is warned
|
|
313
|
+
about. See "Turn restrictions" in the tagging guide.
|
|
314
|
+
- `--json`: the `done` event of `build` and `check` has
|
|
315
|
+
`turn_restrictions`; `info` has `turn_restriction_fields` and
|
|
316
|
+
`tag_values.restriction`.
|
|
317
|
+
|
|
318
|
+
## [0.11.1] - 2026-10-06
|
|
319
|
+
|
|
320
|
+
### Fixed
|
|
321
|
+
Found by further testing (odd inputs, larger areas):
|
|
322
|
+
|
|
323
|
+
- **Attributes that aren't tags now keep their type.** All attributes were
|
|
324
|
+
turned into text, so a number such as a surveyed travel time reached
|
|
325
|
+
the GeoPackage as `'1.5'` and couldn't be used as a cost in QGIS.
|
|
326
|
+
- **A coordinate that isn't a number** (NaN, infinite) is reported for
|
|
327
|
+
its feature instead of crashing the build with a GEOS error.
|
|
328
|
+
- When every feature is outside the box, the message suggests checking
|
|
329
|
+
the layer's CRS and the order of longitude and latitude.
|
|
330
|
+
|
|
331
|
+
### Changed
|
|
332
|
+
- Tag names and values are taken exactly as OSM writes them: text `True`
|
|
333
|
+
/ `False` is no longer turned into `yes` / `no` (a boolean field still
|
|
334
|
+
is, and empty text still counts as no value).
|
|
335
|
+
- Dev container: the environment is `/opt/venv` instead of the shared
|
|
336
|
+
`/workspace/.venv`, which the host's and the container's uv kept
|
|
337
|
+
rebuilding for their own Python. Rebuild the container to use it.
|
|
338
|
+
- Building a network of your own lines is about four times faster: a
|
|
339
|
+
39,000-line network (Malta) takes 25 s instead of 100 s. The steps that
|
|
340
|
+
went through the custom lines one at a time in Python now work on all
|
|
341
|
+
of them at once.
|
|
342
|
+
|
|
343
|
+
## [0.11.0] - 2026-10-05
|
|
344
|
+
|
|
345
|
+
### Changed
|
|
346
|
+
- **`--json` edge counts are streets, not edges.** The `done` event's
|
|
347
|
+
`edges`, `custom_edges`, `modified_edges` and `removed_edges` count one
|
|
348
|
+
per street, as the GeoPackage has rows. They used to count OSMnx's
|
|
349
|
+
edges, which hold a two-way street as two (45 "edges" for a layer of
|
|
350
|
+
24 rows).
|
|
351
|
+
- **GeoPackage `oneway` is always OSM text** (`yes`, `no`, `-1`). Existing
|
|
352
|
+
streets came out as booleans and new or changed lines as text, so a
|
|
353
|
+
mixed build wrote `True`, `False` and `yes` in one column.
|
|
354
|
+
- Standalone builds no longer mention OpenStreetMap in their progress
|
|
355
|
+
messages and log ("Checking custom lines reach the OSM network").
|
|
356
|
+
|
|
357
|
+
### Fixed
|
|
358
|
+
- A line drawn along an existing street joins it at every node it lies
|
|
359
|
+
on; it used to pass over the street's junctions without joining them.
|
|
360
|
+
- When the Overpass API can't be reached (it refuses connections when
|
|
361
|
+
busy), the download is tried again after 10 s and 30 s before failing.
|
|
362
|
+
|
|
363
|
+
### Tests
|
|
364
|
+
- The nightly property test compared Valhalla's distance matrix with
|
|
365
|
+
NetworkForge's own routing. Valhalla 3.9.0's matrix can disagree with
|
|
366
|
+
its own route search on the same graph (229 m against 100 m), and its
|
|
367
|
+
default 5 m node snapping started trips on a nearby dead end; cells
|
|
368
|
+
that disagree are now measured with route(), locations aren't snapped,
|
|
369
|
+
and junctions another line passes within 0.5 m of are left out. The
|
|
370
|
+
cases found are kept as fixed examples.
|
|
371
|
+
- The live city tests checked that each OSM tag was on as many exported
|
|
372
|
+
ways as downloaded edges, which no longer holds since the export writes
|
|
373
|
+
OSM ways as they are (v0.6.0); they now check the file holds the
|
|
374
|
+
downloaded ways and tags exactly.
|
|
375
|
+
- The Overpass-versus-extract test allows up to 1% of rows to differ (a
|
|
376
|
+
day of OpenStreetMap edits between the two sources).
|
|
377
|
+
- A live test whose Overpass download still fails after the retries is
|
|
378
|
+
skipped with the reason, not reported as an error.
|
|
379
|
+
|
|
380
|
+
## [0.10.0] - 2026-10-02
|
|
381
|
+
|
|
382
|
+
### Added
|
|
383
|
+
- **Standalone networks**: `networkforge build --no-osm` (Python:
|
|
384
|
+
`build_network(None, lines, standalone=True)`) builds a network from the
|
|
385
|
+
custom lines alone, with no OpenStreetMap, no area and no download.
|
|
386
|
+
Tags, presets and checks work as usual. `--join-at crossings` (default)
|
|
387
|
+
joins lines wherever they cross; `--join-at vertices` only where they
|
|
388
|
+
share a vertex, for data that already has a vertex at every junction.
|
|
389
|
+
A warning names the features outside the largest connected piece.
|
|
390
|
+
`networkforge info` reports `standalone` and `join_at`.
|
|
391
|
+
- Line ends that stop within the snap distance of each other without
|
|
392
|
+
touching now share one node (also when adding lines to OpenStreetMap).
|
|
393
|
+
|
|
394
|
+
### Changed
|
|
395
|
+
- The package description and README now say what the tool has become:
|
|
396
|
+
building and editing street networks, not only adding proposed lines.
|
|
397
|
+
- `build` no longer requires `--extent` / `--bbox` on the command line
|
|
398
|
+
when `--no-osm` is given (it still does otherwise; exit code 2).
|
|
399
|
+
|
|
400
|
+
### Fixed
|
|
401
|
+
- An area or layer in a world-wide projection such as Web Mercator
|
|
402
|
+
(EPSG:3857) was measured in that projection, where a metre on the map
|
|
403
|
+
is not a metre on the ground (79% too long in Scotland): lengths in the
|
|
404
|
+
GeoPackage and the snap distance were wrong. A local UTM zone is now
|
|
405
|
+
used unless the CRS is a regional one.
|
|
406
|
+
|
|
407
|
+
## [0.9.0] - 2026-10-02
|
|
408
|
+
|
|
409
|
+
### Fixed
|
|
410
|
+
Found by building on whole-country extracts (Liechtenstein, Andorra,
|
|
411
|
+
Isle of Man, Malta, Faroe Islands, Seychelles, Maldives) and comparing
|
|
412
|
+
with Valhalla on the raw data:
|
|
413
|
+
|
|
414
|
+
- **Only the largest connected piece of the network was kept.** Other
|
|
415
|
+
islands, and streets whose link to the rest lies outside the area, were
|
|
416
|
+
dropped: all of Gozo in Malta, 89% of the Maldives. Every piece is now
|
|
417
|
+
kept. Leaving pieces out also changed Valhalla's speeds on the streets
|
|
418
|
+
that remained (it slows traffic where streets are dense).
|
|
419
|
+
- **A new line could weld a tunnel or bridge to the street next to it.**
|
|
420
|
+
A junction point within the snap distance of an existing node was
|
|
421
|
+
merged into that node even when the node belonged to a tunnel or bridge
|
|
422
|
+
the point must not join; and a crossing that lay exactly on a tunnel or
|
|
423
|
+
bridge line joined it. Points now merge only with the node they are on,
|
|
424
|
+
and an existing way is only joined where it may be: at a custom line's
|
|
425
|
+
end, or at grade on the same layer.
|
|
426
|
+
- **Boolean and empty attributes.** A boolean field (`oneway` = true) was
|
|
427
|
+
rejected as `oneway='True'`, and empty text (`maxspeed` = "") as an
|
|
428
|
+
invalid value. They are now read as yes / no and as "no value".
|
|
429
|
+
- A roundabout counts as one-way when comparing a feature's `oneway`
|
|
430
|
+
with the street's.
|
|
431
|
+
- A further piece of a cropped way gets the same new id in the "before"
|
|
432
|
+
and "after" file.
|
|
433
|
+
|
|
434
|
+
### Changed
|
|
435
|
+
- A custom line is reported as not connected when its piece of network
|
|
436
|
+
contains no existing street, rather than when it is outside the largest
|
|
437
|
+
piece (the existing network can itself be in several pieces).
|
|
438
|
+
|
|
439
|
+
## [0.8.0] - 2026-10-02
|
|
440
|
+
|
|
441
|
+
### Added
|
|
442
|
+
- **Removing existing streets.** A feature with an OSM way id and
|
|
443
|
+
`remove=yes` takes the stretch it lies along out of the "after" network:
|
|
444
|
+
it is in neither the GeoPackage nor the OSM file, new lines don't join
|
|
445
|
+
it, and a turn restriction that needs it goes with it. `--json`: the
|
|
446
|
+
`done` event has `removed_edges`; `info` has `remove_field`.
|
|
447
|
+
- **Ferries.** Ferry and shuttle-train routes (`route=ferry`,
|
|
448
|
+
`route=shuttle_train`, ways with no `highway` tag) are written to the OSM
|
|
449
|
+
file as they are in OpenStreetMap, so routers can use them. They are not
|
|
450
|
+
part of the edge table or the GeoPackage. On the Monaco extract this was
|
|
451
|
+
the whole difference between walking routes on the "before" file and on
|
|
452
|
+
raw OpenStreetMap; they are now identical.
|
|
453
|
+
|
|
454
|
+
### Fixed
|
|
455
|
+
- New junction nodes get ids above every node id in the area's OSM data,
|
|
456
|
+
including nodes that are only on ferries or on removed streets.
|
|
457
|
+
|
|
458
|
+
## [0.7.0] - 2026-10-02
|
|
459
|
+
|
|
460
|
+
### Added
|
|
461
|
+
- **Changing existing streets.** A custom feature with an OSM way id
|
|
462
|
+
(an `osm_id` attribute, as on QuickOSM layers, or `osmid`, as in
|
|
463
|
+
NetworkForge's GeoPackage) changes that street instead of adding a
|
|
464
|
+
line: make it one-way, close it, change its speed limit or type. Only
|
|
465
|
+
attributes that differ from OpenStreetMap are applied, and only on the
|
|
466
|
+
stretches the feature lies along. See "Changing existing streets" in
|
|
467
|
+
the tagging guide.
|
|
468
|
+
- Changed stretches are marked `modified` = `yes` in the GeoPackage and
|
|
469
|
+
`nf:modified=yes` in the OSM file; the "before" outputs are untouched.
|
|
470
|
+
- `--json`: the build's `done` event has `modified_edges`; `check`'s has
|
|
471
|
+
`edits`; `info` has `edit_id_fields`. Errors about such features use
|
|
472
|
+
the guide anchor `changing-existing-streets`.
|
|
473
|
+
- A build may consist of changes only, with no new lines.
|
|
474
|
+
|
|
475
|
+
### Changed
|
|
476
|
+
- A turn restriction whose way is written in several pieces (cropped at
|
|
477
|
+
the edge of the area, or partly changed) now follows the piece its via
|
|
478
|
+
node is on, instead of being dropped.
|
|
479
|
+
- `nf_edit` and `modified` join the attribute names set aside as
|
|
480
|
+
internal. Such names are now only noted, not warned about, when the
|
|
481
|
+
layer has OSM ids (rows copied from a NetworkForge layer always have
|
|
482
|
+
them).
|
|
483
|
+
|
|
484
|
+
## [0.6.0] - 2026-10-02
|
|
485
|
+
|
|
486
|
+
### Added
|
|
487
|
+
- Valhalla tests (`tests/valhalla`, `uv run pytest -m valhalla`, CI job
|
|
488
|
+
"PBF in Valhalla"): the exported PBF is built into a Valhalla routing
|
|
489
|
+
graph with a pinned `pyvalhalla` and routed on. They cover every
|
|
490
|
+
feature of Esri's "Create a network dataset" tutorial, who Valhalla
|
|
491
|
+
lets onto each kind of custom line, every way a line can join the
|
|
492
|
+
network, and that the "before" file routes exactly like the OSM data.
|
|
493
|
+
- `docs/network-analyst.md`: each ArcGIS Network Analyst feature, the
|
|
494
|
+
tag that replaces it, the test that proves it, and what isn't covered.
|
|
495
|
+
- A custom line that crosses itself gets a junction at the crossing
|
|
496
|
+
(unless it is a bridge or tunnel).
|
|
497
|
+
|
|
498
|
+
### Changed
|
|
499
|
+
- OSM / PBF export writes the existing network as OpenStreetMap has it,
|
|
500
|
+
instead of one new 2-node way per edge. Every way keeps its id, its
|
|
501
|
+
nodes in order and all its tags (not only the tags NetworkForge lists),
|
|
502
|
+
tagged nodes keep all theirs, and turn restrictions and route relations
|
|
503
|
+
are kept. Where a custom line joins a street mid-way, the new junction
|
|
504
|
+
node is inserted into that way. Each custom line is one way (id above
|
|
505
|
+
every OSM way id). Measured with Valhalla on a Monaco extract: routes on
|
|
506
|
+
the "before" file used to differ from routes on the OSM data itself for
|
|
507
|
+
about a third of trips; car, bicycle, bus and truck routes are now
|
|
508
|
+
identical.
|
|
509
|
+
- The `osmid` edge column (and GeoPackage field) is the OSM way id, empty
|
|
510
|
+
for custom edges. It used to be a row number.
|
|
511
|
+
- The Overpass download and a local extract now share one code path, and
|
|
512
|
+
one further Overpass request fetches the area's turn restrictions.
|
|
513
|
+
- More attributes of custom features are written as tags: time-dependent
|
|
514
|
+
access (`access:conditional`, ...), `taxi`, `hov`, `moped`, `emergency`,
|
|
515
|
+
`motorroad`, `maxaxles`, `hazmat`, `turn:lanes`, `destination`,
|
|
516
|
+
`alt_name`, `sidewalk` and others (see `networkforge info`).
|
|
517
|
+
|
|
518
|
+
- Access rules now follow OSM's defaults where Valhalla showed they
|
|
519
|
+
didn't: cycling on `highway=pedestrian` needs a tag that allows it
|
|
520
|
+
(the `pedestrian_street` preset now sets `bicycle=yes`, so it still
|
|
521
|
+
allows cycling), and `motorroad=yes` closes a road to walking and
|
|
522
|
+
cycling.
|
|
523
|
+
- A custom line only buses or other special vehicles may use (a busway,
|
|
524
|
+
`access=no` + `bus=yes`) is accepted with a note instead of rejected as
|
|
525
|
+
"unusable by every mode".
|
|
526
|
+
- `bus`, `psv`, `hgv`, `goods`, `taxi`, `motorcycle`, `moped`,
|
|
527
|
+
`emergency`, `horse`, `hov` are checked like the other access tags, and
|
|
528
|
+
`maxheight`, `maxwidth`, `maxlength`, `maxweight`, `maxaxleload` must be
|
|
529
|
+
valid OSM limits (`networkforge info`: `tag_values`, `tag_patterns`).
|
|
530
|
+
- GeoPackage `bike_direction` treats `cycleway=opposite*` as contraflow
|
|
531
|
+
cycling, like `oneway:bicycle=no`.
|
|
532
|
+
|
|
533
|
+
### Fixed
|
|
534
|
+
- A two-way street was written to the OSM / PBF file twice, once per
|
|
535
|
+
direction, which routers read as two parallel streets.
|
|
536
|
+
- When a custom line ended on an existing junction, every street at that
|
|
537
|
+
junction gained a second, uncut copy of itself, which bypassed any new
|
|
538
|
+
junction on that street.
|
|
539
|
+
|
|
540
|
+
## [0.5.0] - 2026-10-01
|
|
541
|
+
|
|
542
|
+
### Changed
|
|
543
|
+
- Custom lines that don't connect to the rest of the network no longer
|
|
544
|
+
fail the build (`NetworkIntegrityError`, exit code 5). The build
|
|
545
|
+
finishes with a warning - a `--json` `warning` event - naming the
|
|
546
|
+
`features`; they are kept in the output. A build where no line
|
|
547
|
+
reaches the network still fails (`NoIntersectionError`).
|
|
548
|
+
|
|
549
|
+
### Added
|
|
550
|
+
- `validation.disconnected_custom_edges(edges)`: which custom edges a
|
|
551
|
+
router can't reach.
|
|
552
|
+
|
|
553
|
+
## [0.4.0] - 2026-09-30
|
|
554
|
+
|
|
555
|
+
### Added
|
|
556
|
+
- `networkforge build --baseline-gpkg`: the untouched OSM network as a
|
|
557
|
+
GeoPackage with the same analysis columns, for before/after in QGIS.
|
|
558
|
+
- `--id-field NAME` (build, check): name features in warnings and errors
|
|
559
|
+
by an attribute, e.g. a GeoPackage's `fid`, instead of row number.
|
|
560
|
+
- Errors carry `issues` - `[{"feature": id, "message": ...}]` - on the
|
|
561
|
+
exception (`NetworkForgeError.issues`) and in `--json` error events.
|
|
562
|
+
- `--json` emits `warning` events, with the `features` / `fields`
|
|
563
|
+
they're about.
|
|
564
|
+
- `networkforge info [--json]`: version, presets, network types, valid tag
|
|
565
|
+
values and limits, for front ends building their UI from the engine.
|
|
566
|
+
|
|
567
|
+
### Changed
|
|
568
|
+
- Custom attributes with internal names (`length`, `key`, `u`, `v`, ...)
|
|
569
|
+
are set aside with a warning instead of failing the build.
|
|
570
|
+
- Custom feature ids (the data's index) must be unique.
|
|
571
|
+
|
|
572
|
+
## [0.3.0] - 2026-09-29
|
|
573
|
+
|
|
574
|
+
### Added
|
|
575
|
+
- GeoPackage output for QGIS (`write_gpkg`, `networkforge build --gpkg`):
|
|
576
|
+
edges carry network-analysis columns (`car`/`bike`/`walk`,
|
|
577
|
+
`speed_kph`, `length_m`, travel minutes per mode, `car_direction` /
|
|
578
|
+
`bike_direction` for QGIS's direction field, incl. contraflow cycling).
|
|
579
|
+
One row per street (OSMnx's reverse copies of two-way streets are
|
|
580
|
+
dropped) and every edge ends exactly on its nodes.
|
|
581
|
+
- CI job routing on the GeoPackage with QGIS's own network analysis
|
|
582
|
+
(`qgis_process`, QGIS LTR and latest) and checking the routes.
|
|
583
|
+
|
|
584
|
+
### Removed
|
|
585
|
+
- `scripts/` (`get_test_data.py`, `route_test.py`,
|
|
586
|
+
`diagnose_custom_network.py`): replaced by the CLI (`networkforge build`,
|
|
587
|
+
`networkforge check`) and the test suite.
|
|
588
|
+
|
|
589
|
+
### Fixed
|
|
590
|
+
- The dev container's Dockerfile installs dependencies only
|
|
591
|
+
(`uv sync --no-install-project`); installing the package itself failed
|
|
592
|
+
at image build time because the source isn't in the image.
|
|
593
|
+
|
|
594
|
+
## [0.2.0] - 2026-09-28
|
|
595
|
+
|
|
596
|
+
### Added
|
|
597
|
+
- **Command-line interface**: `networkforge build`, `check` and `presets`
|
|
598
|
+
(also `python -m networkforge`). `--json` writes progress, results and
|
|
599
|
+
errors as JSON lines for programs; documented exit codes.
|
|
600
|
+
- **Local OSM extracts**: `build_network(..., osm_source="area.osm.pbf")`
|
|
601
|
+
reads the existing network from a file (e.g. Geofabrik) instead of
|
|
602
|
+
Overpass, cropped and filtered to match the Overpass result exactly.
|
|
603
|
+
- **PBF export**: `write_osm()` picks the format from the file name:
|
|
604
|
+
`.osm`, `.osm.pbf`, `.pbf`, `.osm.gz`, `.osm.bz2`.
|
|
605
|
+
- **Presets** (`preset="primary_road"`, ...) and per-feature tags:
|
|
606
|
+
each feature's own attributes, with blanket tags filling gaps, or
|
|
607
|
+
replacing values with `overwrite_tags=True`.
|
|
608
|
+
- **Tag validation** before any download: OSM value checks, which modes
|
|
609
|
+
can use each feature, and warnings for misspelt or Shapefile-truncated
|
|
610
|
+
attribute names.
|
|
611
|
+
- **Grade separation**: custom lines don't join motorways, bridges,
|
|
612
|
+
tunnels or other layers they cross, but may end on them (slip roads).
|
|
613
|
+
- **Transport-mode access rules** following the OSM access hierarchy
|
|
614
|
+
(`motorcar` > `motor_vehicle` > `vehicle` > `access`; `bicycle`,
|
|
615
|
+
`foot`), busways, and shared-use paths.
|
|
616
|
+
- **Exception classes** (`NetworkForgeError`, `InputError`,
|
|
617
|
+
`InvalidTagsError`, `NoIntersectionError`, `OSMDownloadError`,
|
|
618
|
+
`NetworkIntegrityError`) with plain-language messages linking to the docs.
|
|
619
|
+
- **Input checks**: CRS, geometry types, bounding box coverage, Z values.
|
|
620
|
+
- Progress reporting via `logging` and a `progress` callback.
|
|
621
|
+
- Docs: `docs/tagging-guide.md`, `docs/osm-data.md`.
|
|
622
|
+
- Tests: unit, synthetic-grid integration, Hypothesis property tests and
|
|
623
|
+
live city tests; CI with coverage.
|
|
624
|
+
|
|
625
|
+
### Changed
|
|
626
|
+
- `network_tags` is optional; `build_network` has 13 steps (the old
|
|
627
|
+
final "apply tags" step is folded into the first).
|
|
628
|
+
- Boxes over 1,000 km² are refused for Overpass; use `osm_source`.
|
|
629
|
+
- Exports keep routing-relevant way tags (one-way exceptions, cycle
|
|
630
|
+
infrastructure, vehicle limits, surface) and node tags (barriers,
|
|
631
|
+
signals, crossings).
|
|
632
|
+
- Much faster: splitting, node assignment and export are vectorised
|
|
633
|
+
(demo area: build excluding download 23 s -> 5 s; 800 custom lines
|
|
634
|
+
191 s -> 52 s).
|
|
635
|
+
|
|
636
|
+
### Fixed
|
|
637
|
+
- Custom node ids could collide with real OSM node ids, moving streets.
|
|
638
|
+
- Snapping could bend or rewire existing streets near custom lines
|
|
639
|
+
(found by property tests).
|
|
640
|
+
- Custom lines could get gaps where segments ended near a node.
|
|
641
|
+
- `oneway` was exported as `True`/`False`, which made one-way streets
|
|
642
|
+
two-way when reloaded; now `yes`/`no`.
|
|
643
|
+
- Access restrictions (`motor_vehicle`, `foot`, `bicycle`, ...) were
|
|
644
|
+
dropped on download and export.
|
|
645
|
+
- Baseline and custom travel times weren't comparable: speeds for
|
|
646
|
+
untagged roads now come from a fixed table.
|
|
647
|
+
|
|
648
|
+
## [0.1.0]
|
|
649
|
+
|
|
650
|
+
- Initial pipeline: merge custom lines into an OSMnx network and export
|
|
651
|
+
OSM XML.
|
|
652
|
+
|
|
653
|
+
[Unreleased]: https://github.com/Yibbzz/networkforge/compare/v1.0.0...HEAD
|
|
654
|
+
[1.0.0]: https://github.com/Yibbzz/networkforge/compare/v0.12.0...v1.0.0
|
|
655
|
+
[0.12.0]: https://github.com/Yibbzz/networkforge/compare/v0.11.1...v0.12.0
|
|
656
|
+
[0.11.1]: https://github.com/Yibbzz/networkforge/compare/v0.11.0...v0.11.1
|
|
657
|
+
[0.11.0]: https://github.com/Yibbzz/networkforge/compare/v0.10.0...v0.11.0
|
|
658
|
+
[0.10.0]: https://github.com/Yibbzz/networkforge/compare/v0.9.0...v0.10.0
|
|
659
|
+
[0.9.0]: https://github.com/Yibbzz/networkforge/compare/v0.8.0...v0.9.0
|
|
660
|
+
[0.8.0]: https://github.com/Yibbzz/networkforge/compare/v0.7.0...v0.8.0
|
|
661
|
+
[0.7.0]: https://github.com/Yibbzz/networkforge/compare/v0.6.0...v0.7.0
|
|
662
|
+
[0.6.0]: https://github.com/Yibbzz/networkforge/compare/v0.5.0...v0.6.0
|
|
663
|
+
[0.5.0]: https://github.com/Yibbzz/networkforge/compare/v0.4.0...v0.5.0
|
|
664
|
+
[0.4.0]: https://github.com/Yibbzz/networkforge/compare/v0.3.0...v0.4.0
|
|
665
|
+
[0.3.0]: https://github.com/Yibbzz/networkforge/compare/v0.2.0...v0.3.0
|
|
666
|
+
[0.2.0]: https://github.com/Yibbzz/networkforge/releases/tag/v0.2.0
|