基于pgRouting生成流域:OSM2PO导入后拆分长道路加顶点的方法
Great question—this is a common pain point when balancing routing network integrity with the need for finer spatial granularity. Let’s break down your options, from the most straightforward to more custom approaches:
1. Modify OSM2PO Configuration to Split Roads During Import
The cleanest solution is to handle vertex insertion before your data hits PostgreSQL, using OSM2PO’s built-in splitting rules. This ensures the routing topology (like source/target fields and connectivity) is maintained natively, so you won’t have to fix broken links later.
In your osm2po.config file, add these parameters to split any road longer than 2km into 2km segments:
# Split ways longer than 2000 meters way.split.minLength=2000 # Force splitting even if the way has no natural nodes way.split.force=true
Re-run OSM2PO with this config, and the resulting PostgreSQL table will already have your segmented roads with intact pgRouting-ready topology. This is my top recommendation because it avoids post-import cleanup entirely.
2. Use pgRouting’s pgr_nodeNetwork for Post-Import Segmentation
If you’ve already imported your data and don’t want to re-run OSM2PO, pgRouting has a dedicated function to add nodes to your network without breaking connectivity: pgr_nodeNetwork.
This function automatically splits long edges into segments based on a minimum distance threshold, creates a new table with the segmented edges, and regenerates the source/target topology for you. Here’s how to use it:
-- Replace 'ways' with your actual table name, 'geom' with your geometry column, and 'gid' with your primary key SELECT pgr_nodeNetwork( 'ways', -- Original network table 2000, -- Minimum distance between nodes (meters) 'geom', -- Geometry column name 'gid' -- Primary key column name );
This will create a new table named ways_noded (suffix depends on your input) with the segmented roads. You can then use this table for your watershed calculations while keeping routing functionality intact.
3. Custom PostGIS Workflow with Topology Cleanup
If you need more control over where vertices are added (e.g., not strictly every 2km), you can use PostGIS to manually insert vertices and then rebuild the pgRouting topology. Here’s a step-by-step example:
Step 1: Add evenly spaced vertices to long roads
First, insert vertices every 2km along roads longer than 2km using ST_LineInterpolatePoint:
WITH long_ways AS ( SELECT gid, geom, ST_Length(geom) AS road_length FROM ways WHERE ST_Length(geom) > 2000 ), interpolation_points AS ( SELECT gid, ST_LineInterpolatePoint(geom, generate_series(2000, road_length - 1, 2000)/road_length) AS vertex FROM long_ways ) UPDATE ways SET geom = ST_AddPoints(geom, array_agg(vertex)) FROM interpolation_points WHERE ways.gid = interpolation_points.gid;
Step 2: Split roads into segments
Next, split the modified roads into individual segments using ST_Dump:
CREATE TABLE ways_segmented AS SELECT gid, (ST_Dump(geom)).geom AS geom, -- Keep any original attributes you need (e.g., road type, name) highway, name FROM ways;
Step 3: Rebuild pgRouting topology
Finally, regenerate the source/target fields and edge connectivity with pgr_createTopology:
SELECT pgr_createTopology( 'ways_segmented', 0.0001, -- Tolerance for snapping nodes (adjust based on your coordinate system) 'geom', 'gid' );
This will ensure your segmented network is ready for pgRouting operations.
内容的提问来源于stack exchange,提问作者Martin

