Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
195 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,6 @@ | |
*.pyc | ||
*.png | ||
*.osm | ||
*.egg | ||
|
||
resources.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
""" | ||
/*************************************************************************** | ||
ChinesePostman | ||
A QGIS plugin | ||
Chinese Postman Solver | ||
------------------- | ||
begin : 2013-05-11 | ||
copyright : (C) 2013 by Ralf Kistner | ||
email : ralf.kistner@gmail.com | ||
***************************************************************************/ | ||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
This script initializes the plugin, making it known to QGIS. | ||
""" | ||
def name(): | ||
return "Chinese Postman Solver" | ||
def description(): | ||
return "Chinese Postman Solver" | ||
def version(): | ||
return "Version 0.1" | ||
def icon(): | ||
return "icon.png" | ||
def qgisMinimumVersion(): | ||
return "1.7" | ||
def classFactory(iface): | ||
# load ChinesePostman class from file ChinesePostman | ||
from chinesepostman import ChinesePostman | ||
return ChinesePostman(iface) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/bin/sh | ||
zip chinesepostman *.py lib/*.egg metadata.txt icon.png |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
""" | ||
/*************************************************************************** | ||
ChinesePostman | ||
A QGIS plugin | ||
Chinese Postman Solver | ||
------------------- | ||
begin : 2013-05-11 | ||
copyright : (C) 2013 by Ralf Kistner | ||
email : ralf.kistner@gmail.com | ||
***************************************************************************/ | ||
/*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
""" | ||
|
||
# To reload this plugin after modifying, run: | ||
# qgis.utils.reloadPlugin('chinesepostman') | ||
|
||
import postman | ||
|
||
# Import the PyQt and QGIS libraries | ||
from PyQt4.QtCore import * | ||
from PyQt4.QtGui import * | ||
from qgis.core import * | ||
import networkx as nx | ||
|
||
# We need to import resources, even though we don't use it directly | ||
import resources | ||
|
||
class ChinesePostman: | ||
|
||
def __init__(self, iface): | ||
# Save reference to the QGIS interface | ||
self.iface = iface | ||
|
||
def initGui(self): | ||
# Create action that will start plugin configuration | ||
self.action = QAction(QIcon(":/plugins/chinesepostman/icon.png"), \ | ||
"Chinese Postman", self.iface.mainWindow()) | ||
# connect the action to the run method | ||
QObject.connect(self.action, SIGNAL("triggered()"), self.run) | ||
|
||
# Add toolbar button and menu item | ||
self.iface.addToolBarIcon(self.action) | ||
self.iface.addPluginToMenu("&Chinese Postman", self.action) | ||
|
||
def unload(self): | ||
# Remove the plugin menu item and icon | ||
self.iface.removePluginMenu("&Chinese Postman",self.action) | ||
self.iface.removeToolBarIcon(self.action) | ||
|
||
# run method that performs all the real work | ||
def run(self): | ||
layer = self.iface.mapCanvas().currentLayer() | ||
|
||
graph = build_graph(layer.selectedFeatures()) | ||
graph = postman.validate_graph(graph) | ||
|
||
paths = postman.chinese_postman_paths(graph, n=1) | ||
|
||
for eulerian_graph, nodes in paths: | ||
|
||
in_length = postman.edge_sum(graph)/1000.0 | ||
path_length = postman.edge_sum(eulerian_graph)/1000.0 | ||
duplicate_length = path_length - in_length | ||
|
||
info = "" | ||
info += "Total length of roads: %.3f km\n" % in_length | ||
info += "Total length of path: %.3f km\n" % path_length | ||
info += "Length of sections visited twice: %.3f km\n" % duplicate_length | ||
|
||
QMessageBox.information(None, "Chinese Postman", "Done:\n%s" % info) | ||
newlayer = build_layer(eulerian_graph, nodes, layer.crs()) | ||
QgsMapLayerRegistry.instance().addMapLayer(newlayer) | ||
|
||
|
||
def build_layer(graph, nodes, crs): | ||
# create layer | ||
|
||
# We want to set the CRS without prompting the user, so we disable prompting first | ||
s = QSettings() | ||
oldValidation = s.value("/Projections/defaultBehaviour", "useGlobal").toString() | ||
s.setValue("/Projections/defaultBehaviour", "useGlobal") | ||
|
||
vl = QgsVectorLayer("LineString", "chinese_postman", "memory") | ||
vl.setCrs(crs) | ||
|
||
s.setValue("/Projections/defaultBehaviour", oldValidation) | ||
|
||
pr = vl.dataProvider() | ||
|
||
# We use a single polyline to represent the route | ||
points = [] | ||
for node in nodes: | ||
points.append(QgsPoint(node[0], node[1])) | ||
|
||
# add the feature | ||
fet = QgsFeature() | ||
fet.setGeometry(QgsGeometry.fromPolyline(points)) | ||
|
||
pr.addFeatures([fet]) | ||
|
||
# update layer's extent when new features have been added | ||
# because change of extent in provider is not propagated to the layer | ||
vl.updateExtents() | ||
return vl | ||
|
||
def build_graph(features): | ||
graph = nx.Graph() | ||
for feature in features: | ||
geom = feature.geometry() | ||
nodes = geom.asPolyline() | ||
for start, end in postman.pairs(nodes): | ||
graph.add_edge((start[0], start[1]), (end[0], end[1]), weight=geom.length()) | ||
return graph | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#!/bin/sh | ||
pyrcc4 -o resources.py resources.qrc | ||
ln -sfn $PWD $HOME/.qgis/python/plugins/chinesepostman |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# This file contains metadata for your plugin. Beginning | ||
# with version 1.8 this is the preferred way to supply information about a | ||
# plugin. The current method of embedding metadata in __init__.py will | ||
# be supported until version 2.0 | ||
|
||
# This file should be included when you package your plugin. | ||
|
||
[general] | ||
name=Chinese Postman Solver | ||
description=Chinese Postman Solver | ||
version=0.1 | ||
qgisMinimumVersion=1.7 | ||
class_name=ChinesePostman | ||
website= | ||
[author] | ||
name=Ralf Kistner | ||
email=ralf.kistner@gmail.com |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<RCC> | ||
<qresource prefix="/plugins/chinesepostman" > | ||
<file>icon.png</file> | ||
</qresource> | ||
</RCC> |