惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
aimingoo的专栏
aimingoo的专栏
H
Help Net Security
L
LangChain Blog
M
MIT News - Artificial intelligence
The GitHub Blog
The GitHub Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Check Point Blog
P
Proofpoint News Feed
J
Java Code Geeks
大猫的无限游戏
大猫的无限游戏
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
U
Unit 42
I
InfoQ
月光博客
月光博客
爱范儿
爱范儿
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
博客园 - Franky
D
Docker
B
Blog

herrkaefer

"Vibe planning \u003e vibe coding" "Anything to Markdown" "Built anocus: anonymous commenting for static sites" "日记与小说 -- AI 续写小说欣赏" "Any-podcast: from newsletters to a podcast" "Made MicPipe: a simple voice input tool using ChatGPT dictation" "关于 Tools 和 Skills 的一点感想" "Realtime monitoring of ComEd hourly price" "Introducing SwiftEdgeTTS" "Thoughts on the philosophy of building AI-native apps" "jelly鼻屎" "等饭的人" "Use home assistant to motivate my kid to brush teeth" "Migrated Blog to Hugo and Cloudflare Pages" "Easy Aspen monitoring for Chicago parents" "Introducing HabitBuilder: A simple Telegram bot for habit tracking" "鼓捣" "Open folder or file with Sublime Text from Finder toolbar" "Python dev workflow on macOS" "Create new text file from Finder toolbar" "Uno reinvented for 3-year-old kids" "Uno变身儿童数字游戏" "自动转发Twitter到微博" "Handle annoying operations of objects in Realm DB" "Move Jekyll blog to Ubuntu VPS" "Introducing Mole" "Note taking without note taking app" "Deploy Python web application on Ubuntu server" "Setup Shadowsocks / VPN on Ubuntu Server" "Linode Notes - Basic Setup"
"psycopgr Tutorial"
"herrkaefer" · 2016-09-01 · via herrkaefer

What is psycopgr

psycopgr is a Python wrapper of pgRouting written by me.

As said in pgRouting docs:

Just considering the different ways that the cost can be calculated, makes it almost impossible to create a general wrapper, that can work on all applications.

Indeed, in many applications you may need to modify the database tables and fill some computed values to fit your specific purpose, which is often done in a preprocessing stage by SQL, before real routing starts working. It is not appropriate to be wrapped.

However, after preprocessing things such as database creation, map data import, tables re-calculation and update, you are ready to use psycopgr to do another simple thing: computing optimal routes from nodes to nodes on real map, in Python.

Note that psycopgr is never a general purpose wrapper of pgRouting. I am a novice in GIS and what I want from this tool is just routes (with lowest costs) from places to places without writing a single line of SQL.

For preprocessing stage, I have a post “pgRouting notes” for my own reference. Before enjoyable Python coding, you have to prepare a few things.

Tutorial

Requirements

  1. Prepare a PostgreSQL database, install PostGIS and pgRouting extensions, and import map data to database. “pgRouting notes” is a practical guide.

  2. Update database tables according to your specific requirement.

Install psycopgr

(Yes, it is on PyPI now.)

Or,

As you may have guessed from the name, psycopgr uses psycopg2 as PostgreSQL driver. The above command will install it automatically.

Steps

First,

from psycopgr import PgrNode, PGRouting

Create a PGRouting instance with database connection:

pgr = PGRouting(database='mydb', user='user')

Adjust meta data of tables including the edge table properties if they are different from the default (only the different properties need to be set), e.g.:

pgr.set_meta_data(cost='cost_s', reverse_cost='reverse_cost_s', directed=True)

This is the default meta data:

{
    'table': 'ways',
    'id': 'gid',
    'source': 'source',
    'target': 'target',
    'cost': 'cost_s', # driving time in second
    'reverse_cost': 'reverse_cost_s', # reverse driving time in second
    'x1': 'x1',
    'y1': 'y1',
    'x2': 'x2',
    'y2': 'y2',
    'geometry': 'the_geom',
    'has_reverse_cost': True,
    'directed': True,
    'srid': 4326
}

Prepare nodes. Nodes are represented by PgrNode namedtuple with geographic coordinates rather than vertex id (vid) in the tables. PgrNode is defined as:

PgrNode = namedtuple('PgrNode', ['id', 'lon', 'lat'])

in which id could be None or self-defined value, and lon and lat are double precision values. Of course nodes could be input from various interfaces such as database or another program.

For example:

nodes = [PgrNode(None, 116.30150, 40.05500),
         PgrNode(None, 116.36577, 40.00253),
         PgrNode(None, 116.30560, 39.95458),
         PgrNode(None, 116.46806, 39.99857)]

Now we can do routings:

# many-to-many
routings = pgr.get_routes(nodes, nodes, end_speed=5.0, gpx_file='r.gpx')

# one-to-one
routings = pgr.get_routes(nodes[0], nodes[1])

# one-to-many
routings = pgr.get_routes(nodes[0], nodes)

# many-to-one
routings = pgr.get_routes(nodes, nodes[2])
  • end_speed: speed from node to nearest vertices on ways in unit km/h.
  • gpx_file: set it to output paths to a gpx file.

The returned is a dict of dict: {(start_node, end_node): {'path': [PgrNode], 'cost': cost}

By default, cost is traveling time along the path in unit second. It depends on the columns of the edge table that you set as cost and reverse_cost. You can assign the relations by set_meta_data function.

We can also get only costs without detailed paths returned:

costs = pgr.get_costs(nodes, nodes)

The returned is also a dict: {(start_node, end_node): cost}

Low-level wrapper of pgRouting functions

psycopgr functionpgRouting function
dijkstrapgr_dijkstra
dijkstra_costpgr_dijkstraCost
astarpgr_astar

These are direct wrappings of pgRouting functions. For example, dijkstra takes vertex ids as input. This list may be extended in the future.